Skip to content
This repository was archived by the owner on Jul 17, 2026. It is now read-only.

Compatibility

Eugene Lazutkin edited this page Apr 20, 2026 · 2 revisions

Compatibility

Target runtimes

The adapter uses only standard Fetch APIs: Request, Response, URL, URLSearchParams, TextDecoder, ReadableStream. Every runtime that ships those primitives is supported. No framework peer dep.

Runtime Status Notes
Node 20+ Fetch globals shipped via @types/node ≥ 20; engines.node: >=20.
Bun Native Fetch; npm run test:bun runs the full suite.
Deno Native Fetch; npm run test:deno runs the full suite.
Cloudflare Workers Full Fetch API in Workers runtime.
Deno Deploy Same as Deno; use Deno.serve(handler).
Hono Pass c.req.raw to the adapter. See Composition.
itty-router Pass the raw Request. See Composition.
AWS Lambda ⚠️ Function URLs expose Fetch; older API Gateway events do not. Use the dedicated dynamodb-toolkit-lambda when shipping to API Gateway.

No framework peer dependency

Unlike dynamodb-toolkit-koa and dynamodb-toolkit-express, this package has no framework peer. Request / Response / URL are ambient globals on every supported runtime; there's nothing to install beyond the toolkit itself.

peerDependencies:

{
  "peerDependencies": {
    "dynamodb-toolkit": "^3.1.1"
  }
}

If you run the adapter inside a router (Hono, itty-router, wrangler, etc.), you install that router separately — it's your choice, not a peer requirement.

Cross-runtime test matrix

The adapter's unit test suite runs identically under:

Runtime Command Tests / Asserts Notes
Node npm test 56 / 117 Includes a .cjs smoke (Node-only)
Bun npm run test:bun 51 / 112 Same suite minus the .cjs smoke
Deno npm run test:deno 51 / 112 Same

The 5-test delta is the .cjs smoke scoped to Node via tape6's node config key — CommonJS-from-ESM-sibling semantics differ between Bun and Deno, so it doesn't run there.

TypeScript smoke (npm run ts-test / ts-test:bun / ts-test:deno): 6 tests / 6 asserts on all three.

Node version floor

engines.node is >=20. Two sub-floors worth knowing:

  • require(esm) interop for CJS consumers — 20.19+ on the 20.x line, 22.12+ on 22.x, unflagged everywhere newer. The .cjs smoke test exercises this.
  • Native TypeScript — Node 22.6+ (with --experimental-strip-types) or 23.6+ (unflagged). Used by npm run ts-test. Bun and Deno run .ts natively without special setup, via npm run ts-test:bun and npm run ts-test:deno.

Both smoke-tests are included so you can verify your target runtime handles the adapter correctly.

CommonJS consumers

require('dynamodb-toolkit-fetch') works on Nodes that ship require(esm) (20.19+ / 22.12+ / anything newer). The .cjs smoke test demonstrates:

const {createFetchAdapter} = require('dynamodb-toolkit-fetch');
const {readJsonBody} = require('dynamodb-toolkit-fetch/read-web-body.js');

TypeScript consumers

Hand-written .d.ts sidecars ship next to each .js file. package.json declares main, module, and types for all resolution styles:

{
  "main": "./src/index.js",
  "module": "./src/index.js",
  "types": "./src/index.d.ts",
  "exports": {
    ".": "./src/index.js",
    "./*": "./src/*"
  }
}

The factory is generic in TItem so typed Adapter<Item, Key> instances flow through without casts:

import {Adapter} from 'dynamodb-toolkit';
import {createFetchAdapter, type FetchAdapterOptions} from 'dynamodb-toolkit-fetch';

interface Planet extends Record<string, unknown> {
  name: string;
  climate?: string;
}
type PlanetKey = Pick<Planet, 'name'>;

const adapter = new Adapter<Planet, PlanetKey>({client, table: 'planets', keyFields: ['name']});

const opts: FetchAdapterOptions<Planet> = {
  mountPath: '/planets',
  keyFromPath: (raw, a) => ({[a.keyFields[0]]: raw}),
  policy: {defaultLimit: 25, maxLimit: 200}
};
const handler = createFetchAdapter(adapter, opts);

See tests/test-typed.ts in the source tree for a runnable typed example.

Conditional return type with onMiss

The factory is overloaded so the handler's return type reflects whether onMiss is supplied:

// No onMiss → Promise<Response>
const terminal = createFetchAdapter(adapter);
const res: Response = await terminal(request);

// With onMiss → Promise<Response | null>
const composable = createFetchAdapter(adapter, {onMiss: () => null});
const res2: Response | null = await composable(request);

The narrower type lets Workers / Bun.serve / Deno.serve consumers use the terminal shape without null-guarding, while router integrations get the accurate | null return.

Package shape

  • ESM-only. The source is .js + hand-written .d.ts, no build step.
  • Zero runtime dependencies. dynamodb-toolkit is a peer dep; no framework peer.
  • No node:* imports at runtime. Type-only imports are absent because there's nothing Node-specific in the source; it runs verbatim on Workers / Deno.

Tested against

The adapter's own test matrix exercises the full route pack:

  • 51 tests, 112 assertions under Bun / Deno (via direct handler invocation with new Request(...)).
  • 56 tests, 117 assertions under Node (adds the .cjs require-interop smoke).
  • 6 TypeScript smoke tests via ts-test — runs on Node (native .ts support on 22.6+), Bun, and Deno.

No wrangler dev / Deno Deploy integration test is wired into CI yet — those runtimes are validated locally via the same test suite through their native Fetch implementations.

Clone this wiki locally