@almadar/shell-runtime 0.1.0 → 1.1.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.
Files changed (167) hide show
  1. package/dist/chunk-2WCVOMZ2.js +112 -0
  2. package/dist/chunk-57SBCUSM.js +62 -0
  3. package/dist/{chunk-Q2H75UYT.js → chunk-A2JJT4GA.js} +1 -37
  4. package/dist/chunk-BAS26HBN.js +10 -0
  5. package/dist/{chunk-REPX5QPI.js → chunk-BOVU4TCQ.js} +11 -3
  6. package/dist/chunk-BY5G4225.js +6 -0
  7. package/dist/chunk-DFDNHVDW.js +284 -0
  8. package/dist/{chunk-NATGCIVM.js → chunk-JVSREWQO.js} +378 -130
  9. package/dist/{chunk-DYOJGLIX.js → chunk-LKWYCYX5.js} +2 -5
  10. package/dist/chunk-LYFIQPXX.js +1 -0
  11. package/dist/{chunk-ODJCZ27I.js → chunk-N7HYNKK6.js} +35 -2
  12. package/dist/{chunk-4J2QEIUV.js → chunk-NTFQ36UN.js} +4 -30
  13. package/dist/chunk-NU6LVKGS.js +15 -0
  14. package/dist/{chunk-VNMG7NKY.js → chunk-OQVSN7DP.js} +21 -26
  15. package/dist/chunk-P2N6K2IV.js +20 -0
  16. package/dist/{chunk-QQRDUMB2.js → chunk-QCJWPXLH.js} +11 -11
  17. package/dist/{chunk-QELZ6TEJ.js → chunk-UD2CXYSJ.js} +39 -3
  18. package/dist/{chunk-UJHOUZAL.js → chunk-V4EMDPCO.js} +2 -5
  19. package/dist/chunk-VKQA2DJX.js +409 -0
  20. package/dist/chunk-VNGXRYFF.js +9 -0
  21. package/dist/{chunk-HNOAZWFH.js → chunk-WGCWJOT2.js} +2 -0
  22. package/dist/chunk-XZGVOBY6.js +33 -0
  23. package/dist/chunk-ZUSM4VW4.js +197 -0
  24. package/dist/client/EventTransport.d.ts +23 -7
  25. package/dist/client/EventTransport.js +1 -2
  26. package/dist/client/awaiting.js +0 -1
  27. package/dist/client/channel-transport.d.ts +6 -6
  28. package/dist/client/channel-transport.js +0 -1
  29. package/dist/client/circuit-store.d.ts +16 -5
  30. package/dist/client/circuit-store.js +2 -3
  31. package/dist/client/client-kernel.d.ts +36 -15
  32. package/dist/client/declared-input-dispatch.d.ts +19 -2
  33. package/dist/client/declared-input-dispatch.js +1 -2
  34. package/dist/client/inbound-dispatch.d.ts +21 -2
  35. package/dist/client/inbound-dispatch.js +1 -2
  36. package/dist/client/local-fold.d.ts +15 -8
  37. package/dist/client/local-fold.js +1 -2
  38. package/dist/client/render-sigils.js +0 -1
  39. package/dist/client/state-book.d.ts +9 -16
  40. package/dist/client/state-book.js +1 -2
  41. package/dist/client/trait-mount-error.js +0 -1
  42. package/dist/credentials/env-vars.d.ts +5 -1
  43. package/dist/credentials/env-vars.js +1 -3
  44. package/dist/credentials/scope.d.ts +8 -7
  45. package/dist/credentials/scope.js +0 -1
  46. package/dist/credentials/vault.d.ts +142 -0
  47. package/dist/credentials/vault.js +1 -0
  48. package/dist/effects/in-flight-calls.js +0 -1
  49. package/dist/effects/on-device-model.js +0 -1
  50. package/dist/events/EventBus.d.ts +1 -4
  51. package/dist/events/EventBus.js +0 -1
  52. package/dist/events/emit-stamp.js +0 -1
  53. package/dist/index.d.ts +25 -42
  54. package/dist/index.js +27 -45
  55. package/dist/kernel/decode.d.ts +10 -10
  56. package/dist/kernel/decode.js +1 -2
  57. package/dist/kernel/engine.d.ts +133 -31
  58. package/dist/kernel/engine.js +7 -9
  59. package/dist/kernel/frame-applier.d.ts +8 -7
  60. package/dist/kernel/frame-applier.js +1 -2
  61. package/dist/kernel/host.d.ts +148 -16
  62. package/dist/kernel/host.js +4 -7
  63. package/dist/kernel/lane.d.ts +1 -22
  64. package/dist/kernel/lane.js +1 -2
  65. package/dist/kernel/os-fetch-port.d.ts +7 -0
  66. package/dist/kernel/os-fetch-port.js +3 -0
  67. package/dist/kernel/os-port.d.ts +30 -8
  68. package/dist/kernel/os-port.js +1 -2
  69. package/dist/kernel/program-effects.d.ts +11 -28
  70. package/dist/kernel/program-effects.js +1 -2
  71. package/dist/kernel/secret-ports.d.ts +139 -0
  72. package/dist/kernel/secret-ports.js +2 -0
  73. package/dist/kernel/wire.d.ts +113 -12
  74. package/dist/loader/fetch-loader.d.ts +26 -0
  75. package/dist/loader/fetch-loader.js +1 -0
  76. package/dist/loader/lazy-page.js +0 -1
  77. package/dist/loader/schema-loader.d.ts +1 -17
  78. package/dist/persistence/native-memory.js +0 -1
  79. package/dist/runtime/entities/declaredCollections.d.ts +6 -0
  80. package/dist/runtime/entities/declaredCollections.js +1 -0
  81. package/dist/runtime/evaluation/local-store-transport.d.ts +16 -23
  82. package/dist/runtime/evaluation/local-store-transport.js +9 -13
  83. package/dist/runtime/evaluation/residence-transport.d.ts +3 -3
  84. package/dist/runtime/evaluation/residence-transport.js +1 -2
  85. package/dist/runtime/evaluation/routed-persistence.js +0 -1
  86. package/dist/runtime/events/identity/routing.d.ts +2 -53
  87. package/dist/runtime/events/identity/routing.js +1 -2
  88. package/dist/runtime/types.d.ts +5 -205
  89. package/dist/runtime/types.js +1 -2
  90. package/dist/service/default-call-service.js +0 -1
  91. package/dist/service/service-provider.js +0 -1
  92. package/package.json +8 -5
  93. package/dist/chunk-2JU7Y4KU.js +0 -21
  94. package/dist/chunk-46RWK2B5.js +0 -28
  95. package/dist/chunk-4ZICQ5PM.js +0 -192
  96. package/dist/chunk-53IPZXDP.js +0 -76
  97. package/dist/chunk-5D63EMO5.js +0 -16
  98. package/dist/chunk-CPSQXEJ6.js +0 -55
  99. package/dist/chunk-CQP5XAX6.js +0 -173
  100. package/dist/chunk-CROS2GEX.js +0 -49
  101. package/dist/chunk-D4XJTBLB.js +0 -217
  102. package/dist/chunk-D5USD2EX.js +0 -232
  103. package/dist/chunk-EV56K4GB.js +0 -63
  104. package/dist/chunk-FQ6IZMIU.js +0 -10
  105. package/dist/chunk-HMK6YMQS.js +0 -135
  106. package/dist/chunk-IHQLE5M7.js +0 -62
  107. package/dist/chunk-JFWFDUTR.js +0 -35
  108. package/dist/chunk-MHYSHSRG.js +0 -54
  109. package/dist/chunk-MLKGABMK.js +0 -7
  110. package/dist/chunk-NAECVIAR.js +0 -322
  111. package/dist/chunk-Q7JK4KY7.js +0 -9
  112. package/dist/chunk-RBUMDYFS.js +0 -681
  113. package/dist/chunk-SAS5KKCR.js +0 -43
  114. package/dist/chunk-SWPDU752.js +0 -28
  115. package/dist/chunk-T775TUCD.js +0 -18
  116. package/dist/chunk-VMOBW7RK.js +0 -21
  117. package/dist/chunk-WNPNNYXY.js +0 -22
  118. package/dist/chunk-XB5GYODW.js +0 -28
  119. package/dist/chunk-YL2SO5TP.js +0 -334
  120. package/dist/chunk-YO4LWS3I.js +0 -606
  121. package/dist/chunk-ZAQSS47X.js +0 -157
  122. package/dist/chunk-ZCQUUJIF.js +0 -129
  123. package/dist/client/ServerBridge.d.ts +0 -126
  124. package/dist/client/ServerBridge.js +0 -3
  125. package/dist/credentials/seed.d.ts +0 -21
  126. package/dist/credentials/seed.js +0 -2
  127. package/dist/credentials/store.d.ts +0 -110
  128. package/dist/credentials/store.js +0 -2
  129. package/dist/index-hT1xCdTq.d.ts +0 -46
  130. package/dist/kernel/beacon.d.ts +0 -32
  131. package/dist/kernel/beacon.js +0 -2
  132. package/dist/kernel/http.d.ts +0 -302
  133. package/dist/kernel/http.js +0 -6
  134. package/dist/kernel/oauth-effects.d.ts +0 -25
  135. package/dist/kernel/oauth-effects.js +0 -7
  136. package/dist/kernel/oauth-port.d.ts +0 -31
  137. package/dist/kernel/oauth-port.js +0 -2
  138. package/dist/loader/http-loader.d.ts +0 -111
  139. package/dist/loader/http-loader.js +0 -2
  140. package/dist/runtime/effects/composition/compose-behaviors.d.ts +0 -58
  141. package/dist/runtime/effects/composition/compose-behaviors.js +0 -4
  142. package/dist/runtime/effects/composition/event-wiring.d.ts +0 -38
  143. package/dist/runtime/effects/composition/event-wiring.js +0 -2
  144. package/dist/runtime/effects/composition/index.d.ts +0 -5
  145. package/dist/runtime/effects/composition/index.js +0 -6
  146. package/dist/runtime/effects/composition/layout-strategy.d.ts +0 -35
  147. package/dist/runtime/effects/composition/layout-strategy.js +0 -2
  148. package/dist/runtime/effects/composition/pipe.d.ts +0 -25
  149. package/dist/runtime/effects/composition/pipe.js +0 -2
  150. package/dist/runtime/entities/mockStoreSeed.d.ts +0 -56
  151. package/dist/runtime/entities/mockStoreSeed.js +0 -3
  152. package/dist/runtime/entities/seedBrowserStore.d.ts +0 -28
  153. package/dist/runtime/entities/seedBrowserStore.js +0 -2
  154. package/dist/runtime/entities/std-mock-seed.d.ts +0 -87
  155. package/dist/runtime/entities/std-mock-seed.js +0 -2
  156. package/dist/runtime/time/TickScheduler.d.ts +0 -77
  157. package/dist/runtime/time/TickScheduler.js +0 -3
  158. package/dist/runtime/time/cron.d.ts +0 -25
  159. package/dist/runtime/time/cron.js +0 -2
  160. package/dist/runtime/time/duration.d.ts +0 -20
  161. package/dist/runtime/time/duration.js +0 -2
  162. package/dist/runtime/traits/OrbitalTraitParsing.d.ts +0 -34
  163. package/dist/runtime/traits/OrbitalTraitParsing.js +0 -2
  164. package/dist/runtime/traits/listen-targets.d.ts +0 -16
  165. package/dist/runtime/traits/listen-targets.js +0 -3
  166. package/dist/runtime/traits/trait-index.d.ts +0 -35
  167. package/dist/runtime/traits/trait-index.js +0 -3
