@rangojs/router 0.0.0-experimental.d7eeaa75 → 0.0.0-experimental.dc2bd2b4
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/README.md +120 -25
- package/dist/bin/rango.js +147 -57
- package/dist/testing/vitest.js +48 -0
- package/dist/vite/index.js +2151 -846
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +57 -11
- package/skills/breadcrumbs/SKILL.md +3 -1
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +220 -30
- package/skills/caching/SKILL.md +116 -8
- package/skills/composability/SKILL.md +27 -2
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +229 -20
- package/skills/host-router/SKILL.md +45 -20
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +46 -4
- package/skills/layout/SKILL.md +28 -7
- package/skills/links/SKILL.md +247 -17
- package/skills/loader/SKILL.md +219 -9
- package/skills/middleware/SKILL.md +47 -12
- package/skills/migrate-nextjs/SKILL.md +562 -0
- package/skills/migrate-react-router/SKILL.md +769 -0
- package/skills/mime-routes/SKILL.md +27 -0
- package/skills/observability/SKILL.md +137 -0
- package/skills/parallel/SKILL.md +71 -6
- package/skills/prerender/SKILL.md +14 -33
- package/skills/rango/SKILL.md +242 -22
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +66 -9
- package/skills/route/SKILL.md +57 -4
- package/skills/router-setup/SKILL.md +3 -3
- package/skills/server-actions/SKILL.md +751 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/testing/SKILL.md +647 -0
- package/skills/typesafety/SKILL.md +319 -27
- package/skills/use-cache/SKILL.md +34 -5
- package/skills/view-transitions/SKILL.md +294 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +117 -0
- package/src/browser/action-coordinator.ts +53 -36
- package/src/browser/app-shell.ts +52 -0
- package/src/browser/event-controller.ts +86 -70
- package/src/browser/history-state.ts +21 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/navigation-bridge.ts +84 -11
- package/src/browser/navigation-client.ts +76 -28
- package/src/browser/navigation-store.ts +32 -9
- package/src/browser/navigation-transaction.ts +10 -28
- package/src/browser/partial-update.ts +64 -26
- package/src/browser/prefetch/cache.ts +129 -21
- package/src/browser/prefetch/fetch.ts +148 -16
- package/src/browser/prefetch/queue.ts +36 -5
- package/src/browser/rango-state.ts +53 -13
- package/src/browser/react/Link.tsx +30 -2
- package/src/browser/react/NavigationProvider.tsx +72 -31
- package/src/browser/react/filter-segment-order.ts +51 -7
- package/src/browser/react/index.ts +3 -0
- package/src/browser/react/location-state-shared.ts +175 -4
- package/src/browser/react/location-state.ts +39 -13
- package/src/browser/react/use-handle.ts +17 -9
- package/src/browser/react/use-navigation.ts +22 -2
- package/src/browser/react/use-params.ts +20 -8
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +22 -2
- package/src/browser/react/use-segments.ts +11 -8
- package/src/browser/response-adapter.ts +25 -0
- package/src/browser/rsc-router.tsx +64 -22
- package/src/browser/scroll-restoration.ts +22 -14
- package/src/browser/segment-reconciler.ts +36 -14
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +23 -30
- package/src/browser/types.ts +21 -0
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +60 -35
- package/src/build/generate-route-types.ts +2 -0
- package/src/build/index.ts +2 -0
- package/src/build/route-trie.ts +52 -25
- package/src/build/route-types/codegen.ts +4 -4
- package/src/build/route-types/include-resolution.ts +1 -1
- package/src/build/route-types/per-module-writer.ts +7 -4
- package/src/build/route-types/router-processing.ts +55 -14
- package/src/build/route-types/scan-filter.ts +1 -1
- package/src/build/route-types/source-scan.ts +118 -0
- package/src/build/runtime-discovery.ts +9 -20
- package/src/cache/cache-scope.ts +28 -42
- package/src/cache/cf/cf-cache-store.ts +54 -13
- package/src/client.rsc.tsx +3 -0
- package/src/client.tsx +92 -182
- package/src/context-var.ts +5 -5
- package/src/decode-loader-results.ts +36 -0
- package/src/errors.ts +30 -1
- package/src/handle.ts +26 -13
- package/src/host/index.ts +2 -2
- package/src/host/router.ts +129 -57
- package/src/host/types.ts +31 -2
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +140 -20
- package/src/index.rsc.ts +9 -4
- package/src/index.ts +53 -15
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +2 -5
- package/src/loader.ts +3 -10
- package/src/missing-id-error.ts +68 -0
- package/src/outlet-context.ts +1 -1
- package/src/prerender.ts +4 -4
- package/src/response-utils.ts +37 -0
- package/src/reverse.ts +65 -36
- package/src/route-content-wrapper.tsx +6 -28
- package/src/route-definition/dsl-helpers.ts +384 -257
- package/src/route-definition/helper-factories.ts +29 -139
- package/src/route-definition/helpers-types.ts +100 -28
- package/src/route-definition/resolve-handler-use.ts +6 -0
- package/src/route-definition/use-item-types.ts +32 -0
- package/src/route-types.ts +26 -41
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +15 -2
- package/src/router/error-handling.ts +1 -1
- package/src/router/handler-context.ts +21 -38
- package/src/router/intercept-resolution.ts +4 -18
- package/src/router/lazy-includes.ts +8 -8
- package/src/router/loader-resolution.ts +19 -2
- package/src/router/manifest.ts +22 -13
- package/src/router/match-api.ts +4 -3
- package/src/router/match-handlers.ts +63 -20
- package/src/router/match-middleware/cache-lookup.ts +44 -91
- package/src/router/match-middleware/cache-store.ts +3 -2
- package/src/router/match-result.ts +53 -32
- package/src/router/metrics.ts +1 -1
- package/src/router/middleware-types.ts +15 -26
- package/src/router/middleware.ts +99 -84
- package/src/router/pattern-matching.ts +101 -17
- package/src/router/prerender-match.ts +1 -1
- package/src/router/preview-match.ts +3 -1
- package/src/router/request-classification.ts +4 -28
- package/src/router/revalidation.ts +58 -2
- package/src/router/router-interfaces.ts +45 -28
- package/src/router/router-options.ts +40 -1
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +27 -6
- package/src/router/segment-resolution/revalidation.ts +147 -106
- package/src/router/segment-resolution/view-transition-default.ts +36 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry.ts +99 -0
- package/src/router/trie-matching.ts +18 -13
- package/src/router/types.ts +8 -0
- package/src/router/url-params.ts +49 -0
- package/src/router.ts +38 -23
- package/src/rsc/handler-context.ts +2 -2
- package/src/rsc/handler.ts +28 -69
- package/src/rsc/helpers.ts +91 -43
- package/src/rsc/index.ts +1 -1
- package/src/rsc/origin-guard.ts +28 -10
- package/src/rsc/progressive-enhancement.ts +4 -0
- package/src/rsc/response-route-handler.ts +46 -53
- package/src/rsc/rsc-rendering.ts +35 -51
- package/src/rsc/runtime-warnings.ts +9 -10
- package/src/rsc/server-action.ts +17 -37
- package/src/rsc/ssr-setup.ts +16 -0
- package/src/rsc/types.ts +8 -2
- package/src/search-params.ts +4 -4
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +122 -0
- package/src/segment-system.tsx +132 -116
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +143 -53
- package/src/server/cookie-store.ts +28 -4
- package/src/server/request-context.ts +20 -42
- package/src/ssr/index.tsx +5 -1
- package/src/static-handler.ts +1 -1
- package/src/testing/cache-status.ts +166 -0
- package/src/testing/collect-handle.ts +63 -0
- package/src/testing/dispatch.ts +440 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +154 -0
- package/src/testing/e2e/index.ts +149 -0
- package/src/testing/e2e/matchers.ts +51 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +306 -0
- package/src/testing/e2e/server.ts +183 -0
- package/src/testing/flight-matchers.ts +104 -0
- package/src/testing/flight-runtime.d.ts +21 -0
- package/src/testing/flight.entry.ts +22 -0
- package/src/testing/flight.ts +182 -0
- package/src/testing/generated-routes.ts +223 -0
- package/src/testing/index.ts +105 -0
- package/src/testing/internal/context.ts +193 -0
- package/src/testing/render-route.tsx +536 -0
- package/src/testing/run-loader.ts +296 -0
- package/src/testing/run-middleware.ts +170 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
- package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
- package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
- package/src/testing/vitest-stubs/version.ts +5 -0
- package/src/testing/vitest.ts +183 -0
- package/src/types/global-namespace.ts +39 -26
- package/src/types/handler-context.ts +68 -50
- package/src/types/index.ts +1 -0
- package/src/types/loader-types.ts +5 -6
- package/src/types/request-scope.ts +126 -0
- package/src/types/route-entry.ts +11 -0
- package/src/types/segments.ts +35 -2
- package/src/urls/include-helper.ts +34 -67
- package/src/urls/index.ts +0 -3
- package/src/urls/path-helper-types.ts +41 -7
- package/src/urls/path-helper.ts +17 -52
- package/src/urls/pattern-types.ts +36 -19
- package/src/urls/response-types.ts +22 -29
- package/src/urls/type-extraction.ts +26 -116
- package/src/urls/urls-function.ts +1 -5
- package/src/use-loader.tsx +413 -42
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +6 -6
- package/src/vite/discovery/discover-routers.ts +101 -51
- package/src/vite/discovery/discovery-errors.ts +194 -0
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +67 -26
- package/src/vite/discovery/route-types-writer.ts +40 -84
- package/src/vite/discovery/self-gen-tracking.ts +27 -1
- package/src/vite/discovery/state.ts +33 -0
- package/src/vite/discovery/virtual-module-codegen.ts +13 -23
- package/src/vite/index.ts +2 -0
- package/src/vite/plugin-types.ts +67 -0
- package/src/vite/plugins/cjs-to-esm.ts +8 -7
- package/src/vite/plugins/client-ref-dedup.ts +16 -0
- package/src/vite/plugins/client-ref-hashing.ts +28 -5
- package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/src/vite/plugins/cloudflare-protocol-stub.ts +214 -0
- package/src/vite/plugins/expose-action-id.ts +54 -30
- package/src/vite/plugins/expose-id-utils.ts +12 -8
- package/src/vite/plugins/expose-ids/export-analysis.ts +100 -20
- package/src/vite/plugins/expose-ids/handler-transform.ts +8 -61
- package/src/vite/plugins/expose-ids/loader-transform.ts +3 -5
- package/src/vite/plugins/expose-ids/router-transform.ts +20 -3
- package/src/vite/plugins/expose-internal-ids.ts +496 -486
- package/src/vite/plugins/performance-tracks.ts +29 -25
- package/src/vite/plugins/use-cache-transform.ts +65 -50
- package/src/vite/plugins/version-injector.ts +39 -23
- package/src/vite/plugins/version-plugin.ts +59 -2
- package/src/vite/plugins/virtual-entries.ts +2 -2
- package/src/vite/rango.ts +116 -29
- package/src/vite/router-discovery.ts +750 -100
- package/src/vite/utils/ast-handler-extract.ts +15 -15
- package/src/vite/utils/banner.ts +1 -1
- package/src/vite/utils/bundle-analysis.ts +4 -2
- package/src/vite/utils/client-chunks.ts +190 -0
- package/src/vite/utils/forward-user-plugins.ts +193 -0
- package/src/vite/utils/manifest-utils.ts +21 -5
- package/src/vite/utils/package-resolution.ts +41 -1
- package/src/vite/utils/prerender-utils.ts +21 -6
- package/src/vite/utils/shared-utils.ts +107 -26
- package/src/browser/action-response-classifier.ts +0 -99
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime-neutral Response shape utilities.
|
|
3
|
+
*
|
|
4
|
+
* Kept at the src/ root so both `router/` and `rsc/` can depend on it
|
|
5
|
+
* without creating a cross-layer import cycle.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* True when a Response represents a WebSocket upgrade handoff and must not
|
|
10
|
+
* be reconstructed or mutated:
|
|
11
|
+
*
|
|
12
|
+
* - Status 101 (Switching Protocols) is outside the standard Response
|
|
13
|
+
* constructor's 200–599 range, so `new Response(body, { status: 101 })`
|
|
14
|
+
* throws RangeError on Node/undici and any spec-compliant runtime.
|
|
15
|
+
* - Cloudflare's workerd attaches a non-standard `webSocket` property on
|
|
16
|
+
* the upgrade Response (e.g. from `acceptWebSocket`/`handleWebSocketUpgrade`
|
|
17
|
+
* or the `agents` library's `routeAgentRequest`). That property is dropped
|
|
18
|
+
* by a `new Response(...)` copy, breaking the upgrade even on workerd
|
|
19
|
+
* where the status range is relaxed.
|
|
20
|
+
*
|
|
21
|
+
* Callers should short-circuit header/body merges for these responses.
|
|
22
|
+
*/
|
|
23
|
+
export function isWebSocketUpgradeResponse(response: Response): boolean {
|
|
24
|
+
return (
|
|
25
|
+
response.status === 101 ||
|
|
26
|
+
(response as unknown as { webSocket?: unknown }).webSocket != null
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Location truthiness (not presence) so an empty `Location: ""` is not a redirect.
|
|
31
|
+
export function isRedirectResponse(response: Response): boolean {
|
|
32
|
+
return (
|
|
33
|
+
response.status >= 300 &&
|
|
34
|
+
response.status < 400 &&
|
|
35
|
+
Boolean(response.headers.get("Location"))
|
|
36
|
+
);
|
|
37
|
+
}
|
package/src/reverse.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ExtractParams } from "./types.js";
|
|
2
2
|
import type { SearchSchema, ResolveSearchSchema } from "./search-params.js";
|
|
3
3
|
import { serializeSearchParams } from "./search-params.js";
|
|
4
|
+
import { substitutePatternParams } from "./router/substitute-pattern-params.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Sanitize prefix string by removing leading slash
|
|
@@ -218,6 +219,67 @@ export type ExtractLocalRoutes<TPatterns> = TPatterns extends {
|
|
|
218
219
|
? TPatterns
|
|
219
220
|
: Record<string, string>;
|
|
220
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Params accepted by `useReverse(routes)`. The route's own params are
|
|
224
|
+
* required, and additional string keys are permitted so callers can
|
|
225
|
+
* override values that would otherwise be auto-filled from the matched
|
|
226
|
+
* route's `useParams()` (e.g. an enclosing `:tenantId` mount segment).
|
|
227
|
+
*/
|
|
228
|
+
export type LocalReverseParams<TPattern extends string> =
|
|
229
|
+
ExtractParams<TPattern> & {
|
|
230
|
+
readonly [extra: string]: string | undefined;
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Type-safe local reverse function.
|
|
235
|
+
*
|
|
236
|
+
* Returned by `useReverse(routes)` on the client. The route map is the
|
|
237
|
+
* exposure boundary (a generated `routes` from a `urls()` module) and the
|
|
238
|
+
* scope is implicit from that import. Names may be written with or without a
|
|
239
|
+
* leading dot — `reverse("post")` and `reverse(".post")` are identical. The dot
|
|
240
|
+
* is a cosmetic readability convention (and parity with `ctx.reverse(".name")`);
|
|
241
|
+
* there is no separate global namespace here, so it carries no meaning.
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```typescript
|
|
245
|
+
* const reverse = useReverse(blogRoutes);
|
|
246
|
+
* reverse("index"); // ✓ no params (dot optional)
|
|
247
|
+
* reverse(".index"); // ✓ identical to the above
|
|
248
|
+
* reverse("post", { postId: "hello" }); // ✓ with params
|
|
249
|
+
* reverse("search", {}, { q: "hi" }); // ✓ with search schema
|
|
250
|
+
* reverse("typo"); // ✗ compile error
|
|
251
|
+
* ```
|
|
252
|
+
*/
|
|
253
|
+
export type LocalReverseFunction<TLocalRoutes> = {
|
|
254
|
+
/**
|
|
255
|
+
* Route without params (leading dot optional)
|
|
256
|
+
*/
|
|
257
|
+
<TName extends keyof TLocalRoutes & string>(
|
|
258
|
+
name: IsEmptyObject<
|
|
259
|
+
ExtractParams<RoutePatternFor<TLocalRoutes, TName>>
|
|
260
|
+
> extends true
|
|
261
|
+
? TName | `.${TName}`
|
|
262
|
+
: never,
|
|
263
|
+
): string;
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Route with params (leading dot optional)
|
|
267
|
+
*/
|
|
268
|
+
<TName extends keyof TLocalRoutes & string>(
|
|
269
|
+
name: TName | `.${TName}`,
|
|
270
|
+
params: LocalReverseParams<RoutePatternFor<TLocalRoutes, TName>>,
|
|
271
|
+
): string;
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Route with params and search (leading dot optional)
|
|
275
|
+
*/
|
|
276
|
+
<TName extends keyof TLocalRoutes & string>(
|
|
277
|
+
name: TName | `.${TName}`,
|
|
278
|
+
params: LocalReverseParams<RoutePatternFor<TLocalRoutes, TName>>,
|
|
279
|
+
search: ResolveSearchSchema<ExtractSearchSchema<TLocalRoutes, TName>>,
|
|
280
|
+
): string;
|
|
281
|
+
};
|
|
282
|
+
|
|
221
283
|
/**
|
|
222
284
|
* Extract the response data type for a named route from a UrlPatterns instance.
|
|
223
285
|
* Re-exported from urls.ts for consumer convenience.
|
|
@@ -301,42 +363,9 @@ export function createReverse<TRoutes extends Record<string, string>>(
|
|
|
301
363
|
throw new Error(`Unknown route: ${name}`);
|
|
302
364
|
}
|
|
303
365
|
|
|
304
|
-
let result =
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
// Strip constraint syntax: :param(a|b) -> use "param" as key
|
|
308
|
-
// Optional params (:param?) are omitted when not provided
|
|
309
|
-
let hadOmittedOptional = false;
|
|
310
|
-
result = result.replace(
|
|
311
|
-
/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))?(\?)/g,
|
|
312
|
-
(_, key, _constraint, optional) => {
|
|
313
|
-
const value = params[key];
|
|
314
|
-
if (value === undefined) {
|
|
315
|
-
hadOmittedOptional = true;
|
|
316
|
-
return "";
|
|
317
|
-
}
|
|
318
|
-
return encodeURIComponent(value);
|
|
319
|
-
},
|
|
320
|
-
);
|
|
321
|
-
// Second pass: required params (no trailing ?)
|
|
322
|
-
result = result.replace(
|
|
323
|
-
/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))?(?!\?)/g,
|
|
324
|
-
(_, key) => {
|
|
325
|
-
const value = params[key];
|
|
326
|
-
if (value === undefined) {
|
|
327
|
-
throw new Error(`Missing param "${key}" for route "${name}"`);
|
|
328
|
-
}
|
|
329
|
-
return encodeURIComponent(value);
|
|
330
|
-
},
|
|
331
|
-
);
|
|
332
|
-
// Clean up slashes only when an optional param was actually omitted,
|
|
333
|
-
// so intentional trailing-slash patterns like "/blog/" are preserved.
|
|
334
|
-
if (hadOmittedOptional) {
|
|
335
|
-
const hadTrailingSlash = pattern.length > 1 && pattern.endsWith("/");
|
|
336
|
-
result = result.replace(/\/\/+/g, "/").replace(/\/+$/, "") || "/";
|
|
337
|
-
if (hadTrailingSlash && !result.endsWith("/")) result += "/";
|
|
338
|
-
}
|
|
339
|
-
}
|
|
366
|
+
let result = params
|
|
367
|
+
? substitutePatternParams(pattern, params, name)
|
|
368
|
+
: pattern;
|
|
340
369
|
|
|
341
370
|
// Append search params as query string
|
|
342
371
|
if (search) {
|
|
@@ -4,7 +4,7 @@ import { Suspense, use, useId } from "react";
|
|
|
4
4
|
import { invariant } from "./errors";
|
|
5
5
|
import { OutletProvider } from "./outlet-provider.js";
|
|
6
6
|
import type { ResolvedSegment } from "./types.js";
|
|
7
|
-
import {
|
|
7
|
+
import { decodeLoaderResults } from "./decode-loader-results.js";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Stable async wrapper component for route content
|
|
@@ -26,10 +26,6 @@ export function RouteContentWrapper({
|
|
|
26
26
|
fallback?: ReactNode;
|
|
27
27
|
segmentId?: string;
|
|
28
28
|
}): ReactNode {
|
|
29
|
-
if (!content) {
|
|
30
|
-
// Already resolved
|
|
31
|
-
return content as ReactNode;
|
|
32
|
-
}
|
|
33
29
|
return (
|
|
34
30
|
<Suspense
|
|
35
31
|
fallback={fallback ?? null}
|
|
@@ -159,28 +155,10 @@ function LoaderResolver({
|
|
|
159
155
|
? use(loaderDataPromise)
|
|
160
156
|
: loaderDataPromise;
|
|
161
157
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
loaderIds.forEach((id, i) => {
|
|
167
|
-
const result = resolvedData[i];
|
|
168
|
-
|
|
169
|
-
if (isLoaderDataResult(result)) {
|
|
170
|
-
if (result.ok) {
|
|
171
|
-
loaderData[id] = result.data;
|
|
172
|
-
} else {
|
|
173
|
-
if (result.fallback) {
|
|
174
|
-
loaderErrorFallback = result.fallback;
|
|
175
|
-
} else {
|
|
176
|
-
throw new Error(result.error.message);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
} else {
|
|
180
|
-
// Legacy format - direct data
|
|
181
|
-
loaderData[id] = result;
|
|
182
|
-
}
|
|
183
|
-
});
|
|
158
|
+
const { loaderData, errorFallback } = decodeLoaderResults(
|
|
159
|
+
resolvedData,
|
|
160
|
+
loaderIds,
|
|
161
|
+
);
|
|
184
162
|
|
|
185
163
|
return (
|
|
186
164
|
<OutletProvider
|
|
@@ -190,7 +168,7 @@ function LoaderResolver({
|
|
|
190
168
|
parallel={parallel}
|
|
191
169
|
loaderData={Object.keys(loaderData).length > 0 ? loaderData : undefined}
|
|
192
170
|
>
|
|
193
|
-
{
|
|
171
|
+
{errorFallback ?? children}
|
|
194
172
|
</OutletProvider>
|
|
195
173
|
);
|
|
196
174
|
}
|