@askrjs/askr 0.3.0 → 0.4.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 (123) hide show
  1. package/CHANGELOG.md +874 -0
  2. package/README.md +61 -29
  3. package/capabilities.json +19 -9
  4. package/dist/actions/index.js +56 -12
  5. package/dist/benchmark.js +10 -15
  6. package/dist/boot/index.d.ts +3 -2
  7. package/dist/boot/index.js +1 -1
  8. package/dist/boot-DaoTYoCw.js +3989 -0
  9. package/dist/browser-activity-CB8e-V4f.js +220 -0
  10. package/dist/components/index.d.ts +8 -1
  11. package/dist/components/index.js +1 -43
  12. package/dist/{aria-hKjThHcp.js → compose-ref-DWzdbxsD.js} +41 -4
  13. package/dist/control/index.d.ts +2 -0
  14. package/dist/control/index.js +1 -1
  15. package/dist/control-nfpT2fbK.js +209 -0
  16. package/dist/core.d.ts +5 -9
  17. package/dist/csp-nonce-DwGw1A6Q.js +35 -0
  18. package/dist/data/index.js +3 -3
  19. package/dist/{data-2edW0jhF.js → data-BCwClJiF.js} +283 -94
  20. package/dist/data-runtime-C1bFAlba.js +242 -0
  21. package/dist/{deferred-CbgNhf67.js → deferred-bEEHHvic.js} +42 -20
  22. package/dist/domains/actions.d.ts +8 -3
  23. package/dist/domains/component.d.ts +1 -107
  24. package/dist/domains/context.d.ts +0 -15
  25. package/dist/domains/control.d.ts +36 -249
  26. package/dist/domains/data.d.ts +31 -13
  27. package/dist/domains/diagnostics.d.ts +1 -2
  28. package/dist/domains/lifecycle.d.ts +2 -5
  29. package/dist/domains/refs.d.ts +0 -2
  30. package/dist/domains/routing.d.ts +43 -8
  31. package/dist/domains/scheduler.d.ts +1 -76
  32. package/dist/domains/server.d.ts +5 -2
  33. package/dist/domains/state.d.ts +2 -5
  34. package/dist/domains/telemetry.d.ts +0 -2
  35. package/dist/elements.d.ts +214 -51
  36. package/dist/error-boundary-Bpwofwps.js +293 -0
  37. package/dist/foundations/icon/index.d.ts +0 -58
  38. package/dist/foundations/icon/index.js +2 -2
  39. package/dist/foundations/index.js +2 -1
  40. package/dist/foundations/interactions/index.js +1 -1
  41. package/dist/foundations/state/index.d.ts +3 -3
  42. package/dist/foundations/state/index.js +5 -3
  43. package/dist/foundations/structures/index.js +2 -1
  44. package/dist/foundations/utilities/index.d.ts +2 -0
  45. package/dist/foundations/utilities/index.js +1 -2
  46. package/dist/fx/index.d.ts +31 -58
  47. package/dist/fx/index.js +313 -195
  48. package/dist/hooks-BimKStr4.js +202 -0
  49. package/dist/index.d.ts +11 -74
  50. package/dist/index.js +8 -447
  51. package/dist/instance-BAnfmXOR.js +988 -0
  52. package/dist/{interactions-CTeACdT_.js → interactions-D2BoREb-.js} +3 -2
  53. package/dist/jsx-dev-runtime.d.ts +41 -18
  54. package/dist/jsx-dev-runtime.js +1 -6
  55. package/dist/{jsx-runtime-CPJXAOBF.js → jsx-runtime-C4idqHY0.js} +18 -7
  56. package/dist/jsx-runtime.js +1 -1
  57. package/dist/jsx.d.ts +61 -37
  58. package/dist/{manifest-D1P3UNWV.js → manifest-CW9gyNBY.js} +3 -3
  59. package/dist/{navigate-prC5V8XV.js → navigate-CP_0Zy5U.js} +454 -87
  60. package/dist/navigation.d.ts +12 -3
  61. package/dist/peer-types.d.ts +8 -0
  62. package/dist/portal-DuOKfnLa.js +349 -0
  63. package/dist/promise-Dz8iIHAm.js +16 -0
  64. package/dist/query-registry-WMCN0BJL.js +320 -0
  65. package/dist/readable-DFWOsTac.js +21 -0
  66. package/dist/{render-context-B7ohlh6t.js → render-context-DGHnEveC.js} +27 -11
  67. package/dist/render-sync-IC5lMFpq.js +1240 -0
  68. package/dist/resolution-Cx82-xjW.js +1244 -0
  69. package/dist/resource-CLjB7RBQ.js +377 -0
  70. package/dist/resources/index.d.ts +21 -11
  71. package/dist/resources/index.js +45 -244
  72. package/dist/router/index.d.ts +14 -5
  73. package/dist/router/index.js +22 -53
  74. package/dist/scope-CwpVSHVf.js +55 -0
  75. package/dist/{shared-kU8yvryp.js → shared-O2ZnmYAf.js} +1 -7
  76. package/dist/{snapshot-source-An4iKajG.js → snapshot-Cjx4N988.js} +6 -1
  77. package/dist/ssg/index.d.ts +1 -2
  78. package/dist/ssg/index.js +5 -13
  79. package/dist/ssr/index.d.ts +26 -28
  80. package/dist/ssr/index.js +4 -4
  81. package/dist/{ssr-CiNm6Vzl.js → ssr-BJ8ug7zH.js} +133 -122
  82. package/dist/ssr-DoV-vJ-5.js +229 -0
  83. package/dist/state-DWO1KzkX.js +232 -0
  84. package/dist/structures-D4dDMqHX.js +231 -0
  85. package/dist/testing/index.d.ts +8 -4
  86. package/dist/testing/index.js +29 -34
  87. package/dist/url-CnbfpX0K.js +185 -0
  88. package/dist/utilities.d.ts +48 -2
  89. package/dist/verify-hydration-DpVaDnqz.js +152 -0
  90. package/package.json +19 -9
  91. package/dist/access-CEA2pOry.js +0 -1046
  92. package/dist/activity-oy2YFTFF.js +0 -201
  93. package/dist/boot-BMBMWUGI.js +0 -1084
  94. package/dist/capabilities-Bbf0mlp9.js +0 -42
  95. package/dist/compose-ref-v0qGlHoN.js +0 -26
  96. package/dist/control-BR_mrX__.js +0 -173
  97. package/dist/control-C-ApnFs1.js +0 -20
  98. package/dist/csp-nonce-BfFWcd0w.js +0 -173
  99. package/dist/data-runtime-CxoY98lX.js +0 -149
  100. package/dist/default-portal-runtime-DvMvWJVp.js +0 -20
  101. package/dist/dom-renderer.d.ts +0 -77
  102. package/dist/domains/renderer.d.ts +0 -127
  103. package/dist/eager-control.d.ts +0 -8
  104. package/dist/effect-C3Zsc1k6.js +0 -292
  105. package/dist/for-state-BDykeOJL.js +0 -1753
  106. package/dist/instance-VAFYVJOa.js +0 -1027
  107. package/dist/notify-DxxuDPeY.js +0 -266
  108. package/dist/portal-w3oQ6oQU.js +0 -29
  109. package/dist/query-registry-LrYpQsDJ.js +0 -83
  110. package/dist/render-resolved-BC0W7_5b.js +0 -1123
  111. package/dist/renderer-CT0HeY58.js +0 -8623
  112. package/dist/resolution-3DskUkjG.js +0 -577
  113. package/dist/resource-18-sFRl9.js +0 -344
  114. package/dist/route-matching-CUzZ31gT.js +0 -551
  115. package/dist/router-internal-7nuNEHfG.js +0 -36
  116. package/dist/scope-Cq_iYbTR.js +0 -403
  117. package/dist/selector-BSPVkjKP.js +0 -311
  118. package/dist/ssr-EPjwJH5R.js +0 -29
  119. package/dist/state-BXJfudq1.js +0 -91
  120. package/dist/structures-CjEzfj4h.js +0 -654
  121. package/dist/timer-C7uqnJVt.js +0 -85
  122. package/dist/verify-hydration-ikaxotf7.js +0 -27
  123. package/dist/vnode-D24p6IW2.js +0 -7