@@ -1,606 +0,0 @@
1
- import { untilAborted } from './chunk-MZKIL5IN.js';
2
- import { deliverBeacon } from './chunk-VMOBW7RK.js';
3
- import { decodeHttpRequest, decodeOAuthAsk } from './chunk-RBUMDYFS.js';
4
- import { resolveCredentialRef, getEffectiveCredentialStore, getModeControl } from './chunk-HLOUDLPI.js';
5
- import { credentialStorageKey, resolveCredentialStatusIdentity, credentialStatusConnected, isJsonObject } from '@almadar/core';
6
-
7
- function userCredentialKey(principal, name) {
8
- return credentialStorageKey({ name, principal });
9
- }
10
- var HttpUnavailableError = class extends Error {
11
- code = "HTTP_KERNEL_UNAVAILABLE";
12
- constructor(detail) {
13
- super(`HTTP_KERNEL_UNAVAILABLE: ${detail}`);
14
- }
15
- };
16
- var HttpEffectFailure = class extends Error {
17
- constructor(payload) {
18
- super(payload.error);
19
- this.payload = payload;
20
- }
21
- payload;
22
- };
23
- var PERSISTED_SERVICE = "kernel";
24
- var installedSecretsHost = {
25
- async store() {
26
- return getEffectiveCredentialStore();
27
- },
28
- async resolve(name, principal) {
29
- return resolveCredentialRef(name, void 0, principal);
30
- }
31
- };
32
- function createHttpSecrets(now = Date.now, host = installedSecretsHost) {
33
- const environmentMinted = /* @__PURE__ */ new Map();
34
- const storeMinted = /* @__PURE__ */ new WeakMap();
35
- const cacheFor = (store) => {
36
- if (store === null) return environmentMinted;
37
- const held = storeMinted.get(store);
38
- if (held !== void 0) return held;
39
- const cache = /* @__PURE__ */ new Map();
40
- storeMinted.set(store, cache);
41
- return cache;
42
- };
43
- const slot = (name, principal) => credentialStorageKey({ name, ...principal !== void 0 ? { principal } : {} });
44
- return {
45
- async get(name, principal) {
46
- const minted = cacheFor(await host.store());
47
- const key = slot(name, principal);
48
- const held = minted.get(key);
49
- if (held !== void 0) {
50
- if (held.expiresAt > now()) return held.value;
51
- minted.delete(key);
52
- }
53
- return host.resolve(name, principal);
54
- },
55
- async set(name, value, ttlMs, principal) {
56
- const minted = cacheFor(await host.store());
57
- const key = slot(name, principal);
58
- if (ttlMs <= 0) minted.delete(key);
59
- else minted.set(key, { value, expiresAt: now() + ttlMs });
60
- },
61
- async rotate(name, value, principal) {
62
- const store = await host.store();
63
- if (store === null) throw new Error("this host keeps no credential store to rotate into");
64
- const stored = store.entries(principal).find((entry) => entry.envVar === name);
65
- if (stored === void 0) throw new Error(`credential ${name} is not in the credential store`);
66
- cacheFor(store).delete(slot(name, principal));
67
- await store.set(stored.service, name, value, principal);
68
- },
69
- async persist(name, value, principal, label) {
70
- const store = await host.store();
71
- if (store === null || !store.enabled) throw new Error("this host keeps no credential store to persist into");
72
- cacheFor(store).delete(slot(name, principal));
73
- await store.set(PERSISTED_SERVICE, name, value, principal, label);
74
- },
75
- async hold(name, value, ttlMs, principal) {
76
- const store = await host.store();
77
- const minted = cacheFor(store);
78
- const key = slot(name, principal);
79
- if (store !== null && store.sharesDerived) {
80
- minted.delete(key);
81
- if (ttlMs > 0) await store.holdDerived(name, value, now() + ttlMs, principal);
82
- return;
83
- }
84
- if (ttlMs <= 0) minted.delete(key);
85
- else minted.set(key, { value, expiresAt: now() + ttlMs });
86
- },
87
- async take(name, principal) {
88
- const store = await host.store();
89
- if (store !== null && store.sharesDerived) {
90
- const shared = await store.takeDerived(name, principal, now());
91
- if (shared !== void 0) return shared;
92
- }
93
- const minted = cacheFor(store);
94
- const key = slot(name, principal);
95
- const held = minted.get(key);
96
- if (held === void 0) return void 0;
97
- minted.delete(key);
98
- return held.expiresAt > now() ? held.value : void 0;
99
- },
100
- async label(name, principal) {
101
- return (await host.store())?.label(name, principal);
102
- },
103
- async durable() {
104
- const store = await host.store();
105
- return store !== null && store.enabled;
106
- },
107
- async forget(name, principal) {
108
- const store = await host.store();
109
- const minted = cacheFor(store);
110
- const key = slot(name, principal);
111
- minted.delete(key);
112
- await store?.remove(name, principal);
113
- }
114
- };
115
- }
116
- function createCredentialAdminPort() {
117
- return {
118
- async list() {
119
- const store = getEffectiveCredentialStore();
120
- if (store === null) return null;
121
- return { enabled: store.enabled, entries: store.entries().map((entry) => ({ service: entry.service, name: entry.envVar })) };
122
- },
123
- async read(name) {
124
- return getEffectiveCredentialStore()?.resolve(name) ?? null;
125
- },
126
- async write(service, name, value) {
127
- const store = getEffectiveCredentialStore();
128
- if (store === null) throw new Error("this host keeps no credential store");
129
- await store.set(service, name, value);
130
- },
131
- async remove(name) {
132
- const store = getEffectiveCredentialStore();
133
- if (store === null) throw new Error("this host keeps no credential store");
134
- return store.remove(name);
135
- },
136
- async rotate() {
137
- const store = getEffectiveCredentialStore();
138
- if (store === null) throw new Error("this host keeps no credential store");
139
- return store.rotate();
140
- },
141
- async mode() {
142
- return getModeControl()?.mode ?? null;
143
- },
144
- async setMode(mode) {
145
- const control = getModeControl();
146
- if (control === null) throw new Error("No integration manager is installed on this host");
147
- if (mode !== "mock" && mode !== "real") throw new Error(`mode must be "mock" or "real", got "${mode}"`);
148
- control.setMode(mode);
149
- return control.mode;
150
- }
151
- };
152
- }
153
- var systemRandom = (bytes) => crypto.getRandomValues(new Uint8Array(bytes));
154
- var RANDOM_BYTES_MAX = 1024;
155
- function binary(bytes) {
156
- let text = "";
157
- for (const byte of bytes) text += String.fromCharCode(byte);
158
- return text;
159
- }
160
- function base64Standard(bytes) {
161
- return btoa(binary(bytes));
162
- }
163
- function base64Url(bytes) {
164
- return base64Standard(bytes).replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
165
- }
166
- function randomBytesPayload(ports, bytes, key) {
167
- if (key !== void 0 && (typeof key !== "string" || key === "")) {
168
- throw new Error(`call key must evaluate to a non-empty string, got ${String(key)}`);
169
- }
170
- if (typeof bytes !== "number" || !Number.isInteger(bytes) || bytes < 1 || bytes > RANDOM_BYTES_MAX) {
171
- throw new Error(`random-bytes: the byte count must be an integer from 1 to ${RANDOM_BYTES_MAX}, got ${String(bytes)}`);
172
- }
173
- const value = base64Url(ports.random(bytes));
174
- return key === void 0 ? { value } : { value, key };
175
- }
176
- function signedIn(head, principal) {
177
- if (principal === void 0) throw new Error(`${head}: nobody is signed in`);
178
- return principal;
179
- }
180
- function credentialName(head, credential) {
181
- if (typeof credential !== "string") throw new Error(`${head}: the credential must be a secret knob's name`);
182
- return credential;
183
- }
184
- async function credentialStatusPayload(ports, credential, principal) {
185
- const identity = resolveCredentialStatusIdentity(credential, principal);
186
- const connected = credentialStatusConnected(await ports.secrets.get(identity.name, identity.principal), identity.principal);
187
- const label = connected ? await ports.secrets.label?.(identity.name, identity.principal) ?? "" : "";
188
- return { connected, label };
189
- }
190
- async function credentialForgetPayload(ports, credential, principal) {
191
- const who = signedIn("credential-forget", principal);
192
- const name = credentialName("credential-forget", credential);
193
- await ports.secrets.forget(name, who);
194
- return { connected: false, label: "" };
195
- }
196
- var installedNet = null;
197
- function installNetPort(port) {
198
- installedNet = port;
199
- }
200
- function netPort() {
201
- if (installedNet === null) throw new Error("createHttpPorts needs a NetPort for its default fetch/resolve: install one (@almadar/shell-node installNodeHostPorts) or pass both");
202
- return installedNet;
203
- }
204
- function createHttpPorts(options) {
205
- return {
206
- kernel: options.kernel,
207
- random: options.random ?? systemRandom,
208
- egress: options.egress,
209
- secrets: options.secrets ?? createHttpSecrets(),
210
- credentials: options.credentials ?? createCredentialAdminPort(),
211
- fetch: options.fetch ?? netPort().fetch,
212
- resolve: options.resolve ?? netPort().resolve,
213
- ...options.oauth !== void 0 ? { oauth: options.oauth } : {}
214
- };
215
- }
216
- var browserSecrets = {
217
- async get(name) {
218
- throw new Error(`credential ${name} is not available in a browser`);
219
- },
220
- async set(name) {
221
- throw new Error(`credential ${name} cannot be stored in a browser`);
222
- },
223
- async forget(name) {
224
- throw new Error(`credential ${name} cannot be forgotten in a browser`);
225
- }
226
- };
227
- function createBrowserHttpPorts(options) {
228
- const browserFetch = options.fetch ?? ((url, init) => fetch(url, init));
229
- return {
230
- kernel: options.kernel,
231
- random: systemRandom,
232
- egress: options.egress,
233
- secrets: browserSecrets,
234
- fetch: (url, init) => browserFetch(url.href, { method: init.method, headers: init.headers, ...init.body !== void 0 ? { body: init.body } : {}, redirect: init.redirect, ...init.signal !== void 0 ? { signal: init.signal } : {} }),
235
- resolve: null,
236
- beacon: options.beacon ?? browserBeaconPorts()
237
- };
238
- }
239
- function browserBeaconPorts() {
240
- const hasQueue = typeof navigator !== "undefined" && typeof navigator.sendBeacon === "function";
241
- return {
242
- ...hasQueue ? { queue: (url, text) => navigator.sendBeacon(url, new Blob([text], { type: "text/plain" })) } : {},
243
- fetch: async (url, init) => ({ status: (await fetch(url, init)).status })
244
- };
245
- }
246
- function parsed(json) {
247
- return JSON.parse(json);
248
- }
249
- function record(value, what) {
250
- if (!isJsonObject(value)) throw new Error(`${what} is not an object`);
251
- return value;
252
- }
253
- function bodyBytes(body) {
254
- switch (body.kind) {
255
- case "empty":
256
- return void 0;
257
- case "text":
258
- return new TextEncoder().encode(body.text);
259
- case "base64":
260
- return Uint8Array.from(atob(body.data), (char) => char.charCodeAt(0));
261
- }
262
- }
263
- function wireBody(bytes) {
264
- if (bytes.length === 0) return { kind: "empty" };
265
- try {
266
- return { kind: "text", text: new TextDecoder("utf-8", { fatal: true }).decode(bytes) };
267
- } catch {
268
- let binary2 = "";
269
- for (const byte of bytes) binary2 += String.fromCharCode(byte);
270
- return { kind: "base64", data: btoa(binary2) };
271
- }
272
- }
273
- function refusal(message) {
274
- return { kind: "failure", failure: { kind: "refused", message } };
275
- }
276
- async function checkedAddress(ports, kernel, url) {
277
- const host = url.hostname.startsWith("[") ? url.hostname.slice(1, -1) : url.hostname;
278
- if (ports.resolve === null) return { address: host };
279
- const resolved = await ports.resolve(host);
280
- const [first] = resolved.addresses;
281
- if (first === void 0) return { refused: `${host} resolves to no address` };
282
- if (resolved.literal && ports.egress.includes(url.origin)) return { address: first };
283
- const closed = resolved.addresses.find((address) => !kernel.isPublicAddress(address));
284
- if (closed !== void 0) return { refused: `${host} resolves to ${closed}, which is not a public address` };
285
- return { address: first };
286
- }
287
- async function dispatch(ports, request, signal, read) {
288
- const kernel = await ports.kernel();
289
- signal?.throwIfAborted();
290
- let url;
291
- try {
292
- url = new URL(request.url);
293
- } catch {
294
- return refusal(`${request.url} is not a URL`);
295
- }
296
- const timeout = request.timeoutMs !== void 0 ? AbortSignal.timeout(request.timeoutMs) : void 0;
297
- const signals = [signal, timeout].filter((s) => s !== void 0);
298
- const operationSignal = signals.length > 0 ? AbortSignal.any(signals) : void 0;
299
- const body = bodyBytes(request.body);
300
- try {
301
- const lookup = checkedAddress(ports, kernel, url);
302
- const checked = operationSignal !== void 0 ? await untilAborted(operationSignal, lookup) : await lookup;
303
- operationSignal?.throwIfAborted();
304
- if ("refused" in checked) return refusal(checked.refused);
305
- const response = await ports.fetch(url, {
306
- method: request.method,
307
- headers: request.headers,
308
- ...body !== void 0 ? { body } : {},
309
- redirect: "manual",
310
- ...operationSignal !== void 0 ? { signal: operationSignal } : {}
311
- }, checked.address);
312
- operationSignal?.throwIfAborted();
313
- return await read(response, operationSignal);
314
- } catch (error) {
315
- if (signal?.aborted === true) throw error;
316
- if (timeout?.aborted === true) return { kind: "failure", failure: { kind: "timedOut" } };
317
- return { kind: "failure", failure: { kind: "failed", message: error instanceof Error ? error.message : String(error) } };
318
- }
319
- }
320
- function headerPairs(response) {
321
- return Array.from(response.headers.entries());
322
- }
323
- async function waitForHttpDelay(delayMs, signal) {
324
- if (!Number.isFinite(delayMs) || !Number.isInteger(delayMs) || delayMs < 0) {
325
- throw new Error("http delayMs must be a nonnegative whole number");
326
- }
327
- signal?.throwIfAborted();
328
- let remaining = delayMs;
329
- while (remaining > 0) {
330
- signal?.throwIfAborted();
331
- const duration = Math.min(remaining, 2147483647);
332
- await new Promise((resolve, reject) => {
333
- const timer = setTimeout(() => {
334
- signal?.removeEventListener("abort", onAbort);
335
- resolve();
336
- }, duration);
337
- function onAbort() {
338
- clearTimeout(timer);
339
- signal?.removeEventListener("abort", onAbort);
340
- reject(signal?.reason ?? new Error("The call was cancelled"));
341
- }
342
- signal?.addEventListener("abort", onAbort, { once: true });
343
- if (signal?.aborted) onAbort();
344
- });
345
- remaining -= duration;
346
- }
347
- }
348
- async function sendHttp(ports, request, signal, delayMs = 0) {
349
- await waitForHttpDelay(delayMs, signal);
350
- return dispatch(ports, request, signal, async (response) => ({
351
- kind: "reply",
352
- response: { status: response.status, headers: headerPairs(response), body: wireBody(new Uint8Array(await response.arrayBuffer())) }
353
- }));
354
- }
355
- function streamEvent(value) {
356
- const event = record(value, "a stream event");
357
- const { data, event: name, id, key } = event;
358
- if (typeof data !== "string" || name !== null && typeof name !== "string" || id !== null && typeof id !== "string" || key !== null && typeof key !== "string") {
359
- throw new Error("a stream event is malformed");
360
- }
361
- return { data, event: name, id, key };
362
- }
363
- function streamHttp(ports, request, stream, onEvent, signal) {
364
- return dispatch(ports, request, signal, async (response, readSignal) => {
365
- const kernel = await ports.kernel();
366
- readSignal?.throwIfAborted();
367
- const decoder = new TextDecoder();
368
- let carry = "";
369
- const publish = (chunk) => {
370
- readSignal?.throwIfAborted();
371
- const framed = record(parsed(kernel.frameStream(stream.framing, stream.key, chunk, carry)), "frameStream result");
372
- const { events, carry: rest } = framed;
373
- if (!Array.isArray(events) || typeof rest !== "string") throw new Error("frameStream result is malformed");
374
- carry = rest;
375
- for (const event of events) {
376
- readSignal?.throwIfAborted();
377
- onEvent(streamEvent(event));
378
- }
379
- };
380
- const reader = response.body?.getReader();
381
- let completed = false;
382
- try {
383
- if (reader !== void 0) {
384
- for (; ; ) {
385
- const pending = reader.read();
386
- const next = readSignal !== void 0 ? await untilAborted(readSignal, pending) : await pending;
387
- readSignal?.throwIfAborted();
388
- if (next.done) break;
389
- publish(decoder.decode(next.value, { stream: true }));
390
- }
391
- }
392
- const tail = decoder.decode();
393
- if (tail !== "") publish(tail);
394
- readSignal?.throwIfAborted();
395
- const flushed = parsed(kernel.frameStreamFinish(stream.framing, stream.key, carry));
396
- if (!Array.isArray(flushed)) throw new Error("frameStreamFinish result is malformed");
397
- for (const event of flushed) {
398
- readSignal?.throwIfAborted();
399
- onEvent(streamEvent(event));
400
- }
401
- readSignal?.throwIfAborted();
402
- completed = true;
403
- return { kind: "reply", response: { status: response.status, headers: headerPairs(response), body: { kind: "empty" } } };
404
- } finally {
405
- if (!completed) {
406
- void Promise.resolve().then(() => reader?.cancel?.()).catch(() => void 0);
407
- }
408
- void Promise.resolve().then(() => reader?.releaseLock?.()).catch(() => void 0);
409
- }
410
- });
411
- }
412
- var BEACON_UNAVAILABLE = "browser/beacon: this host has no beacon port";
413
- async function sendBeaconRequest(ports, request, signal) {
414
- if (ports.beacon === void 0) return { ok: { via: "unavailable", message: BEACON_UNAVAILABLE } };
415
- if (request.body.kind !== "text") throw new Error("a beacon request carries a text body");
416
- signal?.throwIfAborted();
417
- const delivery = deliverBeacon(request.url, request.body.text, ports.beacon).then((taken) => taken.via === "fetch" && taken.status === null ? { error: { kind: "failed", message: "the beacon fetch failed" } } : { ok: taken.via === "queue" ? { via: "queue" } : { via: "fetch", status: taken.status ?? 0 } });
418
- return signal !== void 0 ? untilAborted(signal, delivery) : delivery;
419
- }
420
- function isOAuthCode(value) {
421
- return value === "AUTH_ERROR" || value === "VALIDATION_ERROR" || value === "NOT_CONFIGURED" || value === "SERVICE_ERROR" || value === "NETWORK_ERROR";
422
- }
423
- function isOAuthReason(value) {
424
- switch (value) {
425
- case "state-unknown":
426
- case "state-expired":
427
- case "subject-mismatch":
428
- case "provider-mismatch":
429
- case "not-signed-in":
430
- case "store-unavailable":
431
- case "metadata-invalid":
432
- case "response-invalid":
433
- case "token-rejected":
434
- case "userinfo-mismatch":
435
- case "unconfigured-client":
436
- return true;
437
- default:
438
- return false;
439
- }
440
- }
441
- function unavailableFailure(error, key) {
442
- return { error, kind: "unavailable", key, credential: null, phase: null, grantStatus: null, grantBody: null, code: null, reason: null };
443
- }
444
- function decodeFailurePayload(value) {
445
- const payload = record(value, "a failure payload");
446
- const { error, kind, key, credential, phase, grantStatus, grantBody, code, reason } = payload;
447
- const malformed = () => {
448
- throw new Error("a failure payload is malformed");
449
- };
450
- if (typeof error !== "string" || key !== null && typeof key !== "string") return malformed();
451
- if (phase !== null && phase !== "grant" && phase !== "request") return malformed();
452
- if (grantStatus !== null && typeof grantStatus !== "number") return malformed();
453
- if (grantBody !== null && typeof grantBody !== "string") return malformed();
454
- if (kind === "oauth") {
455
- if (credential !== null || phase !== null || grantStatus !== null || grantBody !== null) return malformed();
456
- if (!isOAuthCode(code) || !isOAuthReason(reason)) return malformed();
457
- return { ...payload, error, kind, key, credential, phase, grantStatus, grantBody, code, reason };
458
- }
459
- if (code !== null || reason !== null) return malformed();
460
- if (kind === "unconfigured" && typeof credential === "string") {
461
- return { ...payload, error, kind, key, credential, phase, grantStatus, grantBody, code, reason };
462
- }
463
- if ((kind === "timeout" || kind === "failed" || kind === "refused" || kind === "unavailable") && credential === null) {
464
- return { ...payload, error, kind, key, credential, phase, grantStatus, grantBody, code, reason };
465
- }
466
- return malformed();
467
- }
468
- function failureAnswer(failure) {
469
- switch (failure.kind) {
470
- case "timedOut":
471
- return { kind: "timedOut" };
472
- case "failed":
473
- case "refused":
474
- return { kind: failure.kind, message: failure.message };
475
- }
476
- }
477
- function exchangeAnswer(exchange) {
478
- return { kind: "http", result: exchange.kind === "reply" ? { ok: { ...exchange.response } } : { error: failureAnswer(exchange.failure) } };
479
- }
480
- function settledAnswer(kind, outcome) {
481
- return { kind, result: outcome };
482
- }
483
- function checkOAuthReply(reply) {
484
- switch (reply.reply) {
485
- case "done":
486
- case "flag":
487
- case "taken":
488
- case "row":
489
- case "subject":
490
- case "metadata":
491
- case "millis":
492
- case "mockToken":
493
- case "code":
494
- return reply;
495
- }
496
- }
497
- var OAUTH_UNAVAILABLE = "this host keeps no OAuth state";
498
- async function oauthAnswer(ports, ask, principal) {
499
- if (ports.oauth === void 0) return { kind: "oauth", result: { error: OAUTH_UNAVAILABLE } };
500
- try {
501
- return { kind: "oauth", result: { ok: checkOAuthReply(await ports.oauth.answer(ask, principal)) } };
502
- } catch (error) {
503
- return { kind: "oauth", result: { error: error instanceof Error ? error.message : String(error) } };
504
- }
505
- }
506
- function askOwner(ask, principal) {
507
- if (ask.scope === void 0 || ask.scope === "app") return { owner: void 0 };
508
- if (ask.scope !== "user") throw new Error(`driver ask "${String(ask.kind)}" has an unknown scope`);
509
- return principal === void 0 ? { error: "nobody is signed in" } : { owner: principal };
510
- }
511
- async function answerAsk(ports, ask, key, options) {
512
- const { kind } = ask;
513
- switch (kind) {
514
- case "secret": {
515
- if (typeof ask.name !== "string") throw new Error('driver ask "secret" has no name');
516
- const who = askOwner(ask, options.principal);
517
- if ("error" in who) return settledAnswer("secret", who);
518
- try {
519
- return settledAnswer("secret", { ok: await ports.secrets.get(ask.name, who.owner) ?? null });
520
- } catch (error) {
521
- return settledAnswer("secret", { error: error instanceof Error ? error.message : String(error) });
522
- }
523
- }
524
- case "secretSet": {
525
- if (typeof ask.name !== "string" || typeof ask.value !== "string" || typeof ask.ttlMs !== "number") throw new Error('driver ask "secretSet" is malformed');
526
- const who = askOwner(ask, options.principal);
527
- if ("error" in who) return settledAnswer("secretSet", who);
528
- try {
529
- await ports.secrets.set(ask.name, ask.value, ask.ttlMs, who.owner);
530
- return settledAnswer("secretSet", { ok: null });
531
- } catch (error) {
532
- return settledAnswer("secretSet", { error: error instanceof Error ? error.message : String(error) });
533
- }
534
- }
535
- case "secretRotate": {
536
- if (typeof ask.name !== "string" || typeof ask.value !== "string") throw new Error('driver ask "secretRotate" is malformed');
537
- const who = askOwner(ask, options.principal);
538
- if ("error" in who) return settledAnswer("secretRotate", who);
539
- try {
540
- if (ports.secrets.rotate === void 0) throw new Error("this host keeps no rotatable credentials");
541
- await ports.secrets.rotate(ask.name, ask.value, who.owner);
542
- return settledAnswer("secretRotate", { ok: null });
543
- } catch (error) {
544
- return settledAnswer("secretRotate", { error: error instanceof Error ? error.message : String(error) });
545
- }
546
- }
547
- case "oauth":
548
- return oauthAnswer(ports, decodeOAuthAsk(ask.ask), options.principal);
549
- case "random": {
550
- if (typeof ask.bytes !== "number" || !Number.isInteger(ask.bytes) || ask.bytes < 0) throw new Error('driver ask "random" is malformed');
551
- try {
552
- return settledAnswer("random", { ok: base64Standard(ports.random(ask.bytes)) });
553
- } catch (error) {
554
- return settledAnswer("random", { error: error instanceof Error ? error.message : String(error) });
555
- }
556
- }
557
- case "http": {
558
- const delayMs = ask.delayMs;
559
- if (delayMs !== void 0 && typeof delayMs !== "number") throw new Error('driver ask "http" has a malformed delayMs');
560
- return exchangeAnswer(await sendHttp(ports, decodeHttpRequest(askRequest(ask)), options.signal, delayMs));
561
- }
562
- case "beacon": {
563
- return { kind: "beacon", result: await sendBeaconRequest(ports, decodeHttpRequest(askRequest(ask)), options.signal) };
564
- }
565
- case "httpStream": {
566
- const framing = ask.framing;
567
- if (framing !== "sse" && framing !== "jsonLines") throw new Error('driver ask "httpStream" has an unknown framing');
568
- const onEvent = options.onMessage ?? (() => void 0);
569
- return exchangeAnswer(await streamHttp(ports, decodeHttpRequest(askRequest(ask)), { framing, key }, onEvent, options.signal));
570
- }
571
- default:
572
- throw new Error(`driver asked for unknown "${String(kind)}"`);
573
- }
574
- }
575
- function askRequest(ask) {
576
- const request = ask.request;
577
- if (request === void 0) throw new Error(`driver ask "${String(ask.kind)}" has no request`);
578
- return request;
579
- }
580
- async function runHttpCall(ports, call, options = {}) {
581
- if (call.delivery === "beacon" && ports.beacon === void 0) return { error: unavailableFailure(BEACON_UNAVAILABLE, call.key ?? null) };
582
- const kernel = await ports.kernel();
583
- const key = call.key ?? null;
584
- const started = options.principal !== void 0 ? { ...call, principal: options.principal } : call;
585
- let progress = record(parsed(kernel.httpDriverStart(JSON.stringify(started), JSON.stringify(ports.egress))), "httpDriverStart result");
586
- for (; ; ) {
587
- const step = record(progress.step ?? null, "the driver step");
588
- if (step.kind === "done") {
589
- const result = record(step.result ?? null, "the driver result");
590
- if (result.ok !== void 0) return { ok: result.ok };
591
- if (result.error !== void 0) return { error: decodeFailurePayload(result.error) };
592
- throw new Error("the driver finished with neither ok nor error");
593
- }
594
- if (step.kind !== "ask") throw new Error(`the driver step "${String(step.kind)}" is unknown`);
595
- const driver = JSON.stringify(progress.driver ?? null);
596
- try {
597
- const answer = await answerAsk(ports, record(step.ask ?? null, "the driver ask"), key, options);
598
- progress = record(parsed(kernel.httpDriverResume(driver, JSON.stringify(answer))), "httpDriverResume result");
599
- } catch (error) {
600
- kernel.httpDriverDrop(driver);
601
- throw error;
602
- }
603
- }
604
- }
605
-
606
- export { HttpEffectFailure, HttpUnavailableError, RANDOM_BYTES_MAX, base64Standard, base64Url, checkOAuthReply, createBrowserHttpPorts, createCredentialAdminPort, createHttpPorts, createHttpSecrets, credentialForgetPayload, credentialStatusPayload, installNetPort, isOAuthCode, isOAuthReason, randomBytesPayload, runHttpCall, sendBeaconRequest, sendHttp, streamHttp, systemRandom, unavailableFailure, userCredentialKey };