Skip to content

Builtins & Globals

Weld has no importable standard library — the useful primitives are built into the language. This page is the exhaustive reference: every builtin function, every builtin statement, and every builtin type/global the compiler recognises. Signatures are written in Weld type notation (T? optional, [T] list, [K: V] map, T! fallible).

Everything here is checked by the compiler: a wrong argument type or arity is a compile-time error, not a runtime surprise.

String functions

All string builtins are pure and total (they never fail).

SignatureReturnsDescription
upper(s: string) -> stringuppercased copyASCII upper-case.
lower(s: string) -> stringlowercased copyASCII lower-case.
trim(s: string) -> stringtrimmed copyStrip leading and trailing ASCII whitespace.
trimPrefix(s: string, prefix: string) -> strings without prefixIf s starts with prefix, drop it; otherwise return s unchanged.
contains(s: string, needle: string) -> boolboolIs needle a substring of s?
startsWith(s: string, prefix: string) -> boolboolDoes s begin with prefix?
endsWith(s: string, suffix: string) -> boolboolDoes s end with suffix?
parseInt(s: string) -> intintParse a base-10 integer (invalid input yields 0).
weld
route GET "/normalize/:raw" (raw: string) -> string {
    let name = trim(lower(raw))
    let tag  = trimPrefix(name, "user-")     # "user-ada" -> "ada"
    respond "name={name} tag={tag} isuser={startsWith(name, "user-")} n={parseInt("42")}"
}

For building strings, use + concatenation and {expr} interpolation — see Expressions & Control Flow. For string → enum, use the enum reinterpreter below.

Conversion functions

SignatureReturnsDescription
str(x: int | float | bool | string | Enum) -> stringstringRender any primitive or enum as text. On an enum it yields the variant's string label.
int(e: Enum) -> intintThe enum variant's underlying number. (For string -> int, use parseInt.)
hash(x: int | float | bool | string | Enum) -> intintA stable 64-bit hash (Wyhash). The building block for hash maps written in Weld.
Enum(x: int | string) -> Enumthe enumEnum reinterpreter — turn a number or string back into an enum value; an unknown input becomes the zero Unspecified variant. Enum is the name of any enum you declared.
weld
enum Role { Admin = 1 : "admin", User = 2 : "user" }

route GET "/role/:name" (name: string) -> string {
    let r = Role(name)                       # string -> enum (unknown -> Unspecified)
    respond "label={str(r)} number={int(r)} again={str(Role(int(r)))} hash={hash(r)}"
}

See Enums & Sum Types for the full enum model.

List functions

[T] is a mutable list (a Zig slice). Indexing (xs[i]) is bounds-checked — an out-of-range index is a recoverable error that fails the request rather than crashing the server.

SignatureReturnsDescription
len(xs: [T]) -> intintNumber of elements.
push(xs: [T], v: T) -> [T]a new listAppend v, returning the grown list. push returns the result — assign it back: xs = push(xs, v).
filled(n: int, v: T) -> [T][T] of length nPreallocate a list of n copies of v.
slice(xs: [T], start: int, end: int) -> [T][T]The sub-range [start, end), clamped to bounds (a bad range yields an empty list, never a crash).
pop(xs: [T]) -> [T][T]The list without its last element; an empty list stays empty.
concat(a: [T], b: [T]) -> [T][T]The two lists joined; element types must match.
reverse(xs: [T]) -> [T][T]The list reversed.
contains(xs: [T], v: T) -> boolboolIs v an element of xs? For primitive or enum element types (strings compared by value).
sort(xs: [T]) -> [T][T]The list sorted ascending. T must be int, float, or string.
insert(xs: [T], i: int, v: T) -> [T][T]A new list with v inserted at index i (clamped to [0, len]).
removeAt(xs: [T], i: int) -> [T][T]A new list without the element at index i (out-of-range: unchanged).
map(xs: [T], f: x => U) -> [U][U]Each element transformed by the closure f.
filter(xs: [T], p: x => bool) -> [T][T]The elements for which the predicate p is true.
reduce(xs: [T], init: A, f: (acc, x) => A) -> AAFold left: start from init, combine each element into the accumulator.