@@ -0,0 +1,320 @@
1
+ import { a as getDefaultDataRuntime, d as writePrefetchedQueryData, i as findDataRuntimeState, t as createDataRuntime } from "./data-runtime-C1bFAlba.js";
2
+ //#region src/common/deferred-value.ts
3
+ const DEFERRED_VALUE = Symbol.for("@askrjs/askr/deferred-value");
4
+ const DEFERRED_BOUNDARY = Symbol.for("@askrjs/askr/deferred-boundary");
5
+ /** Wrap a promise as a {@link Deferred} value that tracks its settled state and result. */
6
+ function defer(promise) {
7
+ let state = "pending";
8
+ let value;
9
+ let error;
10
+ const normalized = Promise.resolve(promise);
11
+ normalized.then((resolved) => {
12
+ state = "fulfilled";
13
+ value = resolved;
14
+ }, (reason) => {
15
+ state = "rejected";
16
+ error = reason;
17
+ });
18
+ return Object.freeze(Object.defineProperties({}, {
19
+ state: {
20
+ enumerable: true,
21
+ get: () => state
22
+ },
23
+ value: {
24
+ enumerable: true,
25
+ get: () => value
26
+ },
27
+ error: {
28
+ enumerable: true,
29
+ get: () => error
30
+ },
31
+ promise: { value: normalized },
32
+ [DEFERRED_VALUE]: { value: true }
33
+ }));
34
+ }
35
+ /** Check whether `value` is a {@link Deferred} produced by {@link defer}. */
36
+ function isDeferred(value) {
37
+ if (!value || typeof value !== "object") return false;
38
+ const marker = Object.getOwnPropertyDescriptor(value, DEFERRED_VALUE);
39
+ return Boolean(marker && "value" in marker && marker.value === true);
40
+ }
41
+ /** @internal Reconstruct settled server data without importing deferred rendering. */
42
+ function reviveDeferredValue(state, value, error) {
43
+ const promise = state === "fulfilled" ? Promise.resolve(value) : Promise.reject(error);
44
+ if (state === "rejected") promise.catch(() => void 0);
45
+ return Object.freeze(Object.defineProperties({}, {
46
+ state: {
47
+ enumerable: true,
48
+ value: state
49
+ },
50
+ value: {
51
+ enumerable: true,
52
+ value
53
+ },
54
+ error: {
55
+ enumerable: true,
56
+ value: error
57
+ },
58
+ promise: { value: promise },
59
+ [DEFERRED_VALUE]: { value: true }
60
+ }));
61
+ }
62
+ //#endregion
63
+ //#region src/common/json-transport.ts
64
+ /** Diagnostic path for an own property of the value at `parent`. */
65
+ function jsonTransportPropertyPath(parent, key) {
66
+ if (/^(?:0|[1-9]\d*)$/.test(key)) return `${parent}[${key}]`;
67
+ if (/^[A-Za-z_$][\w$]*$/.test(key)) return `${parent}.${key}`;
68
+ return `${parent}[${JSON.stringify(key)}]`;
69
+ }
70
+ /** Format a diagnostic path only when a value actually fails. */
71
+ function pathOf(frame, key) {
72
+ const keys = key === void 0 ? [] : [key];
73
+ for (let at = frame; at.p; at = at.p) keys.push(at.k);
74
+ let path = "$";
75
+ for (let index = keys.length - 1; index >= 0; index -= 1) path = jsonTransportPropertyPath(path, keys[index]);
76
+ return path;
77
+ }
78
+ function primitiveReason(value) {
79
+ switch (typeof value) {
80
+ case "number": return Number.isFinite(value) ? void 0 : "non-finite numbers are not supported";
81
+ case "undefined": return "undefined is not supported";
82
+ case "bigint": return "bigint is not supported";
83
+ case "symbol": return "symbols are not supported";
84
+ case "function": return "functions are not supported";
85
+ }
86
+ }
87
+ function objectLabel(value) {
88
+ if (value instanceof Date) return "Date";
89
+ if (value instanceof Map) return "Map";
90
+ if (value instanceof Set) return "Set";
91
+ const constructor = value.constructor;
92
+ return typeof constructor === "function" && constructor.name ? constructor.name : "class instance";
93
+ }
94
+ /**
95
+ * Validate that `value` survives the hydration JSON transport unchanged:
96
+ * `null`, strings, booleans, finite numbers, dense arrays, plain objects, and
97
+ * framework deferred values. Anything `JSON.stringify()` would drop, coerce, or
98
+ * reject (undefined, functions, bigint, `Date`, `Map`, class instances, cycles,
99
+ * and so on) throws a `TypeError` naming `subject` and the value's path, then
100
+ * `hint`. Accessors are rejected without being invoked. The walk is
101
+ * iterative, so nesting depth is bounded by memory rather than the call
102
+ * stack, and paths are formatted only on failure.
103
+ */
104
+ function validateJsonTransportValue(value, subject, hint) {
105
+ const fail = (path, reason) => {
106
+ throw new TypeError(`[Askr] ${subject} at "${path}" is not JSON transport-safe: ${reason}. ${hint}`);
107
+ };
108
+ const stack = [];
109
+ const ancestors = /* @__PURE__ */ new Set();
110
+ const visit = (child, parent, key) => {
111
+ const reason = primitiveReason(child);
112
+ if (reason) fail(parent ? pathOf(parent, key) : "$", reason);
113
+ if (child !== null && typeof child === "object") stack.push({
114
+ o: child,
115
+ p: parent,
116
+ k: key,
117
+ seen: false
118
+ });
119
+ };
120
+ visit(value, void 0, "");
121
+ while (stack.length > 0) {
122
+ const frame = stack[stack.length - 1];
123
+ const object = frame.o;
124
+ if (frame.seen) {
125
+ stack.pop();
126
+ ancestors.delete(object);
127
+ continue;
128
+ }
129
+ if (ancestors.has(object)) fail(pathOf(frame), "cyclic references are not supported");
130
+ frame.seen = true;
131
+ ancestors.add(object);
132
+ const hasSymbols = Object.getOwnPropertySymbols(object).length > 0;
133
+ if (hasSymbols && isDeferred(object)) {
134
+ if (object.state === "fulfilled") visit(object.value, frame, "value");
135
+ continue;
136
+ }
137
+ const array = Array.isArray(object) ? object : void 0;
138
+ if (!array) {
139
+ const prototype = Object.getPrototypeOf(object);
140
+ if (prototype !== Object.prototype && prototype !== null) fail(pathOf(frame), `${objectLabel(object)} instances are not supported; use a plain object`);
141
+ }
142
+ if (hasSymbols) fail(pathOf(frame), "symbol-keyed properties are not supported");
143
+ const keys = Object.keys(object);
144
+ let named = false;
145
+ if (array) {
146
+ const length = array.length;
147
+ if (keys.length !== length || length > 0 && keys[length - 1] !== String(length - 1)) {
148
+ for (let index = 0; index < length; index += 1) if (!(index in array)) fail(pathOf(frame, String(index)), "sparse arrays are not supported");
149
+ named = true;
150
+ }
151
+ }
152
+ const names = Object.getOwnPropertyNames(object);
153
+ if (names.length !== keys.length + (array ? 1 : 0)) {
154
+ for (const name of names) if (!(array && name === "length") && !keys.includes(name)) fail(pathOf(frame, name), "non-enumerable properties are not supported");
155
+ }
156
+ const firstChild = stack.length;
157
+ for (const key of keys) {
158
+ const descriptor = Object.getOwnPropertyDescriptor(object, key);
159
+ if (!("value" in descriptor)) fail(pathOf(frame, key), "accessors are not supported");
160
+ if (named && (!/^(?:0|[1-9]\d*)$/.test(key) || Number(key) >= array.length)) fail(pathOf(frame, key), "named array properties are not supported");
161
+ visit(descriptor.value, frame, key);
162
+ }
163
+ for (let low = firstChild, high = stack.length - 1; low < high;) {
164
+ const child = stack[low];
165
+ stack[low++] = stack[high];
166
+ stack[high--] = child;
167
+ }
168
+ }
169
+ }
170
+ //#endregion
171
+ //#region src/common/telemetry.ts
172
+ function withTelemetry(span, fields, work) {
173
+ return span ? span(fields, work) : work();
174
+ }
175
+ //#endregion
176
+ //#region src/data/query-registry.ts
177
+ /** Pair a {@link QueryDefinition} with the server-side handler that resolves it. */
178
+ function serveQuery(query, handler) {
179
+ return Object.freeze({
180
+ query,
181
+ handler
182
+ });
183
+ }
184
+ /** Build a {@link ServerQueryRegistry} from one or more {@link serveQuery} entries. */
185
+ function defineServerQueries(...entries) {
186
+ const frozenEntries = Object.freeze([...entries]);
187
+ const handlers = new Map(entries.map((entry) => [entry.query, entry.handler]));
188
+ return Object.freeze({
189
+ entries: frozenEntries,
190
+ get(query) {
191
+ return handlers.get(query);
192
+ }
193
+ });
194
+ }
195
+ /** Freeze and return a reusable {@link QueryDefinition}. */
196
+ function defineQuery(definition) {
197
+ return Object.freeze({ ...definition });
198
+ }
199
+ /**
200
+ * Throw when query data cannot cross the hydration JSON transport unchanged.
201
+ * SSR preloads check before anything streams; dehydration checks again.
202
+ */
203
+ function assertQueryDataTransportSafe(key, value) {
204
+ validateJsonTransportValue(value, `Query data for key ${JSON.stringify(key)}`, "Return JSON-compatible query data.");
205
+ }
206
+ /**
207
+ * Settle with `promise`, or reject with the reason of the first of `signals`
208
+ * to abort.
209
+ */
210
+ function raceAbort(promise, signals) {
211
+ return new Promise((resolve, reject) => {
212
+ const abort = () => reject(signals.find((each) => each.aborted).reason);
213
+ for (const each of signals) {
214
+ if (each.aborted) abort();
215
+ each.addEventListener("abort", abort);
216
+ }
217
+ promise.then(resolve, reject).finally(() => {
218
+ for (const each of signals) each.removeEventListener("abort", abort);
219
+ });
220
+ });
221
+ }
222
+ /**
223
+ * Create a {@link QueryPrefetchContext} for prefetching query data ahead of
224
+ * render, e.g. during SSR route resolution.
225
+ */
226
+ function createQueryPrefetchContext(options = {}) {
227
+ const runtime = options.runtime ?? (options.mode === "spa" ? getDefaultDataRuntime() : createDataRuntime());
228
+ const signal = options.signal ?? new AbortController().signal;
229
+ const storePrefetchedValue = (key, value) => {
230
+ if (signal.aborted) return false;
231
+ if (runtime.queryCache.has(key)) return true;
232
+ const runtimeState = options.mode !== "ssr" && typeof window !== "undefined" ? findDataRuntimeState(runtime) : void 0;
233
+ if (runtimeState) writePrefetchedQueryData(runtimeState, key, value);
234
+ else {
235
+ if (options.mode === "ssr") assertQueryDataTransportSafe(key, value);
236
+ runtime.queryData.set(key, value);
237
+ }
238
+ return true;
239
+ };
240
+ return {
241
+ runtime,
242
+ request: options.request,
243
+ signal,
244
+ mode: options.mode ?? "spa",
245
+ async prefetch(query, input) {
246
+ return withTelemetry(options.telemetry?.queryPrefetch, {}, async () => {
247
+ const key = query.key(input);
248
+ if (runtime.queryCache.has(key) || runtime.queryData.has(key)) return true;
249
+ const handler = options.mode === "ssr" ? options.registry?.get(query) : void 0;
250
+ if (options.mode === "ssr" && !handler) return false;
251
+ const inflight = findDataRuntimeState(runtime)?.prefetches ?? /* @__PURE__ */ new Map();
252
+ for (;;) {
253
+ let pending = inflight.get(key);
254
+ const joined = pending !== void 0 && !(pending.signal.aborted && !signal.aborted);
255
+ if (!joined) {
256
+ let promise;
257
+ try {
258
+ promise = Promise.resolve(handler ? handler({
259
+ input,
260
+ request: options.request,
261
+ signal
262
+ }) : query.fetch(input, { signal }));
263
+ } catch (error) {
264
+ promise = Promise.reject(error);
265
+ }
266
+ pending = {
267
+ signal,
268
+ promise,
269
+ waiters: 0
270
+ };
271
+ inflight.set(key, pending);
272
+ }
273
+ const current = pending;
274
+ current.waiters += 1;
275
+ try {
276
+ let value;
277
+ try {
278
+ value = await (joined ? raceAbort(current.promise, [signal, current.signal]) : current.promise);
279
+ } catch (error) {
280
+ if (current.signal.aborted && !signal.aborted) continue;
281
+ throw error;
282
+ }
283
+ return !current.invalidated && storePrefetchedValue(key, value);
284
+ } finally {
285
+ current.waiters -= 1;
286
+ if (current.waiters === 0 && inflight.get(key) === current) inflight.delete(key);
287
+ }
288
+ }
289
+ });
290
+ }
291
+ };
292
+ }
293
+ /** Prefetch `query` with `input` into a {@link QueryPrefetchContext}'s runtime. */
294
+ async function prefetchQuery(context, query, input) {
295
+ return context.prefetch(query, input);
296
+ }
297
+ /**
298
+ * Extract a runtime's cached query data into a JSON-serializable snapshot.
299
+ * Throws a `TypeError` naming the key and path of any value that would not
300
+ * survive JSON transport unchanged (for example a `Date`, `Map`, or bigint).
301
+ */
302
+ function dehydrateDataRuntime(runtime) {
303
+ const result = {};
304
+ for (const [key, value] of runtime.queryData) {
305
+ assertQueryDataTransportSafe(key, value);
306
+ result[key] = value;
307
+ }
308
+ return result;
309
+ }
310
+ /** Load a {@link dehydrateDataRuntime} snapshot back into a runtime's query cache. */
311
+ function hydrateDataRuntime(runtime, data) {
312
+ if (!data || typeof data !== "object" || Array.isArray(data)) return;
313
+ const runtimeState = findDataRuntimeState(runtime);
314
+ for (const [key, value] of Object.entries(data)) {
315
+ runtimeState?.unreadPrefetches.delete(key);
316
+ runtime.queryData.set(key, value);
317
+ }
318
+ }
319
+ //#endregion
320
+ export { hydrateDataRuntime as a, withTelemetry as c, DEFERRED_BOUNDARY as d, defer as f, dehydrateDataRuntime as i, jsonTransportPropertyPath as l, reviveDeferredValue as m, defineQuery as n, prefetchQuery as o, isDeferred as p, defineServerQueries as r, serveQuery as s, createQueryPrefetchContext as t, validateJsonTransportValue as u };
@@ -0,0 +1,21 @@
1
+ //#region src/core/reactive/readable.ts
2
+ /**
3
+ * Readables: callables that read a reactive value (`state()` cells and
4
+ * `derive()` results). A function prop or child that returns a readable
5
+ * renders the readable's value.
6
+ */
7
+ const READABLE = Symbol.for("askr.readable");
8
+ function markReadable(fn) {
9
+ Object.defineProperty(fn, READABLE, { value: true });
10
+ return fn;
11
+ }
12
+ function isReadable(value) {
13
+ return typeof value === "function" && value[READABLE] === true;
14
+ }
15
+ /** Call `fn`; if it returns a readable, read that too. */
16
+ function readValue(fn) {
17
+ const value = fn();
18
+ return isReadable(value) ? value() : value;
19
+ }
20
+ //#endregion
21
+ export { readValue as n, markReadable as t };
@@ -21,6 +21,7 @@ function createPageRenderEnvelope(input = {}) {
21
21
  return Object.freeze({
22
22
  version: PAGE_RENDER_ENVELOPE_VERSION,
23
23
  resources: ownedRecord(input.resources),
24
+ ...input.queries ? { queries: ownedRecord(input.queries) } : {},
24
25
  route: input.route,
25
26
  framework: ownedRecord(input.framework)
26
27
  });
@@ -38,18 +39,14 @@ function pageRenderEnvelope(value, fallback = {}) {
38
39
  });
