devframe 0.9.0-beta.7 → 0.9.0-beta.9

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 (73) hide show
  1. package/dist/{_shared-QkI6ljJS.d.mts → _shared-BPmX9fqK.d.mts} +1 -1
  2. package/dist/adapters/build.d.mts +2 -2
  3. package/dist/adapters/build.mjs +6 -6
  4. package/dist/adapters/cac.d.mts +1 -1
  5. package/dist/adapters/cac.mjs +2 -2
  6. package/dist/adapters/dev.d.mts +4 -4
  7. package/dist/adapters/dev.mjs +1 -1
  8. package/dist/adapters/embedded.d.mts +1 -1
  9. package/dist/adapters/initiate.d.mts +3 -3
  10. package/dist/adapters/initiate.mjs +1 -1
  11. package/dist/adapters/mcp.d.mts +1 -1
  12. package/dist/adapters/mcp.mjs +1 -1
  13. package/dist/cli/main.mjs +3 -3
  14. package/dist/client/index.d.mts +1 -1
  15. package/dist/client/index.mjs +22 -3
  16. package/dist/constants.d.mts +10 -1
  17. package/dist/constants.mjs +10 -1
  18. package/dist/{context-CQkRTbAc.d.mts → context-B3YUu_95.d.mts} +1 -1
  19. package/dist/{context-D0HD0F7C.mjs → context-CEe4PBz1.mjs} +7 -300
  20. package/dist/{context-D0jErmlx.mjs → context-xdynGSLP.mjs} +1 -1
  21. package/dist/{dev-QEuT8SOF.mjs → dev-Chvlqs7I.mjs} +5 -5
  22. package/dist/{devframe-Cfx6doi4.d.mts → devframe-DJMg0WLe.d.mts} +7 -16
  23. package/dist/{diagnostics-hwjXp_UV.mjs → diagnostics-CD8nlgll.mjs} +1 -3
  24. package/dist/{diagnostics-DEuH3P5O.mjs → diagnostics-DOQPnQmX.mjs} +1 -3
  25. package/dist/{host-agent-C5HjzfBz.mjs → host-agent-xLCSe65D.mjs} +1 -1
  26. package/dist/{http-CVwj7b4g.mjs → http-8Kpkap4_.mjs} +4 -4
  27. package/dist/{index-MYi1SZVL.d.mts → index-CB-fSUyn.d.mts} +2 -2
  28. package/dist/index.d.mts +4 -3
  29. package/dist/{instance-registry-M2p-z6xE.mjs → instance-registry-WvQkt42E.mjs} +1 -1
  30. package/dist/{instance-shell-D_UA0Idz.d.mts → instance-shell-CljiKq1c.d.mts} +2 -2
  31. package/dist/{instance-shell-DJ8s-MFw.mjs → instance-shell-XvN5USg4.mjs} +4 -4
  32. package/dist/internal/index.d.mts +8 -13
  33. package/dist/internal/index.mjs +6 -6
  34. package/dist/node/auth.d.mts +2 -2
  35. package/dist/node/hub-internals.d.mts +2 -2
  36. package/dist/node/hub-internals.mjs +1 -1
  37. package/dist/node/index.d.mts +1 -1
  38. package/dist/node/index.mjs +2 -2
  39. package/dist/nostics-CzECRXpE.mjs +59 -0
  40. package/dist/nostics-SPGDgHEP.d.mts +33 -0
  41. package/dist/recipes/common-rpc-functions.d.mts +1 -1
  42. package/dist/recipes/interactive-auth.d.mts +2 -2
  43. package/dist/recipes/interactive-auth.mjs +2 -2
  44. package/dist/{remote-assets-DclsYyoL.d.mts → remote-assets-Bg4gCUZ_.d.mts} +19 -2
  45. package/dist/remote-assets-nTTxY2MU.mjs +636 -0
  46. package/dist/rpc/dump.mjs +1 -1
  47. package/dist/rpc/index.mjs +3 -3
  48. package/dist/rpc/transports/sse-client.mjs +1 -1
  49. package/dist/rpc/transports/sse-server.mjs +2 -2
  50. package/dist/rpc/transports/ws-bun.d.mts +1 -1
  51. package/dist/rpc/transports/ws-bun.mjs +1 -1
  52. package/dist/rpc/transports/ws-client.mjs +1 -1
  53. package/dist/rpc/transports/ws-server.mjs +1 -1
  54. package/dist/{rpc-core-C8JQ3p7A.d.mts → rpc-core-Cc4lucI0.d.mts} +2 -2
  55. package/dist/{rpc-core-IhcWl_xn.mjs → rpc-core-DMTe-hLo.mjs} +1 -1
  56. package/dist/{serialization-BHY8M5NQ.mjs → serialization-BGzEwAdr.mjs} +1 -1
  57. package/dist/{static-CvjkO8QE.mjs → static-BPZ1_OPA.mjs} +2 -2
  58. package/dist/{storage-BVuipbGS.mjs → storage-CYye7P7L.mjs} +1 -1
  59. package/dist/types/index.d.mts +4 -3
  60. package/dist/utils/events.d.mts +1 -1
  61. package/dist/utils/nostics.d.mts +2 -0
  62. package/dist/utils/nostics.mjs +2 -0
  63. package/dist/utils/remote-assets.d.mts +1 -1
  64. package/dist/utils/remote-assets.mjs +1 -308
  65. package/dist/utils/serve-static.d.mts +1 -1
  66. package/dist/utils/serve-static.mjs +16 -0
  67. package/dist/utils/shared-state.d.mts +1 -1
  68. package/dist/utils/streaming-channel.d.mts +1 -1
  69. package/dist/{validation-BiuDXTKW.mjs → validation-CpXFB6Dz.mjs} +1 -1
  70. package/dist/{wire-codec-9VhIKnyp.mjs → wire-codec-GsoRxIsD.mjs} +1 -1
  71. package/dist/{ws-server-Bk1hOG3X.mjs → ws-server-BiUne4K7.mjs} +1 -1
  72. package/package.json +3 -2
  73. package/dist/diagnostics-reporter-CsIG85Q5.mjs +0 -38
