@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.
- package/CHANGELOG.md +874 -0
- package/README.md +61 -29
- package/capabilities.json +19 -9
- package/dist/actions/index.js +56 -12
- package/dist/benchmark.js +10 -15
- package/dist/boot/index.d.ts +3 -2
- package/dist/boot/index.js +1 -1
- package/dist/boot-DaoTYoCw.js +3989 -0
- package/dist/browser-activity-CB8e-V4f.js +220 -0
- package/dist/components/index.d.ts +8 -1
- package/dist/components/index.js +1 -43
- package/dist/{aria-hKjThHcp.js → compose-ref-DWzdbxsD.js} +41 -4
- package/dist/control/index.d.ts +2 -0
- package/dist/control/index.js +1 -1
- package/dist/control-nfpT2fbK.js +209 -0
- package/dist/core.d.ts +5 -9
- package/dist/csp-nonce-DwGw1A6Q.js +35 -0
- package/dist/data/index.js +3 -3
- package/dist/{data-2edW0jhF.js → data-BCwClJiF.js} +283 -94
- package/dist/data-runtime-C1bFAlba.js +242 -0
- package/dist/{deferred-CbgNhf67.js → deferred-bEEHHvic.js} +42 -20
- package/dist/domains/actions.d.ts +8 -3
- package/dist/domains/component.d.ts +1 -107
- package/dist/domains/context.d.ts +0 -15
- package/dist/domains/control.d.ts +36 -249
- package/dist/domains/data.d.ts +31 -13
- package/dist/domains/diagnostics.d.ts +1 -2
- package/dist/domains/lifecycle.d.ts +2 -5
- package/dist/domains/refs.d.ts +0 -2
- package/dist/domains/routing.d.ts +43 -8
- package/dist/domains/scheduler.d.ts +1 -76
- package/dist/domains/server.d.ts +5 -2
- package/dist/domains/state.d.ts +2 -5
- package/dist/domains/telemetry.d.ts +0 -2
- package/dist/elements.d.ts +214 -51
- package/dist/error-boundary-Bpwofwps.js +293 -0
- package/dist/foundations/icon/index.d.ts +0 -58
- package/dist/foundations/icon/index.js +2 -2
- package/dist/foundations/index.js +2 -1
- package/dist/foundations/interactions/index.js +1 -1
- package/dist/foundations/state/index.d.ts +3 -3
- package/dist/foundations/state/index.js +5 -3
- package/dist/foundations/structures/index.js +2 -1
- package/dist/foundations/utilities/index.d.ts +2 -0
- package/dist/foundations/utilities/index.js +1 -2
- package/dist/fx/index.d.ts +31 -58
- package/dist/fx/index.js +313 -195
- package/dist/hooks-BimKStr4.js +202 -0
- package/dist/index.d.ts +11 -74
- package/dist/index.js +8 -447
- package/dist/instance-BAnfmXOR.js +988 -0
- package/dist/{interactions-CTeACdT_.js → interactions-D2BoREb-.js} +3 -2
- package/dist/jsx-dev-runtime.d.ts +41 -18
- package/dist/jsx-dev-runtime.js +1 -6
- package/dist/{jsx-runtime-CPJXAOBF.js → jsx-runtime-C4idqHY0.js} +18 -7
- package/dist/jsx-runtime.js +1 -1
- package/dist/jsx.d.ts +61 -37
- package/dist/{manifest-D1P3UNWV.js → manifest-CW9gyNBY.js} +3 -3
- package/dist/{navigate-prC5V8XV.js → navigate-CP_0Zy5U.js} +454 -87
- package/dist/navigation.d.ts +12 -3
- package/dist/peer-types.d.ts +8 -0
- package/dist/portal-DuOKfnLa.js +349 -0
- package/dist/promise-Dz8iIHAm.js +16 -0
- package/dist/query-registry-WMCN0BJL.js +320 -0
- package/dist/readable-DFWOsTac.js +21 -0
- package/dist/{render-context-B7ohlh6t.js → render-context-DGHnEveC.js} +27 -11
- package/dist/render-sync-IC5lMFpq.js +1240 -0
- package/dist/resolution-Cx82-xjW.js +1244 -0
- package/dist/resource-CLjB7RBQ.js +377 -0
- package/dist/resources/index.d.ts +21 -11
- package/dist/resources/index.js +45 -244
- package/dist/router/index.d.ts +14 -5
- package/dist/router/index.js +22 -53
- package/dist/scope-CwpVSHVf.js +55 -0
- package/dist/{shared-kU8yvryp.js → shared-O2ZnmYAf.js} +1 -7
- package/dist/{snapshot-source-An4iKajG.js → snapshot-Cjx4N988.js} +6 -1
- package/dist/ssg/index.d.ts +1 -2
- package/dist/ssg/index.js +5 -13
- package/dist/ssr/index.d.ts +26 -28
- package/dist/ssr/index.js +4 -4
- package/dist/{ssr-CiNm6Vzl.js → ssr-BJ8ug7zH.js} +133 -122
- package/dist/ssr-DoV-vJ-5.js +229 -0
- package/dist/state-DWO1KzkX.js +232 -0
- package/dist/structures-D4dDMqHX.js +231 -0
- package/dist/testing/index.d.ts +8 -4
- package/dist/testing/index.js +29 -34
- package/dist/url-CnbfpX0K.js +185 -0
- package/dist/utilities.d.ts +48 -2
- package/dist/verify-hydration-DpVaDnqz.js +152 -0
- package/package.json +19 -9
- package/dist/access-CEA2pOry.js +0 -1046
- package/dist/activity-oy2YFTFF.js +0 -201
- package/dist/boot-BMBMWUGI.js +0 -1084
- package/dist/capabilities-Bbf0mlp9.js +0 -42
- package/dist/compose-ref-v0qGlHoN.js +0 -26
- package/dist/control-BR_mrX__.js +0 -173
- package/dist/control-C-ApnFs1.js +0 -20
- package/dist/csp-nonce-BfFWcd0w.js +0 -173
- package/dist/data-runtime-CxoY98lX.js +0 -149
- package/dist/default-portal-runtime-DvMvWJVp.js +0 -20
- package/dist/dom-renderer.d.ts +0 -77
- package/dist/domains/renderer.d.ts +0 -127
- package/dist/eager-control.d.ts +0 -8
- package/dist/effect-C3Zsc1k6.js +0 -292
- package/dist/for-state-BDykeOJL.js +0 -1753
- package/dist/instance-VAFYVJOa.js +0 -1027
- package/dist/notify-DxxuDPeY.js +0 -266
- package/dist/portal-w3oQ6oQU.js +0 -29
- package/dist/query-registry-LrYpQsDJ.js +0 -83
- package/dist/render-resolved-BC0W7_5b.js +0 -1123
- package/dist/renderer-CT0HeY58.js +0 -8623
- package/dist/resolution-3DskUkjG.js +0 -577
- package/dist/resource-18-sFRl9.js +0 -344
- package/dist/route-matching-CUzZ31gT.js +0 -551
- package/dist/router-internal-7nuNEHfG.js +0 -36
- package/dist/scope-Cq_iYbTR.js +0 -403
- package/dist/selector-BSPVkjKP.js +0 -311
- package/dist/ssr-EPjwJH5R.js +0 -29
- package/dist/state-BXJfudq1.js +0 -91
- package/dist/structures-CjEzfj4h.js +0 -654
- package/dist/timer-C7uqnJVt.js +0 -85
- package/dist/verify-hydration-ikaxotf7.js +0 -27
- package/dist/vnode-D24p6IW2.js +0 -7
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
import { A as untrack, F as logger, N as runWithOwner, S as queueTask, d as recordUndo } from "./instance-BAnfmXOR.js";
|
|
2
|
+
import { t as brandSnapshotSource } from "./snapshot-Cjx4N988.js";
|
|
3
|
+
import { c as onCommit, i as currentComponent, n as createSource, o as hookSlot, r as currentAppRuntime, s as notify, u as readSource } from "./hooks-BimKStr4.js";
|
|
4
|
+
import { T as SSRDataMissingError, a as getResourceVerificationSnapshot, h as throwSSRDataMissing, i as getNextRenderKey, n as getActiveRenderContext, o as isHydrationVerificationRender, r as getCurrentRenderData, s as recordResourceVerificationSnapshot } from "./render-context-DGHnEveC.js";
|
|
5
|
+
import { n as isPromiseLike } from "./promise-Dz8iIHAm.js";
|
|
6
|
+
//#region src/core/api/resource-cell.ts
|
|
7
|
+
/**
|
|
8
|
+
* Pure, component-agnostic ResourceCell state machine.
|
|
9
|
+
* - Holds value/pending/error/generation/controller
|
|
10
|
+
* - Exposes a stable `snapshot` object: { value, pending, error, refresh }
|
|
11
|
+
* - Runs the loader's synchronous step under the owner that created it, so
|
|
12
|
+
* it can read scopes; continuations after await do not.
|
|
13
|
+
*/
|
|
14
|
+
var ResourceCell = class {
|
|
15
|
+
constructor(fn, deps, owner) {
|
|
16
|
+
this.value = null;
|
|
17
|
+
this.pending = true;
|
|
18
|
+
this.error = null;
|
|
19
|
+
this.generation = 0;
|
|
20
|
+
this.controller = null;
|
|
21
|
+
this.deps = null;
|
|
22
|
+
this.owner = null;
|
|
23
|
+
this.subscribers = /* @__PURE__ */ new Set();
|
|
24
|
+
this.disposed = false;
|
|
25
|
+
this.fn = fn;
|
|
26
|
+
this.deps = deps ? deps.slice() : null;
|
|
27
|
+
this.owner = owner;
|
|
28
|
+
this.snapshot = brandSnapshotSource({
|
|
29
|
+
value: null,
|
|
30
|
+
pending: true,
|
|
31
|
+
error: null,
|
|
32
|
+
refresh: () => this.refresh()
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
setLoader(fn) {
|
|
36
|
+
this.fn = fn;
|
|
37
|
+
}
|
|
38
|
+
subscribe(cb) {
|
|
39
|
+
this.subscribers.add(cb);
|
|
40
|
+
return () => this.subscribers.delete(cb);
|
|
41
|
+
}
|
|
42
|
+
notifySubscribers() {
|
|
43
|
+
this.snapshot.value = this.value;
|
|
44
|
+
this.snapshot.pending = this.pending;
|
|
45
|
+
this.snapshot.error = this.error;
|
|
46
|
+
for (const cb of this.subscribers) try {
|
|
47
|
+
cb();
|
|
48
|
+
} catch (error) {
|
|
49
|
+
this.reportError(error, "Resource subscriber error");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
reportError(error, label = "Async resource error") {
|
|
53
|
+
try {
|
|
54
|
+
logger.error(`[Askr] ${label}${this.ownerName ? ` in ${this.ownerName}` : ""}:`, error);
|
|
55
|
+
} catch {}
|
|
56
|
+
}
|
|
57
|
+
start(ssr = false, notify = true) {
|
|
58
|
+
if (this.disposed) return;
|
|
59
|
+
const generation = this.generation;
|
|
60
|
+
const previous = this.controller;
|
|
61
|
+
const controller = new AbortController();
|
|
62
|
+
this.controller = controller;
|
|
63
|
+
const current = () => this.generation === generation && this.controller === controller && !controller.signal.aborted;
|
|
64
|
+
previous?.abort();
|
|
65
|
+
if (!current()) return;
|
|
66
|
+
this.pending = true;
|
|
67
|
+
this.error = null;
|
|
68
|
+
if (notify) this.notifySubscribers();
|
|
69
|
+
if (!current()) return;
|
|
70
|
+
const fail = (reason, asynchronous = false) => {
|
|
71
|
+
if (!current()) return;
|
|
72
|
+
let error;
|
|
73
|
+
try {
|
|
74
|
+
if (asynchronous && (reason instanceof Error && reason.name === "AbortError" || typeof DOMException !== "undefined" && reason instanceof DOMException && reason.name === "AbortError")) return;
|
|
75
|
+
error = reason instanceof Error ? reason : new Error(String(reason));
|
|
76
|
+
} catch {
|
|
77
|
+
error = /* @__PURE__ */ new Error("Resource error normalization failed");
|
|
78
|
+
}
|
|
79
|
+
if (!current()) return;
|
|
80
|
+
this.pending = false;
|
|
81
|
+
this.error = error;
|
|
82
|
+
if (asynchronous) this.reportError(reason);
|
|
83
|
+
if (current() && (notify || asynchronous)) this.notifySubscribers();
|
|
84
|
+
};
|
|
85
|
+
let result;
|
|
86
|
+
let asynchronous;
|
|
87
|
+
try {
|
|
88
|
+
result = untrack(() => runWithOwner(this.owner, () => this.fn({ signal: controller.signal })));
|
|
89
|
+
asynchronous = isPromiseLike(result);
|
|
90
|
+
} catch (err) {
|
|
91
|
+
fail(err);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (!asynchronous) {
|
|
95
|
+
if (!current()) return;
|
|
96
|
+
this.value = result;
|
|
97
|
+
this.pending = false;
|
|
98
|
+
this.error = null;
|
|
99
|
+
if (notify) this.notifySubscribers();
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (ssr) {
|
|
103
|
+
new Promise((resolve) => resolve(result)).then(void 0, () => {});
|
|
104
|
+
controller.abort();
|
|
105
|
+
throwSSRDataMissing();
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
Promise.resolve(result).then((val) => {
|
|
109
|
+
if (!current()) return;
|
|
110
|
+
this.value = val;
|
|
111
|
+
this.pending = false;
|
|
112
|
+
this.error = null;
|
|
113
|
+
this.notifySubscribers();
|
|
114
|
+
}, (err) => fail(err, true));
|
|
115
|
+
} catch (err) {
|
|
116
|
+
fail(err);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
refresh() {
|
|
120
|
+
if (this.disposed) return;
|
|
121
|
+
this.generation++;
|
|
122
|
+
this.start();
|
|
123
|
+
}
|
|
124
|
+
abort() {
|
|
125
|
+
this.controller?.abort();
|
|
126
|
+
}
|
|
127
|
+
dispose() {
|
|
128
|
+
if (this.disposed) return;
|
|
129
|
+
this.disposed = true;
|
|
130
|
+
this.controller?.abort();
|
|
131
|
+
this.subscribers.clear();
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region src/core/api/resource.ts
|
|
136
|
+
/**
|
|
137
|
+
* resource(): component-owned async data with cancellation and refresh.
|
|
138
|
+
*
|
|
139
|
+
* The loader starts after the render that declared it commits (never during
|
|
140
|
+
* render on the client). Its state lives in a stable snapshot object; the
|
|
141
|
+
* component reads a readable source alongside it, so a published result
|
|
142
|
+
* re-renders exactly the components that read the snapshot. On the server
|
|
143
|
+
* the loader must be synchronous or preloaded; SSR render keys align server
|
|
144
|
+
* values with hydration.
|
|
145
|
+
*/
|
|
146
|
+
function hydrationVerificationSnapshot() {
|
|
147
|
+
return brandSnapshotSource({
|
|
148
|
+
value: null,
|
|
149
|
+
pending: true,
|
|
150
|
+
error: null,
|
|
151
|
+
refresh: () => {}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* What resource data, if any, the current render was given.
|
|
156
|
+
*
|
|
157
|
+
* Both the outside-a-component path and the in-component path asked this
|
|
158
|
+
* question, each spelling out the same two-part test by hand. One answer keeps
|
|
159
|
+
* the "is this a hydrating render with preloaded values" decision from drifting
|
|
160
|
+
* between them.
|
|
161
|
+
*/
|
|
162
|
+
function resolveResourceRenderData(useRuntimeResources) {
|
|
163
|
+
const renderData = getCurrentRenderData()?.resources ?? (useRuntimeResources ? currentAppRuntime()?.hydrationResources : void 0);
|
|
164
|
+
return {
|
|
165
|
+
renderData,
|
|
166
|
+
hasPreloadedData: Boolean(renderData && (getActiveRenderContext()?.resourceDataProvided || Object.keys(renderData).some((key) => key.startsWith("r:"))))
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Resolve a resource declared outside any component instance.
|
|
171
|
+
*
|
|
172
|
+
* Only legitimate during a synchronous SSR render that already carries resolved
|
|
173
|
+
* data; every other caller is creating a resource where it cannot be owned.
|
|
174
|
+
*/
|
|
175
|
+
function resolveResourceWithoutInstance() {
|
|
176
|
+
const { renderData, hasPreloadedData } = resolveResourceRenderData(false);
|
|
177
|
+
if (renderData && hasPreloadedData) {
|
|
178
|
+
const key = getNextRenderKey();
|
|
179
|
+
if (!(key in renderData)) throwSSRDataMissing();
|
|
180
|
+
return brandSnapshotSource({
|
|
181
|
+
value: renderData[key],
|
|
182
|
+
pending: false,
|
|
183
|
+
error: null,
|
|
184
|
+
refresh: () => {}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
if (getActiveRenderContext()) throwSSRDataMissing();
|
|
188
|
+
throw new Error("[Askr] resource() must be called during component render inside an app. Do not create resources at module scope or outside render.");
|
|
189
|
+
}
|
|
190
|
+
function resource(sourceOrLoader, depsOrLoader) {
|
|
191
|
+
if (typeof depsOrLoader === "function") {
|
|
192
|
+
if (!currentComponent()) return resolveResourceWithoutInstance();
|
|
193
|
+
const source = sourceOrLoader;
|
|
194
|
+
const load = depsOrLoader;
|
|
195
|
+
const value = source();
|
|
196
|
+
return createResource(({ signal }) => load(value, { signal }), [value]);
|
|
197
|
+
}
|
|
198
|
+
return createResource(sourceOrLoader, depsOrLoader ?? []);
|
|
199
|
+
}
|
|
200
|
+
/** Restore render-time snapshot edits when the render transaction is discarded. */
|
|
201
|
+
function journalSnapshot(snapshot) {
|
|
202
|
+
const previous = {
|
|
203
|
+
value: snapshot.value,
|
|
204
|
+
pending: snapshot.pending,
|
|
205
|
+
error: snapshot.error
|
|
206
|
+
};
|
|
207
|
+
recordUndo(() => {
|
|
208
|
+
snapshot.value = previous.value;
|
|
209
|
+
snapshot.pending = previous.pending;
|
|
210
|
+
snapshot.error = previous.error;
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
function createResource(fn, deps = []) {
|
|
214
|
+
const instance = currentComponent();
|
|
215
|
+
if (!instance) return resolveResourceWithoutInstance();
|
|
216
|
+
const inst = instance;
|
|
217
|
+
const { renderData, hasPreloadedData: hasPreloadedResourceData } = resolveResourceRenderData(inst.hydrationResourceKeys !== null);
|
|
218
|
+
const componentKey = inst.hydrationResourceKeys === null ? void 0 : inst.hydrationResourceKeys[inst.hydrationResourceIndex++];
|
|
219
|
+
if (inst.hydrationResourceKeys !== null && !componentKey) throwSSRDataMissing();
|
|
220
|
+
const renderKey = componentKey ?? (inst.server || hasPreloadedResourceData ? getNextRenderKey() : null);
|
|
221
|
+
if (inst.server && renderKey) inst.serverResourceKeys.push(renderKey);
|
|
222
|
+
const verificationSnapshot = renderKey ? getResourceVerificationSnapshot(renderKey, getCurrentRenderData()?.framework ?? (inst.hydrationResourceKeys !== null ? currentAppRuntime()?.framework : void 0)) : null;
|
|
223
|
+
const preloaded = renderData && hasPreloadedResourceData && renderKey && renderKey in renderData ? {
|
|
224
|
+
value: renderData[renderKey],
|
|
225
|
+
pending: false
|
|
226
|
+
} : null;
|
|
227
|
+
if (!preloaded && isHydrationVerificationRender() && verificationSnapshot) {
|
|
228
|
+
const result = hydrationVerificationSnapshot();
|
|
229
|
+
result.value = verificationSnapshot.value;
|
|
230
|
+
result.pending = verificationSnapshot.pending;
|
|
231
|
+
return result;
|
|
232
|
+
}
|
|
233
|
+
if (!preloaded && renderData && hasPreloadedResourceData && renderKey && (inst.server || !verificationSnapshot)) throwSSRDataMissing();
|
|
234
|
+
const ssrRenderKey = inst.server ? renderKey : null;
|
|
235
|
+
let seed = null;
|
|
236
|
+
if (preloaded) seed = preloaded;
|
|
237
|
+
else if (!inst.server && verificationSnapshot) seed = {
|
|
238
|
+
value: verificationSnapshot.value,
|
|
239
|
+
pending: verificationSnapshot.pending
|
|
240
|
+
};
|
|
241
|
+
const h = hookSlot(inst, "resource", () => ({
|
|
242
|
+
cell: void 0,
|
|
243
|
+
uncommittedDeps: false,
|
|
244
|
+
source: createSource(),
|
|
245
|
+
snapshot: brandSnapshotSource({
|
|
246
|
+
value: seed ? seed.value : null,
|
|
247
|
+
pending: seed?.pending ?? true,
|
|
248
|
+
error: null,
|
|
249
|
+
refresh: () => {}
|
|
250
|
+
})
|
|
251
|
+
}));
|
|
252
|
+
readSource(h.source);
|
|
253
|
+
const publish = () => notify(h.source);
|
|
254
|
+
if (!h.cell) {
|
|
255
|
+
const cell = new ResourceCell(fn, deps, inst);
|
|
256
|
+
if (seed) {
|
|
257
|
+
cell.value = seed.value;
|
|
258
|
+
cell.pending = seed.pending;
|
|
259
|
+
cell.snapshot.value = seed.value;
|
|
260
|
+
cell.snapshot.pending = seed.pending;
|
|
261
|
+
}
|
|
262
|
+
cell.ownerName = inst.displayName || "<anonymous>";
|
|
263
|
+
h.cell = cell;
|
|
264
|
+
h.snapshot = cell.snapshot;
|
|
265
|
+
const unsubscribe = cell.subscribe(() => {
|
|
266
|
+
h.snapshot.value = cell.snapshot.value;
|
|
267
|
+
h.snapshot.pending = cell.snapshot.pending;
|
|
268
|
+
h.snapshot.error = cell.snapshot.error;
|
|
269
|
+
publish();
|
|
270
|
+
});
|
|
271
|
+
inst.onCleanup(unsubscribe);
|
|
272
|
+
inst.onCleanup(() => cell.dispose());
|
|
273
|
+
if (!preloaded && inst.server) {
|
|
274
|
+
cell.start(true, false);
|
|
275
|
+
if (!cell.pending) {
|
|
276
|
+
h.snapshot.value = cell.value;
|
|
277
|
+
h.snapshot.pending = cell.pending;
|
|
278
|
+
h.snapshot.error = cell.error;
|
|
279
|
+
}
|
|
280
|
+
if (ssrRenderKey && cell.value === null && cell.error === null) recordResourceVerificationSnapshot(ssrRenderKey, {
|
|
281
|
+
value: null,
|
|
282
|
+
pending: cell.pending
|
|
283
|
+
});
|
|
284
|
+
} else if (!preloaded) {
|
|
285
|
+
const scheduledGeneration = cell.generation;
|
|
286
|
+
onCommit(inst, () => {
|
|
287
|
+
queueTask(() => {
|
|
288
|
+
if (inst.disposed || cell.generation !== scheduledGeneration) return;
|
|
289
|
+
try {
|
|
290
|
+
cell.start(false, false);
|
|
291
|
+
} catch (err) {
|
|
292
|
+
h.snapshot.value = cell.value;
|
|
293
|
+
h.snapshot.pending = cell.pending;
|
|
294
|
+
h.snapshot.error = err ?? null;
|
|
295
|
+
publish();
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
if (!cell.pending) {
|
|
299
|
+
h.snapshot.value = cell.value;
|
|
300
|
+
h.snapshot.pending = cell.pending;
|
|
301
|
+
h.snapshot.error = cell.error;
|
|
302
|
+
publish();
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
const cell = h.cell;
|
|
309
|
+
if (!cell.deps || cell.deps.length !== deps.length || cell.deps.some((d, i) => !Object.is(d, deps[i]))) {
|
|
310
|
+
journalSnapshot(h.snapshot);
|
|
311
|
+
h.snapshot.pending = true;
|
|
312
|
+
h.snapshot.error = null;
|
|
313
|
+
try {
|
|
314
|
+
if (inst.server) {
|
|
315
|
+
cell.setLoader(fn);
|
|
316
|
+
cell.deps = deps.slice();
|
|
317
|
+
cell.generation++;
|
|
318
|
+
cell.pending = true;
|
|
319
|
+
cell.error = null;
|
|
320
|
+
cell.start(true, false);
|
|
321
|
+
if (!cell.pending) {
|
|
322
|
+
h.snapshot.value = cell.value;
|
|
323
|
+
h.snapshot.pending = cell.pending;
|
|
324
|
+
h.snapshot.error = cell.error;
|
|
325
|
+
}
|
|
326
|
+
} else {
|
|
327
|
+
const nextDeps = deps.slice();
|
|
328
|
+
const hadUncommittedDeps = h.uncommittedDeps;
|
|
329
|
+
h.uncommittedDeps = true;
|
|
330
|
+
recordUndo(() => {
|
|
331
|
+
h.uncommittedDeps = hadUncommittedDeps;
|
|
332
|
+
});
|
|
333
|
+
onCommit(inst, () => {
|
|
334
|
+
h.uncommittedDeps = false;
|
|
335
|
+
cell.setLoader(fn);
|
|
336
|
+
cell.deps = nextDeps;
|
|
337
|
+
cell.generation++;
|
|
338
|
+
cell.pending = true;
|
|
339
|
+
cell.error = null;
|
|
340
|
+
const scheduledGeneration = cell.generation;
|
|
341
|
+
queueTask(() => {
|
|
342
|
+
if (inst.disposed || cell.generation !== scheduledGeneration) return;
|
|
343
|
+
cell.start(false, false);
|
|
344
|
+
if (!cell.pending) {
|
|
345
|
+
h.snapshot.value = cell.value;
|
|
346
|
+
h.snapshot.pending = cell.pending;
|
|
347
|
+
h.snapshot.error = cell.error;
|
|
348
|
+
publish();
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
} catch (err) {
|
|
354
|
+
if (err instanceof SSRDataMissingError) throw err;
|
|
355
|
+
cell.error = err;
|
|
356
|
+
cell.pending = false;
|
|
357
|
+
h.snapshot.value = cell.value;
|
|
358
|
+
h.snapshot.pending = cell.pending;
|
|
359
|
+
h.snapshot.error = cell.error;
|
|
360
|
+
}
|
|
361
|
+
} else {
|
|
362
|
+
onCommit(inst, () => cell.setLoader(fn));
|
|
363
|
+
if (h.uncommittedDeps) {
|
|
364
|
+
const hadUncommittedDeps = h.uncommittedDeps;
|
|
365
|
+
journalSnapshot(h.snapshot);
|
|
366
|
+
h.uncommittedDeps = false;
|
|
367
|
+
recordUndo(() => {
|
|
368
|
+
h.uncommittedDeps = hadUncommittedDeps;
|
|
369
|
+
});
|
|
370
|
+
h.snapshot.pending = cell.pending;
|
|
371
|
+
h.snapshot.error = cell.error;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return h.snapshot;
|
|
375
|
+
}
|
|
376
|
+
//#endregion
|
|
377
|
+
export { resource as t };
|
|
@@ -11,16 +11,10 @@ import {
|
|
|
11
11
|
documentVisible,
|
|
12
12
|
task,
|
|
13
13
|
watch,
|
|
14
|
-
getSignal,
|
|
15
14
|
WatchContext,
|
|
16
15
|
windowFocused,
|
|
17
16
|
timer,
|
|
18
17
|
} from '../core.js';
|
|
19
|
-
import {
|
|
20
|
-
onRouteChange,
|
|
21
|
-
RouteChangeOptions,
|
|
22
|
-
RouteChangeCleanup,
|
|
23
|
-
} from '../route-activity.js';
|
|
24
18
|
/** Reactive result of a {@link resource}: current value, loading state, and controls. */
|
|
25
19
|
interface ResourceResult<T> {
|
|
26
20
|
value: T | null;
|
|
@@ -28,11 +22,22 @@ interface ResourceResult<T> {
|
|
|
28
22
|
error: Error | null;
|
|
29
23
|
refresh(): void;
|
|
30
24
|
}
|
|
25
|
+
/** Create a source-driven resource whose loader receives the latest source value. */
|
|
26
|
+
declare function resource<TSource, T>(
|
|
27
|
+
source: () => TSource,
|
|
28
|
+
load: (value: TSource, opts: { signal: AbortSignal }) => PromiseLike<T> | T
|
|
29
|
+
): ResourceResult<T>;
|
|
31
30
|
/** Creates a render-scoped async resource with cancellation and refresh; SSR has special data rules. */
|
|
32
|
-
declare function resource<
|
|
31
|
+
declare function resource<
|
|
32
|
+
T,
|
|
33
|
+
const TDeps extends readonly unknown[] = readonly unknown[],
|
|
34
|
+
>(
|
|
33
35
|
fn: (opts: { signal: AbortSignal }) => PromiseLike<T> | T,
|
|
34
36
|
deps: TDeps
|
|
35
37
|
): ResourceResult<T>;
|
|
38
|
+
declare function resource<T>(
|
|
39
|
+
fn: (opts: { signal: AbortSignal }) => PromiseLike<T> | T
|
|
40
|
+
): ResourceResult<T>;
|
|
36
41
|
/** Connection status of a {@link stream}. */
|
|
37
42
|
type StreamStatus =
|
|
38
43
|
| 'connecting'
|
|
@@ -58,6 +63,15 @@ interface StreamOptions<T> {
|
|
|
58
63
|
type StreamSource<T> = (context: {
|
|
59
64
|
signal: AbortSignal;
|
|
60
65
|
}) => AsyncIterable<T> | PromiseLike<AsyncIterable<T>>;
|
|
66
|
+
/** Connect a stream from an input read during a positional component render. */
|
|
67
|
+
declare function stream<TSource, T>(
|
|
68
|
+
source: () => TSource,
|
|
69
|
+
connect: (
|
|
70
|
+
value: TSource,
|
|
71
|
+
context: { signal: AbortSignal }
|
|
72
|
+
) => AsyncIterable<T> | PromiseLike<AsyncIterable<T>>,
|
|
73
|
+
options?: Omit<StreamOptions<T>, 'deps'>
|
|
74
|
+
): StreamResult<T>;
|
|
61
75
|
/** Subscribe to a streaming data source for the current component's lifetime, with auto reconnect/cleanup. */
|
|
62
76
|
declare function stream<T>(
|
|
63
77
|
source: StreamSource<T>,
|
|
@@ -67,8 +81,6 @@ export {
|
|
|
67
81
|
type ActivityPredicate,
|
|
68
82
|
type ListenerTarget,
|
|
69
83
|
type ResourceResult,
|
|
70
|
-
type RouteChangeCleanup,
|
|
71
|
-
type RouteChangeOptions,
|
|
72
84
|
type StreamOptions,
|
|
73
85
|
type StreamResult,
|
|
74
86
|
type StreamStatus,
|
|
@@ -79,9 +91,7 @@ export {
|
|
|
79
91
|
type WatchValues,
|
|
80
92
|
capture,
|
|
81
93
|
documentVisible,
|
|
82
|
-
getSignal,
|
|
83
94
|
on,
|
|
84
|
-
onRouteChange,
|
|
85
95
|
resource,
|
|
86
96
|
routeActive,
|
|
87
97
|
stream,
|