Documentation menu
Built-ins

Network & concurrency

Talking to the outside world, and doing more than one thing at a time. Task lives here rather than with the language because a worker is a real OS thread with its own arena.

Networking (fetch)

fetch is a general-purpose HTTP client. Declare it once as a native fn, then call it. Only http:// and https:// URLs are allowed, and URLs/headers with control characters are rejected (CRLF / header-injection safe).

native fn string fetch(string url)

let body = fetch("https://pokeapi.co/api/v2/pokemon/ditto")
out JSON.pretty(body)   // pretty-print the JSON response

Signature: fetch(url, [method], [body], [options]). Arguments after the url are sniffed by type — the first string is the method, the second is the body, and a dict is the options.

Default headers: fetch always sends User-Agent: Serez-Code/<version> unless you set your own (without it, some CDNs/WAFs reply 503). When a body is sent it also defaults Content-Type: application/json unless you set one. Any caller-provided header wins.

// POST with a JSON body (build it with JSON.stringify — no raw braces)
let payload <string, any> = ({"name", "serez"}, {"stars", 10})
let res = fetch("https://example.com/api", "POST", JSON.stringify(payload))

// Custom headers (override the default User-Agent, add auth, ...)
let headers <string, string> = ({"Authorization", "Bearer TOKEN"}, {"User-Agent", "my-app/1.0"})
let opts <string, any> = ({"headers", headers}, {"timeout", 10})
let r = fetch("https://example.com/api", opts)

Options dict (a <string, any> dict): headers (a <string, string> dict), timeout (seconds, default 60), full(return a structured response and don't throw on HTTP status), and binary (return the body as a byte array [int] for images/zips/PDFs).

native fn any fetch(string url, any options)

// full mode → { status, ok, statusText, headers, body }, never throws on status
let opts <string, any> = ({"full", true})
let r = fetch("https://pokeapi.co/api/v2/pokemon/ditto", opts)
if (r["ok"] == true) {
    out "status " + r["status"]    // 200
    out JSON.pretty(r["body"])     // headers keyed by lowercased name; missing key → null
}

Default mode (no full) returns the body string and throws on status ≥ 400 (the response body is embedded in the error), so wrap calls in try / catch:

try {
    let body = fetch("https://pokeapi.co/api/v2/pokemon/ditto")
    out body.length()
} catch (e) {
    out "request failed: " + e
}

Socket (TCP & WebSocket)

Raw TCP client/server sockets over the standard library, plus RFC 6455 WebSocket text frames. These are the low-level networking primitives — for a full HTTP/WebSocket server with routing, use the serez-http package. Requires the Socket permission — declare it in your serez.json or at the top of your script:

// serez.json
{ "permissions": ["Socket"] }
// or inline
use permissions { Socket }

TCP client

use permissions { Socket }

// Connect, send a request, read the reply
let sock = Socket.connect("example.com", 80)   // → socket id (int)
Socket.send(sock, "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n")
let reply = Socket.recv(sock, 4096)            // read up to 4096 bytes → string
out reply
Socket.close(sock)

TCP server

use permissions { Socket }

// Listen, accept a connection, echo a message back
let server = Socket.listen(8080)   // → listener id (int)
let conn   = Socket.accept(server) // blocks until a client connects → socket id
let msg    = Socket.recv(conn, 1024)
Socket.send(conn, "echo: " + msg)
Socket.close(conn)
Socket.close(server)

WebSocket frames

After a connection is established, exchange WebSocket text frames. recvWsFrame returns the decoded payload, or nullon a close frame / end of connection. Frames larger than 16 MiB are rejected (DoS-safe).

Socket.sendWsFrame(conn, "ping")        // encode + send a text frame → null
let frame = Socket.recvWsFrame(conn)    // → text payload, or null on close
if (frame != null) {
    out "received: " + frame
}
MethodReturnsDescription
Socket.connect(host, port)intOpen a TCP connection → socket id
Socket.send(id, data)intSend a string → bytes written
Socket.recv(id, max_bytes)stringRead up to max_bytes
Socket.listen(port)intBind + listen → listener id
Socket.accept(listener_id)intAccept a connection (blocks) → socket id
Socket.close(id)nullClose a socket or listener
Socket.sendWsFrame(id, data)nullSend a WebSocket text frame
Socket.recvWsFrame(id)string | nullRead one WebSocket text frame

Task (Concurrencia)

Execute background scripts in native threads to prevent blocking the main thread (highly critical to keep GUI apps running smoothly). Requires use permissions { Task }.

use permissions { Task, Time }

// 1. Spawns the worker script in the background
let taskId = Task.run("worker.sz", "Serez Developer")

// 2. Poll for completion (non-blocking)
while (!Task.isDone(taskId)) {
    Time.sleep(10)
}

// 3. Retrieve the final result
let result = Task.poll(taskId)
out result

Inside the worker script (e.g. worker.sz), use Task.message() to retrieve the input argument, and Task.reply(result) to return the response and terminate the worker:

// worker.sz
use permissions { Task }

let input = Task.message()
let response = "Hello, " + input
Task.reply(response)
MethodReturnsDescription
Task.run(script_path, arg)intSpawns a background worker thread → task id
Task.message()string(Worker only) Retrieves the input argument
Task.reply(result)null(Worker only) Sends the result and terminates the worker
Task.isDone(id)boolChecks if the task has finished or failed
Task.poll(id)string | nullReturns the result if finished, null if running, or error message