TypeScript Runtime API Reference
The TypeScript runtime provides the execution host, memory allocators, and WebAssembly loader for generated modules.
Generated Module Exports
Each module generated by emitTsGlueFiles exports:
initNimTs(options?: NimTsOptions): Promise<Exports>
Initializes the WebAssembly module. Subsequent calls return the cached exports object.
import { initNimTs } from './synth.js';
const exports = await initNimTs({
wasmPath: '/wasm/synth.wasm'
});getNimTs(): Exports
Synchronous getter returning the module's exported functions. Throws an error if initNimTs() has not been called and awaited.
getNimTsModule(): any
Returns the raw WebAssembly instance exports (WebAssembly.Instance.exports).
isInitialized(): boolean
Returns true if the WebAssembly module has finished loading and is ready for invocation.
NimTsOptions
export interface NimTsOptions {
/** URL or file path to the .wasm binary */
wasmPath?: string | URL;
/** Pre-compiled WebAssembly.Module (ideal for AudioWorklet & Web Workers) */
wasmModule?: WebAssembly.Module;
/** Raw WebAssembly binary buffer (Uint8Array or ArrayBuffer) */
wasmBytes?: BufferSource;
/** Pre-existing WebAssembly.Instance */
wasmInstance?: WebAssembly.Instance;
/** Custom WebAssembly imports to merge into the import object */
imports?: WebAssembly.Imports;
}NimTsRuntime Class (@axiomantic/nimts/runtime)
The low-level runtime class used internally by generated wrappers:
import { NimTsRuntime } from '@axiomantic/nimts/runtime';
const runtime = new NimTsRuntime();
await runtime.init(wasmSource);Methods
init(source?: string | Uint8Array | WebAssembly.Module): Promise<NimTsExports>: Compiles and instantiates the WebAssembly module.getMemory(): WebAssembly.Memory: Accesses the underlyingWebAssembly.Memoryinstance. Throws if uninitialized.passString(str: string): { ptr: number; len: number }: Encodes a string into UTF-8, allocates memory in WASM, and writes the bytes.readString(ptr: number, len: number): string: Decodes a UTF-8 string from WebAssembly linear memory.passBytes(buf: Uint8Array | ArrayBuffer): { ptr: number; len: number }: Allocates memory in WASM and copies a byte buffer.readBytes(ptr: number, len: number): Uint8Array: Creates a copy of a byte slice from WebAssembly linear memory.free(ptr: number): void: Frees allocated memory in WASM.createImportObject(): WebAssembly.Imports: Creates the standard WebAssembly imports object providing promise callbacks and the WASI preview1 proxy.
Projections & Streaming Classes
NimTsIterator<T>
Wraps an active Nim closure iterator in WebAssembly linear memory and implements the ES2015 IterableIterator<T> protocol.
const iter = exports.countUp(1, 10);
// Use in standard for..of loops
for (const n of iter) {
console.log(n);
if (n === 5) break; // Automatically triggers .return() and reclaims WASM memory
}
// Or spread into an array
const arr = [...exports.countUp(1, 5)];next(): IteratorResult<T>: Retrieves the next element from the iterator.return(): IteratorResult<T>: Deterministically disposes the iterator slot in WASM and frees heap handles upon early loop termination.[Symbol.iterator](): Enables native JavaScript iteration.
NimTsChannel<T>
Wraps an asynchronous SPSC wait-free bounded channel and implements the ES2018 AsyncIterable<T> protocol.
const channel = exports.createEventStream();
// Consume asynchronously
for await (const event of channel) {
processEvent(event);
}send(item: T): boolean: Sends an item into the channel buffer.recv(): Promise<T | null>: Awaits the next item from the channel.close(): void: Closes the channel.[Symbol.asyncIterator](): Enables native JavaScriptfor await..ofiteration.
Web Worker Client Runtime (@axiomantic/nimts/worker)
The worker runtime hosts WebAssembly modules in background threads (browser Web Workers or node:worker_threads) and proxies function invocations asynchronously.
import { spawnWorker, extractTransfers, type WorkerClient } from '@axiomantic/nimts/worker';spawnWorker<T>(moduleOrUrl: any, options?: SpawnWorkerOptions): Promise<WorkerClient<T>>
Spawns an isolated WebWorker or worker_threads worker, initializes the compiled NimTS module, and returns a typed proxy client.
const worker = await spawnWorker<MyExports>('./engine.js', {
wasmPath: '/wasm/engine.wasm',
transferBuffers: true
});SpawnWorkerOptions
export interface SpawnWorkerOptions {
/** Path or URL to the .wasm binary */
wasmPath?: string | URL;
/** Pre-compiled WebAssembly.Module */
wasmModule?: WebAssembly.Module;
/** WebAssembly binary bytes */
wasmBytes?: BufferSource;
/** Options forwarded to module initNimTs(opts) */
initOptions?: Record<string, any>;
/** Underlying Worker constructor options */
workerOptions?: any;
/** Automatically detach and transfer ArrayBuffer / TypedArray instances (default: true) */
transferBuffers?: boolean;
}WorkerClient<T> Interface
A transparent dynamic proxy wrapping all exported functions on T:
- Transparent Promise Wrapping: Every exported synchronous proc
(...args) => Rbecomes an asynchronous method(...args) => Promise<R>. - Automatic
Future[T]Awaiting: Procs returning NimFuture[T]are awaited off-thread inside the worker, settling the caller's Promise with the unwrapped value or rejecting on exception. - Dual Promise &
AsyncIterableStreaming: Procs returningChannel[T]orNimTsChannel[T]stream items across a dedicatedMessagePort. The returned call object can be consumed viafor await (const chunk of worker.stream())or directly awaited as an aggregated array withawait worker.stream(). terminate(): Promise<void>: Cleanly terminates the worker thread, closes communication ports, and rejects any pending RPC calls with'Worker has been terminated'.readonly isTerminated: boolean: Flag indicating whether the worker has been terminated.readonly rawWorker: Worker: Direct access to the underlying platformWorkerinstance.
Zero-Copy Buffer Transfers
By default (transferBuffers: true), any argument or return value containing an ArrayBuffer or TypedArray backing buffer is automatically collected via extractTransfers and included in the postMessage transfer list.
IMPORTANT
When a buffer is transferred, its memory ownership moves to the recipient thread and the sender's buffer is detached (byteLength becomes 0). This eliminates memory copying overhead and provides maximum throughput for large audio DSP blocks and binary streams. If you need to keep the sender's buffer intact, pass { transferBuffers: false } or .slice() the buffer before passing.
extractTransfers(val: unknown, set?: Set<ArrayBuffer>): ArrayBuffer[]
Recursively inspects an object, array, or primitive and extracts all unique ArrayBuffer and TypedArray.buffer references suitable for the postMessage transfer list.
Vite ?worker Query Integration
When using @axiomantic/nimts/vite, importing any .nim file with ?worker emits an instantiable Worker class:
import EngineWorker from './engine.nim?worker';
// Instantiates and spawns the worker client:
const worker = await new EngineWorker();
// Or using static helper:
// const worker = await EngineWorker.spawn();
const result = await worker.addNumbers(10, 20); // 30
await worker.terminate();