@perfscale/library-sdk
v0.1.2
Published
TypeScript/JavaScript SDK for authoring perfscale WASM value-generator libraries (RFC 005)
Readme
@perfscale/library-sdk
TypeScript/JavaScript SDK for authoring perfscale libraries — WASM
components that provide value-generating functions to ${alias.fn(...)}
tokens in perfscale test payloads
(RFC 005):
libraries:
- use: ./hello.wasm
capabilities: [fs]
steps:
- use: std/file-write@v1
with:
path: out.txt
content: "greeting: ${hello.greet(world)}" # → "greeting: hello, world!"The engine runs each library in a wasmtime sandbox under a fail-closed
capability model; the ABI contract (perfscale:[email protected]) is
wit/library.wit, mirrored from the main repo's single
source of truth.
Quickstart
$ npm install @perfscale/library-sdkWrite a library (mylib.ts):
import { args, defineLibrary } from "@perfscale/library-sdk";
export default defineLibrary({
name: "mylib",
functions: {
token: {
description: "Deterministic per-instance token; memo key reuses it within one message",
call(argv, ctx) {
const mint = () => `tok-${ctx.rng().nextU64().toString(16)}`;
const key = args.optionalString(argv, 0);
return key === undefined ? mint() : ctx.memo(key, mint);
},
},
},
});Build it to a WASM component with the bundled CLI (ComponentizeJS embeds a JS engine — that is how TS becomes a component):
$ npx perfscale-library-build mylib.ts -o mylib.wasmReference the component from your perfscale YAML (path relative to the
declaring file) and call it from ${...} tokens in payloads.
What the SDK gives you
defineLibrary— declares the library name and its functions; the default export is what the build wires to theperfscale:libraryABI.Ctx— per-call context (messageSeq,iterationSeq,vuId,seed,timeMsasbigint),ctx.memo(key, fn)(keyed reuse within one message), andctx.rng()— a seeded xorshift64 PRNG bit-identical to the Rust SDK and the engine's built-in generator, soseed:runs reproduce.Args helpers (
args.string/int/float/optionalString) with author-friendly errors.testCall— a runtime-free harness fornode:testunit tests; no WASM needed:import assert from "node:assert/strict"; import { Ctx, testCall } from "@perfscale/library-sdk"; import lib from "./mylib.ts"; const ctx = new Ctx(42); assert.equal(testCall(lib, ctx, "token", []), testCall(lib, ctx, "token", []));
A complete runnable example lives in
examples/hello (library, perfscale YAML, expected output).
Sandboxing notes for TS authors
- jco (StarlingMonkey) components always import
wasi:filesystem/*andwasi:clocks/wall-clock; declarecapabilities: [fs]on thelibraries:entry (onefsgrant satisfies both — a read-only preopen of the run'sfs_root) and setallow_library_capabilities: truein the config. The build already disableswasi:random,wasi:httpand timers, which the engine never grants — draw all randomness fromctx.rng()and all time fromctx.timeMs. - The WIT contract is vendored at
wit/library.wit;scripts/sync-wit.shre-fetches it pinned to a perfscale release tag (bumpPERFSCALE_TAGdeliberately).
Requirements
Node.js ≥ 24 (the test harness relies on native type stripping). The build
CLI wraps @bytecodealliance/jco
and needs no other toolchain.
License
Dual-licensed under MIT or Apache-2.0, same as the main perfscale repo.
