@polyengine/wasi 0.2.0-pre.g2125a06 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/esm/http.js CHANGED
@@ -65,7 +65,7 @@
65
65
  // A10: case names are data, kebab-case as written, including capitals).
66
66
  // Fetch failures are TypeErrors with prose; a small sniff table maps the
67
67
  // recognizable ones and everything else is `internal-error(message)`.
68
- import { ComponentException } from "@polyengine/runtime/embedder";
68
+ import { ComponentException, isComponentException } from "@polyengine/runtime/embedder";
69
69
  /**
70
70
  * The compatibility track the fragment registers on by default.
71
71
  *
@@ -679,7 +679,10 @@ export function http(options = {}) {
679
679
  }
680
680
  let resp;
681
681
  try {
682
- resp = await fetch(url, {
682
+ // Constructing the `Request` happens inside this try: a throw here
683
+ // (e.g. a GET with a body) maps through mapFetchError exactly as a
684
+ // fetch throw does, per the same catch below.
685
+ const req = new globalThis.Request(url, {
683
686
  method,
684
687
  headers,
685
688
  body: body === undefined || body.length === 0 ? undefined : body,
@@ -687,8 +690,20 @@ export function http(options = {}) {
687
690
  cache: "no-store",
688
691
  credentials: "omit",
689
692
  });
693
+ // Resolved at call time (not captured at http() construction), so
694
+ // a test stubbing globalThis.fetch after the fragment exists still
695
+ // takes effect.
696
+ const transport = options.fetch ?? ((r) => globalThis.fetch(r));
697
+ resp = await transport(req);
690
698
  }
691
699
  catch (e) {
700
+ if (isComponentException(e)) {
701
+ // Branded exception passthrough: the transport named the
702
+ // guest-visible WIT error-code itself; do not run it through
703
+ // mapFetchError's prose sniffing, and rethrow unchanged.
704
+ request.settleTransmission({ kind: "err", value: e.payload });
705
+ throw e;
706
+ }
692
707
  const code = mapFetchError(e);
693
708
  request.settleTransmission({ kind: "err", value: code });
694
709
  throw httpError(code, `client.send: ${e instanceof Error ? e.message : String(e)}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polyengine/wasi",
3
- "version": "0.2.0-pre.g2125a06",
3
+ "version": "0.3.0",
4
4
  "description": "WASI providers for polyengine hosts: the p2 baseline and p3 clocks, one module per semver track.",
5
5
  "homepage": "https://github.com/polymorph-components/polyengine#readme",
6
6
  "repository": {
@@ -91,8 +91,8 @@
91
91
  "access": "public"
92
92
  },
93
93
  "dependencies": {
94
- "@polyengine/protocol": "0.2.0-pre.g2125a06",
95
- "@polyengine/runtime": "0.2.0-pre.g2125a06"
94
+ "@polyengine/protocol": "0.3.0",
95
+ "@polyengine/runtime": "0.3.0"
96
96
  },
97
97
  "_generatedBy": "dnt@0.43.2"
98
98
  }
package/types/http.d.ts CHANGED
@@ -131,6 +131,32 @@ export interface HttpOptions {
131
131
  method: string;
132
132
  headers: Headers;
133
133
  }) => boolean | Promise<boolean>);
134
+ /**
135
+ * Injectable transport: replaces the `fetch(request)` call `client.send`
136
+ * otherwise makes directly. Default (when omitted): `globalThis.fetch`,
137
+ * resolved AT CALL TIME — not captured when `http()` constructs the
138
+ * fragment — so stubbing `globalThis.fetch` after the fragment exists
139
+ * still takes effect.
140
+ *
141
+ * The `Request` handed to the transport already carries this
142
+ * fragment's hardening (`redirect: "manual"`, `cache: "no-store"`,
143
+ * `credentials: "omit"`). A transport that forwards to the real
144
+ * `fetch` with its own `init` can override these — re-enabling
145
+ * redirect-following in particular would break the property that every
146
+ * redirect hop re-enters `send` and is re-checked by `allowRequest`.
147
+ * The transport is trusted embedder code; this is a caution, not a
148
+ * hole.
149
+ *
150
+ * `request.clone()` is how to inspect the body without consuming it,
151
+ * so a transport can peek (e.g. for logging) and still forward the
152
+ * original request.
153
+ *
154
+ * A transport that throws a branded `ComponentException` names the
155
+ * guest-visible WIT error-code exactly (the fragment rethrows it
156
+ * unchanged); anything else it throws is mapped by this fragment's
157
+ * `mapFetchError` sniffing, which usually lands on `internal-error`.
158
+ */
159
+ fetch?: (request: globalThis.Request) => Promise<globalThis.Response>;
134
160
  }
135
161
  /** What `http()` returns: the imports fragment plus the fragment's classes. */
136
162
  export interface HttpFragment {