New:Socket for Asana Is Now Available.Learn more
Get Started

@dynoxide/wasm-engine

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@dynoxide/wasm-engine

The Dynoxide DynamoDB emulator compiled to WebAssembly, with a Web Worker client for running DynamoDB operations in the browser.

latest
Source
npmnpm
Version
1.1.0
Version published
Maintainers
1
Created
Source

@dynoxide/wasm-engine

The dynoxide DynamoDB-compatible engine, compiled to WebAssembly and packaged to run in the browser. It carries the engine .wasm, the official @sqlite.org/sqlite-wasm SQLite build, the bundled Web Worker, and an EngineClient that drives them, so you can run real DynamoDB operations client-side against a SQLite-backed store persisted to OPFS.

The wasm build is a scored target in the same conformance suite that backs dynoxide's native build; current results are published with every other target. It leaves several operations unimplemented - TransactWriteItems, streams, tags and TTL - so it is not a like-for-like replacement for the native engine.

Install

npm install @dynoxide/wasm-engine

The package is versioned in lockstep with every other dynoxide artefact; see docs/versioning.md for what that number promises and what the conformance suite does and does not exercise. npm install @dynoxide/wasm-engine gets the current release; use ~1.1.0 to hold behaviour still across minors.

Quick start

import { EngineClient } from "@dynoxide/wasm-engine";

const client = new EngineClient();
await client.ready();

await client.execute("CreateTable", {
  TableName: "Music",
  KeySchema: [
    { AttributeName: "artist", KeyType: "HASH" },
    { AttributeName: "song", KeyType: "RANGE" },
  ],
  AttributeDefinitions: [
    { AttributeName: "artist", AttributeType: "S" },
    { AttributeName: "song", AttributeType: "S" },
  ],
  BillingMode: "PAY_PER_REQUEST",
});

await client.execute("PutItem", {
  TableName: "Music",
  Item: { artist: { S: "Pixies" }, song: { S: "Debaser" } },
});

const { Items } = await client.execute("Query", {
  TableName: "Music",
  KeyConditionExpression: "artist = :a",
  ExpressionAttributeValues: { ":a": { S: "Pixies" } },
});

execute takes the operation name and a plain DynamoDB-JSON request, resolves with the response, and rejects with a typed EngineError. The client runs the engine in a Web Worker (OPFS's synchronous file handles are Worker-only) and owns the message round-trip, so you deal in objects rather than postMessage envelopes.

API

  • new EngineClient(opts?) - boots the engine eagerly. Calls queue behind boot, so you can issue work before ready() resolves.
  • await client.ready() - resolves with the boot descriptor ({ contractVersion, capabilities, persistenceMode }).
  • client.execute(op, request) - run one operation.
  • client.supports(op) - whether the engine implements an operation, for capability-gating your UI.
  • client.persistent - true when the session persists across reloads (OPFS), false in the in-memory fallback.
  • client.terminate() - tear the Worker down and reject any in-flight calls.

The package also exports EngineError (the engine's __type is on .type) and CONTRACT_VERSION. TypeScript declarations ship with it, so the client and its boot descriptor are typed out of the box.

Where the assets live

The Worker and the two .wasm travel inside the package. new EngineClient() with no arguments resolves the Worker next to this module, and the Worker resolves its .wasm next to itself, so a bundler that copies the package's files - or a plain static deploy of them - needs no configuration.

Serving the assets from a CDN or a different origin? Two options:

  • assetBase - the directory the assets sit in, e.g. new EngineClient({ assetBase: "https://cdn.example.com/dynoxide/" }).
  • workerUrl - the exact Worker URL, if it doesn't sit beside its .wasm under a shared base.

If you'd rather construct the Worker yourself - to let a bundler handle it, say - the package exposes it at the ./worker subpath. Build it and hand it back through createWorker:

new EngineClient({
  createWorker: () =>
    new Worker(new URL("@dynoxide/wasm-engine/worker", import.meta.url), { type: "module" }),
});

Two clients on one page are fine: each gets its own storage pool, keyed on name (default dynoxide.db), so give them distinct names if both should persist.

Hosting

The engine needs a secure context (HTTPS, or localhost for development) for OPFS, but no COOP/COEP cross-origin isolation. A Content-Security-Policy must allow 'wasm-unsafe-eval', or the engine won't instantiate. Serve the .wasm as application/wasm, and serve the assets gzip- or brotli-encoded - the wasm and the Worker both more than halve over the wire.

Versioning

CONTRACT_VERSION stamps the message-envelope shape, not the engine version. Adding an operation leaves it alone; changing a request, response, or error envelope bumps it. The client validates it against the engine on boot and fails loudly on a mismatch, so a pinned consumer fails with a clear error rather than mis-reading a newer engine. The shipped engine and contract versions sit in manifest.json. manifest.engineVersion is the dynoxide crate version, and the npm package ships at that same version: every dynoxide artefact shares one number. See docs/versioning.md.

Persistence

State persists across reloads via OPFS. Where OPFS synchronous access handles are unavailable (Firefox private windows, older Safari), the client falls back to an in-memory session and reports it through persistent / persistenceMode rather than failing.

Licence

MIT OR Apache-2.0. See LICENSE-MIT and LICENSE-APACHE.

Keywords

dynamodb

FAQs

Package last updated on 03 Sep 2026

Related posts