@askrjs/askr 0.0.70 → 0.0.71
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/capabilities.json +66 -0
- package/dist/actions/index.d.ts +1 -1
- package/dist/actions/index.js +9 -2
- package/dist/activity-C2tPn9Fr.js +152 -0
- package/dist/activity-DZ-NCYr8.d.ts +10 -0
- package/dist/{authoring-uaJ556aG.js → authoring-CXmUcaCe.js} +2 -2
- package/dist/benchmark.d.ts +1 -1
- package/dist/benchmark.js +6 -6
- package/dist/boot/index.d.ts +2 -2
- package/dist/boot/index.js +1 -1
- package/dist/{boot-8gP6mB3c.js → boot-DIKbEA4Y.js} +11 -10
- package/dist/{cleanup-B4BiQHx-.js → cleanup-D8Ufd9Ix.js} +16 -2
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/control/index.d.ts +1 -1
- package/dist/control/index.js +1 -1
- package/dist/{control-CA45Yvvu.js → control-DVRBkN2X.js} +7 -2
- package/dist/{csp-nonce-HGZ0vbqT.js → csp-nonce-CwSRP3Jl.js} +16 -1
- package/dist/css-BuPaTOfe.js +70 -0
- package/dist/data/index.js +3 -3
- package/dist/{data-DHt_zO1G.js → data-DFcSmGvN.js} +2 -2
- package/dist/{data-runtime-SJ1BSUvk.js → data-runtime-rpV6-3XW.js} +13 -2
- package/dist/{deferred-zHtUheIQ.js → deferred-Cr58yIQD.js} +3 -4
- package/dist/foundations/index.d.ts +1 -1
- package/dist/foundations/index.js +1 -1
- package/dist/foundations/structures/index.d.ts +1 -1
- package/dist/foundations/structures/index.js +1 -1
- package/dist/{index-BFnTM1a8.d.ts → index-BOBtoY_r.d.ts} +34 -2
- package/dist/{index-DSClfSoC.d.ts → index-DxYJPVC4.d.ts} +1 -1
- package/dist/{index-Dh6ZF9yW.d.ts → index-UmwPZ8ZN.d.ts} +5 -0
- package/dist/{index-DjusBb1I.d.ts → index-u3KYoHlM.d.ts} +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.js +12 -7
- package/dist/jsx-dev-runtime.d.ts +1 -0
- package/dist/jsx-runtime-C6Fs8Mmc.d.ts +2 -0
- package/dist/{jsx-runtime-aYZ8zb4q.d.ts → jsx-runtime-CL2r2HHQ.d.ts} +1 -0
- package/dist/jsx-runtime.d.ts +1 -1
- package/dist/{lifecycle-operations-SlPEK68H.js → lifecycle-operations-Db-_MG-O.js} +9 -12
- package/dist/{navigate-CV-RDqYP.d.ts → navigate-Cbq6QHVl.d.ts} +1 -1
- package/dist/{navigate-BTPrVhqI.js → navigate-CuGQzS_Y.js} +8 -104
- package/dist/{portal-D7TC986A.js → portal-wY3j0vvp.js} +59 -1
- package/dist/{query-registry-CQIT4mXr.js → query-registry-Bu_cuMch.js} +1 -1
- package/dist/{renderer-DF0hyjEr.js → renderer-BJYY2Y8s.js} +91 -10
- package/dist/resources/index.d.ts +27 -8
- package/dist/resources/index.js +218 -4
- package/dist/{route-matching-DLBWDeXX.js → route-matching-M-f1VQRu.js} +276 -2
- package/dist/router/index.d.ts +7 -7
- package/dist/router/index.js +28 -17
- package/dist/{router-C0XQA62W.d.ts → router-C3vENhUh.d.ts} +1 -1
- package/dist/{selector-DueeR6Oz.js → selector-DEfqO1rA.js} +8 -0
- package/dist/ssg/index.d.ts +8 -1
- package/dist/ssg/index.js +53 -17
- package/dist/ssr/index.d.ts +15 -1
- package/dist/ssr/index.js +1 -1
- package/dist/{ssr-vE-KUgDV.js → ssr-BSUA9Y64.js} +72 -78
- package/dist/testing/index.d.ts +35 -2
- package/dist/testing/index.js +182 -3
- package/dist/{verify-hydration-ChyEiBAn.js → verify-hydration-CVSGv6Vs.js} +1 -1
- package/package.json +4 -2
- package/dist/attr-names-CjhzmHOn.js +0 -15
- package/dist/component-scope-CvPba6O6.d.ts +0 -12
- package/dist/invalidation-listeners-Des3AHYs.js +0 -13
- package/dist/jsx-runtime-X2SX2y8V.d.ts +0 -2
- package/dist/resource-operation-BJiLoLYZ.js +0 -276
package/dist/testing/index.js
CHANGED
|
@@ -1,5 +1,184 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { r as computeRouteActivityMatches } from "../route-matching-
|
|
1
|
+
import { r as flushRuntimeScheduler } from "../access-ePqdQqkV.js";
|
|
2
|
+
import { r as computeRouteActivityMatches } from "../route-matching-M-f1VQRu.js";
|
|
3
|
+
import { l as addInvalidationListener } from "../data-runtime-rpV6-3XW.js";
|
|
4
|
+
import { a as cleanupApp, r as createSPA, t as createIsland } from "../boot-DIKbEA4Y.js";
|
|
5
|
+
//#region src/testing/render.ts
|
|
6
|
+
const renderStates = /* @__PURE__ */ new WeakMap();
|
|
7
|
+
const eventConstructorNames = {
|
|
8
|
+
auxclick: ["MouseEvent"],
|
|
9
|
+
click: ["MouseEvent"],
|
|
10
|
+
contextmenu: ["MouseEvent"],
|
|
11
|
+
dblclick: ["MouseEvent"],
|
|
12
|
+
mousedown: ["MouseEvent"],
|
|
13
|
+
mouseenter: ["MouseEvent"],
|
|
14
|
+
mouseleave: ["MouseEvent"],
|
|
15
|
+
mousemove: ["MouseEvent"],
|
|
16
|
+
mouseout: ["MouseEvent"],
|
|
17
|
+
mouseover: ["MouseEvent"],
|
|
18
|
+
mouseup: ["MouseEvent"],
|
|
19
|
+
pointercancel: ["PointerEvent", "MouseEvent"],
|
|
20
|
+
pointerdown: ["PointerEvent", "MouseEvent"],
|
|
21
|
+
pointerenter: ["PointerEvent", "MouseEvent"],
|
|
22
|
+
pointerleave: ["PointerEvent", "MouseEvent"],
|
|
23
|
+
pointermove: ["PointerEvent", "MouseEvent"],
|
|
24
|
+
pointerout: ["PointerEvent", "MouseEvent"],
|
|
25
|
+
pointerover: ["PointerEvent", "MouseEvent"],
|
|
26
|
+
pointerup: ["PointerEvent", "MouseEvent"],
|
|
27
|
+
keydown: ["KeyboardEvent"],
|
|
28
|
+
keypress: ["KeyboardEvent"],
|
|
29
|
+
keyup: ["KeyboardEvent"],
|
|
30
|
+
blur: ["FocusEvent"],
|
|
31
|
+
focus: ["FocusEvent"],
|
|
32
|
+
focusin: ["FocusEvent"],
|
|
33
|
+
focusout: ["FocusEvent"],
|
|
34
|
+
beforeinput: ["InputEvent"],
|
|
35
|
+
input: ["InputEvent"],
|
|
36
|
+
compositionend: ["CompositionEvent"],
|
|
37
|
+
compositionstart: ["CompositionEvent"],
|
|
38
|
+
compositionupdate: ["CompositionEvent"],
|
|
39
|
+
drag: ["DragEvent", "MouseEvent"],
|
|
40
|
+
dragend: ["DragEvent", "MouseEvent"],
|
|
41
|
+
dragenter: ["DragEvent", "MouseEvent"],
|
|
42
|
+
dragleave: ["DragEvent", "MouseEvent"],
|
|
43
|
+
dragover: ["DragEvent", "MouseEvent"],
|
|
44
|
+
dragstart: ["DragEvent", "MouseEvent"],
|
|
45
|
+
drop: ["DragEvent", "MouseEvent"],
|
|
46
|
+
touchcancel: ["TouchEvent"],
|
|
47
|
+
touchend: ["TouchEvent"],
|
|
48
|
+
touchmove: ["TouchEvent"],
|
|
49
|
+
touchstart: ["TouchEvent"],
|
|
50
|
+
wheel: ["WheelEvent", "MouseEvent"]
|
|
51
|
+
};
|
|
52
|
+
function requireDocument() {
|
|
53
|
+
if (typeof document === "undefined" || typeof document.createElement !== "function" || !document.body) throw new Error("@askrjs/askr/testing render requires a DOM environment. Configure Vitest with environment: \"jsdom\".");
|
|
54
|
+
return document;
|
|
55
|
+
}
|
|
56
|
+
function requireWindow() {
|
|
57
|
+
if (typeof window === "undefined" || !window.location || !window.history || typeof window.history.replaceState !== "function") throw new Error("@askrjs/askr/testing renderRoute requires a browser-like DOM environment. Configure Vitest with environment: \"jsdom\".");
|
|
58
|
+
return window;
|
|
59
|
+
}
|
|
60
|
+
function prepareContainer(options) {
|
|
61
|
+
const currentDocument = requireDocument();
|
|
62
|
+
const managed = options?.container === void 0;
|
|
63
|
+
const providedContainer = options?.container;
|
|
64
|
+
if (providedContainer !== void 0 && (!providedContainer || providedContainer.nodeType !== 1 || typeof providedContainer.querySelector !== "function" || typeof providedContainer.replaceChildren !== "function")) throw new TypeError("@askrjs/askr/testing render options.container must be an HTMLElement.");
|
|
65
|
+
const container = providedContainer ?? currentDocument.createElement("div");
|
|
66
|
+
if (renderStates.get(container)?.active) throw new Error("@askrjs/askr/testing cannot render into a container that already has an active render.");
|
|
67
|
+
if (managed) {
|
|
68
|
+
container.setAttribute("data-askr-testing-root", "");
|
|
69
|
+
currentDocument.body.appendChild(container);
|
|
70
|
+
}
|
|
71
|
+
const state = {
|
|
72
|
+
active: true,
|
|
73
|
+
managed
|
|
74
|
+
};
|
|
75
|
+
renderStates.set(container, state);
|
|
76
|
+
return {
|
|
77
|
+
container,
|
|
78
|
+
state
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function getBaseEventConstructor(target) {
|
|
82
|
+
if (typeof Element !== "undefined" && target instanceof Element) return target.ownerDocument.defaultView?.Event ?? Event;
|
|
83
|
+
return Event;
|
|
84
|
+
}
|
|
85
|
+
function getEventConstructor(target, type) {
|
|
86
|
+
const realm = (typeof Element !== "undefined" && target instanceof Element ? target.ownerDocument.defaultView : typeof window !== "undefined" ? window : void 0) ?? globalThis;
|
|
87
|
+
for (const name of eventConstructorNames[type] ?? []) {
|
|
88
|
+
const constructor = realm[name];
|
|
89
|
+
if (typeof constructor === "function") return constructor;
|
|
90
|
+
}
|
|
91
|
+
return getBaseEventConstructor(target);
|
|
92
|
+
}
|
|
93
|
+
function isEventForTarget(target, value) {
|
|
94
|
+
if (value instanceof getBaseEventConstructor(target)) return true;
|
|
95
|
+
return typeof Event !== "undefined" && value instanceof Event;
|
|
96
|
+
}
|
|
97
|
+
function flush() {
|
|
98
|
+
flushRuntimeScheduler();
|
|
99
|
+
}
|
|
100
|
+
function dispatch(target, event, init = {}) {
|
|
101
|
+
if (!target || typeof target.dispatchEvent !== "function") throw new TypeError("@askrjs/askr/testing dispatch requires an EventTarget.");
|
|
102
|
+
if (typeof event !== "string" && !isEventForTarget(target, event)) throw new TypeError("@askrjs/askr/testing dispatch requires an Event instance or event type string.");
|
|
103
|
+
const dispatchedEvent = typeof event === "string" ? new (getEventConstructor(target, event))(event, {
|
|
104
|
+
bubbles: true,
|
|
105
|
+
cancelable: true,
|
|
106
|
+
...init
|
|
107
|
+
}) : event;
|
|
108
|
+
return target.dispatchEvent(dispatchedEvent);
|
|
109
|
+
}
|
|
110
|
+
function cleanupContainer(container) {
|
|
111
|
+
const state = renderStates.get(container);
|
|
112
|
+
if (!state?.active) return;
|
|
113
|
+
state.active = false;
|
|
114
|
+
try {
|
|
115
|
+
cleanupApp(container);
|
|
116
|
+
} finally {
|
|
117
|
+
container.replaceChildren();
|
|
118
|
+
if (state.managed) container.remove();
|
|
119
|
+
if (state.restoreHistory && state.restoreUrl) state.restoreHistory.replaceState({}, "", state.restoreUrl);
|
|
120
|
+
renderStates.delete(container);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function isRenderResult(target) {
|
|
124
|
+
return "container" in target && "cleanup" in target;
|
|
125
|
+
}
|
|
126
|
+
function cleanup(target) {
|
|
127
|
+
cleanupContainer(isRenderResult(target) ? target.container : target);
|
|
128
|
+
}
|
|
129
|
+
function createRenderResult(container) {
|
|
130
|
+
return {
|
|
131
|
+
container,
|
|
132
|
+
root: container,
|
|
133
|
+
flush,
|
|
134
|
+
dispatch,
|
|
135
|
+
unmount: () => cleanupContainer(container),
|
|
136
|
+
cleanup: () => cleanupContainer(container)
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function render(component, options) {
|
|
140
|
+
if (typeof component !== "function") throw new TypeError("@askrjs/askr/testing render requires a component function.");
|
|
141
|
+
const { container } = prepareContainer(options);
|
|
142
|
+
try {
|
|
143
|
+
createIsland({
|
|
144
|
+
root: container,
|
|
145
|
+
component,
|
|
146
|
+
cleanupStrict: options?.cleanupStrict
|
|
147
|
+
});
|
|
148
|
+
flush();
|
|
149
|
+
return createRenderResult(container);
|
|
150
|
+
} catch (error) {
|
|
151
|
+
cleanupContainer(container);
|
|
152
|
+
throw error;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function mount(component, options) {
|
|
156
|
+
return render(component, options);
|
|
157
|
+
}
|
|
158
|
+
async function renderRoute(options) {
|
|
159
|
+
if (!options?.registry) throw new TypeError("@askrjs/askr/testing renderRoute requires a route registry.");
|
|
160
|
+
const currentWindow = requireWindow();
|
|
161
|
+
const { container, state } = prepareContainer(options);
|
|
162
|
+
try {
|
|
163
|
+
if (options.url !== void 0) {
|
|
164
|
+
state.restoreHistory = currentWindow.history;
|
|
165
|
+
state.restoreUrl = `${currentWindow.location.pathname}${currentWindow.location.search}${currentWindow.location.hash}`;
|
|
166
|
+
currentWindow.history.replaceState({}, "", options.url);
|
|
167
|
+
}
|
|
168
|
+
await createSPA({
|
|
169
|
+
root: container,
|
|
170
|
+
registry: options.registry,
|
|
171
|
+
auth: options.auth,
|
|
172
|
+
cleanupStrict: options.cleanupStrict
|
|
173
|
+
});
|
|
174
|
+
flush();
|
|
175
|
+
return createRenderResult(container);
|
|
176
|
+
} catch (error) {
|
|
177
|
+
cleanupContainer(container);
|
|
178
|
+
throw error;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
//#endregion
|
|
3
182
|
//#region src/testing/index.ts
|
|
4
183
|
function normalizeRefresh(options) {
|
|
5
184
|
return async () => {
|
|
@@ -163,4 +342,4 @@ function getRouteWarnings(options) {
|
|
|
163
342
|
});
|
|
164
343
|
}
|
|
165
344
|
//#endregion
|
|
166
|
-
export { createInvalidationRecorder, getRouteWarnings, matchRoute, mockQuery, queryState };
|
|
345
|
+
export { cleanup, createInvalidationRecorder, dispatch, flush, getRouteWarnings, matchRoute, mockQuery, mount, queryState, render, renderRoute };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as SSR_RENDER_DATA_ATTR } from "./ssr-CbQO5xd3.js";
|
|
2
|
-
import { a as renderResolvedToStringSync } from "./ssr-
|
|
2
|
+
import { a as renderResolvedToStringSync } from "./ssr-BSUA9Y64.js";
|
|
3
3
|
//#region src/ssr/verify-hydration.ts
|
|
4
4
|
function normalizeHydrationHtml(html) {
|
|
5
5
|
const template = document.createElement("template");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askrjs/askr",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.71",
|
|
4
4
|
"description": "Actor-backed deterministic UI framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"askr",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"url": "git+https://github.com/askrjs/askr.git"
|
|
24
24
|
},
|
|
25
25
|
"files": [
|
|
26
|
+
"capabilities.json",
|
|
26
27
|
"dist/**/*.js",
|
|
27
28
|
"dist/**/*.d.ts"
|
|
28
29
|
],
|
|
@@ -113,7 +114,8 @@
|
|
|
113
114
|
"types": "./dist/jsx-dev-runtime.d.ts",
|
|
114
115
|
"import": "./dist/jsx-dev-runtime.js"
|
|
115
116
|
},
|
|
116
|
-
"./package.json": "./package.json"
|
|
117
|
+
"./package.json": "./package.json",
|
|
118
|
+
"./capabilities.json": "./capabilities.json"
|
|
117
119
|
},
|
|
118
120
|
"publishConfig": {
|
|
119
121
|
"access": "public"
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
//#region src/common/attr-names.ts
|
|
2
|
-
const PUBLIC_ATTRIBUTE_NAME_MAP = {
|
|
3
|
-
className: "class",
|
|
4
|
-
htmlFor: "for",
|
|
5
|
-
strokeWidth: "stroke-width",
|
|
6
|
-
strokeLinecap: "stroke-linecap",
|
|
7
|
-
strokeLinejoin: "stroke-linejoin",
|
|
8
|
-
fillRule: "fill-rule",
|
|
9
|
-
clipRule: "clip-rule"
|
|
10
|
-
};
|
|
11
|
-
function getPublicAttributeName(propName) {
|
|
12
|
-
return PUBLIC_ATTRIBUTE_NAME_MAP[propName] ?? propName;
|
|
13
|
-
}
|
|
14
|
-
//#endregion
|
|
15
|
-
export { getPublicAttributeName as t };
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
//#region src/runtime/component-scope.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Get the abort signal for the current component.
|
|
4
|
-
*
|
|
5
|
-
* The signal is guaranteed to be aborted when:
|
|
6
|
-
* - Component unmounts
|
|
7
|
-
* - Navigation occurs (different route)
|
|
8
|
-
* - Parent is destroyed
|
|
9
|
-
*/
|
|
10
|
-
declare function getSignal(): AbortSignal;
|
|
11
|
-
//#endregion
|
|
12
|
-
export { getSignal as t };
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
//#region src/data/invalidation-listeners.ts
|
|
2
|
-
const invalidationListeners = /* @__PURE__ */ new Set();
|
|
3
|
-
function addInvalidationListener(listener) {
|
|
4
|
-
invalidationListeners.add(listener);
|
|
5
|
-
return () => {
|
|
6
|
-
invalidationListeners.delete(listener);
|
|
7
|
-
};
|
|
8
|
-
}
|
|
9
|
-
function emitInvalidation(event) {
|
|
10
|
-
for (const listener of invalidationListeners) listener(event);
|
|
11
|
-
}
|
|
12
|
-
//#endregion
|
|
13
|
-
export { emitInvalidation as n, addInvalidationListener as t };
|
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
import { t as enqueueRuntimeLane, v as logger } from "./access-ePqdQqkV.js";
|
|
2
|
-
import { c as registerCommitOperationForInstance, d as getCurrentContextFrame, g as withAsyncResourceContext } from "./component-internal-CPjM4n8M.js";
|
|
3
|
-
import { f as getCurrentComponentInstance } from "./component-scope-CC3cojX9.js";
|
|
4
|
-
import { p as isPromiseLike } from "./lifecycle-batch-COgl8jMS.js";
|
|
5
|
-
import { t as brandSnapshotSource } from "./snapshot-source-BB42xgwb.js";
|
|
6
|
-
import { i as getNextRenderKey, l as throwSSRDataMissing, n as getActiveRenderContext, r as getCurrentRenderData, u as SSRDataMissingError } from "./render-context-Clw3rFiO.js";
|
|
7
|
-
import { t as state } from "./state-CVuQVjvK.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
|
-
/**
|
|
116
|
-
* Resource primitive — simple, deterministic async primitive
|
|
117
|
-
* Usage: resource(fn, deps)
|
|
118
|
-
* - fn receives { signal }
|
|
119
|
-
* - captures execution context once at creation (synchronous step only)
|
|
120
|
-
* - executes at most once per generation; stale async results are ignored
|
|
121
|
-
* - refresh() cancels in-flight execution, increments generation and re-runs
|
|
122
|
-
* - exposes { value, pending, error, refresh }
|
|
123
|
-
* - during SSR, async results are disallowed and will throw synchronously
|
|
124
|
-
*/
|
|
125
|
-
function resource(fn, deps = []) {
|
|
126
|
-
const instance = getCurrentComponentInstance();
|
|
127
|
-
const inst = instance;
|
|
128
|
-
if (!instance) {
|
|
129
|
-
const renderData = getCurrentRenderData()?.resources;
|
|
130
|
-
if (renderData && (getActiveRenderContext()?.resourceDataProvided || Object.keys(renderData).some((key) => key.startsWith("r:")))) {
|
|
131
|
-
const key = getNextRenderKey();
|
|
132
|
-
if (!(key in renderData)) throwSSRDataMissing();
|
|
133
|
-
const val = renderData[key];
|
|
134
|
-
return brandSnapshotSource({
|
|
135
|
-
value: val,
|
|
136
|
-
pending: false,
|
|
137
|
-
error: null,
|
|
138
|
-
refresh: () => {}
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
if (getActiveRenderContext()) throwSSRDataMissing();
|
|
142
|
-
throw new Error("[Askr] resource() must be called during component render inside an app. Do not create resources at module scope or outside render.");
|
|
143
|
-
}
|
|
144
|
-
const renderData = getCurrentRenderData()?.resources;
|
|
145
|
-
if (renderData && (getActiveRenderContext()?.resourceDataProvided || Object.keys(renderData).some((key) => key.startsWith("r:")))) {
|
|
146
|
-
const key = getNextRenderKey();
|
|
147
|
-
if (!(key in renderData)) throwSSRDataMissing();
|
|
148
|
-
const val = renderData[key];
|
|
149
|
-
const h = state({
|
|
150
|
-
cell: void 0,
|
|
151
|
-
snapshot: brandSnapshotSource({
|
|
152
|
-
value: val,
|
|
153
|
-
pending: false,
|
|
154
|
-
error: null,
|
|
155
|
-
refresh: () => {}
|
|
156
|
-
})
|
|
157
|
-
})();
|
|
158
|
-
h.snapshot.value = val;
|
|
159
|
-
h.snapshot.pending = false;
|
|
160
|
-
h.snapshot.error = null;
|
|
161
|
-
return h.snapshot;
|
|
162
|
-
}
|
|
163
|
-
const holder = state({
|
|
164
|
-
cell: void 0,
|
|
165
|
-
snapshot: brandSnapshotSource({
|
|
166
|
-
value: null,
|
|
167
|
-
pending: true,
|
|
168
|
-
error: null,
|
|
169
|
-
refresh: () => {}
|
|
170
|
-
})
|
|
171
|
-
});
|
|
172
|
-
const h = holder();
|
|
173
|
-
if (!h.cell) {
|
|
174
|
-
const cell = new ResourceCell(fn, deps, getCurrentContextFrame());
|
|
175
|
-
cell.ownerName = inst.fn?.name || "<anonymous>";
|
|
176
|
-
h.cell = cell;
|
|
177
|
-
h.snapshot = cell.snapshot;
|
|
178
|
-
const unsubscribe = cell.subscribe(() => {
|
|
179
|
-
const cur = holder();
|
|
180
|
-
cur.snapshot.value = cell.snapshot.value;
|
|
181
|
-
cur.snapshot.pending = cell.snapshot.pending;
|
|
182
|
-
cur.snapshot.error = cell.snapshot.error;
|
|
183
|
-
holder.set(cur);
|
|
184
|
-
try {
|
|
185
|
-
inst.notifyUpdate?.();
|
|
186
|
-
} catch {}
|
|
187
|
-
});
|
|
188
|
-
(inst.cleanupFns ??= []).push(() => {
|
|
189
|
-
unsubscribe();
|
|
190
|
-
cell.dispose();
|
|
191
|
-
});
|
|
192
|
-
if (inst.ssr) {
|
|
193
|
-
cell.start(true, false);
|
|
194
|
-
if (!cell.pending) {
|
|
195
|
-
const cur = holder();
|
|
196
|
-
cur.snapshot.value = cell.value;
|
|
197
|
-
cur.snapshot.pending = cell.pending;
|
|
198
|
-
cur.snapshot.error = cell.error;
|
|
199
|
-
}
|
|
200
|
-
} else {
|
|
201
|
-
const scheduledGeneration = cell.generation;
|
|
202
|
-
registerCommitOperationForInstance(inst, () => {
|
|
203
|
-
enqueueRuntimeLane("post", () => {
|
|
204
|
-
if (!inst.notifyUpdate || cell.generation !== scheduledGeneration) return;
|
|
205
|
-
try {
|
|
206
|
-
cell.start(false, false);
|
|
207
|
-
} catch (err) {
|
|
208
|
-
const cur = holder();
|
|
209
|
-
cur.snapshot.value = cell.value;
|
|
210
|
-
cur.snapshot.pending = cell.pending;
|
|
211
|
-
cur.snapshot.error = err ?? null;
|
|
212
|
-
holder.set(cur);
|
|
213
|
-
inst.notifyUpdate?.();
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
if (!cell.pending) {
|
|
217
|
-
const cur = holder();
|
|
218
|
-
cur.snapshot.value = cell.value;
|
|
219
|
-
cur.snapshot.pending = cell.pending;
|
|
220
|
-
cur.snapshot.error = cell.error;
|
|
221
|
-
holder.set(cur);
|
|
222
|
-
inst.notifyUpdate?.();
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
const cell = h.cell;
|
|
229
|
-
cell.setLoader(fn);
|
|
230
|
-
if (!cell.deps || cell.deps.length !== deps.length || cell.deps.some((d, i) => !Object.is(d, deps[i]))) {
|
|
231
|
-
cell.deps = deps.slice();
|
|
232
|
-
cell.generation++;
|
|
233
|
-
cell.pending = true;
|
|
234
|
-
cell.error = null;
|
|
235
|
-
h.snapshot.pending = true;
|
|
236
|
-
h.snapshot.error = null;
|
|
237
|
-
try {
|
|
238
|
-
if (inst.ssr) {
|
|
239
|
-
cell.start(true, false);
|
|
240
|
-
if (!cell.pending) {
|
|
241
|
-
const cur = holder();
|
|
242
|
-
cur.snapshot.value = cell.value;
|
|
243
|
-
cur.snapshot.pending = cell.pending;
|
|
244
|
-
cur.snapshot.error = cell.error;
|
|
245
|
-
}
|
|
246
|
-
} else {
|
|
247
|
-
const scheduledGeneration = cell.generation;
|
|
248
|
-
registerCommitOperationForInstance(inst, () => {
|
|
249
|
-
enqueueRuntimeLane("post", () => {
|
|
250
|
-
if (!inst.notifyUpdate || cell.generation !== scheduledGeneration) return;
|
|
251
|
-
cell.start(false, false);
|
|
252
|
-
if (!cell.pending) {
|
|
253
|
-
const cur = holder();
|
|
254
|
-
cur.snapshot.value = cell.value;
|
|
255
|
-
cur.snapshot.pending = cell.pending;
|
|
256
|
-
cur.snapshot.error = cell.error;
|
|
257
|
-
holder.set(cur);
|
|
258
|
-
inst.notifyUpdate?.();
|
|
259
|
-
}
|
|
260
|
-
});
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
} catch (err) {
|
|
264
|
-
if (err instanceof SSRDataMissingError) throw err;
|
|
265
|
-
cell.error = err;
|
|
266
|
-
cell.pending = false;
|
|
267
|
-
const cur = holder();
|
|
268
|
-
cur.snapshot.value = cell.value;
|
|
269
|
-
cur.snapshot.pending = cell.pending;
|
|
270
|
-
cur.snapshot.error = cell.error;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
return h.snapshot;
|
|
274
|
-
}
|
|
275
|
-
//#endregion
|
|
276
|
-
export { resource as t };
|