All of these are also methodsxs.op(…) is the same as op(xs, …), and reads better when chained: xs.filter(x => x > 0).map(x => x * 2).sort(). The higher-order ops take closures: a one-parameter x => … for map/filter, and a two-parameter (acc, x) => … combiner for reduce.

weld
route GET "/build/:n" (n: int) -> string {
    var xs = filled(3, 0)          # [0, 0, 0]
    xs = push(xs, n)               # [0, 0, 0, n]
    xs = concat(xs, [1, 2])        # [0, 0, 0, n, 1, 2]
    xs = slice(xs, 2, len(xs))     # drop the first two
    xs = reverse(pop(xs))          # drop the last, then reverse
    xs[0] = 100                    # index-assign (bounds-checked)
    var total = 0
    for i, x in xs { total = total + x + i }   # indexed iteration
    respond "len={len(xs)} first={xs[0]} has100={contains(xs, 100)} total={total}"
}

The higher-order ops read best as a method chain:

weld
route GET "/stats" -> string {
    let xs = [5, 3, 8, 1, 9, 2]
    let bigs = xs.filter(x => x > 3).map(x => x * 10)   # [50, 80, 90]
    let total = xs.reduce(0, (acc, x) => acc + x)       # 28
    let ranked = xs.sort()                              # [1, 2, 3, 5, 8, 9]
    respond "n_big={len(bigs)} total={total} min={ranked[0]} max={ranked[len(ranked) - 1]}"
}

An empty list literal takes its element type from context — a declared type, a return type, filled, or the left of a ??: let seen = maybe ?? [].

Map functions

[K: V] is a hash map with string or int keys. A lookup m[k] yields V? (null when the key is absent); m[k] = v inserts or overwrites.

SignatureReturnsDescription
len(m: [K: V]) -> intintNumber of entries.
has(m: [K: V], k: K) -> boolboolIs k present?
remove(m: [K: V], k: K) -> boolboolRemove k; returns whether it was present.

Iterate with for k, v in m { … }. Maps are commonly stored in state so they persist across requests.

weld
state counts { var hits: [string: int] = [:] }

route GET "/hit/:page" (page: string) -> string {
    let n = (counts.hits[page] ?? 0) + 1     # m[k] -> V?, ?? gives a default
    counts.hits[page] = n
    if has(counts.hits, "admin") { let _ = remove(counts.hits, "admin") }
    respond "{page}={n} total_pages={len(counts.hits)}"
}

Environment & time

SignatureReturnsDescription
env(name: string) -> stringstringRead an environment variable (empty string if unset). Used for configuration — database URLs, secrets, upstream bases.
now_ms() -> intintCurrent Unix time in milliseconds. Available anywhere.
ready() -> boolbooltrue normally, false once the server is draining (SIGTERM received). Serve it from a readiness probe so the load balancer stops routing before shutdown — see Graceful shutdown.

env() is the idiomatic way to configure the resource blocks:

weld
database db { url env("DATABASE_URL") }
upstream api { base env("BACKEND_URL") }
grpc Svc { addr env("GRPC_ADDR") }

Request context

These read from the in-flight HTTP request, so they are only valid inside a route handler or a decorator (using them elsewhere is a compile-time error).

SignatureReturnsDescription
request_header(name: string) -> string?string?A request header value, or null if absent. Case-insensitive name.
request_cookie(name: string) -> string?string?A cookie value from the request's Cookie header, or null if absent.
client_ip() -> stringstringThe client IP, honouring X-Forwarded-For / X-Real-IP when present.
weld
route GET "/whoami" -> string {
    let ua = request_header("User-Agent") ?? "unknown"
    let sid = request_cookie("session") ?? "anonymous"
    respond "ip={client_ip()} agent={ua} session={sid} at={now_ms()}"
}

These are the primitives that rate limiting and auth are built from — in Weld itself, with no dedicated middleware.

Form bodies & file uploads

Read a submitted HTML form or file upload from the request body. All return an optional (null when the field is absent), so pair them with ?? or else.