@@ -0,0 +1,636 @@
1
+ import { t as diagnostics } from "./diagnostics-DOQPnQmX.mjs";
2
+ import { createRequire } from "node:module";
3
+ import { isatty } from "node:tty";
4
+ import { formatWithOptions, inspect } from "node:util";
5
+ import { createReadStream, existsSync } from "node:fs";
6
+ import { Buffer } from "node:buffer";
7
+ import { mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
8
+ import { Readable } from "node:stream";
9
+ import { lookup } from "mrmime";
10
+ import { dirname, extname, join, normalize, sep } from "pathe";
11
+ //#region ../../node_modules/.pnpm/obug@2.1.4/node_modules/obug/dist/core.js
12
+ /**
13
+ * Coerce `value`.
14
+ */
15
+ function coerce(value) {
16
+ if (value instanceof Error) return value.stack || value.message;
17
+ return value;
18
+ }
19
+ /**
20
+ * Selects a color for a debug namespace
21
+ * @return An ANSI color code for the given namespace
22
+ */
23
+ function selectColor(colors, namespace) {
24
+ let hash = 0;
25
+ for (let i = 0; i < namespace.length; i++) {
26
+ hash = (hash << 5) - hash + namespace.charCodeAt(i);
27
+ hash |= 0;
28
+ }
29
+ return colors[Math.abs(hash) % colors.length];
30
+ }
31
+ /**
32
+ * Checks if the given string matches a namespace template, honoring
33
+ * asterisks as wildcards.
34
+ */
35
+ function matchesTemplate(search, template) {
36
+ let searchIndex = 0;
37
+ let templateIndex = 0;
38
+ let starIndex = -1;
39
+ let matchIndex = 0;
40
+ while (searchIndex < search.length) if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === "*")) if (template[templateIndex] === "*") {
41
+ starIndex = templateIndex;
42
+ matchIndex = searchIndex;
43
+ templateIndex++;
44
+ } else {
45
+ searchIndex++;
46
+ templateIndex++;
47
+ }
48
+ else if (starIndex !== -1) {
49
+ templateIndex = starIndex + 1;
50
+ matchIndex++;
51
+ searchIndex = matchIndex;
52
+ } else return false;
53
+ while (templateIndex < template.length && template[templateIndex] === "*") templateIndex++;
54
+ return templateIndex === template.length;
55
+ }
56
+ function humanize(value) {
57
+ if (value >= 1e3) return `${(value / 1e3).toFixed(1)}s`;
58
+ return `${value}ms`;
59
+ }
60
+ let globalNamespaces = "";
61
+ function createDebug$1(namespace, options) {
62
+ let prevTime;
63
+ let enableOverride;
64
+ let namespacesCache;
65
+ let enabledCache;
66
+ const debug = (...args) => {
67
+ if (!debug.enabled) return;
68
+ const curr = Date.now();
69
+ const diff = curr - (prevTime || curr);
70
+ prevTime = curr;
71
+ args[0] = coerce(args[0]);
72
+ if (typeof args[0] !== "string") args.unshift("%O");
73
+ let index = 0;
74
+ args[0] = args[0].replace(/%([a-z%])/gi, (match, format) => {
75
+ if (match === "%%") return "%";
76
+ index++;
77
+ const formatter = options.formatters[format];
78
+ if (typeof formatter === "function") {
79
+ const value = args[index];
80
+ match = formatter.call(debug, value);
81
+ args.splice(index, 1);
82
+ index--;
83
+ }
84
+ return match;
85
+ });
86
+ options.formatArgs.call(debug, diff, args);
87
+ debug.log(...args);
88
+ };
89
+ debug.extend = function(namespace, delimiter = ":") {
90
+ return createDebug$1(this.namespace + delimiter + namespace, {
91
+ useColors: this.useColors,
92
+ color: this.color,
93
+ formatArgs: this.formatArgs,
94
+ formatters: this.formatters,
95
+ inspectOpts: this.inspectOpts,
96
+ log: this.log,
97
+ humanize: this.humanize
98
+ });
99
+ };
100
+ Object.assign(debug, options);
101
+ debug.namespace = namespace;
102
+ Object.defineProperty(debug, "enabled", {
103
+ enumerable: true,
104
+ configurable: false,
105
+ get: () => {
106
+ if (enableOverride != null) return enableOverride;
107
+ if (namespacesCache !== globalNamespaces) {
108
+ namespacesCache = globalNamespaces;
109
+ enabledCache = enabled(namespace);
110
+ }
111
+ return enabledCache;
112
+ },
113
+ set: (v) => {
114
+ enableOverride = v;
115
+ }
116
+ });
117
+ return debug;
118
+ }
119
+ let names = [];
120
+ let skips = [];
121
+ function enable(namespaces) {
122
+ globalNamespaces = namespaces;
123
+ names = [];
124
+ skips = [];
125
+ const split = globalNamespaces.trim().replace(/\s+/g, ",").split(",").filter(Boolean);
126
+ for (const ns of split) if (ns[0] === "-") skips.push(ns.slice(1));
127
+ else names.push(ns);
128
+ }
129
+ /**
130
+ * Returns true if the given mode name is enabled, false otherwise.
131
+ */
132
+ function enabled(name) {
133
+ for (const skip of skips) if (matchesTemplate(name, skip)) return false;
134
+ for (const ns of names) if (matchesTemplate(name, ns)) return true;
135
+ return false;
136
+ }
137
+ //#endregion
138
+ //#region ../../node_modules/.pnpm/obug@2.1.4/node_modules/obug/dist/node.js
139
+ let env = {};
140
+ try {
141
+ process.env.DEBUG;
142
+ env = process.env;
143
+ } catch (_unused) {}
144
+ const colors = process.stderr.getColorDepth && process.stderr.getColorDepth(env) > 2 ? [
145
+ 20,
146
+ 21,
147
+ 26,
148
+ 27,
149
+ 32,
150
+ 33,
151
+ 38,
152
+ 39,
153
+ 40,
154
+ 41,
155
+ 42,
156
+ 43,
157
+ 44,
158
+ 45,
159
+ 56,
160
+ 57,
161
+ 62,
162
+ 63,
163
+ 68,
164
+ 69,
165
+ 74,
166
+ 75,
167
+ 76,
168
+ 77,
169
+ 78,
170
+ 79,
171
+ 80,
172
+ 81,
173
+ 92,
174
+ 93,
175
+ 98,
176
+ 99,
177
+ 112,
178
+ 113,
179
+ 128,
180
+ 129,
181
+ 134,
182
+ 135,
183
+ 148,
184
+ 149,
185
+ 160,
186
+ 161,
187
+ 162,
188
+ 163,
189
+ 164,
190
+ 165,
191
+ 166,
192
+ 167,
193
+ 168,
194
+ 169,
195
+ 170,
196
+ 171,
197
+ 172,
198
+ 173,
199
+ 178,
200
+ 179,
201
+ 184,
202
+ 185,
203
+ 196,
204
+ 197,
205
+ 198,
206
+ 199,
207
+ 200,
208
+ 201,
209
+ 202,
210
+ 203,
211
+ 204,
212
+ 205,
213
+ 206,
214
+ 207,
215
+ 208,
216
+ 209,
217
+ 214,
218
+ 215,
219
+ 220,
220
+ 221
221
+ ] : [
222
+ 6,
223
+ 2,
224
+ 3,
225
+ 4,
226
+ 5,
227
+ 1
228
+ ];
229
+ const inspectOpts = Object.keys(env).filter((key) => /^debug_/i.test(key)).reduce((obj, key) => {
230
+ const prop = key.slice(6).toLowerCase().replace(/_([a-z])/g, (_, k) => k.toUpperCase());
231
+ let value = env[key];
232
+ const lowerCase = typeof value === "string" && value.toLowerCase();
233
+ if (value === "null") value = null;
234
+ else if (lowerCase === "yes" || lowerCase === "on" || lowerCase === "true" || lowerCase === "enabled") value = true;
235
+ else if (lowerCase === "no" || lowerCase === "off" || lowerCase === "false" || lowerCase === "disabled") value = false;
236
+ else value = Number(value);
237
+ obj[prop] = value;
238
+ return obj;
239
+ }, Object.create(null));
240
+ /**
241
+ * Is stdout a TTY? Colored output is enabled when `true`.
242
+ */
243
+ function useColors() {
244
+ return "colors" in inspectOpts ? Boolean(inspectOpts.colors) : isatty(process.stderr.fd);
245
+ }
246
+ function getDate() {
247
+ if (inspectOpts.hideDate) return "";
248
+ return `${(/* @__PURE__ */ new Date()).toISOString()} `;
249
+ }
250
+ /**
251
+ * Adds ANSI color escape codes if enabled.
252
+ */
253
+ function formatArgs(diff, args) {
254
+ const { namespace: name, useColors } = this;
255
+ if (useColors) {
256
+ const c = this.color;
257
+ const colorCode = `\u001B[3${c < 8 ? c : `8;5;${c}`}`;
258
+ const prefix = ` ${colorCode};1m${name} \u001B[0m`;
259
+ args[0] = prefix + args[0].split("\n").join(`\n${prefix}`);
260
+ args.push(`${colorCode}m+${this.humanize(diff)}\u001B[0m`);
261
+ } else args[0] = `${getDate()}${name} ${args[0]}`;
262
+ }
263
+ function log(...args) {
264
+ process.stderr.write(`${formatWithOptions(this.inspectOpts, ...args)}\n`);
265
+ }
266
+ const defaultOptions = {
267
+ useColors: useColors(),
268
+ formatArgs,
269
+ formatters: {
270
+ /**
271
+ * Map %o to `util.inspect()`, all on a single line.
272
+ */
273
+ o(v) {
274
+ this.inspectOpts.colors = this.useColors;
275
+ return inspect(v, this.inspectOpts).split("\n").map((str) => str.trim()).join(" ");
276
+ },
277
+ /**
278
+ * Map %O to `util.inspect()`, allowing multiple lines if needed.
279
+ */
280
+ O(v) {
281
+ this.inspectOpts.colors = this.useColors;
282
+ return inspect(v, this.inspectOpts);
283
+ }
284
+ },
285
+ inspectOpts,
286
+ log,
287
+ humanize
288
+ };
289
+ function createDebug(namespace, options) {
290
+ var _ref;
291
+ const color = (_ref = options && options.color) !== null && _ref !== void 0 ? _ref : selectColor(colors, namespace);
292
+ return createDebug$1(namespace, Object.assign(defaultOptions, { color }, options));
293
+ }
294
+ enable(env.DEBUG || "");
295
+ //#endregion
296
+ //#region src/utils/remote-assets.ts
297
+ const debugFetch = createDebug("devframe:remote-assets:fetch");
298
+ const debugCache = createDebug("devframe:remote-assets:cache");
299
+ const MANIFEST_FILENAME = ".manifest.json";
300
+ /**
301
+ * Upstream response headers replayed to the browser. Everything outside this
302
+ * list is dropped, because it describes the *provider's* transfer rather than
303
+ * the file: hop-by-hop and encoding headers no longer match the body `fetch`
304
+ * already decoded, and a CDN's policy headers (`set-cookie`, `cache-control`,
305
+ * framing/CSP) belong to its origin — replaying them under the dev server's
306
+ * origin could just as well break the iframe these assets render in.
307
+ */
308
+ const PROXIED_HEADERS = [
309
+ "content-language",
310
+ "etag",
311
+ "last-modified"
312
+ ];
313
+ const CACHE_CONTROL_HEADER = "no-store";
314
+ /** Flatten a jsDelivr (`name`/`files`) or unpkg (`path`/`files`) file tree. */
315
+ function flattenTree(nodes, style) {
316
+ const out = [];
317
+ const walk = (list, prefix) => {
318
+ for (const node of list) if (style === "path") if (node.type === "file") out.push((node.path ?? "").replace(/^\//, ""));
319
+ else walk(node.files ?? [], "");
320
+ else if (node.type === "file") out.push(prefix + (node.name ?? ""));
321
+ else if (node.files) walk(node.files, `${prefix}${node.name}/`);
322
+ };
323
+ walk(nodes, "");
324
+ return out;
325
+ }
326
+ const providers = {
327
+ jsdelivr: {
328
+ fileUrl: (pkg, version, filePath) => `https://cdn.jsdelivr.net/npm/${pkg}@${version}/${filePath}`,
329
+ listFiles: async (pkg, version, fetchImpl) => {
330
+ const url = `https://data.jsdelivr.com/v1/packages/npm/${pkg}@${version}`;
331
+ debugFetch("listing files for %s@%s from %s", pkg, version, url);
332
+ const res = await fetchImpl(url);
333
+ if (!res.ok) throw new Error(`HTTP ${res.status} from ${url}`);
334
+ return flattenTree((await res.json()).files ?? [], "name");
335
+ }
336
+ },
337
+ unpkg: {
338
+ fileUrl: (pkg, version, filePath) => `https://unpkg.com/${pkg}@${version}/${filePath}`,
339
+ listFiles: async (pkg, version, fetchImpl) => {
340
+ const url = `https://unpkg.com/${pkg}@${version}/?meta`;
341
+ debugFetch("listing files for %s@%s from %s", pkg, version, url);
342
+ const res = await fetchImpl(url);
343
+ if (!res.ok) throw new Error(`HTTP ${res.status} from ${url}`);
344
+ return flattenTree([await res.json()], "path");
345
+ }
346
+ }
347
+ };
348
+ function resolveProvider(assets) {
349
+ const p = assets.provider ?? "jsdelivr";
350
+ return typeof p === "string" ? {
351
+ provider: providers[p],
352
+ name: p
353
+ } : {
354
+ provider: p,
355
+ name: "custom"
356
+ };
357
+ }
358
+ /**
359
+ * Resolve a locally installed copy of `assets.package` from
360
+ * `assets.resolveFrom`'s dependency graph and return its assets directory,
361
+ * or `undefined` when the package (or directory) is absent. A different
362
+ * installed version warns (`DF0062`); a different major throws (`DF0061`).
363
+ */
364
+ function resolveInstalled(assets) {
365
+ if (assets.resolveFrom == null) return void 0;
366
+ let pkgJsonPath;
367
+ let installed;
368
+ try {
369
+ const requireFrom = createRequire(assets.resolveFrom);
370
+ pkgJsonPath = requireFrom.resolve(`${assets.package}/package.json`);
371
+ installed = requireFrom(`${assets.package}/package.json`).version;
372
+ } catch {
373
+ return;
374
+ }
375
+ if (typeof installed !== "string") return void 0;
376
+ if (installed !== assets.version) {
377
+ const major = (v) => v.trim().split(".")[0] ?? v;
378
+ if (major(installed) !== major(assets.version)) throw diagnostics.DF0061({
379
+ package: assets.package,
380
+ required: assets.version,
381
+ installed
382
+ });
383
+ diagnostics.DF0062({
384
+ package: assets.package,
385
+ required: assets.version,
386
+ installed
387
+ });
388
+ }
389
+ const dir = join(dirname(pkgJsonPath), assets.path ?? "dist");
390
+ return existsSync(dir) ? dir : void 0;
391
+ }
392
+ function contentTypeFor(filePath) {
393
+ const type = lookup(filePath);
394
+ if (!type) return "application/octet-stream";
395
+ return type === "text/html" ? "text/html; charset=utf-8" : type;
396
+ }
397
+ /**
398
+ * Headers for a file streamed through from the provider. `Content-Type` and
399
+ * `Cache-Control` are ours, so a file looks identical whether it came from the
400
+ * provider or from the cache ({@link createStore}'s `serveCached`).
401
+ */
402
+ function proxyHeaders(filePath, upstream) {
403
+ const headers = new Headers({
404
+ "Content-Type": contentTypeFor(filePath),
405
+ "Cache-Control": CACHE_CONTROL_HEADER
406
+ });
407
+ const encoding = upstream.get("content-encoding");
408
+ const length = upstream.get("content-length");
409
+ if (length && (!encoding || encoding === "identity")) headers.set("Content-Length", length);
410
+ for (const name of PROXIED_HEADERS) {
411
+ const value = upstream.get(name);
412
+ if (value != null) headers.set(name, value);
413
+ }
414
+ return headers;
415
+ }
416
+ /** Clean a request path into a safe package-relative POSIX path, or `null` if it escapes root. */
417
+ function cleanRequestPath(urlPath) {
418
+ let cleaned;
419
+ try {
420
+ cleaned = decodeURIComponent(urlPath || "/");
421
+ } catch {
422
+ return null;
423
+ }
424
+ cleaned = cleaned.replace(/[?#].*$/, "").replace(/^\/+|\/+$/g, "");
425
+ const normalized = normalize(cleaned);
426
+ if (normalized === ".." || normalized.startsWith(`..${sep}`) || normalized.startsWith("/")) return null;
427
+ return normalized === "." ? "" : normalized;
428
+ }
429
+ /** Candidate files for a request, in order: direct hit, index, `.html`, SPA fallback. */
430
+ function candidatePaths(prefix, cleaned) {
431
+ const candidates = [];
432
+ if (cleaned) candidates.push(prefix + cleaned);
433
+ candidates.push(`${prefix}${cleaned ? `${cleaned}/` : ""}index.html`);
434
+ if (cleaned && !extname(cleaned)) candidates.push(`${prefix + cleaned}.html`);
435
+ if (!/\.[a-z0-9]+$/i.test(cleaned) && !candidates.includes(`${prefix}index.html`)) candidates.push(`${prefix}index.html`);
436
+ return candidates;
437
+ }
438
+ function createStore(assets, cacheDir) {
439
+ const normalized = {
440
+ ...assets,
441
+ path: assets.path ?? "dist"
442
+ };
443
+ const { provider, name: providerName } = resolveProvider(assets);
444
+ const fetchImpl = assets.fetch ?? globalThis.fetch;
445
+ const prefix = `${normalized.path}/`;
446
+ let manifestPromise;
447
+ let manifestReported = false;
448
+ async function loadManifest() {
449
+ const manifestFile = join(cacheDir, MANIFEST_FILENAME);
450
+ if (existsSync(manifestFile)) try {
451
+ return new Set(JSON.parse(await readFile(manifestFile, "utf8")));
452
+ } catch {}
453
+ if (assets.offline || !provider.listFiles) return null;
454
+ try {
455
+ const files = await provider.listFiles(normalized.package, normalized.version, fetchImpl);
456
+ await mkdir(cacheDir, { recursive: true });
457
+ await writeFile(manifestFile, JSON.stringify(files), "utf8").catch(() => {});
458
+ return new Set(files);
459
+ } catch (error) {
460
+ if (!manifestReported) {
461
+ manifestReported = true;
462
+ diagnostics.DF0059({
463
+ package: normalized.package,
464
+ version: normalized.version,
465
+ provider: providerName,
466
+ reason: errText(error),
467
+ cause: error
468
+ });
469
+ }
470
+ return null;
471
+ }
472
+ }
473
+ async function serveCached(filePath) {
474
+ const abs = join(cacheDir, filePath);
475
+ let size;
476
+ try {
477
+ const s = await stat(abs);
478
+ if (!s.isFile()) return null;
479
+ size = s.size;
480
+ } catch {
481
+ return null;
482
+ }
483
+ debugCache("serving %s from cache (%d bytes)", filePath, size);
484
+ return new Response(Readable.toWeb(createReadStream(abs)), { headers: {
485
+ "Content-Type": contentTypeFor(filePath),
486
+ "Content-Length": String(size),
487
+ "Cache-Control": CACHE_CONTROL_HEADER
488
+ } });
489
+ }
490
+ /** Persist `body` to the cache at `filePath` (tmp + rename); failures warn (`DF0063`). */
491
+ async function persist(filePath, body) {
492
+ const target = join(cacheDir, filePath);
493
+ const tmp = `${target}.${Math.random().toString(36).slice(2)}.tmp`;
494
+ try {
495
+ await mkdir(dirname(target), { recursive: true });
496
+ await writeFile(tmp, Buffer.from(await new Response(body).arrayBuffer()));
497
+ await rename(tmp, target);
498
+ } catch (error) {
499
+ await rm(tmp, { force: true }).catch(() => {});
500
+ diagnostics.DF0063({
501
+ filepath: target,
502
+ reason: errText(error),
503
+ cause: error
504
+ });
505
+ }
506
+ }
507
+ /** Fetch `filePath` through the provider: `null` on 404, a `Response` on 200, throws (`DF0060`) otherwise. */
508
+ async function serveRemote(filePath) {
509
+ const url = provider.fileUrl(normalized.package, normalized.version, filePath);
510
+ let res;
511
+ try {
512
+ debugFetch("fetching %s from %s", filePath, url);
513
+ res = await fetchImpl(url);
514
+ } catch (error) {
515
+ throw diagnostics.DF0060({
516
+ url,
517
+ package: normalized.package,
518
+ reason: errText(error),
519
+ cause: error
520
+ });
521
+ }
522
+ if (res.status === 404) {
523
+ await res.body?.cancel().catch(() => {});
524
+ return null;
525
+ }
526
+ if (!res.ok || !res.body) {
527
+ await res.body?.cancel().catch(() => {});
528
+ throw diagnostics.DF0060({
529
+ url,
530
+ package: normalized.package,
531
+ reason: `HTTP ${res.status}`
532
+ });
533
+ }
534
+ const [toClient, toCache] = res.body.tee();
535
+ persist(filePath, toCache);
536
+ return new Response(toClient, {
537
+ status: res.status,
538
+ statusText: res.statusText,
539
+ headers: proxyHeaders(filePath, res.headers)
540
+ });
541
+ }
542
+ async function serve(urlPath) {
543
+ const cleaned = cleanRequestPath(urlPath);
544
+ if (cleaned === null) return null;
545
+ const candidates = candidatePaths(prefix, cleaned);
546
+ manifestPromise ??= loadManifest();
547
+ const manifest = await manifestPromise;
548
+ if (manifest) {
549
+ const filePath = candidates.find((c) => manifest.has(c));
550
+ if (!filePath) return null;
551
+ return await serveCached(filePath) ?? (assets.offline ? Promise.reject(diagnostics.DF0060({
552
+ url: filePath,
553
+ package: normalized.package,
554
+ reason: "offline: true and the file is not in the cache"
555
+ })) : serveRemote(filePath));
556
+ }
557
+ for (const candidate of candidates) {
558
+ const cached = await serveCached(candidate);
559
+ if (cached) return cached;
560
+ }
561
+ if (assets.offline) return null;
562
+ for (const candidate of candidates) {
563
+ const remote = await serveRemote(candidate);
564
+ if (remote) return remote;
565
+ }
566
+ return null;
567
+ }
568
+ async function materialize(targetDir) {
569
+ const fail = (reason, cause) => {
570
+ throw diagnostics.DF0064({
571
+ package: normalized.package,
572
+ version: normalized.version,
573
+ reason,
574
+ cause
575
+ });
576
+ };
577
+ if (!provider.listFiles) fail("the configured provider has no file listing (`listFiles`)");
578
+ let files;
579
+ try {
580
+ files = await provider.listFiles(normalized.package, normalized.version, fetchImpl);
581
+ } catch (error) {
582
+ return fail(errText(error), error);
583
+ }
584
+ for (const filePath of files.filter((f) => f.startsWith(prefix))) {
585
+ const target = join(targetDir, filePath.slice(prefix.length));
586
+ const url = provider.fileUrl(normalized.package, normalized.version, filePath);
587
+ let res;
588
+ try {
589
+ res = await fetchImpl(url);
590
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
591
+ } catch (error) {
592
+ return fail(`failed to download ${filePath}: ${errText(error)}`, error);
593
+ }
594
+ await mkdir(dirname(target), { recursive: true });
595
+ await writeFile(target, Buffer.from(await res.arrayBuffer()));
596
+ }
597
+ }
598
+ return {
599
+ assets: normalized,
600
+ serve,
601
+ materialize
602
+ };
603
+ }
604
+ function errText(error) {
605
+ return error instanceof Error ? error.message : String(error);
606
+ }
607
+ const PACKAGE_NAME_RE = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
608
+ const VERSION_RE = /^\d+\.\d+\.\d+(?:-[a-z0-9-]+(?:\.[a-z0-9-]+)*)?(?:\+[a-z0-9-]+(?:\.[a-z0-9-]+)*)?$/i;
609
+ /** Reject a {@link RemoteAssets} with an unsafe package name or version (`DF0065`). */
610
+ function assertValidRemoteAssets(assets) {
611
+ if (assets.package.length > 214 || !PACKAGE_NAME_RE.test(assets.package)) throw diagnostics.DF0065({
612
+ field: "package",
613
+ value: assets.package
614
+ });
615
+ if (!VERSION_RE.test(assets.version)) throw diagnostics.DF0065({
616
+ field: "version",
617
+ value: assets.version
618
+ });
619
+ }
620
+ /**
621
+ * Normalize a {@link StaticAssetsSource} into something servable: a local
622
+ * directory (strings pass through; a remote source short-circuits to a
623
+ * locally installed copy of its package when present) or a caching
624
+ * {@link RemoteAssetsStore} back-proxy. Remote caches live under
625
+ * `<projectStorageDir>/.remote-assets/<package>@<version>/`.
626
+ *
627
+ * A remote source's `package`/`version` are validated first (`DF0065`) — both
628
+ * are interpolated into CDN URLs and the cache path.
629
+ */
630
+ function resolveStaticAssetsSource(source, projectStorageDir) {
631
+ if (typeof source === "string") return source;
632
+ assertValidRemoteAssets(source);
633
+ return resolveInstalled(source) ?? createStore(source, join(projectStorageDir, ".remote-assets", `${source.package.replace(/\//g, "+")}@${source.version}`));
634
+ }
635
+ //#endregion
636
+ export { createDebug as n, resolveStaticAssetsSource as t };
package/dist/rpc/dump.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { a as reviveDumpError, i as getDefinitionsWithDumps, n as createClientFromDump, o as serializeDumpError, r as dumpFunctions, t as collectStaticRpcDump } from "../static-CvjkO8QE.mjs";
1
+ import { a as reviveDumpError, i as getDefinitionsWithDumps, n as createClientFromDump, o as serializeDumpError, r as dumpFunctions, t as collectStaticRpcDump } from "../static-BPZ1_OPA.mjs";
2
2
  export { collectStaticRpcDump, createClientFromDump, dumpFunctions, getDefinitionsWithDumps, reviveDumpError, serializeDumpError };
@@ -1,7 +1,7 @@
1
- import { a as validateRpcArgs, i as getRpcResolvedSetupResult, n as validateDefinitions, o as validateRpcReturn, r as getRpcHandler, s as hash, t as validateDefinition } from "../validation-BiuDXTKW.mjs";
2
- import { t as diagnostics } from "../diagnostics-hwjXp_UV.mjs";
1
+ import { a as validateRpcArgs, i as getRpcResolvedSetupResult, n as validateDefinitions, o as validateRpcReturn, r as getRpcHandler, s as hash, t as validateDefinition } from "../validation-CpXFB6Dz.mjs";
2
+ import { t as diagnostics } from "../diagnostics-CD8nlgll.mjs";
3
3
  import { n as defineRpcFunction, t as createDefineWrapperWithContext } from "../define-BLWPsH6y.mjs";
4
- import { n as strictJsonStringify, t as STRUCTURED_CLONE_PREFIX } from "../serialization-BHY8M5NQ.mjs";
4
+ import { n as strictJsonStringify, t as STRUCTURED_CLONE_PREFIX } from "../serialization-BGzEwAdr.mjs";
5
5
  //#region src/rpc/cache.ts
6
6
  /**
7
7
  * @experimental API is expected to change.
@@ -1,5 +1,5 @@
1
1
  import { DEVFRAME_AUTH_TOKEN_QUERY_PARAM, DEVFRAME_SSE_SESSION_HEADER } from "../../constants.mjs";
2
- import { t as createRpcWireCodec } from "../../wire-codec-9VhIKnyp.mjs";
2
+ import { t as createRpcWireCodec } from "../../wire-codec-GsoRxIsD.mjs";
3
3
  //#region src/rpc/transports/sse-client.ts
4
4
  function NOOP() {}
5
5
  /**
@@ -1,6 +1,6 @@
1
1
  import { DEVFRAME_SSE_SESSION_HEADER } from "../../constants.mjs";
2
- import { n as peekRpcWireFrame, t as createRpcWireCodec } from "../../wire-codec-9VhIKnyp.mjs";
3
- import { i as isAllowedOrigin, o as createRpcSessionMeta } from "../../ws-server-Bk1hOG3X.mjs";
2
+ import { n as peekRpcWireFrame, t as createRpcWireCodec } from "../../wire-codec-GsoRxIsD.mjs";
3
+ import { i as isAllowedOrigin, o as createRpcSessionMeta } from "../../ws-server-BiUne4K7.mjs";
4
4
  //#region src/rpc/transports/sse-server.ts
5
5
  const SSE_STREAM_HEADERS = {
6
6
  "content-type": "text/event-stream",
@@ -1,5 +1,5 @@
1
1
  import { n as WsOriginRegistry } from "../../ws-server-D1d3QM9f.mjs";
2
- import { t as ContextRpcServer } from "../../rpc-core-C8JQ3p7A.mjs";
2
+ import { t as ContextRpcServer } from "../../rpc-core-Cc4lucI0.mjs";
3
3
  //#region src/rpc/transports/ws-bun.d.ts
4
4
  interface AttachBunWsTransportOptions {
5
5
  /** Same contract as `WsRpcTransportOptions.allowedOrigins`. */
@@ -1,4 +1,4 @@
1
- import { i as isAllowedOrigin, r as createWsRpcPeerHooks } from "../../ws-server-Bk1hOG3X.mjs";
1
+ import { i as isAllowedOrigin, r as createWsRpcPeerHooks } from "../../ws-server-BiUne4K7.mjs";
2
2
  //#region src/rpc/transports/ws-bun.ts
3
3
  /**
4
4
  * The Bun fetch-upgrade WebSocket tier for `initDevframe` / `initHub` — the
@@ -1,5 +1,5 @@
1
1
  import { DEVFRAME_AUTH_TOKEN_QUERY_PARAM } from "../../constants.mjs";
2
- import { t as createRpcWireCodec } from "../../wire-codec-9VhIKnyp.mjs";
2
+ import { t as createRpcWireCodec } from "../../wire-codec-GsoRxIsD.mjs";
3
3
  //#region src/rpc/transports/ws-client.ts
4
4
  function NOOP() {}
5
5
  const EMPTY_DEFS = /* @__PURE__ */ new Map();
@@ -1,2 +1,2 @@
1
- import { a as isLoopbackHostname, i as isAllowedOrigin, n as createWsOriginRegistry, r as createWsRpcPeerHooks, t as attachWsRpcTransport } from "../../ws-server-Bk1hOG3X.mjs";
1
+ import { a as isLoopbackHostname, i as isAllowedOrigin, n as createWsOriginRegistry, r as createWsRpcPeerHooks, t as attachWsRpcTransport } from "../../ws-server-BiUne4K7.mjs";
2
2
  export { attachWsRpcTransport, createWsOriginRegistry, createWsRpcPeerHooks, isAllowedOrigin, isLoopbackHostname };