Symmetra logo

Package Reference

Every package Symmetra ships, every function it exposes, what each parameter does, and what each call returns. All signatures below match the published type definitions exactly.

Beta software. These APIs are functional but may change between releases. Packages marked with implementation notes have known limitations — check the constraints page before relying on advanced patterns.

One important concept before you start: Symmetra packages contain no JavaScript runtime code. They are compile-time type definitions. When you run sym server.ts, the Symmetra engine reads your source, resolves these imports, and generates CUDA C++ for your handlers. Your code never executes in Node.js.

@symmetra/http HTTP server

The GPU-native HTTP server. This is the package every Symmetra application starts with.

import { Router, serve } from '@symmetra/http'

new Router()

Creates a route table. Each route handler you register compiles to a CUDA device function.

MethodParametersReturnsWhat it does
get(path, handler)path: string, handler: (ctx) => void | Promise<void>thisRegisters a GET route. Chainable.
post(path, handler)samethisRegisters a POST route.
put(path, handler)samethisRegisters a PUT route.
delete(path, handler)samethisRegisters a DELETE route.
patch(path, handler)samethisRegisters a PATCH route.
route(prefix)prefix: stringRouterGroupReturns a sub-router whose routes are all prefixed (e.g. /api).
use(middleware)(ctx, next) => Promise<void>thisRegisters middleware that runs before route handlers.
const app = new Router()

app.get('/health', ctx => {
  ctx.json({ status: 'ok' })
})

// Grouped routes — everything under /api
const api = app.route('/api')
api.get('/users', ctx => { /* GET /api/users */ })
api.post('/users', ctx => { /* POST /api/users */ })

serve(app, options?)

The entry point. The Symmetra engine intercepts this call at compile time and uses it to configure the GPU server. Returns nothing — the process stays alive serving requests.

Returns: void (the server runs until the process is stopped)

All options are covered in depth with complete examples on the Server Configuration page. Summary:

OptionTypeDefaultMeaning
portnumber8080TCP port to listen on.
hostnamestring'0.0.0.0'Bind address.
streamsnumber32CUDA stream pool size (max 64).
batchnumber64Requests grouped per GPU dispatch.
logLevel'debug'|'info'|'warn'|'error''info'Runtime log verbosity.
maxBodyBytesnumberReject request bodies larger than this.
schedulerSchedulerOptionsAdvanced GPU/IO tuning — see scheduler options.

The ctx object (SymmCtx)

Every handler receives one argument: the request/response context. This is how you read the request and write the response.

Reading the request:

Property / MethodReturnsWhat it gives you
ctx.methodstringHTTP method ('GET', 'POST', …)
ctx.pathstringRequest path ('/api/users')
ctx.queryRecord<string,string>Parsed query string (?a=1{ a: '1' })
ctx.paramsRecord<string,string>Route parameters
ctx.headersRecord<string,string>All request headers
ctx.header(name)string | undefinedOne header value
ctx.text()Promise<string>Body as a string
ctx.json<T>()Promise<T>Body parsed as JSON
ctx.body<T>()Promise<GpuBuffer<T>>Raw body as a VRAM buffer — zero-copy, already on GPU

Writing the response:

MethodReturnsWhat it does
ctx.status(code)thisSets the HTTP status code. Chainable: ctx.status(404).json({...})
ctx.json(data)voidSerializes data to JSON and sends it with Content-Type: application/json
ctx.text(data)voidSends a plain-text response
ctx.send(data)voidSends raw bytes — accepts a GpuBuffer or Uint8Array
ctx.header(name, value)thisSets a response header. Chainable.

Utilities on ctx:

PropertyTypeWhat it gives you
ctx.gpuGpuApiDevice info and compute primitives — see gpu API
ctx.kvKvApiThe VRAM key-value store — see @symmetra/kv
app.post('/echo', async ctx => {
  const body = await ctx.json<{ name: string }>()
  ctx.status(200)
     .header('X-Engine', 'symmetra')
  ctx.json({ hello: body.name, device: ctx.gpu.deviceName })
})

@symmetra/core GPU primitives

GPU buffer types, VRAM containers, and compute primitives. Most of these are standard JavaScript shapes (Map, Set, Promise, EventEmitter) that the compiler maps to GPU equivalents — you usually don't import them explicitly.

