@askrjs/askr 0.0.85 → 0.0.87
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +60 -0
- package/capabilities.json +25 -0
- package/dist/actions/index.d.ts +1 -1
- package/dist/actions/index.js +2 -2
- package/dist/{activity-Jd9CgEa3.js → activity-BnkhdIXm.js} +3 -3
- package/dist/{activity-B1I5HJQI.d.ts → activity-DNYL__cW.d.ts} +1 -1
- package/dist/benchmark.js +5 -5
- package/dist/boot/index.d.ts +3 -3
- package/dist/boot/index.js +1 -1
- package/dist/{boot-DWe880Et.js → boot-Bd-j_BL5.js} +15 -14
- package/dist/{component-internal-DcrLymUJ.js → component-internal-uVCJAre6.js} +1 -1
- package/dist/control/index.js +1 -1
- package/dist/{control-oLADku43.js → control-BF3geQKh.js} +1 -1
- package/dist/{csp-nonce-Bc52OIVc.js → csp-nonce-CUscoNF1.js} +1 -1
- package/dist/data/index.d.ts +1 -1
- package/dist/data/index.js +3 -3
- package/dist/{data-Dkqb8_QP.js → data-CXZ-FOa7.js} +6 -3
- package/dist/{data-runtime-D68YOo9L.js → data-runtime-CnVeSvJz.js} +7 -5
- package/dist/default-portal-runtime-DvMvWJVp.js +20 -0
- package/dist/{authoring-DdQ3pHqt.js → deferred-_DaSfpsr.js} +81 -4
- package/dist/{for-internal-B_mnQhan.js → for-internal-Dxf3iZ9E.js} +1 -1
- package/dist/foundations/index.d.ts +1 -1
- package/dist/foundations/index.js +1 -2
- package/dist/foundations/structures/index.d.ts +1 -1
- package/dist/foundations/structures/index.js +1 -2
- package/dist/{index-pIgGaXvS.d.ts → index-BvNkcegT.d.ts} +1 -1
- package/dist/{index-Bkh9S9-t.d.ts → index-DflhL1h8.d.ts} +15 -15
- package/dist/{index-5S-fi2xy.d.ts → index-SGxMZLAc.d.ts} +3 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +7 -7
- package/dist/{lifecycle-operations-BrYrBsXY.js → lifecycle-operations-DTO93Hrl.js} +1 -1
- package/dist/manifest-D1P9uTlz.js +53 -0
- package/dist/{navigate-NyIjQUwI.d.ts → navigate-B_fcLDAG.d.ts} +1 -1
- package/dist/{navigate-b4GGxO_l.js → navigate-DSATWfHh.js} +8 -8
- package/dist/{query-registry-BL6rjGsO.js → query-registry-p_0kkieE.js} +1 -1
- package/dist/render-context-D0Hoj9dW.js +161 -0
- package/dist/{renderer-CZzNtoj2.js → renderer-BGMaUrVj.js} +10 -7
- package/dist/{deferred-vUOy-awa.js → resolution-BRmiFYvw.js} +61 -231
- package/dist/resource-operation-B94oj6xT.js +304 -0
- package/dist/resources/index.d.ts +2 -2
- package/dist/resources/index.js +4 -4
- package/dist/{route-matching-DHduNiGk.js → route-matching-DqULzZtC.js} +2 -276
- package/dist/router/index.d.ts +8 -6
- package/dist/router/index.js +7 -6
- package/dist/ssg/index.d.ts +1 -1
- package/dist/ssg/index.js +5 -4
- package/dist/ssr/index.d.ts +2 -2
- package/dist/ssr/index.js +2 -2
- package/dist/{ssr-CpiBHMNv.js → ssr-q250YlKo.js} +36 -18
- package/dist/{portal-BVWjAhNQ.js → structures-DsOm-clq.js} +232 -3
- package/dist/testing/index.d.ts +17 -3
- package/dist/testing/index.js +42 -4
- package/dist/{verify-hydration-C3QBBQqR.js → verify-hydration-DkISyZCo.js} +4 -3
- package/package.json +3 -2
- package/dist/render-context-D-DFk2WN.js +0 -73
- package/dist/structures-DSLF_iis.js +0 -223
|
@@ -1,23 +1,10 @@
|
|
|
1
|
-
import { d as getCurrentAppRenderRuntime } from "./component-scope-DzJEbYGE.js";
|
|
2
1
|
import { n as Fragment, t as ELEMENT_TYPE } from "./jsx-C3IECePB.js";
|
|
3
|
-
import { g as readScope, u as defineScope } from "./component-internal-
|
|
2
|
+
import { g as readScope, u as defineScope } from "./component-internal-uVCJAre6.js";
|
|
4
3
|
import { p as isPromiseLike } from "./lifecycle-batch-Dfpid9-A.js";
|
|
5
|
-
import { n as getActiveRenderContext,
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { c as
|
|
9
|
-
//#region src/runtime/execution-model.ts
|
|
10
|
-
const EXECUTION_MODEL_KEY = Symbol.for("__ASKR_EXECUTION_MODEL__");
|
|
11
|
-
function getExecutionModel() {
|
|
12
|
-
return globalThis[EXECUTION_MODEL_KEY];
|
|
13
|
-
}
|
|
14
|
-
function assertExecutionModel(model) {
|
|
15
|
-
const g = globalThis;
|
|
16
|
-
const cur = g[EXECUTION_MODEL_KEY];
|
|
17
|
-
if (cur && cur !== model) throw new Error(`[Askr] mixing execution models is not allowed (current: ${cur}, attempted: ${model}). Choose exactly one: createSPA, createSSR, or createIslands.`);
|
|
18
|
-
if (!cur) g[EXECUTION_MODEL_KEY] = model;
|
|
19
|
-
}
|
|
20
|
-
//#endregion
|
|
4
|
+
import { b as withPageFramework, n as getActiveRenderContext, y as replacePageRoute } from "./render-context-D0Hoj9dW.js";
|
|
5
|
+
import { i as ROUTE_ROOT_COMPONENT } from "./csp-nonce-CUscoNF1.js";
|
|
6
|
+
import { c as withTelemetry, t as createQueryPrefetchContext } from "./query-registry-p_0kkieE.js";
|
|
7
|
+
import { c as removeRouteBasePath, i as getMatchingRouteRecord, l as buildRouteContext, o as addRouteBasePath, s as normalizeRouteBasePath, u as buildRouteContextBase, v as getActiveRouteAuthOptions } from "./route-matching-DqULzZtC.js";
|
|
21
8
|
//#region src/router/lazy.ts
|
|
22
9
|
const pendingLazy = /* @__PURE__ */ new Set();
|
|
23
10
|
const lazyStates = /* @__PURE__ */ new WeakMap();
|
|
@@ -140,57 +127,68 @@ function setCurrentAuth(context) {
|
|
|
140
127
|
if (render) render.authContext = context;
|
|
141
128
|
}
|
|
142
129
|
//#endregion
|
|
143
|
-
//#region src/common/
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
158
|
-
const candidate = value;
|
|
159
|
-
return candidate.version === PAGE_RENDER_ENVELOPE_VERSION && Boolean(candidate.resources && typeof candidate.resources === "object" && !Array.isArray(candidate.resources)) && Boolean(candidate.framework && typeof candidate.framework === "object" && !Array.isArray(candidate.framework));
|
|
160
|
-
}
|
|
161
|
-
function pageRenderEnvelope(value, fallback = {}) {
|
|
162
|
-
if (isPageRenderEnvelope(value)) return value;
|
|
163
|
-
return createPageRenderEnvelope({
|
|
164
|
-
...fallback,
|
|
165
|
-
route: value ?? fallback.route
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
function replacePageRoute(value, route) {
|
|
169
|
-
const current = pageRenderEnvelope(value);
|
|
170
|
-
return createPageRenderEnvelope({
|
|
171
|
-
resources: current.resources,
|
|
172
|
-
route,
|
|
173
|
-
framework: current.framework
|
|
130
|
+
//#region src/common/deferred-value.ts
|
|
131
|
+
const DEFERRED_VALUE = Symbol.for("@askrjs/askr/deferred-value");
|
|
132
|
+
const DEFERRED_BOUNDARY = Symbol.for("@askrjs/askr/deferred-boundary");
|
|
133
|
+
function defer(promise) {
|
|
134
|
+
let state = "pending";
|
|
135
|
+
let value;
|
|
136
|
+
let error;
|
|
137
|
+
const normalized = Promise.resolve(promise);
|
|
138
|
+
normalized.then((resolved) => {
|
|
139
|
+
state = "fulfilled";
|
|
140
|
+
value = resolved;
|
|
141
|
+
}, (reason) => {
|
|
142
|
+
state = "rejected";
|
|
143
|
+
error = reason;
|
|
174
144
|
});
|
|
145
|
+
return Object.freeze(Object.defineProperties({}, {
|
|
146
|
+
state: {
|
|
147
|
+
enumerable: true,
|
|
148
|
+
get: () => state
|
|
149
|
+
},
|
|
150
|
+
value: {
|
|
151
|
+
enumerable: true,
|
|
152
|
+
get: () => value
|
|
153
|
+
},
|
|
154
|
+
error: {
|
|
155
|
+
enumerable: true,
|
|
156
|
+
get: () => error
|
|
157
|
+
},
|
|
158
|
+
promise: { value: normalized },
|
|
159
|
+
[DEFERRED_VALUE]: { value: true }
|
|
160
|
+
}));
|
|
175
161
|
}
|
|
176
|
-
function
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
route: current.route,
|
|
181
|
-
framework
|
|
182
|
-
});
|
|
162
|
+
function isDeferred(value) {
|
|
163
|
+
if (!value || typeof value !== "object") return false;
|
|
164
|
+
const marker = Object.getOwnPropertyDescriptor(value, DEFERRED_VALUE);
|
|
165
|
+
return Boolean(marker && "value" in marker && marker.value === true);
|
|
183
166
|
}
|
|
184
|
-
|
|
185
|
-
|
|
167
|
+
/** @internal Reconstruct settled server data without importing deferred rendering. */
|
|
168
|
+
function reviveDeferredValue(state, value, error) {
|
|
169
|
+
const promise = state === "fulfilled" ? Promise.resolve(value) : Promise.reject(error);
|
|
170
|
+
if (state === "rejected") promise.catch(() => void 0);
|
|
171
|
+
return Object.freeze(Object.defineProperties({}, {
|
|
172
|
+
state: {
|
|
173
|
+
enumerable: true,
|
|
174
|
+
value: state
|
|
175
|
+
},
|
|
176
|
+
value: {
|
|
177
|
+
enumerable: true,
|
|
178
|
+
value
|
|
179
|
+
},
|
|
180
|
+
error: {
|
|
181
|
+
enumerable: true,
|
|
182
|
+
value: error
|
|
183
|
+
},
|
|
184
|
+
promise: { value: promise },
|
|
185
|
+
[DEFERRED_VALUE]: { value: true }
|
|
186
|
+
}));
|
|
186
187
|
}
|
|
187
188
|
//#endregion
|
|
188
189
|
//#region src/router/route-hydration.ts
|
|
189
|
-
const DEFERRED_VALUE$1 = Symbol.for("@askrjs/askr/deferred-value");
|
|
190
190
|
function isDeferredHydrationValue(value) {
|
|
191
|
-
|
|
192
|
-
const marker = Object.getOwnPropertyDescriptor(value, DEFERRED_VALUE$1);
|
|
193
|
-
return Boolean(marker && "value" in marker && marker.value === true);
|
|
191
|
+
return isDeferred(value);
|
|
194
192
|
}
|
|
195
193
|
const omissionGuards = /* @__PURE__ */ new WeakMap();
|
|
196
194
|
function propertyPath(parent, key) {
|
|
@@ -513,172 +511,4 @@ function resolveRouteRequest(target, options) {
|
|
|
513
511
|
});
|
|
514
512
|
}
|
|
515
513
|
//#endregion
|
|
516
|
-
|
|
517
|
-
function createRouteManifest() {
|
|
518
|
-
const auth = getDefaultRouteAuthOptions();
|
|
519
|
-
return {
|
|
520
|
-
records: [...getRouteRecords()],
|
|
521
|
-
...auth ? { auth } : {},
|
|
522
|
-
...getDefaultRouteBasePath() ? { basePath: getDefaultRouteBasePath() } : {}
|
|
523
|
-
};
|
|
524
|
-
}
|
|
525
|
-
function _applyManifest(manifest) {
|
|
526
|
-
setDefaultRouteAuthOptions(manifest.auth);
|
|
527
|
-
setDefaultRouteBasePath(normalizeRouteBasePath(manifest.basePath));
|
|
528
|
-
for (const record of manifest.records) {
|
|
529
|
-
insertRecordSorted(record);
|
|
530
|
-
addRouteToStores({
|
|
531
|
-
path: record.path,
|
|
532
|
-
handler: record.handler,
|
|
533
|
-
namespace: record.options.namespace,
|
|
534
|
-
..."fallbackPrefix" in record && typeof record.fallbackPrefix === "string" ? { fallbackPrefix: record.fallbackPrefix } : {}
|
|
535
|
-
});
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
function createRouteRegistry(definition, options = {}) {
|
|
539
|
-
const previous = snapshotRouteState();
|
|
540
|
-
clearRouteState();
|
|
541
|
-
try {
|
|
542
|
-
setDefaultRouteAuthOptions(options.auth);
|
|
543
|
-
setDefaultRouteBasePath(normalizeRouteBasePath(options.basePath));
|
|
544
|
-
definition();
|
|
545
|
-
const manifest = createRouteManifest();
|
|
546
|
-
return Object.freeze({
|
|
547
|
-
manifest,
|
|
548
|
-
routes: getRouteList()
|
|
549
|
-
});
|
|
550
|
-
} finally {
|
|
551
|
-
restoreRouteState(previous);
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
//#endregion
|
|
555
|
-
//#region src/router/deferred.tsx
|
|
556
|
-
const DEFERRED_VALUE = Symbol.for("@askrjs/askr/deferred-value");
|
|
557
|
-
const DEFERRED_BOUNDARY = Symbol.for("@askrjs/askr/deferred-boundary");
|
|
558
|
-
function defer(promise) {
|
|
559
|
-
let state = "pending";
|
|
560
|
-
let value;
|
|
561
|
-
let error;
|
|
562
|
-
const normalized = Promise.resolve(promise);
|
|
563
|
-
normalized.then((resolved) => {
|
|
564
|
-
state = "fulfilled";
|
|
565
|
-
value = resolved;
|
|
566
|
-
}, (reason) => {
|
|
567
|
-
state = "rejected";
|
|
568
|
-
error = reason;
|
|
569
|
-
});
|
|
570
|
-
return Object.freeze(Object.defineProperties({}, {
|
|
571
|
-
state: {
|
|
572
|
-
enumerable: true,
|
|
573
|
-
get: () => state
|
|
574
|
-
},
|
|
575
|
-
value: {
|
|
576
|
-
enumerable: true,
|
|
577
|
-
get: () => value
|
|
578
|
-
},
|
|
579
|
-
error: {
|
|
580
|
-
enumerable: true,
|
|
581
|
-
get: () => error
|
|
582
|
-
},
|
|
583
|
-
promise: { value: normalized },
|
|
584
|
-
[DEFERRED_VALUE]: { value: true }
|
|
585
|
-
}));
|
|
586
|
-
}
|
|
587
|
-
function isDeferred(value) {
|
|
588
|
-
return Boolean(value && typeof value === "object" && value[DEFERRED_VALUE] === true);
|
|
589
|
-
}
|
|
590
|
-
/** @internal Reconstruct settled server data without starting loader work. */
|
|
591
|
-
function reviveDeferredValue(state, value, error) {
|
|
592
|
-
const promise = state === "fulfilled" ? Promise.resolve(value) : Promise.reject(error);
|
|
593
|
-
if (state === "rejected") promise.catch(() => void 0);
|
|
594
|
-
return Object.freeze(Object.defineProperties({}, {
|
|
595
|
-
state: {
|
|
596
|
-
enumerable: true,
|
|
597
|
-
value: state
|
|
598
|
-
},
|
|
599
|
-
value: {
|
|
600
|
-
enumerable: true,
|
|
601
|
-
value
|
|
602
|
-
},
|
|
603
|
-
error: {
|
|
604
|
-
enumerable: true,
|
|
605
|
-
value: error
|
|
606
|
-
},
|
|
607
|
-
promise: { value: promise },
|
|
608
|
-
[DEFERRED_VALUE]: { value: true }
|
|
609
|
-
}));
|
|
610
|
-
}
|
|
611
|
-
function abortError() {
|
|
612
|
-
const error = /* @__PURE__ */ new Error("Deferred route data was aborted.");
|
|
613
|
-
error.name = "AbortError";
|
|
614
|
-
return error;
|
|
615
|
-
}
|
|
616
|
-
function awaitWithSignal(promise, signal) {
|
|
617
|
-
if (!signal) return promise;
|
|
618
|
-
if (signal.aborted) return Promise.reject(abortError());
|
|
619
|
-
return new Promise((resolve, reject) => {
|
|
620
|
-
const abort = () => reject(abortError());
|
|
621
|
-
signal.addEventListener("abort", abort, { once: true });
|
|
622
|
-
promise.then((value) => {
|
|
623
|
-
signal.removeEventListener("abort", abort);
|
|
624
|
-
resolve(value);
|
|
625
|
-
}, (error) => {
|
|
626
|
-
signal.removeEventListener("abort", abort);
|
|
627
|
-
reject(error);
|
|
628
|
-
});
|
|
629
|
-
});
|
|
630
|
-
}
|
|
631
|
-
async function resolveDeferredValues(input, signal) {
|
|
632
|
-
const seen = /* @__PURE__ */ new Set();
|
|
633
|
-
const visit = async (value) => {
|
|
634
|
-
if (!value || typeof value !== "object") return;
|
|
635
|
-
if (isDeferred(value)) {
|
|
636
|
-
const resolved = await awaitWithSignal(value.promise, signal);
|
|
637
|
-
await visit(resolved);
|
|
638
|
-
return;
|
|
639
|
-
}
|
|
640
|
-
if (seen.has(value)) return;
|
|
641
|
-
seen.add(value);
|
|
642
|
-
const children = Array.isArray(value) ? value : Object.values(value);
|
|
643
|
-
await Promise.all(children.map(visit));
|
|
644
|
-
};
|
|
645
|
-
await visit(input);
|
|
646
|
-
return input;
|
|
647
|
-
}
|
|
648
|
-
function routeData() {
|
|
649
|
-
const envelope = getCurrentRenderData();
|
|
650
|
-
if (envelope) return guardHydratedRouteData(envelope.route, envelope.framework);
|
|
651
|
-
const runtime = getCurrentAppRenderRuntime();
|
|
652
|
-
if (!runtime?.hasRoute) throw new Error("routeData() can only be read while rendering a route with loader data.");
|
|
653
|
-
return guardHydratedRouteData(runtime.route, runtime.framework);
|
|
654
|
-
}
|
|
655
|
-
function rejectedChild(props, error) {
|
|
656
|
-
return typeof props.rejected === "function" ? props.rejected(error) : props.rejected ?? null;
|
|
657
|
-
}
|
|
658
|
-
function Resolve(props) {
|
|
659
|
-
if (props.value.state === "fulfilled") return props.children(props.value.value);
|
|
660
|
-
if (props.value.state === "rejected") return rejectedChild(props, props.value.error);
|
|
661
|
-
const renderContext = getActiveRenderContext();
|
|
662
|
-
if (renderContext) {
|
|
663
|
-
const id = `d:${renderContext.deferredBoundaries.length}`;
|
|
664
|
-
renderContext.deferredBoundaries.push({
|
|
665
|
-
id,
|
|
666
|
-
promise: props.value.promise,
|
|
667
|
-
fulfilled: (value) => props.children(value),
|
|
668
|
-
rejected: (error) => rejectedChild(props, error)
|
|
669
|
-
});
|
|
670
|
-
return {
|
|
671
|
-
type: DEFERRED_BOUNDARY,
|
|
672
|
-
props: {
|
|
673
|
-
id,
|
|
674
|
-
pending: props.pending ?? null
|
|
675
|
-
}
|
|
676
|
-
};
|
|
677
|
-
}
|
|
678
|
-
const result = resource(() => props.value.promise, [props.value]);
|
|
679
|
-
if (result.error) return rejectedChild(props, result.error);
|
|
680
|
-
if (result.pending || result.value === null) return props.pending ?? null;
|
|
681
|
-
return props.children(result.value);
|
|
682
|
-
}
|
|
683
|
-
//#endregion
|
|
684
|
-
export { getExecutionModel as A, currentAuth as C, _preloadRouteHandler as D, getRenderHandler as E, lazy as O, pageRenderEnvelope as S, createRouteHandler as T, validateRouteHydrationData as _, resolveDeferredValues as a, isEmptyPageRenderEnvelope as b, _applyManifest as c, getRouteRenderContext as d, getRouteRenderData as f, prepareRouteHydrationData as g, getRouteHydrationMetadata as h, isDeferred as i, assertExecutionModel as k, createRouteRegistry as l, resolveRouteRequest as m, Resolve as n, reviveDeferredValue as o, hasRouteRenderData as p, defer as r, routeData as s, DEFERRED_BOUNDARY as t, bindResolvedRouteData as u, withoutRouteHydrationMetadata as v, Outlet as w, isPageRenderEnvelope as x, createPageRenderEnvelope as y };
|
|
514
|
+
export { createRouteHandler as _, resolveRouteRequest as a, lazy as b, prepareRouteHydrationData as c, DEFERRED_BOUNDARY as d, defer as f, Outlet as g, currentAuth as h, hasRouteRenderData as i, validateRouteHydrationData as l, reviveDeferredValue as m, getRouteRenderContext as n, getRouteHydrationMetadata as o, isDeferred as p, getRouteRenderData as r, guardHydratedRouteData as s, bindResolvedRouteData as t, withoutRouteHydrationMetadata as u, getRenderHandler as v, _preloadRouteHandler as y };
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import { t as enqueueRuntimeLane, v as logger } from "./access-Dpfoi4cA.js";
|
|
2
|
+
import { f as getCurrentComponentInstance } from "./component-scope-DzJEbYGE.js";
|
|
3
|
+
import { c as registerCommitOperationForInstance, d as getCurrentContextFrame, v as withAsyncResourceContext } from "./component-internal-uVCJAre6.js";
|
|
4
|
+
import { p as isPromiseLike } from "./lifecycle-batch-Dfpid9-A.js";
|
|
5
|
+
import { t as brandSnapshotSource } from "./snapshot-source-BB42xgwb.js";
|
|
6
|
+
import { a as getResourceVerificationSnapshot, i as getNextRenderKey, n as getActiveRenderContext, o as isHydrationVerificationRender, p as throwSSRDataMissing, r as getCurrentRenderData, s as recordResourceVerificationSnapshot, x as SSRDataMissingError } from "./render-context-D0Hoj9dW.js";
|
|
7
|
+
import { t as state } from "./state-DCjONcHK.js";
|
|
8
|
+
//#region src/runtime/resource-cell.ts
|
|
9
|
+
/**
|
|
10
|
+
* Pure, component-agnostic ResourceCell state machine.
|
|
11
|
+
* - Holds value/pending/error/generation/controller
|
|
12
|
+
* - Exposes a stable `snapshot` object: { value, pending, error, refresh }
|
|
13
|
+
* - Uses `withAsyncResourceContext` to bind the synchronous execution step
|
|
14
|
+
* to a captured frame. Continuations after await do not see the frame.
|
|
15
|
+
*/
|
|
16
|
+
var ResourceCell = class {
|
|
17
|
+
constructor(fn, deps, resourceFrame) {
|
|
18
|
+
this.value = null;
|
|
19
|
+
this.pending = true;
|
|
20
|
+
this.error = null;
|
|
21
|
+
this.generation = 0;
|
|
22
|
+
this.controller = null;
|
|
23
|
+
this.deps = null;
|
|
24
|
+
this.resourceFrame = null;
|
|
25
|
+
this.subscribers = /* @__PURE__ */ new Set();
|
|
26
|
+
this.disposed = false;
|
|
27
|
+
this.fn = fn;
|
|
28
|
+
this.deps = deps ? deps.slice() : null;
|
|
29
|
+
this.resourceFrame = resourceFrame;
|
|
30
|
+
this.snapshot = brandSnapshotSource({
|
|
31
|
+
value: null,
|
|
32
|
+
pending: true,
|
|
33
|
+
error: null,
|
|
34
|
+
refresh: () => this.refresh()
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
setLoader(fn) {
|
|
38
|
+
this.fn = fn;
|
|
39
|
+
}
|
|
40
|
+
subscribe(cb) {
|
|
41
|
+
this.subscribers.add(cb);
|
|
42
|
+
return () => this.subscribers.delete(cb);
|
|
43
|
+
}
|
|
44
|
+
notifySubscribers() {
|
|
45
|
+
this.snapshot.value = this.value;
|
|
46
|
+
this.snapshot.pending = this.pending;
|
|
47
|
+
this.snapshot.error = this.error;
|
|
48
|
+
for (const cb of this.subscribers) cb();
|
|
49
|
+
}
|
|
50
|
+
start(ssr = false, notify = true) {
|
|
51
|
+
if (this.disposed) return;
|
|
52
|
+
const generation = this.generation;
|
|
53
|
+
this.controller?.abort();
|
|
54
|
+
const controller = new AbortController();
|
|
55
|
+
this.controller = controller;
|
|
56
|
+
this.pending = true;
|
|
57
|
+
this.error = null;
|
|
58
|
+
if (notify) this.notifySubscribers();
|
|
59
|
+
let result;
|
|
60
|
+
try {
|
|
61
|
+
result = withAsyncResourceContext(this.resourceFrame, () => this.fn({ signal: controller.signal }));
|
|
62
|
+
} catch (err) {
|
|
63
|
+
this.pending = false;
|
|
64
|
+
this.error = err instanceof Error ? err : new Error(String(err));
|
|
65
|
+
if (notify) this.notifySubscribers();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (!isPromiseLike(result)) {
|
|
69
|
+
this.value = result;
|
|
70
|
+
this.pending = false;
|
|
71
|
+
this.error = null;
|
|
72
|
+
if (notify) this.notifySubscribers();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (ssr) throwSSRDataMissing();
|
|
76
|
+
Promise.resolve(result).then((val) => {
|
|
77
|
+
if (this.generation !== generation) return;
|
|
78
|
+
if (this.controller !== controller) return;
|
|
79
|
+
if (controller.signal.aborted) return;
|
|
80
|
+
this.value = val;
|
|
81
|
+
this.pending = false;
|
|
82
|
+
this.error = null;
|
|
83
|
+
this.notifySubscribers();
|
|
84
|
+
}).catch((err) => {
|
|
85
|
+
if (this.generation !== generation) return;
|
|
86
|
+
if (this.controller !== controller) return;
|
|
87
|
+
if (controller.signal.aborted || err instanceof Error && err.name === "AbortError" || typeof DOMException !== "undefined" && err instanceof DOMException && err.name === "AbortError") return;
|
|
88
|
+
this.pending = false;
|
|
89
|
+
this.error = err instanceof Error ? err : new Error(String(err));
|
|
90
|
+
try {
|
|
91
|
+
if (this.ownerName) logger.error(`[Askr] Async resource error in ${this.ownerName}:`, err);
|
|
92
|
+
else logger.error("[Askr] Async resource error:", err);
|
|
93
|
+
} catch {}
|
|
94
|
+
this.notifySubscribers();
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
refresh() {
|
|
98
|
+
if (this.disposed) return;
|
|
99
|
+
this.generation++;
|
|
100
|
+
this.controller?.abort();
|
|
101
|
+
this.start();
|
|
102
|
+
}
|
|
103
|
+
abort() {
|
|
104
|
+
this.controller?.abort();
|
|
105
|
+
}
|
|
106
|
+
dispose() {
|
|
107
|
+
if (this.disposed) return;
|
|
108
|
+
this.disposed = true;
|
|
109
|
+
this.controller?.abort();
|
|
110
|
+
this.subscribers.clear();
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region src/runtime/resource-operation.ts
|
|
115
|
+
function hydrationVerificationSnapshot() {
|
|
116
|
+
return brandSnapshotSource({
|
|
117
|
+
value: null,
|
|
118
|
+
pending: true,
|
|
119
|
+
error: null,
|
|
120
|
+
refresh: () => {}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Resource primitive — simple, deterministic async primitive
|
|
125
|
+
* Usage: resource(fn, deps)
|
|
126
|
+
* - fn receives { signal }
|
|
127
|
+
* - captures execution context once at creation (synchronous step only)
|
|
128
|
+
* - executes at most once per generation; stale async results are ignored
|
|
129
|
+
* - refresh() cancels in-flight execution, increments generation and re-runs
|
|
130
|
+
* - exposes { value, pending, error, refresh }
|
|
131
|
+
* - during SSR, async results are disallowed and will throw synchronously
|
|
132
|
+
*/
|
|
133
|
+
function resource(fn, deps = []) {
|
|
134
|
+
const instance = getCurrentComponentInstance();
|
|
135
|
+
const inst = instance;
|
|
136
|
+
if (!instance) {
|
|
137
|
+
const renderData = getCurrentRenderData()?.resources;
|
|
138
|
+
if (renderData && (getActiveRenderContext()?.resourceDataProvided || Object.keys(renderData).some((key) => key.startsWith("r:")))) {
|
|
139
|
+
const key = getNextRenderKey();
|
|
140
|
+
if (!(key in renderData)) throwSSRDataMissing();
|
|
141
|
+
const val = renderData[key];
|
|
142
|
+
return brandSnapshotSource({
|
|
143
|
+
value: val,
|
|
144
|
+
pending: false,
|
|
145
|
+
error: null,
|
|
146
|
+
refresh: () => {}
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
if (getActiveRenderContext()) throwSSRDataMissing();
|
|
150
|
+
throw new Error("[Askr] resource() must be called during component render inside an app. Do not create resources at module scope or outside render.");
|
|
151
|
+
}
|
|
152
|
+
const renderData = getCurrentRenderData()?.resources;
|
|
153
|
+
const hasPreloadedResourceData = Boolean(renderData && (getActiveRenderContext()?.resourceDataProvided || Object.keys(renderData).some((key) => key.startsWith("r:"))));
|
|
154
|
+
const renderKey = inst.ssr || hasPreloadedResourceData ? getNextRenderKey() : null;
|
|
155
|
+
const verificationSnapshot = renderKey ? getResourceVerificationSnapshot(renderKey) : null;
|
|
156
|
+
if (renderData && hasPreloadedResourceData && renderKey && renderKey in renderData) {
|
|
157
|
+
const val = renderData[renderKey];
|
|
158
|
+
const h = state({
|
|
159
|
+
cell: void 0,
|
|
160
|
+
snapshot: brandSnapshotSource({
|
|
161
|
+
value: val,
|
|
162
|
+
pending: false,
|
|
163
|
+
error: null,
|
|
164
|
+
refresh: () => {}
|
|
165
|
+
})
|
|
166
|
+
})();
|
|
167
|
+
h.snapshot.value = val;
|
|
168
|
+
h.snapshot.pending = false;
|
|
169
|
+
h.snapshot.error = null;
|
|
170
|
+
return h.snapshot;
|
|
171
|
+
}
|
|
172
|
+
if (isHydrationVerificationRender() && verificationSnapshot) {
|
|
173
|
+
const result = hydrationVerificationSnapshot();
|
|
174
|
+
result.value = verificationSnapshot.value;
|
|
175
|
+
result.pending = verificationSnapshot.pending;
|
|
176
|
+
return result;
|
|
177
|
+
}
|
|
178
|
+
if (renderData && hasPreloadedResourceData && renderKey && (inst.ssr || !verificationSnapshot)) throwSSRDataMissing();
|
|
179
|
+
const ssrRenderKey = inst.ssr ? renderKey : null;
|
|
180
|
+
const clientHydrationSnapshot = inst.ssr ? null : verificationSnapshot;
|
|
181
|
+
const holder = state({
|
|
182
|
+
cell: void 0,
|
|
183
|
+
snapshot: brandSnapshotSource({
|
|
184
|
+
value: clientHydrationSnapshot ? clientHydrationSnapshot.value : null,
|
|
185
|
+
pending: clientHydrationSnapshot?.pending ?? true,
|
|
186
|
+
error: null,
|
|
187
|
+
refresh: () => {}
|
|
188
|
+
})
|
|
189
|
+
});
|
|
190
|
+
const h = holder();
|
|
191
|
+
if (!h.cell) {
|
|
192
|
+
const cell = new ResourceCell(fn, deps, getCurrentContextFrame());
|
|
193
|
+
if (clientHydrationSnapshot) {
|
|
194
|
+
cell.value = clientHydrationSnapshot.value;
|
|
195
|
+
cell.pending = clientHydrationSnapshot.pending;
|
|
196
|
+
cell.snapshot.value = clientHydrationSnapshot.value;
|
|
197
|
+
cell.snapshot.pending = clientHydrationSnapshot.pending;
|
|
198
|
+
}
|
|
199
|
+
cell.ownerName = inst.fn?.name || "<anonymous>";
|
|
200
|
+
h.cell = cell;
|
|
201
|
+
h.snapshot = cell.snapshot;
|
|
202
|
+
const unsubscribe = cell.subscribe(() => {
|
|
203
|
+
const cur = holder();
|
|
204
|
+
cur.snapshot.value = cell.snapshot.value;
|
|
205
|
+
cur.snapshot.pending = cell.snapshot.pending;
|
|
206
|
+
cur.snapshot.error = cell.snapshot.error;
|
|
207
|
+
holder.set(cur);
|
|
208
|
+
try {
|
|
209
|
+
inst.notifyUpdate?.();
|
|
210
|
+
} catch {}
|
|
211
|
+
});
|
|
212
|
+
(inst.cleanupFns ??= []).push(() => {
|
|
213
|
+
unsubscribe();
|
|
214
|
+
cell.dispose();
|
|
215
|
+
});
|
|
216
|
+
if (inst.ssr) {
|
|
217
|
+
cell.start(true, false);
|
|
218
|
+
if (!cell.pending) {
|
|
219
|
+
const cur = holder();
|
|
220
|
+
cur.snapshot.value = cell.value;
|
|
221
|
+
cur.snapshot.pending = cell.pending;
|
|
222
|
+
cur.snapshot.error = cell.error;
|
|
223
|
+
}
|
|
224
|
+
if (ssrRenderKey && cell.value === null && cell.error === null) recordResourceVerificationSnapshot(ssrRenderKey, {
|
|
225
|
+
value: null,
|
|
226
|
+
pending: cell.pending
|
|
227
|
+
});
|
|
228
|
+
} else {
|
|
229
|
+
const scheduledGeneration = cell.generation;
|
|
230
|
+
registerCommitOperationForInstance(inst, () => {
|
|
231
|
+
enqueueRuntimeLane("post", () => {
|
|
232
|
+
if (!inst.notifyUpdate || cell.generation !== scheduledGeneration) return;
|
|
233
|
+
try {
|
|
234
|
+
cell.start(false, false);
|
|
235
|
+
} catch (err) {
|
|
236
|
+
const cur = holder();
|
|
237
|
+
cur.snapshot.value = cell.value;
|
|
238
|
+
cur.snapshot.pending = cell.pending;
|
|
239
|
+
cur.snapshot.error = err ?? null;
|
|
240
|
+
holder.set(cur);
|
|
241
|
+
inst.notifyUpdate?.();
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (!cell.pending) {
|
|
245
|
+
const cur = holder();
|
|
246
|
+
cur.snapshot.value = cell.value;
|
|
247
|
+
cur.snapshot.pending = cell.pending;
|
|
248
|
+
cur.snapshot.error = cell.error;
|
|
249
|
+
holder.set(cur);
|
|
250
|
+
inst.notifyUpdate?.();
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
const cell = h.cell;
|
|
257
|
+
cell.setLoader(fn);
|
|
258
|
+
if (!cell.deps || cell.deps.length !== deps.length || cell.deps.some((d, i) => !Object.is(d, deps[i]))) {
|
|
259
|
+
cell.deps = deps.slice();
|
|
260
|
+
cell.generation++;
|
|
261
|
+
cell.pending = true;
|
|
262
|
+
cell.error = null;
|
|
263
|
+
h.snapshot.pending = true;
|
|
264
|
+
h.snapshot.error = null;
|
|
265
|
+
try {
|
|
266
|
+
if (inst.ssr) {
|
|
267
|
+
cell.start(true, false);
|
|
268
|
+
if (!cell.pending) {
|
|
269
|
+
const cur = holder();
|
|
270
|
+
cur.snapshot.value = cell.value;
|
|
271
|
+
cur.snapshot.pending = cell.pending;
|
|
272
|
+
cur.snapshot.error = cell.error;
|
|
273
|
+
}
|
|
274
|
+
} else {
|
|
275
|
+
const scheduledGeneration = cell.generation;
|
|
276
|
+
registerCommitOperationForInstance(inst, () => {
|
|
277
|
+
enqueueRuntimeLane("post", () => {
|
|
278
|
+
if (!inst.notifyUpdate || cell.generation !== scheduledGeneration) return;
|
|
279
|
+
cell.start(false, false);
|
|
280
|
+
if (!cell.pending) {
|
|
281
|
+
const cur = holder();
|
|
282
|
+
cur.snapshot.value = cell.value;
|
|
283
|
+
cur.snapshot.pending = cell.pending;
|
|
284
|
+
cur.snapshot.error = cell.error;
|
|
285
|
+
holder.set(cur);
|
|
286
|
+
inst.notifyUpdate?.();
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
} catch (err) {
|
|
292
|
+
if (err instanceof SSRDataMissingError) throw err;
|
|
293
|
+
cell.error = err;
|
|
294
|
+
cell.pending = false;
|
|
295
|
+
const cur = holder();
|
|
296
|
+
cur.snapshot.value = cell.value;
|
|
297
|
+
cur.snapshot.pending = cell.pending;
|
|
298
|
+
cur.snapshot.error = cell.error;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return h.snapshot;
|
|
302
|
+
}
|
|
303
|
+
//#endregion
|
|
304
|
+
export { resource as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ut as getSignal } from "../index-
|
|
2
|
-
import { i as onRouteChange, n as RouteChangeOptions, t as RouteChangeCleanup } from "../activity-
|
|
1
|
+
import { ut as getSignal } from "../index-BvNkcegT.js";
|
|
2
|
+
import { i as onRouteChange, n as RouteChangeOptions, t as RouteChangeCleanup } from "../activity-DNYL__cW.js";
|
|
3
3
|
//#region src/runtime/resource-operation.d.ts
|
|
4
4
|
interface ResourceResult<T> {
|
|
5
5
|
value: T | null;
|
package/dist/resources/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as enqueueRuntimeLane } from "../access-Dpfoi4cA.js";
|
|
2
2
|
import { f as getCurrentComponentInstance, g as getSignal, i as claimHookIndex } from "../component-scope-DzJEbYGE.js";
|
|
3
|
-
import { a as registerCommitOperation } from "../component-internal-
|
|
4
|
-
import {
|
|
5
|
-
import { a as task, i as routeActive, n as documentVisible, o as timer, r as on, s as windowFocused, t as capture } from "../lifecycle-operations-
|
|
6
|
-
import { n as onRouteChange } from "../activity-
|
|
3
|
+
import { a as registerCommitOperation } from "../component-internal-uVCJAre6.js";
|
|
4
|
+
import { t as resource } from "../resource-operation-B94oj6xT.js";
|
|
5
|
+
import { a as task, i as routeActive, n as documentVisible, o as timer, r as on, s as windowFocused, t as capture } from "../lifecycle-operations-DTO93Hrl.js";
|
|
6
|
+
import { n as onRouteChange } from "../activity-BnkhdIXm.js";
|
|
7
7
|
//#region src/runtime/stream-operation.ts
|
|
8
8
|
function toError(value) {
|
|
9
9
|
return value instanceof Error ? value : new Error(String(value));
|