39
40
  }
40
41
  function replacePageRoute(value, route) {
41
- const current = pageRenderEnvelope(value);
42
42
  return createPageRenderEnvelope({
43
- resources: current.resources,
44
- route,
45
- framework: current.framework
43
+ ...pageRenderEnvelope(value),
44
+ route
46
45
  });
47
46
  }
48
47
  function withPageFramework(value, framework) {
49
- const current = pageRenderEnvelope(value);
50
48
  return createPageRenderEnvelope({
51
- resources: current.resources,
52
- route: current.route,
49
+ ...pageRenderEnvelope(value),
53
50
  framework
54
51
  });
55
52
  }
@@ -69,7 +66,7 @@ function getHydrationRenderUrl(value) {
69
66
  return typeof url === "string" ? url : void 0;
70
67
  }
71
68
  function isEmptyPageRenderEnvelope(value) {
72
- return value.route === void 0 && Object.keys(value.resources).length === 0 && Object.keys(value.framework).length === 0;
69
+ return value.route === void 0 && Object.keys(value.resources).length === 0 && Object.keys(value.queries ?? {}).length === 0 && Object.keys(value.framework).length === 0;
73
70
  }
74
71
  //#endregion
75
72
  //#region src/common/render-context.ts
@@ -86,6 +83,25 @@ function configureRenderContextProvider(nextProvider) {
86
83
  function getActiveRenderContext() {
87
84
  return provider.getRenderContext();
88
85
  }
86
+ const deferredBoundaryParents = /* @__PURE__ */ new WeakMap();
87
+ /**
88
+ * Scope deferred boundaries registered in `context` under an already streamed
89
+ * parent boundary, so nested ids (`d:0.0`) never collide with top-level ones.
90
+ */
91
+ function setDeferredBoundaryParent(context, parentId) {
92
+ deferredBoundaryParents.set(context, parentId);
93
+ }
94
+ /** Register a pending `Resolve` boundary for streaming and return its deterministic id. */
95
+ function registerDeferredBoundary(context, registration) {
96
+ const parent = deferredBoundaryParents.get(context);
97
+ const index = context.deferredBoundaries.length;
98
+ const id = parent === void 0 ? `d:${index}` : `${parent}.${index}`;
99
+ context.deferredBoundaries.push({
100
+ id,
101
+ ...registration
102
+ });
103
+ return id;
104
+ }
89
105
  /** Register request-local CSS produced during SSR without importing the SSR renderer in clients. */
90
106
  function registerSSRStyle(id, cssText) {
91
107
  const context = getActiveRenderContext();
@@ -129,8 +145,8 @@ function isHydrationVerificationRender() {
129
145
  return hydrationVerificationDepth > 0;
130
146
  }
131
147
  /** @internal Read a server-captured resource branch without invoking its loader. */
132
- function getResourceVerificationSnapshot(key) {
133
- const snapshots = getCurrentRenderData()?.framework[RESOURCE_VERIFICATION_SNAPSHOTS];
148
+ function getResourceVerificationSnapshot(key, framework = getCurrentRenderData()?.framework) {
149
+ const snapshots = framework?.[RESOURCE_VERIFICATION_SNAPSHOTS];
134
150
  if (!snapshots || typeof snapshots !== "object" || Array.isArray(snapshots)) return null;
135
151
  if (!Object.prototype.hasOwnProperty.call(snapshots, key)) return null;
136
152
  const snapshot = snapshots[key];
@@ -174,4 +190,4 @@ function throwSSRDataMissing() {
174
190
  throw new SSRDataMissingError();
175
191
  }
176
192
  //#endregion
177
- export { SSRDataMissingError as C, withPageFramework as S, isEmptyPageRenderEnvelope as _, getResourceVerificationSnapshot as a, replacePageRoute as b, registerSSRStyle as c, stopHydrationRenderPhase as d, stopRenderPhase as f, getHydrationRenderUrl as g, createPageRenderEnvelope as h, getNextRenderKey as i, startHydrationRenderPhase as l, withHydrationVerificationRender as m, getActiveRenderContext as n, isHydrationVerificationRender as o, throwSSRDataMissing as p, getCurrentRenderData as r, recordResourceVerificationSnapshot as s, configureRenderContextProvider as t, startRenderPhase as u, isPageRenderEnvelope as v, withHydrationRenderUrl as x, pageRenderEnvelope as y };
193
+ export { withHydrationRenderUrl as C, replacePageRoute as S, SSRDataMissingError as T, createPageRenderEnvelope as _, getResourceVerificationSnapshot as a, isPageRenderEnvelope as b, registerDeferredBoundary as c, startHydrationRenderPhase as d, startRenderPhase as f, withHydrationVerificationRender as g, throwSSRDataMissing as h, getNextRenderKey as i, registerSSRStyle as l, stopRenderPhase as m, getActiveRenderContext as n, isHydrationVerificationRender as o, stopHydrationRenderPhase as p, getCurrentRenderData as r, recordResourceVerificationSnapshot as s, configureRenderContextProvider as t, setDeferredBoundaryParent as u, getHydrationRenderUrl as v, withPageFramework as w, pageRenderEnvelope as x, isEmptyPageRenderEnvelope as y };