GpuBuffer<T>

A typed array resident in VRAM. Array operations compile to parallel CUDA kernels — one GPU thread per element instead of a CPU loop.

MemberReturnsWhat it does
lengthnumberElement count.
byteLengthnumberSize in bytes.
map(fn)GpuBuffer<U>Parallel transform — each element processed by its own GPU thread.
filter(fn)GpuBuffer<T>Parallel filter.
reduce(fn, init)numberParallel tree reduction.
forEach(fn)voidParallel iteration (side effects only).
slice(start?, end?)GpuBuffer<T>Sub-range — zero-copy view when possible.
toCpu()T (the typed array)Copies data back to CPU memory. Avoid in hot paths — it crosses the PCIe bus.
toArray()number[]Copies back as a plain JS array. Same cost warning.

gpu (GpuApi)

Available as ctx.gpu inside handlers or imported as gpu from @symmetra/http.

MemberReturnsWhat it does
fingerprint(data)Promise<bigint>Hashes a string or buffer entirely on GPU.
alloc<T>(length)GpuBuffer<T>Allocates a typed array in VRAM.
upload(data)Promise<GpuBuffer<T>>Uploads a CPU typed array to VRAM via pinned-memory DMA.
parallel(n, fn)Promise<void>Runs fn(tid) across n GPU threads — raw parallel kernel.
deviceNamestringe.g. "NVIDIA GeForce RTX 5070"
computeSmstringCompute capability, e.g. "sm_120"
vramTotal / vramFreenumberVRAM in bytes.
streamCountnumberActive CUDA streams.

GpuMap, GpuSet, GpuRegExp

Standard JavaScript Map, Set, and RegExp literals compile to VRAM-resident equivalents automatically. The interfaces match the standard built-ins — get/set/has/delete/clear/size, iteration, test/exec. RegExp literals compile to a GPU DFA at kernel-compile time, so there is no runtime regex JIT cost. Explicit constructors GpuMapOf(entries?) and GpuSetOf(values?) exist if you want to be explicit.

EventEmitter & Streams

EventEmitter matches the Node.js shape: on / once / off / emit / removeAllListeners / listenerCount. Event dispatch state lives in VRAM.

Streams follow the Node.js model — Readable, Writable, Transform, and pipeline(). Each pipeline stage maps to a VRAM ring buffer; data never leaves GPU memory between stages.

APIReturnsNotes
Readable.from(path, opts?)ReadableWraps a file in a VRAM-backed readable stream. opts.chunkSize controls chunking.
Writable.toFile(path)WritableWritable stream that flushes to a file.
pipeline(source, ...stages)Promise<void>Connects source → transforms → destination; resolves when all data is flushed.
highWaterMarkConstructor option on all streams: VRAM ring-buffer capacity in chunks. Default 8.

GpuWorker, MessageChannel, Atomics

GpuWorker maps to the Node.js worker_threads API. Each worker gets its own CUDA stream and an isolated VRAM slab.

MemberReturnsWhat it does
new GpuWorker(path, opts?)GpuWorkeropts.heapBytes (default 4 MB private VRAM), opts.shareGpuMemory, opts.name.
postMessage(data, transfer?)voidSends structured data. Transferred GpuBuffers move zero-copy — ownership transfers to the worker.
nextMessage<T>()Promise<T>Resolves with the next message from the worker.
terminate()voidStops the worker immediately.
sharedBuffer(byteLength)SharedGpuBufferVRAM region visible to both parent and worker streams.
Atomics.add / sub / and / or / xor / load / store / exchange / compareExchangenumberCompile to CUDA atomic intrinsics (atomicAdd, atomicCAS, …) on shared VRAM. No CPU involved.

URL, URLSearchParams, TextEncoder/Decoder, Timers, AbortController

@symmetra/kv VRAM key-value store

A key-value cache that lives in GPU memory. No Redis process, no DRAM round-trip, no serialization between your handler and the store.

import { KvStore } from '@symmetra/kv'