SignatureReturnsDescription
form_field(name: string) -> string?string?A field from a application/x-www-form-urlencoded or multipart/form-data body (auto-detected by Content-Type; urlencoded values are %/+-decoded).
upload(name: string) -> string?string?A multipart file part's raw bytes (binary-safe).
upload_filename(name: string) -> string?string?The filename of a multipart file part.
weld
route POST "/upload" -> string {
    let file = upload("file") else { fail 400 "no file part" }
    let name = upload_filename("file") ?? "upload.bin"
    let note = form_field("note") ?? ""
    respond "stored {name} ({len(file)} bytes), note: {note}"
}

The buffered body (JSON body params, form_field, upload) is capped by MAX_BODY_SIZE (default 8 MB). For larger inputs, stream instead.

Streaming the request body

SignatureReturnsDescription
request_body() -> Stream<string>a stream of chunksThe raw request body as a stream of byte chunks, consumed by for chunk in request_body() { … }. Read in constant memory — the whole body is never buffered, so it handles inputs far larger than MAX_BODY_SIZE.
weld
route POST "/measure" -> string {
    var bytes = 0
    for chunk in request_body() {          # each chunk is a slice of raw bytes
        bytes = bytes + len(chunk)
    }
    respond "received {bytes} bytes"
}

A streaming route cannot also declare a JSON body parameter (that needs the whole body); read what you need from the chunks instead.

JWT

HS256 JSON Web Tokens. The first argument is a record type naming the claims to decode the payload into; the compiler checks it and produces a value of that type.

SignatureReturnsDescription
jwt_sign(claims: Record, secret: string) -> stringstringSign a claims record as an HS256 token. The record's fields become the payload — include exp/iat/nbf as int fields (Unix seconds) to set the standard claims.
jwt_verify(Type, token: string, secret: string) -> Type!Type! (fallible)Verify the HS256 signature (constant-time) and decode the payload into Type. A bad signature, a malformed token, an expired exp, or a not-yet-valid nbf all fail — combine with try/else.
jwt_decode(Type, token: string) -> Type?Type? (optional)Decode the payload without verifying. null on a malformed token. Use only when another layer already established trust.

When the claims Type carries exp/nbf as plain int fields, jwt_verify enforces them automatically (an expired token becomes a 401).

weld
type Claims = { sub: string, exp: int }

route GET "/login/:user" (user: string) -> string {
    let claims = Claims { sub: user, exp: now_ms() / 1000 + 3600 }
    respond jwt_sign(claims, env("JWT_SECRET"))     # issue a 1-hour token
}

route GET "/me" (query token: string) -> Claims {
    let claims = try jwt_verify(Claims, token, env("JWT_SECRET"))   # rejects expired/tampered
    respond claims
}

Unknown JSON fields in the payload are ignored, so your Claims record only needs the fields you use.

Crypto & encoding

Hashing, HMAC, secure randomness, password hashing, and encodings — the building blocks of tokens, sessions, and signatures. Hex/base64 outputs are lowercase; decoders return "" on malformed input (like parseInt returning 0).

