@timber-js/app 0.2.0-alpha.210 → 0.2.0-alpha.212
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/agent-skill.md +10 -5
- package/dist/_chunks/{actions-Rjk4htmA.js → actions-CCdnVtWm.js} +8 -6
- package/dist/_chunks/actions-CCdnVtWm.js.map +1 -0
- package/dist/_chunks/{als-registry-DaxkVjt5.js → als-registry-BZqHCtq-.js} +2 -4
- package/dist/_chunks/als-registry-BZqHCtq-.js.map +1 -0
- package/dist/_chunks/{cache-api-DGdYfNJn.js → cache-api-LA3sBpUS.js} +5 -5
- package/dist/_chunks/{cache-api-DGdYfNJn.js.map → cache-api-LA3sBpUS.js.map} +1 -1
- package/dist/_chunks/{chains-BoO51joc.js → chains-BfoPFraI.js} +5 -146
- package/dist/_chunks/chains-BfoPFraI.js.map +1 -0
- package/dist/_chunks/classify-BT66U83D.js +147 -0
- package/dist/_chunks/classify-BT66U83D.js.map +1 -0
- package/dist/_chunks/{cli-check-ajNY3B2e.js → cli-check-BfQ54-UJ.js} +3 -3
- package/dist/_chunks/{cli-check-ajNY3B2e.js.map → cli-check-BfQ54-UJ.js.map} +1 -1
- package/dist/_chunks/{cli-schema-sync-D2eI8jEg.js → cli-schema-sync-czh2dsLs.js} +2 -2
- package/dist/_chunks/{cli-schema-sync-D2eI8jEg.js.map → cli-schema-sync-czh2dsLs.js.map} +1 -1
- package/dist/_chunks/client-dep-entries-CQwpb8dI.js +66 -0
- package/dist/_chunks/client-dep-entries-CQwpb8dI.js.map +1 -0
- package/dist/_chunks/{convention-lint-DLmhGsRS.js → convention-lint-BEVW4EID.js} +3 -3
- package/dist/_chunks/{convention-lint-DLmhGsRS.js.map → convention-lint-BEVW4EID.js.map} +1 -1
- package/dist/_chunks/{dev-server-v97rQH4b.js → dev-server-FKxptbnI.js} +2 -2
- package/dist/_chunks/{dev-server-v97rQH4b.js.map → dev-server-FKxptbnI.js.map} +1 -1
- package/dist/_chunks/{json-lossy-check-CVuRs2hG.js → json-lossy-check-C8zBY2uZ.js} +2 -2
- package/dist/_chunks/{json-lossy-check-CVuRs2hG.js.map → json-lossy-check-C8zBY2uZ.js.map} +1 -1
- package/dist/_chunks/{live-graph-9cSnn_h9.js → live-graph-C_4v-fHv.js} +4 -3
- package/dist/_chunks/{live-graph-9cSnn_h9.js.map → live-graph-C_4v-fHv.js.map} +1 -1
- package/dist/_chunks/{logger-BP0LN6vP.js → logger-CbLdcy-W.js} +2 -2
- package/dist/_chunks/{logger-BP0LN6vP.js.map → logger-CbLdcy-W.js.map} +1 -1
- package/dist/_chunks/{poison-scan-vGV7Re0B.js → poison-scan-C92liMAr.js} +2 -4
- package/dist/_chunks/poison-scan-C92liMAr.js.map +1 -0
- package/dist/_chunks/{scanner-DmqdxzbW.js → scanner-CQt12vE2.js} +2 -2
- package/dist/_chunks/{scanner-DmqdxzbW.js.map → scanner-CQt12vE2.js.map} +1 -1
- package/dist/_chunks/{sizeof-BM1409x2.js → sizeof-QPE5nd3u.js} +2 -2
- package/dist/_chunks/{sizeof-BM1409x2.js.map → sizeof-QPE5nd3u.js.map} +1 -1
- package/dist/_chunks/{walkers-Czu2jXFq.js → walkers-DAT4avhZ.js} +3 -3
- package/dist/_chunks/{walkers-Czu2jXFq.js.map → walkers-DAT4avhZ.js.map} +1 -1
- package/dist/adapters/cloudflare-kv-cache.js +1 -1
- package/dist/analyze/classify.d.ts +2 -0
- package/dist/analyze/classify.d.ts.map +1 -1
- package/dist/analyze/crawl-entry.js +3 -2
- package/dist/analyze/crawl-entry.js.map +1 -1
- package/dist/analyze/graph-command.js +2 -2
- package/dist/analyze/poison-scan.d.ts.map +1 -1
- package/dist/cache/index.js +2 -2
- package/dist/cache/stores/memory.js +1 -1
- package/dist/cdn/workers-cache-purge.js +1 -1
- package/dist/cli.js +3 -3
- package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
- package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
- package/dist/client/browser-entry/router-init.d.ts.map +1 -1
- package/dist/client/form.d.ts +17 -64
- package/dist/client/form.d.ts.map +1 -1
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +23 -51
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.js +25 -25
- package/dist/client/internal.js.map +1 -1
- package/dist/client/navigation-api.d.ts +25 -63
- package/dist/client/navigation-api.d.ts.map +1 -1
- package/dist/client/router-lifecycle.d.ts +17 -11
- package/dist/client/router-lifecycle.d.ts.map +1 -1
- package/dist/client/router-pipeline.d.ts +0 -1
- package/dist/client/router-pipeline.d.ts.map +1 -1
- package/dist/client/router-types.d.ts +14 -45
- package/dist/client/router-types.d.ts.map +1 -1
- package/dist/client/router.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -7
- package/dist/index.js.map +1 -1
- package/dist/plugins/client-dep-entries.d.ts +44 -0
- package/dist/plugins/client-dep-entries.d.ts.map +1 -0
- package/dist/plugins/content.d.ts.map +1 -1
- package/dist/plugins/entries.d.ts +6 -0
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/shims.d.ts.map +1 -1
- package/dist/routing/index.js +2 -2
- package/dist/rsc-runtime/rsc.d.ts +1 -1
- package/dist/rsc-runtime/rsc.d.ts.map +1 -1
- package/dist/server/action-client.d.ts +9 -5
- package/dist/server/action-client.d.ts.map +1 -1
- package/dist/server/action-handler.d.ts +27 -8
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +22 -2
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/client-error-message.d.ts +12 -0
- package/dist/server/client-error-message.d.ts.map +1 -0
- package/dist/server/form-state-embed.d.ts +32 -0
- package/dist/server/form-state-embed.d.ts.map +1 -0
- package/dist/server/index.d.ts +0 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +7 -40
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.js +10 -6
- package/dist/server/internal.js.map +1 -1
- package/dist/server/logger.d.ts +1 -0
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/pipeline.d.ts +20 -6
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/request-context.d.ts +27 -2
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts.map +1 -1
- package/dist/server/rsc-entry/action-dispatcher.d.ts +6 -5
- package/dist/server/rsc-entry/action-dispatcher.d.ts.map +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/ssr-bridge-types.d.ts +8 -0
- package/dist/server/ssr-bridge-types.d.ts.map +1 -1
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/ssr-render.d.ts +3 -0
- package/dist/server/ssr-render.d.ts.map +1 -1
- package/docs/api/31-api-client.mdx +9 -3
- package/docs/learn/08-forms-and-actions.mdx +21 -28
- package/package.json +1 -1
- package/src/analyze/classify.ts +1 -1
- package/src/analyze/poison-scan.ts +1 -4
- package/src/client/browser-entry/action-dispatch.ts +74 -18
- package/src/client/browser-entry/hydrate.ts +18 -0
- package/src/client/browser-entry/router-init.ts +4 -18
- package/src/client/form.tsx +33 -98
- package/src/client/index.ts +2 -2
- package/src/client/navigation-api.ts +47 -173
- package/src/client/navigation-transition.ts +2 -2
- package/src/client/router-lifecycle.ts +40 -20
- package/src/client/router-pipeline.ts +3 -9
- package/src/client/router-types.ts +14 -49
- package/src/client/router.ts +38 -58
- package/src/index.ts +21 -2
- package/src/plugins/client-dep-entries.ts +78 -0
- package/src/plugins/content.ts +26 -1
- package/src/plugins/entries.ts +7 -0
- package/src/plugins/shims.ts +0 -2
- package/src/rsc-runtime/rsc.ts +3 -0
- package/src/rsc-runtime/vendor-types.d.ts +14 -0
- package/src/server/action-client.ts +18 -20
- package/src/server/action-handler.ts +133 -95
- package/src/server/als-registry.ts +23 -9
- package/src/server/client-error-message.ts +18 -0
- package/src/server/form-state-embed.ts +63 -0
- package/src/server/index.ts +0 -4
- package/src/server/logger.ts +6 -1
- package/src/server/pipeline.ts +27 -8
- package/src/server/request-context.ts +39 -2
- package/src/server/route-element-builder.ts +12 -1
- package/src/server/rsc-entry/action-dispatcher.ts +37 -34
- package/src/server/rsc-entry/error-renderer.ts +2 -1
- package/src/server/rsc-entry/rsc-stream.ts +20 -11
- package/src/server/rsc-entry/ssr-renderer.ts +14 -1
- package/src/server/ssr-bridge-types.ts +9 -0
- package/src/server/ssr-entry.ts +1 -0
- package/src/server/ssr-render.ts +5 -0
- package/dist/_chunks/actions-Rjk4htmA.js.map +0 -1
- package/dist/_chunks/als-registry-DaxkVjt5.js.map +0 -1
- package/dist/_chunks/chains-BoO51joc.js.map +0 -1
- package/dist/_chunks/poison-scan-vGV7Re0B.js.map +0 -1
- package/dist/server/form-flash.d.ts +0 -78
- package/dist/server/form-flash.d.ts.map +0 -1
- package/src/server/form-flash.ts +0 -89
package/dist/client/internal.js
CHANGED
|
@@ -121,13 +121,16 @@ function isAbortError(error) {
|
|
|
121
121
|
if (error instanceof Error && error.name === "AbortError") return true;
|
|
122
122
|
return false;
|
|
123
123
|
}
|
|
124
|
-
function createNavigationLifecycle(
|
|
124
|
+
function createNavigationLifecycle() {
|
|
125
125
|
let current = null;
|
|
126
126
|
let pendingCommit = null;
|
|
127
127
|
let routerPhase = { phase: "idle" };
|
|
128
128
|
const pendingListeners = /* @__PURE__ */ new Set();
|
|
129
129
|
let navigationSeq = 0;
|
|
130
130
|
let idleTask = null;
|
|
131
|
+
const idleListeners = /* @__PURE__ */ new Set();
|
|
132
|
+
const treeCommitListeners = /* @__PURE__ */ new Set();
|
|
133
|
+
const ownerSeq = /* @__PURE__ */ new WeakMap();
|
|
131
134
|
/**
|
|
132
135
|
* Whether a handed-off tree has not yet committed. Derived from the slot:
|
|
133
136
|
* true when `current` is handed off but not yet settled.
|
|
@@ -155,23 +158,18 @@ function createNavigationLifecycle(deps) {
|
|
|
155
158
|
* in-flight navigation. Optionally links to an external signal (e.g.,
|
|
156
159
|
* from the Navigation API's NavigateEvent.signal).
|
|
157
160
|
*
|
|
158
|
-
* Superseding is one operation with
|
|
161
|
+
* Superseding is one operation with two parts:
|
|
159
162
|
* 1. Abort the previous navigation's fetch — UNLESS its tree is the one on
|
|
160
163
|
* screen, in which case tearing the stream down would error the page the
|
|
161
164
|
* user is currently looking at. See `RenderOwner.handedOff`.
|
|
162
165
|
* 2. Settle the previous owner as 'superseded' so its transition detects
|
|
163
166
|
* it lost and never hands a stale tree to React. This replaces both
|
|
164
167
|
* `supersedeNavigationTransitions()` and the transition counter bump.
|
|
165
|
-
* 3. Resolve its Navigation API deferred — the superseded navigation's
|
|
166
|
-
* finally block is staleness-guarded (see TIM-1034) and no longer
|
|
167
|
-
* cleans up after itself, so the browser's native loading state for
|
|
168
|
-
* the dead navigation is cleared here.
|
|
169
168
|
*/
|
|
170
169
|
function createNavOwner(kind, externalSignal) {
|
|
171
170
|
if (current) {
|
|
172
171
|
abortUnlessHandedOff(current);
|
|
173
172
|
current.settle("superseded");
|
|
174
|
-
deps.completeRouterNavigation?.();
|
|
175
173
|
}
|
|
176
174
|
if (pendingCommit) {
|
|
177
175
|
pendingCommit.settle("superseded");
|
|
@@ -179,6 +177,7 @@ function createNavigationLifecycle(deps) {
|
|
|
179
177
|
}
|
|
180
178
|
navigationSeq += 1;
|
|
181
179
|
const owner = createRenderOwner(kind);
|
|
180
|
+
ownerSeq.set(owner, navigationSeq);
|
|
182
181
|
current = owner;
|
|
183
182
|
if (externalSignal) {
|
|
184
183
|
if (externalSignal.aborted) abortUnlessHandedOff(owner);
|
|
@@ -214,13 +213,14 @@ function createNavigationLifecycle(deps) {
|
|
|
214
213
|
if (current === owner) {
|
|
215
214
|
current = null;
|
|
216
215
|
setPending(false);
|
|
217
|
-
deps.completeRouterNavigation?.();
|
|
218
216
|
flushIdleTask();
|
|
219
217
|
}
|
|
220
218
|
}
|
|
221
219
|
}
|
|
222
220
|
function flushIdleTask() {
|
|
223
|
-
if (routerPhase.phase !== "idle" || hasUncommittedNav()
|
|
221
|
+
if (routerPhase.phase !== "idle" || hasUncommittedNav()) return;
|
|
222
|
+
for (const listener of [...idleListeners]) listener();
|
|
223
|
+
if (!idleTask) return;
|
|
224
224
|
const task = idleTask;
|
|
225
225
|
idleTask = null;
|
|
226
226
|
task();
|
|
@@ -237,9 +237,12 @@ function createNavigationLifecycle(deps) {
|
|
|
237
237
|
forgetOlderHandoffs(owner) {
|
|
238
238
|
owner.settle("committed");
|
|
239
239
|
if (pendingCommit === owner) pendingCommit = null;
|
|
240
|
+
const seq = ownerSeq.get(owner) ?? navigationSeq;
|
|
241
|
+
for (const listener of [...treeCommitListeners]) listener(seq);
|
|
240
242
|
flushIdleTask();
|
|
241
243
|
},
|
|
242
244
|
placeRevalidationOwner(owner) {
|
|
245
|
+
ownerSeq.set(owner, navigationSeq);
|
|
243
246
|
current = owner;
|
|
244
247
|
},
|
|
245
248
|
isPending: () => routerPhase.phase === "navigating",
|
|
@@ -264,6 +267,14 @@ function createNavigationLifecycle(deps) {
|
|
|
264
267
|
}
|
|
265
268
|
idleTask = task;
|
|
266
269
|
},
|
|
270
|
+
onIdle(listener) {
|
|
271
|
+
idleListeners.add(listener);
|
|
272
|
+
return () => idleListeners.delete(listener);
|
|
273
|
+
},
|
|
274
|
+
onTreeCommit(listener) {
|
|
275
|
+
treeCommitListeners.add(listener);
|
|
276
|
+
return () => treeCommitListeners.delete(listener);
|
|
277
|
+
},
|
|
267
278
|
settleHandoffs() {
|
|
268
279
|
if (pendingCommit) {
|
|
269
280
|
pendingCommit.settle("superseded");
|
|
@@ -461,9 +472,7 @@ function createNavigationPipeline({ deps, prefetchCache, currentStateTree, prepa
|
|
|
461
472
|
result = await fetchRscPayload(url, deps, freshStateTree, currentUrl, options.signal);
|
|
462
473
|
}
|
|
463
474
|
const commitHistoryUrl = () => {
|
|
464
|
-
if (options.skipHistory) return;
|
|
465
475
|
const commitUrl = options.commitUrl ?? url;
|
|
466
|
-
deps.setRouterNavigating?.(true);
|
|
467
476
|
if (options.replace) deps.replaceState({
|
|
468
477
|
timber: true,
|
|
469
478
|
scrollY: 0
|
|
@@ -472,7 +481,6 @@ function createNavigationPipeline({ deps, prefetchCache, currentStateTree, prepa
|
|
|
472
481
|
timber: true,
|
|
473
482
|
scrollY: 0
|
|
474
483
|
}, "", commitUrl);
|
|
475
|
-
deps.setRouterNavigating?.(false);
|
|
476
484
|
};
|
|
477
485
|
const params = await result.params;
|
|
478
486
|
const { navState, commit } = prepareNavigation(url, {
|
|
@@ -513,7 +521,7 @@ function createRouter(deps) {
|
|
|
513
521
|
historyStack,
|
|
514
522
|
clientSegmentCache: () => deps.clientSegmentCache
|
|
515
523
|
});
|
|
516
|
-
const lifecycle = createNavigationLifecycle(
|
|
524
|
+
const lifecycle = createNavigationLifecycle();
|
|
517
525
|
const { currentOwner, createNavOwner, runNavigation, markHandedOff, forgetOlderHandoffs, isPending, getPendingUrl, onPendingChange } = lifecycle;
|
|
518
526
|
const { performNavigationFetch, renderViaTransition } = createNavigationPipeline({
|
|
519
527
|
deps,
|
|
@@ -541,13 +549,11 @@ function createRouter(deps) {
|
|
|
541
549
|
async function navigate(url, options = {}) {
|
|
542
550
|
const scroll = options.scroll !== false;
|
|
543
551
|
const replace = options.replace === true;
|
|
544
|
-
const externalSignal = options._signal;
|
|
545
|
-
const skipHistory = options._skipHistory === true;
|
|
546
552
|
const types = options._renderTypes ?? ["navigation-forward", ...options.transitionTypes ?? []];
|
|
547
553
|
const hashIndex = url.indexOf("#");
|
|
548
554
|
const hash = hashIndex === -1 ? "" : url.slice(hashIndex);
|
|
549
555
|
const fetchUrl = hashIndex === -1 ? url : url.slice(0, hashIndex);
|
|
550
|
-
const departingUrl =
|
|
556
|
+
const departingUrl = deps.getCurrentUrl();
|
|
551
557
|
const currentScrollY = deps.getScrollY();
|
|
552
558
|
if (deps.saveNavigationEntryScroll) deps.saveNavigationEntryScroll(currentScrollY);
|
|
553
559
|
else deps.replaceState({
|
|
@@ -555,20 +561,12 @@ function createRouter(deps) {
|
|
|
555
561
|
scrollY: currentScrollY
|
|
556
562
|
}, "", deps.getCurrentUrl());
|
|
557
563
|
if (isClientStale()) await leaveSpaSuperseding(url, departingUrl);
|
|
558
|
-
let effectiveSkipHistory = skipHistory;
|
|
559
564
|
await runNavigation(url, async (owner) => {
|
|
560
|
-
if (!effectiveSkipHistory && deps.navigationNavigate) {
|
|
561
|
-
deps.setRouterNavigating?.(true);
|
|
562
|
-
deps.navigationNavigate(url, replace);
|
|
563
|
-
deps.setRouterNavigating?.(false);
|
|
564
|
-
effectiveSkipHistory = true;
|
|
565
|
-
}
|
|
566
565
|
try {
|
|
567
566
|
await renderViaTransition(fetchUrl, owner, types, () => performNavigationFetch(fetchUrl, {
|
|
568
567
|
replace,
|
|
569
568
|
commitUrl: url,
|
|
570
569
|
signal: owner.fetchAbort.signal,
|
|
571
|
-
skipHistory: effectiveSkipHistory,
|
|
572
570
|
departingUrl
|
|
573
571
|
}), options.onCommit);
|
|
574
572
|
if (scroll && hash) scrollToHashAfterPaint(hash);
|
|
@@ -577,7 +575,7 @@ function createRouter(deps) {
|
|
|
577
575
|
if (await recoverFromNavigationError(error, owner, url, departingUrl, types)) return;
|
|
578
576
|
throw error;
|
|
579
577
|
}
|
|
580
|
-
}
|
|
578
|
+
});
|
|
581
579
|
}
|
|
582
580
|
/**
|
|
583
581
|
* Fetch a URL's RSC payload, commit it, and render — the pipeline shared by
|
|
@@ -717,6 +715,8 @@ function createRouter(deps) {
|
|
|
717
715
|
return outcome === "committed";
|
|
718
716
|
},
|
|
719
717
|
runWhenIdle: (task) => lifecycle.runWhenIdle(task),
|
|
718
|
+
onIdle: (listener) => lifecycle.onIdle(listener),
|
|
719
|
+
onTreeCommit: (listener) => lifecycle.onTreeCommit(listener),
|
|
720
720
|
settleHandoffs: () => lifecycle.settleHandoffs(),
|
|
721
721
|
suppressSegmentReuse() {
|
|
722
722
|
segmentCache.invalidateReuse();
|