// Instantiate at module scope — maps to a VRAM allocation
const cache = new KvStore({ maxMb: 256, namespace: 'app' })
MethodReturnsWhat it does
get<T>(key)Promise<T | null>Reads a value. null when missing or expired.
set<T>(key, value, opts?)Promise<void>Writes a value. opts.ttlMs sets expiry in milliseconds.
del(key)Promise<void>Deletes a key.
has(key)Promise<boolean>Existence check.
stats()Promise<{hits, misses, evictions, sizeBytes}>Cache statistics.

Constructor options: maxMb (VRAM budget, default 256) and namespace (key prefix, default empty). The per-request ctx.kv exposes the same API plus keys(pattern?).

Measured behavior (beta, 128 of 6,144 CUDA cores): on our RTX 5070 test rig, a handler doing one KV set + one KV get per request sustained ~3.5K req/s at 6.4ms median — cooperative GPU↔CPU I/O has real cost. Cache-friendly patterns (e.g. memoized Fibonacci) measured ~5.9K req/s at 553µs median.

@symmetra/db Database clients

Typed clients for PostgreSQL, SQLite, and Redis. Database I/O is handled by the CPU side of the runtime (the GPU requests it cooperatively), so treat these as standard async clients.

import { postgres, sqlite, redis } from '@symmetra/db'

postgres(config)PgClient

MethodReturnsNotes
query<T>(sql, params?)Promise<PgResult<T>>PgResult = { rows: T[], rowCount, fields }
queryOne<T>(sql, params?)Promise<T | null>First row or null.
prepare<T>(name, sql)Promise<PreparedStatement<T>>Statement has execute(), executeOne(), close().
transaction<T>(fn)Promise<T>Runs fn inside BEGIN/COMMIT; the passed client adds rollback().
close()Promise<void>Closes the pool.

Config: host, port, database, user, password, ssl?, maxConnections?, idleTimeoutMs?.

sqlite(options)SqliteClient — options: path, readOnly?, walMode?. Same query/queryOne/execute shape (SqliteResult adds lastInsertRowid and changes), plus one GPU-specific method:

tableToGpu<T>(sql, params?)Promise<GpuBuffer<T>>Runs a query and uploads the numeric result column(s) straight into VRAM — query once, compute many times on GPU.

redis(config?)RedisClient — standard command set: get, set (with ex/px/nx/xx options), del, exists, expire, ttl, incr, incrBy, hashes (hset/hget/hgetall), sets (sadd/smembers/sismember), lists (lpush/rpush/lrange), and pipeline() for batched commands ending in exec()Promise<(string|number|null)[]>.

@symmetra/fs Filesystem

import { fs, jsonFs } from '@symmetra/fs'
MethodReturnsWhat it does
fs.read(path, { encoding: 'utf8' })Promise<string>Reads a text file.
fs.read(path)Promise<GpuBuffer<Uint8Array>>Binary read — lands directly in VRAM. offset/length options for partial reads.
fs.write(path, data, opts?)Promise<void>Accepts string | Uint8Array | GpuBuffer. opts.flag: 'w' | 'wx' | 'a' | 'ax'.
fs.append(path, data)Promise<void>Appends.
fs.stat(path)Promise<FileStat>{ size, isFile, isDirectory, isSymlink, modifiedAt, createdAt }
fs.exists(path)Promise<boolean>
fs.delete / fs.rename / fs.copyPromise<void>
fs.mkdir(path, opts?) / fs.rmdir(path, opts?)Promise<void>opts.recursive supported on both.
fs.readdir(path)Promise<{name, type}[]>type is 'file' | 'dir' | 'symlink'
fs.watch(path, opts?)AsyncIterable<WatchEvent>for await-able change events: { type: 'create'|'modify'|'delete'|'rename', path }. opts.signal stops it.
jsonFs.read<T>(path)Promise<T>Read + parse JSON in one call.
jsonFs.write(path, value, opts?)Promise<void>Stringify + write. opts.pretty formats output.

@symmetra/crypto Cryptography

