{"_id":"@apsis-io/periapsis-sdk","_rev":"4-97be6a2f26152570a405034ffbc7093e","name":"@apsis-io/periapsis-sdk","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@apsis-io/periapsis-sdk","version":"0.1.0","license":"Apache-2.0","_id":"@apsis-io/periapsis-sdk@0.1.0","maintainers":[{"name":"malformed","email":"enderman08@gmail.com"}],"homepage":"https://github.com/apsis-io/sdk#readme","bugs":{"url":"https://github.com/apsis-io/sdk/issues"},"dist":{"shasum":"ab2d6376de1c3d90e4f08fa107f49a927dfa207f","tarball":"https://registry.npmjs.org/@apsis-io/periapsis-sdk/-/periapsis-sdk-0.1.0.tgz","fileCount":33,"integrity":"sha512-2S4n+MStM3LLjpHgBUFaAVTMQUup9/SwnbIY1ZipHXYs0oR6l7a+a4QruM9DTu8OJjhHzeNXdGgQDiidhYOujQ==","signatures":[{"sig":"MEUCIAYRaTNxcnf3G7wO4137cP6FZZ6wDlHwZcm9V3wRKebQAiEApp5YsyPGmbWDq0rHkmjCfMON9o3tAQPDYmbgkgS60Cs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":297329},"type":"module","exports":{".":"./index.ts","./*":"./*.ts","./*.js":"./*.ts"},"gitHead":"baa7abe54d0e5e7ea38dc6b99ee3d726a32022f4","scripts":{"test":"bun test"},"_npmUser":{"name":"malformed","email":"enderman08@gmail.com"},"repository":{"url":"git+https://github.com/apsis-io/sdk.git","type":"git","directory":"ts/periapsis"},"_npmVersion":"12.0.2","description":"TypeScript SDK for Periapsis's periapsis:* WASI component-model interfaces (identity, config, log, metrics, status, checkpoint, exec, magic-seam RPC) - for WASM components built with dwarf (WASI 0.3/Preview 3, QuickJS) and run under the trail runtime.","directories":{},"_nodeVersion":"22.22.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/periapsis-sdk_0.1.0_1788372568388_0.8673223834979498","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@apsis-io/periapsis-sdk","version":"0.1.1","keywords":["periapsis","wasi","component-model","wasm","dwarf","preview3"],"license":"Apache-2.0","_id":"@apsis-io/periapsis-sdk@0.1.1","maintainers":[{"name":"malformed","email":"enderman08@gmail.com"}],"homepage":"https://github.com/apsis-io/sdk#readme","bugs":{"url":"https://github.com/apsis-io/sdk/issues"},"dist":{"shasum":"9d01fd11bf9026b362f258876d685c4214e91ff6","tarball":"https://registry.npmjs.org/@apsis-io/periapsis-sdk/-/periapsis-sdk-0.1.1.tgz","fileCount":33,"integrity":"sha512-1rKjUZIuuIr9qBwMMgipTX+k2L+6XZYqp5HZR6YggXt4OROG/B4g7me4fsHA0teIC+UBPX9imKc0hUGwdF9s/A==","signatures":[{"sig":"MEQCIGAJT1Ptsc2qG+DsOSyi7CxdutAxJ+s+N17L2axqjH3BAiAUliRAsnHPrmTaXexnW4e2eo9eKbcb8orWazuVQFn61Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIGRPFYkaqThDt6+coFH8kpvE3Yy21H+ov/+wNHGCGwgKAiAn85yq2loEpg8+ieN+b4dZID7yyDBcuyI2aOO3w1VnMQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":296628},"type":"module","exports":{".":"./index.ts","./*":"./*.ts","./*.js":"./*.ts"},"gitHead":"fe21854bddf72d9e8b580a0795c5b1a0fa056e2c","scripts":{"test":"bun test"},"_npmUser":{"name":"malformed","email":"enderman08@gmail.com"},"repository":{"url":"git+https://github.com/apsis-io/sdk.git","type":"git","directory":"ts/periapsis"},"_npmVersion":"12.0.2","description":"TypeScript SDK for Periapsis's periapsis:* WASI component-model interfaces (identity, config, log, metrics, status, checkpoint, exec, magic-seam RPC) - for WASM components built with dwarf (WASI 0.3/Preview 3, QuickJS) and run under the trail runtime.","directories":{},"_nodeVersion":"22.22.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/periapsis-sdk_0.1.1_1788378169581_0.7809259535350335","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@apsis-io/periapsis-sdk","version":"0.1.2","keywords":["periapsis","wasi","component-model","wasm","dwarf","preview3"],"license":"Apache-2.0","_id":"@apsis-io/periapsis-sdk@0.1.2","maintainers":[{"name":"malformed","email":"enderman08@gmail.com"}],"homepage":"https://github.com/apsis-io/sdk#readme","bugs":{"url":"https://github.com/apsis-io/sdk/issues"},"dist":{"shasum":"587f7cb782583004844be82e4c8b70e230e755b9","tarball":"https://registry.npmjs.org/@apsis-io/periapsis-sdk/-/periapsis-sdk-0.1.2.tgz","fileCount":34,"integrity":"sha512-cQsNFck6eQoaMzCvPweWvGLT44vdV/kVyocmkMTE1Nm2LcewPG5YjdeaOK478FINOoHf8IEtDkJsjgH5NNHNXg==","signatures":[{"sig":"MEYCIQCsIhKLA38kj3rqfrfz4aB77VS3h2wyPbZRLEsxZsWg1wIhAKk+2Pv7qkQwll8DBVRrycJK1lFUb7A/qrXq+1mfjOAQ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDobQ1V9fYGJUJkxYVWcc/oY3jmyREl4hadmDXL1zTVMgIhAOjaGAlC4T6b8dtmgApCryQL9VDx8/55JGoGCW1KujNa","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@apsis-io%2fperiapsis-sdk@0.1.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":308328},"type":"module","exports":{".":"./index.ts","./*":"./*.ts","./*.js":"./*.ts"},"gitHead":"435e66b947710cad0c0f659d72e609cd824e4cab","scripts":{"test":"bun test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:364a8105-2a92-42b7-b509-ba1b7e7be781"}},"repository":{"url":"git+https://github.com/apsis-io/sdk.git","type":"git","directory":"ts/periapsis"},"_npmVersion":"12.0.2","description":"TypeScript SDK for Periapsis's periapsis:* WASI component-model interfaces (identity, config, log, metrics, status, checkpoint, exec, magic-seam RPC) - for WASM components built with dwarf (WASI 0.3/Preview 3, QuickJS) and run under the trail runtime.","directories":{},"_nodeVersion":"22.23.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest","typescript":"7.0.1-rc","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/periapsis-sdk_0.1.2_1788449846982_0.4927692146618199","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"_id":"@apsis-io/periapsis-sdk@0.2.0","bugs":{"url":"https://github.com/apsis-io/sdk/issues"},"dist":{"shasum":"074fab472c7697457a7f3df3163898efb7c1b4f2","tarball":"https://registry.npmjs.org/@apsis-io/periapsis-sdk/-/periapsis-sdk-0.2.0.tgz","fileCount":34,"integrity":"sha512-/TKACzL38WoX6BKlzWq8sswfbNcwbq6KY8kdHOXwifrrvtGoSTDlge5b7gdlinYj9hVUzKpKl2zeHafxDHG1Kg==","signatures":[{"sig":"MEYCIQDMBAadA2Cf6J9yfhQ/YYch8G8+e0T0SHMHszI/37g6OwIhAI3N9/QD80tOQ7hX+Xy2JqGO0vrQJztNomWUJ/LQsQ6D","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIBRRf/Fap1ptU3yMFLrhKNrtHxME8H7iEh+5DlnyKuO7AiB8YYSQKis4tVi543StwNaFs3natr6UoZxAOd/Z4d24lA=="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@apsis-io%2fperiapsis-sdk@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":311631},"name":"@apsis-io/periapsis-sdk","type":"module","exports":{".":"./index.ts","./*":"./*.ts","./*.js":"./*.ts"},"gitHead":"fd50c732e0a919f582a4ff61153e97e71305e3fc","license":"Apache-2.0","scripts":{"test":"bun test"},"version":"0.2.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:364a8105-2a92-42b7-b509-ba1b7e7be781"}},"homepage":"https://github.com/apsis-io/sdk#readme","keywords":["periapsis","wasi","component-model","wasm","dwarf","preview3"],"repository":{"url":"git+https://github.com/apsis-io/sdk.git","type":"git","directory":"ts/periapsis"},"_npmVersion":"12.0.2","description":"TypeScript SDK for Periapsis's periapsis:* WASI component-model interfaces (identity, config, log, metrics, status, checkpoint, exec, magic-seam RPC) - for WASM components built with dwarf (WASI 0.3/Preview 3, QuickJS) and run under the trail runtime.","directories":{},"maintainers":[{"name":"malformed","email":"enderman08@gmail.com"}],"_nodeVersion":"22.23.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest","typescript":"7.0.1-rc","@types/node":"^22.0.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/periapsis-sdk_0.2.0_1788450664123_0.5384948928929392"}}},"time":{"created":"2026-09-02T18:09:28.214Z","modified":"2026-09-03T15:51:04.554Z","0.1.0":"2026-09-02T18:09:28.625Z","0.1.1":"2026-09-02T19:42:49.736Z","0.1.2":"2026-09-03T15:37:27.112Z","0.2.0":"2026-09-03T15:51:04.214Z"},"bugs":{"url":"https://github.com/apsis-io/sdk/issues"},"license":"Apache-2.0","homepage":"https://github.com/apsis-io/sdk#readme","keywords":["periapsis","wasi","component-model","wasm","dwarf","preview3"],"repository":{"url":"git+https://github.com/apsis-io/sdk.git","type":"git","directory":"ts/periapsis"},"description":"TypeScript SDK for Periapsis's periapsis:* WASI component-model interfaces (identity, config, log, metrics, status, checkpoint, exec, magic-seam RPC) - for WASM components built with dwarf (WASI 0.3/Preview 3, QuickJS) and run under the trail runtime.","maintainers":[{"name":"malformed","email":"enderman08@gmail.com"}],"readme":"# periapsis\n\nSee also: [CHEATSHEET.md](CHEATSHEET.md) for a dense, single-page quick\nreference (signatures, gotchas, recipes) without the surrounding prose.\n\nErgonomic TypeScript wrappers around Periapsis's `periapsis:*` WIT interfaces,\nfor components built with [dwarf](https://github.com/apsis-io/dwarf)\n(QuickJS, genuine WASI 0.3/Preview 3 async). Consolidates what used to be a\nhand-copied `src/periapsis.ts` per `examples/wasm/*` example into one shared\nmodule, plus two new pieces (`exec`, `magic`) that had no wrapper before.\n\nPublished as `@apsis-io/periapsis-sdk`. It ships no `.wasm`: `fetch()` needs a\nseparate component that the package deliberately does not carry, only the recipe\nto build it (`fetch-provider/build.sh`, which needs a dwarf checkout). Every\nother module works from the package alone. It ships TypeScript SOURCE rather than\nbuilt output - dwarf componentizes each consumer's own Vite bundle, so there is\nnothing to compile here - and its `exports` map resolves `./x.js` to `./x.ts`,\nwhich is why the imports below carry a `.js` suffix that no `.js` file has:\n\n```ts\nimport { identity } from \"@apsis-io/periapsis-sdk/identity.js\";\nimport { config } from \"@apsis-io/periapsis-sdk/config.js\";\nimport { info } from \"@apsis-io/periapsis-sdk/log.js\";\nimport { reportStatus } from \"@apsis-io/periapsis-sdk/status.js\";\nimport { exec } from \"@apsis-io/periapsis-sdk/exec.js\";\nimport { definePlugProvider } from \"@apsis-io/periapsis-sdk/magic.js\";\n```\n\n**Cannot install it from a registry?** Vendor a snapshot instead - which is what\nperiapsis itself does, because npm and bun cannot resolve a git dependency that\nlives in a subdirectory of a private repo:\n\n```sh\n<path-to-this-repo>/sync-consumer.sh ts/periapsis vendor/periapsis-sdk\n```\n\nThen depend on the copy by NAME, so imports do not change:\n\n```json\n\"@apsis-io/periapsis-sdk\": \"file:vendor/periapsis-sdk\"\n```\n\nCopies the whole SDK (every module, `types/`, `fetch-provider/`) into\n`vendor/periapsis-sdk/` in your own tree; re-run it to pick up upstream\nchanges (it's a snapshot copy, not a symlink - `--delete`d and replaced each\nrun, same model as the WIT sync script). Update your imports to point at\nthat directory instead.\n\n**Or install it from npm.** This directory now has a `package.json`\n(`@apsis-io/periapsis-sdk`, Apache-2.0 - deliberately NOT this repo's own\nBusiness Source License 1.1, the same reasoning `shardkit` was carved out\nunder GPL-3.0-or-later: a thin client SDK should be unencumbered even though\n`periapsis` core (the \"Licensed Work\") isn't - see CLAUDE.md). Ships raw\n`.ts` source, no build step (matches how every in-repo example already\nconsumes it - Vite/esbuild transpile on the fly); `exports` maps both\n`./foo.js` and `./foo` specifiers to `./foo.ts`, so `import { identity }\nfrom \"@apsis-io/periapsis-sdk/identity.js\"` resolves the same way the\nin-repo relative imports already do. A consumer using plain `tsc` (no\nbundler) needs `allowArbitraryExtensions`/`noEmit` to resolve `.ts` from\n`node_modules` - not the common case for a dwarf-targeting project, but\nworth knowing.\n\n**Import each module directly, not the `index.js` barrel** (unless you\nalready use every `periapsis:component/*` interface): Vite/Rollup treats an\n`external` import (`periapsis:*`/`wasi:*` are marked external in every\nexample's `vite.config.ts`, since dwarf/the host satisfies them, not the\nbundle) as having unknowable side effects and keeps it in the output even\nwhen the imported binding ends up unused. A single shared module importing\nall six `periapsis:component/*` interfaces would force every consumer's\n`world.wit` to declare all six regardless of which ones it actually calls -\nbreaking this codebase's minimal-capability-surface principle\n(`--host-caps`: an unlisted interface fails closed at instantiation). That's\nwhy this package is six small per-interface modules instead of one\n`component.ts` (confirmed live: the monolithic version broke\n`js-dwarf-plug`'s build with an unresolved `periapsis:component/identity`\nimport it never called).\n\n## Modules\n\n- **`identity.ts`** - `identity()`.\n- **`config.ts`** - `config(key)`.\n- **`log.ts`** - `log`/`trace`/`debug`/`info`/`warn`/`error`.\n- **`metrics.ts`** - `counter`/`gauge`/`histogram`.\n- **`status.ts`** - `reportStatus` (depends on `identity.ts` - a real\n  dependency, `status.notify` needs identity's component/instance fields).\n- **`checkpoint.ts`** - `checkpointRequested`/`checkpointSave`/`checkpointLoad`.\n\n  All six wrap `periapsis:component/*` - plain sync functions, usable from\n  any world (p2 or p3).\n- **`exec.ts`** - `exec(name, args?, input?)` and the lower-level `spawn`/`drainStdout`.\n  Wraps `periapsis:host/exec@0.1.0` (ADR: the exec seam, `trail's exec implementation`) -\n  allowlisted child-component spawning. **p3-only** (`stream<u8>` + an `async\n  func` need trail's `--p3` launch path); a guest may only spawn a name\n  declared at pod launch via `--exec-with <name>=<path>`.\n- **`magic.ts`** - `definePlugProvider(handle)` for authoring a magic-seam\n  provider, `callSeam(handle, request)` for consuming one, and the typed\n  `SeamError`/`seamUnavailable`/`seamRejected`/`seamTooLarge` instead of raw\n  `throw { tag: \"...\" }` object literals. Wraps `periapsis:magic/handler`\n  (ADR-0028) - `handle` is a plain sync WIT func, not `async func`, so a\n  provider can't do async I/O through this seam (see `exec.ts` for the\n  subprocess-shaped alternative).\n- **`fetch.ts`** - `fetch(input, init) -> Response`, a standard outbound\n  `fetch()`. Unlike every other module here, this one needs a build-time\n  compose step, not just an import - see \"Outbound HTTP (`fetch.ts`)\" below.\n- **`console.ts`** - `consoleP3`, a typed, documented binding to dwarf's own\n  pinned `consoleP3` global - see the `console` section below for why it's\n  pinned rather than just re-exporting the plain `console`.\n- **`sockets.ts`** - `TcpSender`, a server-side (accepted) `tcp-socket`'s\n  send stream done right: ONE `send()` call and one long-lived writable per\n  *connection*, not per message. Wraps `wasi:sockets@0.3` (not\n  periapsis-specific) - extracted from `examples/wasm/js-dwarf-websocket`\n  after a real usage-pattern bug there (dropping the writable after every\n  message correctly end-of-streams `send()`'s own stream, triggering a\n  genuine TCP half-close of the write side - a well-behaved peer then\n  closes its own write side too, so the next `receive()` read legitimately\n  sees EOF) looked exactly like a platform bug for two separate\n  investigation passes before the actual mechanism was found. Also\n  `readExact(readable, n)`, a small loop-until-full helper. **p3-only**\n  (`wasi:sockets@0.3`'s `bind`/`listen`/accept has no p2 equivalent here).\n- **`websocket.ts`** - a real WebSocket **server**, hand-rolled on\n  `sockets.ts` + `sha1.ts`: `computeAcceptKey`/`parseUpgradeRequest`/\n  `buildUpgradeResponse` (the RFC 6455 handshake), `readHttpHeaders`,\n  `readFrame`/`buildTextFrame`/`buildBinaryFrame`/`buildCloseFrame`/\n  `WS_OPCODE` (RFC 6455 framing). `wasi:http/service` has no socket-hijack/\n  upgrade primitive, so this only works from a command-style component\n  (`wasi:cli/command`, not `http-service`/`trail --serve`) whose own `run()`\n  binds+listens directly - see `examples/wasm/js-dwarf-websocket`'s README\n  for the full story (live-validated: a real `WebSocket` client, multiple\n  messages round-tripped, clean close). **p3-only**, same reason as\n  `sockets.ts`.\n- **`sha1.ts`** - a minimal pure-JS SHA-1 (RFC 3174), no WIT dependency.\n  dwarf has no `crypto`/`crypto.subtle` at all; `websocket.ts`'s handshake\n  needs one for `Sec-WebSocket-Accept` (a checksum over fixed,\n  non-adversarial input - not a place SHA-1's broken collision resistance\n  would matter even if a real `crypto.subtle` were available).\n\n## Type declarations\n\nThree ambient `.d.ts` files under `types/`, split by what actually owns each\ndeclaration - not one grab-bag:\n\n- **`types/periapsis.d.ts`** - the `periapsis:*` WIT interfaces this package\n  wraps (`periapsis:component/*`, `periapsis:host/exec@0.1.0`,\n  `periapsis:magic/handler@0.1.0`).\n- **`types/wit.d.ts`** - the generic component-model-async stream plumbing\n  (the `wit` global's `Stream` helper, `StreamReadableU8`/`StreamWritableU8`)\n  - not periapsis-specific, applies to any WASI 0.3/p3 world.\n- **`types/dwarf.d.ts`** - dwarf's own runtime globals that aren't derived\n  from any WIT interface at all: `console` (see dwarf's own README \"Console\"\n  section), `TextEncoder`/`TextDecoder` (always on, no `--polyfill`, real\n  UTF-8 - `codec.ts` uses these instead of a hand-rolled ASCII-only codec, a\n  correctness fix as well as a simplification), and `process` (also always\n  on - `env`/`argv`/`cwd()`/`exit()`, no stdout/stderr surface; doesn't\n  overlap with `config.ts` - `process.env` is raw OS env vars, `config.ts`\n  is periapsis's own structured per-pod config).\n\ndwarf does no type-checking of its own (and `jco types`/`--emit-types`\ndoesn't actually match dwarf's runtime conventions - see `exec.ts`'s header\ncomment) - these three files are purely for the author's `tsc`/editor\nexperience and never affect the build. A consuming example that needs MORE\nthan this package covers (its own `wasi:filesystem`/`wasi:sockets` usage, say)\nstill declares those itself, same as before.\n\n**`console` (`types/dwarf.d.ts`) vs `log.ts`**: two different logging paths,\nnot redundant. `console.{log,info,debug,warn,error}` now try WASI 0.2 first\n(`wasi:cli/stdout`/`stderr@0.2.12` - sync, returns `void`) and fall back to\nWASI 0.3's async write-via-stream (`Promise<void>`) when only that's\nimported, and `console.{print,println,eprint,eprintln}` are unconditionally\nasync, `Promise`-returning, with the same 0.3-preferred/0.2-fallback\npriority - see `types/dwarf.d.ts`'s `Console` interface doc comment for the\nfull behavior, including two real safety constraints: (1) the async family\ncrashes if called from a plain SYNC export (no active component-model-async\ntask state outside an async export call), and (2) in the 0.3-fallback case,\nan *unawaited* call is only safe if something else in the same async export\nsubsequently awaits/yields afterward - as the literal last statement before\nthe export returns, it silently produces no output at all (confirmed\nempirically). Reach for `console` during local/interactive debugging (e.g.\n`trail --component` against a real terminal). `log.ts`'s `info`/`warn`/etc go\nthrough `periapsis:component/log` to the HOST, which routes to\njournald/`kubectl logs` - use that for anything meant to actually be visible\nonce deployed as a pod.\n\n**`console.ts`** exports `consoleP3`, a typed binding to dwarf's own pinned\n`consoleP3` global (`types/dwarf.d.ts`) - all nine methods, all\n`Promise`-returning. This used to be a `consoleP2`/`consoleP3` split (a\nguaranteed-sync view for p2 worlds alongside the async p3 one), for a real,\nconfirmed reason: **mixing `wasi:cli/stdout@0.2.x` with\n`wasi:cli/command@0.3.0` (any p3 world) in the same world fails at\nWIT-resolution time.** Confirmed empirically (not inferred): a world with\nboth `include wasi:cli/command@0.3.0;` and `import wasi:cli/stdout@0.2.12;`\nerrors `package 'wasi:cli@0.2.12' not found` during auto-vendoring, even via\na clean full auto-vendor - dwarf's WIT tooling can't resolve two different\nversions of the same package name in one world. Since trail dropped WASI P2\nsupport entirely (ADR-0045), no world in this repo can be p2-only anymore, so\n`consoleP2` had no shape left that could use it and was removed - every\nworld here is p3-only, so `consoleP3`'s async-only shape (**every call must\nbe awaited** per the safety constraint above) is just how logging works now.\n\ndwarf itself now builds `consoleP3` as a real, separately-implemented global\n(not just a type-level view) and aliases the plain `console` FROM it - so\n`console.ts`'s `consoleP3` binds directly to that pinned global via\n`globalThis.consoleP3`, rather than casting the plain `console` (which\nremains free to repoint at a future WASI version without affecting this\nbinding).\n\n(The WIT-mixing limitation itself was reported to dwarf-main as a real\ngap/feature request; dwarf-main confirmed it as an upstream wkg/wit-parser\ndependency-resolution constraint, not a dwarf bug it can paper over, and\nshipped the `log`/`info`/`debug`/`warn`/`error` p3-fallback described above in\nresponse - both independently verified live against a fresh dwarf build.)\n\n## Outbound HTTP (`fetch.ts`)\n\n`fetch.ts` wraps `dwarf:fetch/client` (a SEPARATE component,\n`fetch-provider/fetch-provider.wasm`, built from dwarf's own\n`examples/fetch-provider` - not part of dwarf itself, adapted from that\nexample's own `fetch.js` DX wrapper). Unlike every other module in this\npackage, importing it isn't enough on its own - `dwarf:fetch/client`'s\nimplementation needs `wit.Future`/`wit.Stream` type indices that only make\nsense inside `fetch-provider`'s own fixed, minimal world, so it has to be\ncomposed in as a separate component at build time:\n\n1. Vendor `fetch-provider/package.wit`'s `interface client {...}` block into\n   your own `wit/deps/dwarf-fetch/package.wit`, and\n   `import dwarf:fetch/client;` in your world (auto-vendoring also works -\n   the global wkg config's `dwarf` namespace mapping, alongside `periapsis`,\n   points at the same local registry `wit/.registry/`, which includes a copy\n   of this interface).\n2. Build with `--polyfill fetch-classes` (for `Request`/`Response`/`Headers`),\n   then compose `fetch-provider.wasm` in via `wac plug`:\n   ```bash\n   dwarf --wit wit --js dist/main.js -o my-app.wasm --polyfill fetch-classes\n   wac plug --plug .@apsis-io/periapsis-sdk/fetch-provider/fetch-provider.wasm my-app.wasm -o my-app.composed.wasm\n   ```\n   Run the COMPOSED output, not the plain one - the plain one has an\n   unsatisfied `dwarf:fetch/client` import and fails to instantiate.\n\n`fetch` is `async` end to end - only callable from an async export.\n`fetch-provider/build.sh` rebuilds `fetch-provider.wasm` from dwarf's own\nexample (`$DWARF_REPO`, defaults to `~/git/dwarf`) - re-run it when picking\nup a newer dwarf.\n\nLive-validated end to end: a real POST with a body, through `fetch.ts`,\ncomposed via `wac plug`, run on `trail --p3` against a real local HTTP\nserver - correct status/body round-trip. (One real dead end along the way,\nworth recording: an empty response body first looked like a `fetch-provider`\nor trail bug, reproduced identically under raw `wasmtime` too - turned out to\nbe the test's OWN throwaway HTTP server not decoding `Transfer-Encoding:\nchunked` request bodies, nothing to do with `fetch-provider`/trail at all.)\n\nKnown limits (inherited from `fetch-provider`, not fixed here): response\nbodies are read with a single `read(65536)` call, not a drain loop - bodies\nlarger than 64KB are truncated. `request.url` is parsed with a small regex\n(`http(s)://host[:port]/path?query`), not full WHATWG URL parsing.\n\n## What this doesn't replace\n\nFilesystem (`writeFile`/`readFile`) helpers already exist in some examples'\nown `periapsis.ts` (e.g. `js-dwarf-p3`) but weren't part of this package's\nscope - still per-example for now. (Socket helpers moved in as `sockets.ts`\n- see \"Modules\" above.)\n","readmeFilename":"README.md"}