SignatureReturnsDescription
password_hash(pw: string) -> stringstringA bcrypt hash (cost 10) with a random salt — the $2b$… string to store.
password_verify(pw: string, hash: string) -> boolboolCheck a password against a stored bcrypt hash (constant-time).
random_bytes(n: int) -> bytesbytesn cryptographically-secure random bytes. Encode (hex/base64) before storing or sending as text.
uuid() -> stringstringA random v4 UUID, e.g. 2f1f4051-1790-443d-bc97-86daac32cbec.
sha256(data) -> stringstringLowercase-hex SHA-256 digest (64 chars). data is a string or bytes.
hmac_sha256(msg, key) -> stringstringLowercase-hex HMAC-SHA-256 (64 chars). Args are string or bytes.
base64_encode(data) -> string / base64_decode(s: string) -> bytesStandard Base64 (with padding). Encoders take string/bytes; decoders yield bytes.
base64url_encode(data) -> string / base64url_decode(s) -> bytesURL-safe Base64, no padding (as used in JWTs).
hex_encode(data) -> string / hex_decode(s) -> bytesLowercase hex.
base32_encode(data) -> string / base32_decode(s) -> bytesRFC 4648 Base32 (for TOTP secrets, authenticator apps).
encrypt(key, data) -> bytesbytesAES-256-GCM authenticated encryption. key is hashed to 32 bytes; output is nonce ‖ ciphertext ‖ tag.
decrypt(key, data) -> bytes?bytes?Decrypt & authenticate; null on a wrong key or tampered data.
seal(key, data) -> string / unseal(key, token) -> bytes?Like encrypt/decrypt but the token is compact base64url — handy for signed+encrypted cookies.
totp(secret) -> stringstringCurrent 6-digit TOTP code (RFC 6238, 30 s window, HMAC-SHA1).
totp_verify(secret, code) -> boolboolCheck a code against the current window ±1 (clock-skew tolerant).
es256_keygen() -> string / es256_public(priv) -> stringstringGenerate an ECDSA P-256 private key (hex), and derive its SEC1 public key (hex).
jwt_sign_es256(claims, priv) -> stringstringSign a claims record as an ES256 (asymmetric) JWT with a hex private key.
jwt_verify_es256(T, token, pub) -> T!T!Verify an ES256 JWT with the hex public key and decode into T (enforces exp/nbf).
pem_key(pem) -> stringstringExtract a P-256 key from PEM (SEC1/PKCS#8 private, or SPKI public) into the hex the es256_*/jwt_*_es256 builtins accept; "" on a malformed PEM.
to_bytes(s: string) -> bytes / to_string(b: bytes) -> stringReinterpret text ⇄ raw bytes (no copy).
read_file(path: string) -> bytes?bytes?Read a file's contents (up to 16 MiB) as bytes; null if it can't be read. Serve a file with respond read_file(...) else { … } plus type/header. Beware path traversal — never pass unvalidated request input as the path.
read_file_stream(path: string) -> Stream<bytes>a stream of chunksStream a file's bytes chunk-by-chunk (constant memory, any size), consumed by for chunk in read_file_stream(path) { emit chunk } — for chunked file downloads. No chunks if the file can't open. Same path-traversal caveat as read_file.
ice_servers(id: string, ttl: int) -> stringstring (JSON)Browser-ready RTCConfiguration JSON with a short-lived TURN-REST credential (valid ttl seconds) for the turn relay. Requires a turn { } block.
weld
type Creds = { username: string, password: string }

state accounts { var hashes: [string: string] = [:] }

route POST "/register" (body creds: Creds) -> string {
    accounts.hashes[creds.username] = password_hash(creds.password)   # bcrypt
    respond "token={hex_encode(random_bytes(24))} id={uuid()}"        # opaque token + id
}

route POST "/login" (body creds: Creds) -> string {
    let stored = accounts.hashes[creds.username] ?? ""
    if !password_verify(creds.password, stored) { fail 401 "invalid credentials" }
    respond "signature={hmac_sha256(creds.username, env("HMAC_KEY"))}"
}

hash() (above, under Conversion) is Wyhash — fast but not cryptographic; never use it for passwords or signatures. Reach for password_hash or hmac_sha256/sha256 instead.

Files & directories (std)

Low-level file I/O and filesystem queries, namespaced under std. Paths are resolved relative to the server process's working directory. File descriptors are plain ints (< 0 means the open failed). Reads and writes stream, so you can move files of any size in constant memory. For a self-contained whole-file download, read_file/read_file_stream (above) are simpler; these are the building blocks when you manage the descriptor yourself (e.g. writing an upload straight to disk).

SignatureReturnsDescription
std.open_file_write(path: string) -> intfd, or -1Create/truncate path for writing and return its descriptor.
std.open_file_read(path: string) -> intfd, or -1Open path for reading and return its descriptor.
std.write(fd: int, data: bytes) -> intbytes written, or -1Write data (a string or bytes) to the descriptor.
std.read_stream(fd: int) -> Stream<bytes>a stream of chunksRead the descriptor chunk-by-chunk, consumed by for chunk in std.read_stream(fd) { … }. Closes fd when the stream is exhausted.
std.close(fd: int)Close a descriptor (a no-op for fd < 0).
std.file_exists(path: string) -> boolboolDoes path exist and is it reachable?
std.is_file(path: string) -> boolboolIs path a regular file?
std.is_dir(path: string) -> boolboolIs path a directory?
std.make_dir(path: string) -> boolboolCreate a directory and any missing parents (like mkdir -p); true on success or if it already exists.
std.delete_file(path: string) -> boolboolDelete a file; true if it was removed, false if it was missing or couldn't be deleted.
std.list_dir(path: string) -> [string][string]The entry names in a directory (empty if it can't be read).

Stream an upload straight to disk, then stream it back — constant memory in both directions:

weld
route POST "/files/:name" (name: string) -> string {
    let fd = std.open_file_write("uploads/{name}")
    if fd < 0 { fail 500 "cannot open file" }
    for chunk in request_body() {                 # raw body, chunk by chunk
        if std.write(fd, chunk) < 0 { std.close(fd)  fail 500 "write failed" }
    }
    std.close(fd)
    respond "stored {name}"
}

route GET "/files/:name" (name: string) -> bytes {
    let path = "uploads/{name}"
    if !std.file_exists(path) { fail 404 "no such file" }
    let fd = std.open_file_read(path)
    type "application/octet-stream"
    for chunk in std.read_stream(fd) { emit chunk }   # closes fd at EOF
}

WARNING

path is used verbatim — never pass unvalidated request input (a caller could send ../etc/passwd). Confine writes to a directory you control and validate or replace the name, as the upload route does by only using the :name segment inside uploads/.

Statements

Weld handlers are made of statements. These keywords are the statement vocabulary.

Response statements

Valid inside a route handler.

StatementEffect
respond ExprSend the value and finish the handler. A record/list/sum encodes as JSON (application/json); a string is sent as text; a number/bool is rendered.
status <int | HttpStatus>Set the HTTP status code (default 200). Takes an int (status 404) or a value of the built-in std.HttpStatus enum (status std.HttpStatus.NotFound).
type <string | MimeType>Set the Content-Type header (default text/plain). Takes a literal string (type "application/json") or a value of the built-in std.MimeType enum (type std.MimeType.Json) to avoid mis-spelling common types.
header Name ValueAdd an arbitrary response header (both strings), e.g. header "Cache-Control" "no-store". Use for CORS, caching, or a raw Set-Cookie. Also valid in a decorator.
cookie Name ValueSet a Set-Cookie with secure session defaults (Path=/; HttpOnly; SameSite=Lax). For full control (Max-Age, Secure) use header "Set-Cookie" "…".
emit ExprStream one chunk (a string or bytes) via HTTP chunked transfer; the body is never fully buffered. Repeatable — e.g. for chunk in read_file_stream(path) { emit chunk } for a chunked download. Any type/header/cookie (and configured CORS headers) set before the first emit are carried in the chunked reply's head; a respond before the first emit is a terminal early bail-out (sends a normal buffered reply and returns).
serve BASE SUBSend the file at BASE/SUB; content type inferred from the extension, 404 if missing, 403 on a .. traversal.
fail STATUS MESSAGEShort-circuit with an error response. STATUS is any int expression (a literal, a variable, or a std.HttpStatus value like std.HttpStatus.NotFound); MESSAGE is any string expression. Also usable in decorators, hubs, and transactions. In a typed-error function, fail Variant(…) raises a typed value instead.
weld
route GET "/report" {
    type std.MimeType.Text   # or: type "text/plain; charset=utf-8"
    status 200
    emit "line 1\n"
    emit "line 2\n"          # each emit is flushed immediately
}

route GET "/assets/*path" (path: string) {
    serve "public" path       # ./public/<path>
}

The std namespace

std is the built-in standard-library namespace. Its members are ordinary proto-style enums, referenced with the std. prefix (there is no bare MimeType — only std.MimeType). They need no import, work with str() / int() / Mime(s)-style reinterpretation like any enum, and only appear in the generated code when you reference them.

std.MimeType — well-known content types, so you write type std.MimeType.Json instead of a mis-spellable "application/json". Each variant's string is the MIME type (str(std.MimeType.Html)"text/html; charset=utf-8"). std.MimeType.Bytes (application/octet-stream) is the zero/fallback.

VariantContent typeVariantContent type
.Jsonapplication/json.Bytesapplication/octet-stream
.Htmltext/html; charset=utf-8.Texttext/plain; charset=utf-8
.Csstext/css; charset=utf-8.Jstext/javascript; charset=utf-8
.Xmlapplication/xml.Yamlapplication/yaml
.Csvtext/csv; charset=utf-8.EventStreamtext/event-stream
.Formapplication/x-www-form-urlencoded.Multipartmultipart/form-data
.Pngimage/png.Jpegimage/jpeg
.Gifimage/gif.Webpimage/webp
.Svgimage/svg+xml.Icoimage/x-icon
.Pdfapplication/pdf.Wasmapplication/wasm
.Zipapplication/zip.Gzipapplication/gzip
.Woff2font/woff2.Mp4video/mp4
.Mpegaudio/mpeg

std.HttpStatus — named status codes, so you write status std.HttpStatus.NotFound instead of 404. Each variant's number is the code (used by status) and its string is the reason phrase (str(std.HttpStatus.NotFound)"Not Found"). Covers the common 1xx–5xx codes: .Continue, .SwitchingProtocols, .Ok, .Created, .Accepted, .NoContent, .PartialContent, .MovedPermanently, .Found, .SeeOther, .NotModified, .TemporaryRedirect, .PermanentRedirect, .BadRequest, .Unauthorized, .Forbidden, .NotFound, .MethodNotAllowed, .NotAcceptable, .RequestTimeout, .Conflict, .Gone, .PayloadTooLarge, .UnsupportedMediaType, .UnprocessableEntity, .TooManyRequests, .InternalServerError, .NotImplemented, .BadGateway, .ServiceUnavailable, .GatewayTimeout.

Bindings & assignment

StatementEffect
let name [: T] = ExprImmutable binding. Optional explicit type.
var name [: T] = ExprMutable binding.
name = ExprReassign a var.
obj.field = ExprAssign a record field (through a mut self or a state field).
xs[i] = ExprList index-assign (bounds-checked).
m[k] = ExprMap insert / overwrite.
let _ = ExprEvaluate for effect and discard (e.g. an ignored fallible result).

Control flow

StatementEffect
if C { … } else if C2 { … } else { … }Conditional. else if / else are optional.
for x in Iterable { … }Iterate a list, a stream, or any type with a next(mut self) -> T? method.
for i, x in List { … }Iterate a list with a 0-based int index i and the element x.
for k, v in Map { … }Iterate a map's key/value pairs.
return [Expr]Return from a fn (bare return in a void fn).
assert CondIn a test block, assert a boolean; a failing assert fails the test run.
transaction db { … }Run the body inside a Postgres BEGIN/COMMIT, rolling back on any failure.

match is an expression, not a statement — see below.

Fallible & optional handling

FormEffect
try ExprEvaluate a fallible T!; on failure, propagate (auto error response in a route, .err in a fallible fn). Yields the unwrapped T.
let x = Expr else e { … }Handle a fallible failure: e is bound to the error (Error, or the declared typed error) and the block must diverge (respond/fail/return).
let x = Expr else { … }Unwrap an optional T?; the block runs (and must diverge) when the value is null.
weld
route GET "/u/:id" (id: int) -> User {
    let u = db.findUser(id) else e {         # fallible: bind the Error
        status 404
        respond "not found: {e.message}"
    }
    let email = u.email else { fail 400 "no email on file" }   # optional: unwrap or fail
    respond User { id: u.id, name: u.name, email: email }
}

See Error Handling for the full model.

Hub surface

These are only meaningful inside a WebSocket hub. They manage a connection's identity/membership and let you push server-initiated events.

Per-connection operations

Valid inside a hub's connect block or a method. Each acts on the current connection.

SignatureEffect
identify(id: string)Tag this connection with an identity (e.g. a user id) so it can be targeted by c.identity.
join(group: string)Add this connection to a named listener group.
leave(group: string)Remove this connection from a group.

Broadcasting to clients

Hub.clients (where Hub is your hub's name) is a queryable set of live connections. Filter it, then push an event to the survivors.

ExpressionMeaning
Hub.clientsThe set of all connected clients.
.filter(c => Bool)Keep connections matching a predicate. Chainable.
.send(Record)Push a record to each connection as {"event":"<TypeName>","data":{…}}.
.count() -> intThe number of live connections (after any .filter). Also valid in a plain route handler.

A hub may also declare a disconnect { … } block that runs when a socket drops — the connect-time injected bindings stay in scope, so it can broadcast a departure, but it has no client to reply to. See WebSocket Hubs.

Inside a filter predicate the parameter (c) is a connection handle:

Field / methodTypeMeaning
c.identitystringThe connection's identify(…) tag.
c.idintA stable per-connection id.
c.subscribed(group: string) -> boolboolIs the connection in group?
c.<injected>injected typeAny binding from the hub's connect (…) injects (x: T) clause, e.g. c.user.
weld
type Notice = { text: string }

hub Chat {
    connect (query token: string, query room: string) injects (user: Claims) {
        user = try jwt_verify(Claims, token, env("JWT_SECRET"))
        identify(user.sub)                    # target by user id later
        join(room)                            # add to the room group
        Chat.clients.filter(c => c.subscribed(room))
            .send(Notice { text: "{user.sub} joined" })
    }

    method dm(to: string, text: string) {
        Chat.clients.filter(c => c.identity == to)   # a direct message
            .send(Notice { text: text })
    }
}

Builtin types & globals

NameKindDescription
intprimitive64-bit signed integer. Arithmetic wraps on overflow.
floatprimitive64-bit floating point.
boolprimitivetrue / false.
stringprimitiveUTF-8 text (a byte slice).
T?type formerOptional — the value or null.
[T]type formerMutable list.
[K: V]type formerMap (K is string or int).
T!type formerFallible result (carries Error or a declared typed error).
Errorbuiltin record{ status: int, message: string }. The error a bare else e { … } binds, and the shape of the automatic error response. You can construct and read it like any record.
Selfbuiltin typeInside an interface method signature or a generic method, refers to the implementing type.
nullliteralThe absent value of any T?.
injected bindingsvalueNames introduced by a decorator's or hub's injects (…) clause (e.g. user), typed and in scope in the handler/method body.

Sum-type variants are constructed qualifiedShape.Circle(2.0), Role.Admin — and matched unqualified. Sum types and the Error type together power typed errors.

Quick index

  • Strings: upper · lower · trim · trimPrefix · contains · startsWith · endsWith · parseInt
  • Conversion: str · int · hash · Enum(x)
  • Lists: len · push · filled · slice · pop · concat · reverse · contains · sort · insert · removeAt · map · filter · reduce (all callable as xs.op(…))
  • Maps: len · has · remove
  • Env & time: env · now_ms
  • Request: request_header · request_cookie · client_ip · form_field · upload · upload_filename · request_body
  • JWT: jwt_sign · jwt_verify · jwt_decode (HS256) · jwt_sign_es256 · jwt_verify_es256 · es256_keygen · es256_public · pem_key (ES256)
  • Crypto & encoding: password_hash · password_verify · random_bytes · uuid · sha256 · hmac_sha256 · encrypt · decrypt · seal · unseal · totp · totp_verify · base64_encode · base64_decode · base64url_encode · base64url_decode · hex_encode · hex_decode · base32_encode · base32_decode
  • Bytes & files: to_bytes · to_string · read_file · read_file_stream (see the bytes type)
  • Files & dirs (std): std.open_file_write · std.open_file_read · std.write · std.read_stream · std.close · std.file_exists · std.is_file · std.is_dir · std.make_dir · std.delete_file · std.list_dir
  • Hub: identify · join · leave · Hub.clients.filter(…).send(…) · .count()
  • WebRTC: ice_servers (with a turn { } block)
  • Statements: respond · status · type · header · cookie · emit · serve · fail · let · var · if · for · match · return · assert · transaction · try · else