import { hash, cipher, kdf, random, jwt, password } from '@symmetra/crypto'
APIReturnsWhat it does
hash.hash(alg, data)Promise<string>Hex digest. alg: 'sha256' | 'sha512' | 'blake3'. Accepts strings, bytes, or GpuBuffers.
hash.hmac(alg, key, data)Promise<string>Keyed HMAC digest.
hash.batchHash(alg, items)Promise<GpuBuffer<Uint8Array>>Hashes many VRAM buffers in one parallel dispatch.
hash.compare(a, b)booleanConstant-time comparison — use for digests/tokens, never ===.
cipher.encrypt(alg, key, plaintext)Promise<{ciphertext, iv, tag}>AEAD encryption. alg: 'aes-256-gcm' | 'chacha20-poly1305'.
cipher.decrypt(alg, key, ciphertext, iv, tag)Promise<Uint8Array>Throws if the auth tag doesn't verify.
cipher.encryptString / decryptStringPromise<string>Same, but packs iv+tag+ciphertext into one encoded string for easy storage.
kdf.pbkdf2(password, salt, opts?)Promise<string>opts: iterations, keyLength, algorithm.
kdf.argon2id(password, salt?, opts?)Promise<string>opts: memoryCost, timeCost, parallelism, keyLength.
kdf.hkdf(inputKey, salt, opts?)Promise<Uint8Array>Key derivation for protocols.
random.bytes(n) / hex(n?) / uuid() / int(min?, max?)variesCryptographically secure randomness.
jwt.sign(payload, secret, opts?)Promise<string>opts: algorithm (HS256/HS512/RS256/ES256), expiresIn, issuer, audience.
jwt.verify<T>(token, secret)Promise<T>Throws on invalid signature or expiry.
jwt.decode<T>(token)T | nullDecodes without verifying — never trust this alone.
password.hash(pw) / password.verify(pw, hash)Promise<string> / Promise<boolean>Opinionated password hashing — use these instead of raw KDFs for login flows.

@symmetra/env Configuration

import { env, config } from '@symmetra/env'

// Schema-validated, fully typed environment loading
const settings = env.load({
  PORT:         { type: 'port',    default: 8080 },
  DATABASE_URL: { type: 'url',     required: true },
  DEBUG:        { type: 'boolean', default: false },
})
// settings.PORT is number, settings.DATABASE_URL is string, settings.DEBUG is boolean
APIReturnsWhat it does
env.load(schema, opts?)typed objectValidates env vars against a schema. Field types: string, number, boolean, url, email, port. Per-field: required, default, min/max, pattern, choices. Throws with a clear message when validation fails.
env.get(key, default?)string | undefinedRaw read with optional fallback.
env.getNumber / env.getBooleannumber/boolean | undefinedCoerced reads.
env.require(key)stringThrows if the variable is missing.
env.all()Record<string,string>Everything.
config.loadJson<T>(path) / loadToml<T>(path)Promise<T>Typed config file loading.
config.watch<T>(path, cb)() => voidCalls cb with re-parsed config on file change. Returns an unsubscribe function.

@symmetra/net Networking

import { http, connect, createUdp, websocket, dns } from '@symmetra/net'

http — outbound HTTP client. All methods return Promise<HttpResponse> where the response has status, ok, headers, and body accessors text(), json<T>(), bytes():

http.get(url, opts?)Promise<HttpResponse>opts: headers, timeout, followRedirects, maxRedirects, body. Outbound requests are dispatched to a dedicated CPU fetch pool so GPU I/O threads stay free.
http.post / put / patch(url, body?, opts?)Promise<HttpResponse>
http.delete(url, opts?) / http.fetch(url, opts?)Promise<HttpResponse>

Measured behavior (beta): a handler that performs an outbound fetch back into itself (full GPU → CPU → GPU round trip) measured ~166 req/s at 30ms median on our test rig. Outbound I/O is the most expensive thing a handler can do — cache aggressively.

connect(options)Promise<TcpSocket> — raw TCP with optional TLS. Socket: write(), read(length?), readLine(), readAll(), close(), plus connected, remoteAddress, remotePort.

createUdp(options?)Promise<UdpSocket>send(data, host, port), receive(){ data, remoteAddress, remotePort }, close(). Supports broadcast and multicast groups.

websocket(url, options?)Promise<WebSocket>send(), receive(){ type: 'text'|'binary'|'close'|'ping', data }, close(code?, reason?), and a readyState property.

dnsresolve(hostname, type?), lookup(hostname), reverse(ip), records(hostname, type) for A/AAAA/CNAME/MX/TXT/NS records.

Found a gap or a bug? The fastest way to get it fixed during beta is a support ticket with a minimal server.ts that reproduces it.