@timber-js/app 0.1.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/bin/timber.mjs +5 -0
- package/dist/_chunks/error-boundary-dj-WO5uq.js +121 -0
- package/dist/_chunks/error-boundary-dj-WO5uq.js.map +1 -0
- package/dist/_chunks/format-DNt20Kt8.js +163 -0
- package/dist/_chunks/format-DNt20Kt8.js.map +1 -0
- package/dist/_chunks/interception-DIaZN1bF.js +669 -0
- package/dist/_chunks/interception-DIaZN1bF.js.map +1 -0
- package/dist/_chunks/metadata-routes-BDnswgRO.js +141 -0
- package/dist/_chunks/metadata-routes-BDnswgRO.js.map +1 -0
- package/dist/_chunks/registry-DUIpYD_x.js +20 -0
- package/dist/_chunks/registry-DUIpYD_x.js.map +1 -0
- package/dist/_chunks/request-context-D6XHINkR.js +330 -0
- package/dist/_chunks/request-context-D6XHINkR.js.map +1 -0
- package/dist/_chunks/tracing-BtOwb8O6.js +174 -0
- package/dist/_chunks/tracing-BtOwb8O6.js.map +1 -0
- package/dist/_chunks/use-cookie-8ZlA0rr3.js +125 -0
- package/dist/_chunks/use-cookie-8ZlA0rr3.js.map +1 -0
- package/dist/adapters/cloudflare.d.ts +92 -0
- package/dist/adapters/cloudflare.d.ts.map +1 -0
- package/dist/adapters/cloudflare.js +188 -0
- package/dist/adapters/cloudflare.js.map +1 -0
- package/dist/adapters/nitro.d.ts +72 -0
- package/dist/adapters/nitro.d.ts.map +1 -0
- package/dist/adapters/nitro.js +217 -0
- package/dist/adapters/nitro.js.map +1 -0
- package/dist/adapters/types.d.ts +53 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/cache/index.d.ts +52 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +283 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/redis-handler.d.ts +45 -0
- package/dist/cache/redis-handler.d.ts.map +1 -0
- package/dist/cache/register-cached-function.d.ts +17 -0
- package/dist/cache/register-cached-function.d.ts.map +1 -0
- package/dist/cache/singleflight.d.ts +11 -0
- package/dist/cache/singleflight.d.ts.map +1 -0
- package/dist/cache/stable-stringify.d.ts +7 -0
- package/dist/cache/stable-stringify.d.ts.map +1 -0
- package/dist/cache/timber-cache.d.ts +21 -0
- package/dist/cache/timber-cache.d.ts.map +1 -0
- package/dist/cli.d.ts +44 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +135 -0
- package/dist/cli.js.map +1 -0
- package/dist/client/browser-entry.d.ts +22 -0
- package/dist/client/browser-entry.d.ts.map +1 -0
- package/dist/client/error-boundary.d.ts +42 -0
- package/dist/client/error-boundary.d.ts.map +1 -0
- package/dist/client/form.d.ts +115 -0
- package/dist/client/form.d.ts.map +1 -0
- package/dist/client/head.d.ts +16 -0
- package/dist/client/head.d.ts.map +1 -0
- package/dist/client/history.d.ts +29 -0
- package/dist/client/history.d.ts.map +1 -0
- package/dist/client/index.d.ts +32 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +1218 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/link-navigate-interceptor.d.ts +28 -0
- package/dist/client/link-navigate-interceptor.d.ts.map +1 -0
- package/dist/client/link-status-provider.d.ts +11 -0
- package/dist/client/link-status-provider.d.ts.map +1 -0
- package/dist/client/link.d.ts +119 -0
- package/dist/client/link.d.ts.map +1 -0
- package/dist/client/nuqs-adapter.d.ts +11 -0
- package/dist/client/nuqs-adapter.d.ts.map +1 -0
- package/dist/client/router-ref.d.ts +11 -0
- package/dist/client/router-ref.d.ts.map +1 -0
- package/dist/client/router.d.ts +85 -0
- package/dist/client/router.d.ts.map +1 -0
- package/dist/client/segment-cache.d.ts +88 -0
- package/dist/client/segment-cache.d.ts.map +1 -0
- package/dist/client/segment-context.d.ts +32 -0
- package/dist/client/segment-context.d.ts.map +1 -0
- package/dist/client/ssr-data.d.ts +64 -0
- package/dist/client/ssr-data.d.ts.map +1 -0
- package/dist/client/types.d.ts +5 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/unload-guard.d.ts +18 -0
- package/dist/client/unload-guard.d.ts.map +1 -0
- package/dist/client/use-cookie.d.ts +37 -0
- package/dist/client/use-cookie.d.ts.map +1 -0
- package/dist/client/use-link-status.d.ts +35 -0
- package/dist/client/use-link-status.d.ts.map +1 -0
- package/dist/client/use-navigation-pending.d.ts +26 -0
- package/dist/client/use-navigation-pending.d.ts.map +1 -0
- package/dist/client/use-params.d.ts +50 -0
- package/dist/client/use-params.d.ts.map +1 -0
- package/dist/client/use-pathname.d.ts +20 -0
- package/dist/client/use-pathname.d.ts.map +1 -0
- package/dist/client/use-query-states.d.ts +36 -0
- package/dist/client/use-query-states.d.ts.map +1 -0
- package/dist/client/use-router.d.ts +39 -0
- package/dist/client/use-router.d.ts.map +1 -0
- package/dist/client/use-search-params.d.ts +24 -0
- package/dist/client/use-search-params.d.ts.map +1 -0
- package/dist/client/use-selected-layout-segment.d.ts +68 -0
- package/dist/client/use-selected-layout-segment.d.ts.map +1 -0
- package/dist/content/index.d.ts +11 -0
- package/dist/content/index.d.ts.map +1 -0
- package/dist/content/index.js +2 -0
- package/dist/cookies/define-cookie.d.ts +61 -0
- package/dist/cookies/define-cookie.d.ts.map +1 -0
- package/dist/cookies/index.d.ts +3 -0
- package/dist/cookies/index.d.ts.map +1 -0
- package/dist/cookies/index.js +82 -0
- package/dist/cookies/index.js.map +1 -0
- package/dist/fonts/ast.d.ts +38 -0
- package/dist/fonts/ast.d.ts.map +1 -0
- package/dist/fonts/css.d.ts +43 -0
- package/dist/fonts/css.d.ts.map +1 -0
- package/dist/fonts/fallbacks.d.ts +36 -0
- package/dist/fonts/fallbacks.d.ts.map +1 -0
- package/dist/fonts/google.d.ts +122 -0
- package/dist/fonts/google.d.ts.map +1 -0
- package/dist/fonts/local.d.ts +76 -0
- package/dist/fonts/local.d.ts.map +1 -0
- package/dist/fonts/types.d.ts +85 -0
- package/dist/fonts/types.d.ts.map +1 -0
- package/dist/index.d.ts +150 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14701 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/adapter-build.d.ts +18 -0
- package/dist/plugins/adapter-build.d.ts.map +1 -0
- package/dist/plugins/build-manifest.d.ts +79 -0
- package/dist/plugins/build-manifest.d.ts.map +1 -0
- package/dist/plugins/build-report.d.ts +63 -0
- package/dist/plugins/build-report.d.ts.map +1 -0
- package/dist/plugins/cache-transform.d.ts +36 -0
- package/dist/plugins/cache-transform.d.ts.map +1 -0
- package/dist/plugins/chunks.d.ts +45 -0
- package/dist/plugins/chunks.d.ts.map +1 -0
- package/dist/plugins/content.d.ts +19 -0
- package/dist/plugins/content.d.ts.map +1 -0
- package/dist/plugins/dev-error-overlay.d.ts +60 -0
- package/dist/plugins/dev-error-overlay.d.ts.map +1 -0
- package/dist/plugins/dev-logs.d.ts +46 -0
- package/dist/plugins/dev-logs.d.ts.map +1 -0
- package/dist/plugins/dev-server.d.ts +22 -0
- package/dist/plugins/dev-server.d.ts.map +1 -0
- package/dist/plugins/dynamic-transform.d.ts +72 -0
- package/dist/plugins/dynamic-transform.d.ts.map +1 -0
- package/dist/plugins/entries.d.ts +21 -0
- package/dist/plugins/entries.d.ts.map +1 -0
- package/dist/plugins/fonts.d.ts +77 -0
- package/dist/plugins/fonts.d.ts.map +1 -0
- package/dist/plugins/mdx.d.ts +21 -0
- package/dist/plugins/mdx.d.ts.map +1 -0
- package/dist/plugins/react-prod.d.ts +18 -0
- package/dist/plugins/react-prod.d.ts.map +1 -0
- package/dist/plugins/routing.d.ts +13 -0
- package/dist/plugins/routing.d.ts.map +1 -0
- package/dist/plugins/server-action-exports.d.ts +26 -0
- package/dist/plugins/server-action-exports.d.ts.map +1 -0
- package/dist/plugins/server-bundle.d.ts +15 -0
- package/dist/plugins/server-bundle.d.ts.map +1 -0
- package/dist/plugins/shims.d.ts +18 -0
- package/dist/plugins/shims.d.ts.map +1 -0
- package/dist/plugins/static-build.d.ts +55 -0
- package/dist/plugins/static-build.d.ts.map +1 -0
- package/dist/routing/codegen.d.ts +29 -0
- package/dist/routing/codegen.d.ts.map +1 -0
- package/dist/routing/index.d.ts +8 -0
- package/dist/routing/index.d.ts.map +1 -0
- package/dist/routing/index.js +2 -0
- package/dist/routing/interception.d.ts +46 -0
- package/dist/routing/interception.d.ts.map +1 -0
- package/dist/routing/scanner.d.ts +28 -0
- package/dist/routing/scanner.d.ts.map +1 -0
- package/dist/routing/status-file-lint.d.ts +33 -0
- package/dist/routing/status-file-lint.d.ts.map +1 -0
- package/dist/routing/types.d.ts +81 -0
- package/dist/routing/types.d.ts.map +1 -0
- package/dist/search-params/analyze.d.ts +54 -0
- package/dist/search-params/analyze.d.ts.map +1 -0
- package/dist/search-params/codecs.d.ts +53 -0
- package/dist/search-params/codecs.d.ts.map +1 -0
- package/dist/search-params/create.d.ts +106 -0
- package/dist/search-params/create.d.ts.map +1 -0
- package/dist/search-params/index.d.ts +7 -0
- package/dist/search-params/index.d.ts.map +1 -0
- package/dist/search-params/index.js +300 -0
- package/dist/search-params/index.js.map +1 -0
- package/dist/search-params/registry.d.ts +20 -0
- package/dist/search-params/registry.d.ts.map +1 -0
- package/dist/server/access-gate.d.ts +42 -0
- package/dist/server/access-gate.d.ts.map +1 -0
- package/dist/server/action-client.d.ts +190 -0
- package/dist/server/action-client.d.ts.map +1 -0
- package/dist/server/action-handler.d.ts +48 -0
- package/dist/server/action-handler.d.ts.map +1 -0
- package/dist/server/actions.d.ts +108 -0
- package/dist/server/actions.d.ts.map +1 -0
- package/dist/server/asset-headers.d.ts +42 -0
- package/dist/server/asset-headers.d.ts.map +1 -0
- package/dist/server/body-limits.d.ts +30 -0
- package/dist/server/body-limits.d.ts.map +1 -0
- package/dist/server/build-manifest.d.ts +120 -0
- package/dist/server/build-manifest.d.ts.map +1 -0
- package/dist/server/canonicalize.d.ts +30 -0
- package/dist/server/canonicalize.d.ts.map +1 -0
- package/dist/server/client-module-map.d.ts +47 -0
- package/dist/server/client-module-map.d.ts.map +1 -0
- package/dist/server/csrf.d.ts +34 -0
- package/dist/server/csrf.d.ts.map +1 -0
- package/dist/server/deny-renderer.d.ts +49 -0
- package/dist/server/deny-renderer.d.ts.map +1 -0
- package/dist/server/dev-logger.d.ts +44 -0
- package/dist/server/dev-logger.d.ts.map +1 -0
- package/dist/server/dev-span-processor.d.ts +29 -0
- package/dist/server/dev-span-processor.d.ts.map +1 -0
- package/dist/server/dev-warnings.d.ts +129 -0
- package/dist/server/dev-warnings.d.ts.map +1 -0
- package/dist/server/early-hints-sender.d.ts +38 -0
- package/dist/server/early-hints-sender.d.ts.map +1 -0
- package/dist/server/early-hints.d.ts +83 -0
- package/dist/server/early-hints.d.ts.map +1 -0
- package/dist/server/error-boundary-wrapper.d.ts +17 -0
- package/dist/server/error-boundary-wrapper.d.ts.map +1 -0
- package/dist/server/error-formatter.d.ts +17 -0
- package/dist/server/error-formatter.d.ts.map +1 -0
- package/dist/server/flush.d.ts +74 -0
- package/dist/server/flush.d.ts.map +1 -0
- package/dist/server/form-data.d.ts +60 -0
- package/dist/server/form-data.d.ts.map +1 -0
- package/dist/server/form-flash.d.ts +78 -0
- package/dist/server/form-flash.d.ts.map +1 -0
- package/dist/server/html-injectors.d.ts +101 -0
- package/dist/server/html-injectors.d.ts.map +1 -0
- package/dist/server/index.d.ts +54 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +2925 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/instrumentation.d.ts +61 -0
- package/dist/server/instrumentation.d.ts.map +1 -0
- package/dist/server/logger.d.ts +83 -0
- package/dist/server/logger.d.ts.map +1 -0
- package/dist/server/manifest-status-resolver.d.ts +58 -0
- package/dist/server/manifest-status-resolver.d.ts.map +1 -0
- package/dist/server/metadata-render.d.ts +20 -0
- package/dist/server/metadata-render.d.ts.map +1 -0
- package/dist/server/metadata-routes.d.ts +67 -0
- package/dist/server/metadata-routes.d.ts.map +1 -0
- package/dist/server/metadata.d.ts +67 -0
- package/dist/server/metadata.d.ts.map +1 -0
- package/dist/server/middleware-runner.d.ts +21 -0
- package/dist/server/middleware-runner.d.ts.map +1 -0
- package/dist/server/nuqs-ssr-provider.d.ts +28 -0
- package/dist/server/nuqs-ssr-provider.d.ts.map +1 -0
- package/dist/server/pipeline.d.ts +81 -0
- package/dist/server/pipeline.d.ts.map +1 -0
- package/dist/server/prerender.d.ts +77 -0
- package/dist/server/prerender.d.ts.map +1 -0
- package/dist/server/primitives.d.ts +131 -0
- package/dist/server/primitives.d.ts.map +1 -0
- package/dist/server/proxy.d.ts +23 -0
- package/dist/server/proxy.d.ts.map +1 -0
- package/dist/server/request-context.d.ts +175 -0
- package/dist/server/request-context.d.ts.map +1 -0
- package/dist/server/route-element-builder.d.ts +66 -0
- package/dist/server/route-element-builder.d.ts.map +1 -0
- package/dist/server/route-handler.d.ts +35 -0
- package/dist/server/route-handler.d.ts.map +1 -0
- package/dist/server/route-matcher.d.ts +78 -0
- package/dist/server/route-matcher.d.ts.map +1 -0
- package/dist/server/rsc-entry/api-handler.d.ts +11 -0
- package/dist/server/rsc-entry/api-handler.d.ts.map +1 -0
- package/dist/server/rsc-entry/error-renderer.d.ts +30 -0
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -0
- package/dist/server/rsc-entry/helpers.d.ts +73 -0
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -0
- package/dist/server/rsc-entry/index.d.ts +11 -0
- package/dist/server/rsc-entry/index.d.ts.map +1 -0
- package/dist/server/rsc-entry/ssr-bridge.d.ts +6 -0
- package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -0
- package/dist/server/slot-resolver.d.ts +34 -0
- package/dist/server/slot-resolver.d.ts.map +1 -0
- package/dist/server/ssr-entry.d.ts +73 -0
- package/dist/server/ssr-entry.d.ts.map +1 -0
- package/dist/server/ssr-render.d.ts +67 -0
- package/dist/server/ssr-render.d.ts.map +1 -0
- package/dist/server/status-code-resolver.d.ts +77 -0
- package/dist/server/status-code-resolver.d.ts.map +1 -0
- package/dist/server/tracing.d.ts +99 -0
- package/dist/server/tracing.d.ts.map +1 -0
- package/dist/server/tree-builder.d.ts +116 -0
- package/dist/server/tree-builder.d.ts.map +1 -0
- package/dist/server/types.d.ts +231 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/shims/font-google.d.ts +41 -0
- package/dist/shims/font-google.d.ts.map +1 -0
- package/dist/shims/headers.d.ts +11 -0
- package/dist/shims/headers.d.ts.map +1 -0
- package/dist/shims/image.d.ts +328 -0
- package/dist/shims/image.d.ts.map +1 -0
- package/dist/shims/link.d.ts +9 -0
- package/dist/shims/link.d.ts.map +1 -0
- package/dist/shims/navigation-client.d.ts +25 -0
- package/dist/shims/navigation-client.d.ts.map +1 -0
- package/dist/shims/navigation.d.ts +25 -0
- package/dist/shims/navigation.d.ts.map +1 -0
- package/dist/utils/directive-parser.d.ts +70 -0
- package/dist/utils/directive-parser.d.ts.map +1 -0
- package/dist/utils/format.d.ts +6 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/startup-timer.d.ts +34 -0
- package/dist/utils/startup-timer.d.ts.map +1 -0
- package/package.json +140 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RSC Entry Helpers — shared utilities for the RSC request handler.
|
|
3
|
+
*
|
|
4
|
+
* Small, stateless functions used across the RSC entry modules.
|
|
5
|
+
*/
|
|
6
|
+
import type { ManifestSegmentNode } from '#/server/route-matcher.js';
|
|
7
|
+
import { RedirectSignal } from '#/server/primitives.js';
|
|
8
|
+
/** RSC content type for client navigation payload requests. */
|
|
9
|
+
export declare const RSC_CONTENT_TYPE = "text/x-component";
|
|
10
|
+
/**
|
|
11
|
+
* Create a debug channel sink that discards all debug data.
|
|
12
|
+
*
|
|
13
|
+
* React Flight's dev mode serializes server component source code as `$E`
|
|
14
|
+
* entries for DevTools. Without a separate debugChannel, this data is
|
|
15
|
+
* embedded inline in the main RSC stream — leaking source code to the
|
|
16
|
+
* browser. By providing a debug channel, debug data goes to a separate
|
|
17
|
+
* stream that we drain and discard.
|
|
18
|
+
*
|
|
19
|
+
* See design/13-security.md §"Server component source leak"
|
|
20
|
+
*
|
|
21
|
+
* TODO: In the future, expose this debug data to the browser in dev mode
|
|
22
|
+
* for inline error overlays (e.g. component stack traces).
|
|
23
|
+
*/
|
|
24
|
+
export declare function createDebugChannelSink(): {
|
|
25
|
+
readable: ReadableStream;
|
|
26
|
+
writable: WritableStream;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Build segment metadata for the X-Timber-Segments response header.
|
|
30
|
+
* Describes the rendered segment chain with async status, enabling
|
|
31
|
+
* the client to populate its segment cache for state tree diffing.
|
|
32
|
+
*
|
|
33
|
+
* Async detection: server components defined as `async function` have
|
|
34
|
+
* constructor.name === 'AsyncFunction'. These layouts always re-render
|
|
35
|
+
* on navigation (they may depend on request context like cookies/params).
|
|
36
|
+
* See design/07-routing.md §"Server Diffing Rules".
|
|
37
|
+
*/
|
|
38
|
+
export declare function buildSegmentInfo(segments: ManifestSegmentNode[], layoutComponents: Array<{
|
|
39
|
+
component: (...args: unknown[]) => unknown;
|
|
40
|
+
segment: ManifestSegmentNode;
|
|
41
|
+
}>): Array<{
|
|
42
|
+
path: string;
|
|
43
|
+
isAsync: boolean;
|
|
44
|
+
}>;
|
|
45
|
+
/**
|
|
46
|
+
* Check if a request is asking for an RSC payload (client navigation)
|
|
47
|
+
* rather than full HTML. Client-side navigation sends Accept: text/x-component.
|
|
48
|
+
*/
|
|
49
|
+
export declare function isRscPayloadRequest(req: Request): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Build a redirect Response. For RSC payload requests (client navigation),
|
|
52
|
+
* return 204 + X-Timber-Redirect header instead of a raw 302. The browser's
|
|
53
|
+
* fetch with redirect: "manual" turns a 302 into an opaque redirect (status 0,
|
|
54
|
+
* null body, inaccessible headers), which crashes createFromFetch when it
|
|
55
|
+
* tries to call .body.getReader(). The X-Timber-Redirect header lets the
|
|
56
|
+
* client detect the redirect and perform a soft SPA navigation.
|
|
57
|
+
*/
|
|
58
|
+
export declare function buildRedirectResponse(req: Request, signal: RedirectSignal, responseHeaders: Headers): Response;
|
|
59
|
+
/**
|
|
60
|
+
* Check if an error is an abort error (connection closed by client).
|
|
61
|
+
*
|
|
62
|
+
* When the browser aborts a request (page refresh, navigation away),
|
|
63
|
+
* the AbortSignal fires and React/streams throw an AbortError. This
|
|
64
|
+
* is not an application error — suppress it from error boundaries and logs.
|
|
65
|
+
*/
|
|
66
|
+
export declare function isAbortError(error: unknown): boolean;
|
|
67
|
+
export declare function escapeHtml(str: string): string;
|
|
68
|
+
/**
|
|
69
|
+
* Parse a Cookie header string into a name→value Map.
|
|
70
|
+
* Used to populate NavContext.cookies for SSR hooks (useCookie).
|
|
71
|
+
*/
|
|
72
|
+
export declare function parseCookiesFromHeader(header: string): Map<string, string>;
|
|
73
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/helpers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,+DAA+D;AAC/D,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AAEnD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,IAAI;IAAE,QAAQ,EAAE,cAAc,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAA;CAAE,CAQ/F;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,gBAAgB,EAAE,KAAK,CAAC;IACtB,SAAS,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;IAC3C,OAAO,EAAE,mBAAmB,CAAC;CAC9B,CAAC,GACD,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CA0B3C;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAGzD;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,cAAc,EACtB,eAAe,EAAE,OAAO,GACvB,QAAQ,CAOV;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAIpD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM9C;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAW1E"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Set the dev pipeline error handler.
|
|
3
|
+
*
|
|
4
|
+
* Called by the dev server after importing this module to wire pipeline
|
|
5
|
+
* errors into the Vite browser error overlay. No-op in production.
|
|
6
|
+
*/
|
|
7
|
+
export declare function setDevPipelineErrorHandler(handler: (error: Error, phase: string) => void): void;
|
|
8
|
+
export { runWithEarlyHintsSender } from '#/server/early-hints-sender.js';
|
|
9
|
+
declare const _default: (req: Request) => Promise<Response>;
|
|
10
|
+
export default _default;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/index.ts"],"names":[],"mappings":"AA0EA;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAE/F;AA2lBD,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;8BA3epD,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC;AA6ehD,wBAAiE"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSR Bridge — loads the SSR entry and passes the RSC stream for HTML rendering.
|
|
3
|
+
*/
|
|
4
|
+
import type { NavContext } from '#/server/ssr-entry.js';
|
|
5
|
+
export declare function callSsr(rscStream: ReadableStream<Uint8Array>, navContext: NavContext): Promise<Response>;
|
|
6
|
+
//# sourceMappingURL=ssr-bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssr-bridge.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/ssr-bridge.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,wBAAsB,OAAO,CAC3B,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,EACrC,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,QAAQ,CAAC,CAMnB"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parallel slot resolution for RSC rendering.
|
|
3
|
+
*
|
|
4
|
+
* Resolves slot elements for a layout's parallel routes (@slot directories).
|
|
5
|
+
* Each slot either matches the current URL (renders its page) or doesn't
|
|
6
|
+
* match (renders default.tsx fallback).
|
|
7
|
+
*
|
|
8
|
+
* Slots are rendered within the single renderToReadableStream call as
|
|
9
|
+
* named props to their parent layout — no separate render passes.
|
|
10
|
+
*
|
|
11
|
+
* Each slot gets its own error boundaries (from error.tsx / status files
|
|
12
|
+
* along the matched slot segment chain) and layouts (from layout.tsx files
|
|
13
|
+
* in the slot's sub-tree). This enables independent error handling and
|
|
14
|
+
* chrome per slot.
|
|
15
|
+
*
|
|
16
|
+
* See design/02-rendering-pipeline.md §"Parallel Slots"
|
|
17
|
+
*/
|
|
18
|
+
import type { ManifestSegmentNode } from './route-matcher.js';
|
|
19
|
+
import type { RouteMatch, InterceptionContext } from './pipeline.js';
|
|
20
|
+
type CreateElementFn = (...args: unknown[]) => React.ReactElement;
|
|
21
|
+
/**
|
|
22
|
+
* Resolve the element for a parallel slot.
|
|
23
|
+
*
|
|
24
|
+
* Finds a matching page in the slot's sub-tree for the current route.
|
|
25
|
+
* Falls back to default.tsx if no match, or null if no default.
|
|
26
|
+
*
|
|
27
|
+
* When a match is found, the element is wrapped with:
|
|
28
|
+
* 1. Error boundaries from each segment in the slot's matched chain
|
|
29
|
+
* 2. Layouts from each segment in the slot's matched chain
|
|
30
|
+
* 3. SlotAccessGate if the slot root has access.ts
|
|
31
|
+
*/
|
|
32
|
+
export declare function resolveSlotElement(slotNode: ManifestSegmentNode, match: RouteMatch, paramsPromise: Promise<Record<string, string | string[]>>, h: CreateElementFn, interception?: InterceptionContext): Promise<React.ReactElement | null>;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=slot-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slot-resolver.d.ts","sourceRoot":"","sources":["../../src/server/slot-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAIrE,KAAK,eAAe,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,KAAK,CAAC,YAAY,CAAC;AAElE;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,mBAAmB,EAC7B,KAAK,EAAE,UAAU,EACjB,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,EACzD,CAAC,EAAE,eAAe,EAClB,YAAY,CAAC,EAAE,mBAAmB,GACjC,OAAO,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CAqHpC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSR Entry — Receives RSC stream and renders HTML with hydration markers.
|
|
3
|
+
*
|
|
4
|
+
* This is a real TypeScript file, not codegen. The RSC environment calls
|
|
5
|
+
* handleSsr() to convert the RSC stream + navigation context into
|
|
6
|
+
* an HTML Response with React hydration support.
|
|
7
|
+
*
|
|
8
|
+
* The RSC and SSR environments are separate Vite module graphs with
|
|
9
|
+
* separate module instances. Per-request state is explicitly passed
|
|
10
|
+
* via NavContext.
|
|
11
|
+
*
|
|
12
|
+
* Design docs: 18-build-system.md §"Entry Files", 02-rendering-pipeline.md
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Navigation context passed from the RSC environment to SSR.
|
|
16
|
+
*
|
|
17
|
+
* Per-request state must be explicitly passed across the RSC→SSR
|
|
18
|
+
* environment boundary since they are separate Vite module graphs.
|
|
19
|
+
*/
|
|
20
|
+
export interface NavContext {
|
|
21
|
+
/** The requested pathname */
|
|
22
|
+
pathname: string;
|
|
23
|
+
/** Extracted route params (catch-all segments produce string[]) */
|
|
24
|
+
params: Record<string, string | string[]>;
|
|
25
|
+
/** Search params from the URL */
|
|
26
|
+
searchParams: Record<string, string>;
|
|
27
|
+
/** The committed HTTP status code */
|
|
28
|
+
statusCode: number;
|
|
29
|
+
/** Response headers from middleware/proxy */
|
|
30
|
+
responseHeaders: Headers;
|
|
31
|
+
/** Pre-rendered metadata HTML to inject before </head> */
|
|
32
|
+
headHtml: string;
|
|
33
|
+
/** Inline JS for React's bootstrapScriptContent — kicks off module loading */
|
|
34
|
+
bootstrapScriptContent: string;
|
|
35
|
+
/** Tee'd RSC stream for client-side hydration (inlined into HTML) */
|
|
36
|
+
rscStream?: ReadableStream<Uint8Array>;
|
|
37
|
+
/** Max Suspense hold window (ms). SSR delays the first flush by this
|
|
38
|
+
* duration, racing allReady so that fast-resolving boundaries render inline
|
|
39
|
+
* without ever showing a fallback. Derived from route `deferSuspenseFor` exports.
|
|
40
|
+
* See design/05-streaming.md §"deferSuspenseFor". */
|
|
41
|
+
deferSuspenseFor?: number;
|
|
42
|
+
/** Request abort signal. When the client disconnects (page refresh,
|
|
43
|
+
* navigation away), this signal fires. Passed to renderToReadableStream
|
|
44
|
+
* so React stops rendering and doesn't fire error boundaries for aborts. */
|
|
45
|
+
signal?: AbortSignal;
|
|
46
|
+
/** Request cookies as name→value pairs. Used by useCookie() during SSR
|
|
47
|
+
* to return correct cookie values before hydration. */
|
|
48
|
+
cookies?: Map<string, string>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Handle SSR: decode an RSC stream and render it to hydration-ready HTML.
|
|
52
|
+
*
|
|
53
|
+
* Steps:
|
|
54
|
+
* 1. Decode the RSC stream into a React element tree via createFromReadableStream
|
|
55
|
+
* (resolves "use client" references to actual component modules for SSR)
|
|
56
|
+
* 2. Render the decoded tree to HTML via renderToReadableStream (streaming)
|
|
57
|
+
* 3. Wait for onShellReady before flushing (handled by renderSsrStream)
|
|
58
|
+
* 4. Inject metadata into <head> and client scripts before </body>
|
|
59
|
+
* 5. Return Response with navContext.statusCode and navContext.responseHeaders
|
|
60
|
+
*
|
|
61
|
+
* The RSC stream is piped progressively — not buffered. For deny() outside
|
|
62
|
+
* Suspense, the RSC stream encodes an error in the shell region, causing
|
|
63
|
+
* renderToReadableStream to reject. The error propagates back to the RSC
|
|
64
|
+
* entry which renders the deny page. For deny() inside Suspense, the shell
|
|
65
|
+
* succeeds and the error streams as a React error boundary after flush.
|
|
66
|
+
*
|
|
67
|
+
* @param rscStream - The ReadableStream from the RSC environment
|
|
68
|
+
* @param navContext - Per-request state passed across RSC→SSR boundary
|
|
69
|
+
* @returns A Response containing the HTML stream with hydration markers
|
|
70
|
+
*/
|
|
71
|
+
export declare function handleSsr(rscStream: ReadableStream<Uint8Array>, navContext: NavContext): Promise<Response>;
|
|
72
|
+
export default handleSsr;
|
|
73
|
+
//# sourceMappingURL=ssr-entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssr-entry.d.ts","sourceRoot":"","sources":["../../src/server/ssr-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA2BH;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,iCAAiC;IACjC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,eAAe,EAAE,OAAO,CAAC;IACzB,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,sBAAsB,EAAE,MAAM,CAAC;IAC/B,qEAAqE;IACrE,SAAS,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACvC;;;0DAGsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;iFAE6E;IAC7E,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;4DACwD;IACxD,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,EACrC,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,QAAQ,CAAC,CA0DnB;AAED,eAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSR rendering utilities — testable core of the SSR entry.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from ssr-entry.ts so the rendering logic can be tested
|
|
5
|
+
* independently of the Vite RSC plugin runtime (which provides
|
|
6
|
+
* createFromReadableStream for decoding RSC streams).
|
|
7
|
+
*
|
|
8
|
+
* Design docs: 02-rendering-pipeline.md §"Single-Pass Rendering",
|
|
9
|
+
* 18-build-system.md §"Entry Files"
|
|
10
|
+
*/
|
|
11
|
+
import type { ReactNode } from 'react';
|
|
12
|
+
/**
|
|
13
|
+
* Render a React element tree to a ReadableStream of HTML.
|
|
14
|
+
*
|
|
15
|
+
* Uses renderToReadableStream (NOT renderToString) for streaming SSR.
|
|
16
|
+
* The returned stream begins yielding after onShellReady — everything
|
|
17
|
+
* outside <Suspense> boundaries is in the shell.
|
|
18
|
+
*
|
|
19
|
+
* With progressive streaming, the RSC stream is piped directly to SSR
|
|
20
|
+
* without buffering. If deny() was called outside a Suspense boundary,
|
|
21
|
+
* the RSC stream encodes an error in the shell — renderToReadableStream
|
|
22
|
+
* rejects, and the RSC entry catches this to render a deny page with
|
|
23
|
+
* the correct HTTP status code. If deny() was inside Suspense, the shell
|
|
24
|
+
* succeeds (200 committed) and the error streams as an error boundary.
|
|
25
|
+
*
|
|
26
|
+
* @param element - The React element tree decoded from the RSC stream
|
|
27
|
+
* @param options - Optional configuration
|
|
28
|
+
* @param options.bootstrapScriptContent - Inline JS injected by React as a
|
|
29
|
+
* non-deferred `<script>` in the shell HTML. Executes immediately during
|
|
30
|
+
* parsing — even while Suspense boundaries are still streaming. Used to
|
|
31
|
+
* kick off module loading via dynamic `import()` so hydration can start
|
|
32
|
+
* before the HTML stream closes.
|
|
33
|
+
* @returns A ReadableStream of HTML bytes with hydration markers
|
|
34
|
+
*/
|
|
35
|
+
export declare function renderSsrStream(element: ReactNode, options?: {
|
|
36
|
+
bootstrapScriptContent?: string;
|
|
37
|
+
deferSuspenseFor?: number;
|
|
38
|
+
signal?: AbortSignal;
|
|
39
|
+
}): Promise<ReadableStream<Uint8Array>>;
|
|
40
|
+
/**
|
|
41
|
+
* Wrap an HTML stream with error handling for the streaming phase.
|
|
42
|
+
*
|
|
43
|
+
* During progressive RSC→SSR streaming, errors in Suspense boundaries
|
|
44
|
+
* (e.g. deny() inside Suspense, throws in async components) cause
|
|
45
|
+
* React DOM's renderToReadableStream to error after the shell has been
|
|
46
|
+
* flushed. Without this wrapper, the stream error becomes an unhandled
|
|
47
|
+
* promise rejection that crashes the process.
|
|
48
|
+
*
|
|
49
|
+
* The wrapper catches streaming-phase errors, logs them, and closes
|
|
50
|
+
* the output stream cleanly. The shell (headers, status code, content
|
|
51
|
+
* outside Suspense) has already been sent to the client.
|
|
52
|
+
*/
|
|
53
|
+
/** @internal Exported for testing only. */
|
|
54
|
+
export declare function wrapStreamWithErrorHandling(stream: ReadableStream<Uint8Array>, signal?: AbortSignal): ReadableStream<Uint8Array>;
|
|
55
|
+
/**
|
|
56
|
+
* Build a Response from the SSR HTML stream with the correct
|
|
57
|
+
* status code and headers from the navigation context.
|
|
58
|
+
*
|
|
59
|
+
* Sets content-type to text/html if not already set by middleware.
|
|
60
|
+
*
|
|
61
|
+
* @param htmlStream - The HTML stream from renderSsrStream
|
|
62
|
+
* @param statusCode - The committed HTTP status code from RSC
|
|
63
|
+
* @param responseHeaders - Response headers from middleware/proxy
|
|
64
|
+
* @returns A Response ready to send to the client
|
|
65
|
+
*/
|
|
66
|
+
export declare function buildSsrResponse(htmlStream: ReadableStream<Uint8Array>, statusCode: number, responseHeaders: Headers): Response;
|
|
67
|
+
//# sourceMappingURL=ssr-render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssr-render.d.ts","sourceRoot":"","sources":["../../src/server/ssr-render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAmBvC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,SAAS,EAClB,OAAO,CAAC,EAAE;IAAE,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,GAC7F,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAmDrC;AAED;;;;;;;;;;;;GAYG;AACH,2CAA2C;AAC3C,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,EAClC,MAAM,CAAC,EAAE,WAAW,GACnB,cAAc,CAAC,UAAU,CAAC,CAkC5B;AAeD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,cAAc,CAAC,UAAU,CAAC,EACtC,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,OAAO,GACvB,QAAQ,CASV"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status-code file resolver for timber.js error/denial rendering.
|
|
3
|
+
*
|
|
4
|
+
* Given an HTTP status code and a matched segment chain, resolves the
|
|
5
|
+
* correct file to render by walking the fallback chain described in
|
|
6
|
+
* design/10-error-handling.md §"Status-Code Files".
|
|
7
|
+
*
|
|
8
|
+
* Supports two format families:
|
|
9
|
+
* - 'component' (default): .tsx/.jsx/.mdx status files → React rendering pipeline
|
|
10
|
+
* - 'json': .json status files → raw JSON response, no React
|
|
11
|
+
*
|
|
12
|
+
* Fallback chains operate within the same format family (no cross-format fallback).
|
|
13
|
+
*
|
|
14
|
+
* **Component chain (4xx):**
|
|
15
|
+
* Pass 1 — status files (leaf → root): {status}.tsx → 4xx.tsx
|
|
16
|
+
* Pass 2 — legacy compat (leaf → root): not-found.tsx / forbidden.tsx / unauthorized.tsx
|
|
17
|
+
* Pass 3 — error.tsx (leaf → root)
|
|
18
|
+
* Pass 4 — framework default (returns null)
|
|
19
|
+
*
|
|
20
|
+
* **JSON chain (4xx):**
|
|
21
|
+
* Pass 1 — json status files (leaf → root): {status}.json → 4xx.json
|
|
22
|
+
* Pass 2 — framework default JSON (returns null, caller provides bare JSON)
|
|
23
|
+
*
|
|
24
|
+
* **5xx (component only):**
|
|
25
|
+
* Per-segment (leaf → root): {status}.tsx → 5xx.tsx → error.tsx
|
|
26
|
+
* Then global-error.tsx (future)
|
|
27
|
+
* Then framework default (returns null)
|
|
28
|
+
*/
|
|
29
|
+
import type { SegmentNode, RouteFile } from '#/routing/types.js';
|
|
30
|
+
/** How the status-code file was matched. */
|
|
31
|
+
export type StatusFileKind = 'exact' | 'category' | 'legacy' | 'error';
|
|
32
|
+
/** Response format family for status-code resolution. */
|
|
33
|
+
export type StatusFileFormat = 'component' | 'json';
|
|
34
|
+
/** Result of resolving a status-code file for a segment chain. */
|
|
35
|
+
export interface StatusFileResolution {
|
|
36
|
+
/** The matched route file. */
|
|
37
|
+
file: RouteFile;
|
|
38
|
+
/** The HTTP status code (always the original status, not the file's code). */
|
|
39
|
+
status: number;
|
|
40
|
+
/** How the file was matched. */
|
|
41
|
+
kind: StatusFileKind;
|
|
42
|
+
/** Index into the segments array where the file was found. */
|
|
43
|
+
segmentIndex: number;
|
|
44
|
+
}
|
|
45
|
+
/** How a slot denial file was matched. */
|
|
46
|
+
export type SlotDeniedKind = 'denied' | 'default';
|
|
47
|
+
/** Result of resolving a slot denied file. */
|
|
48
|
+
export interface SlotDeniedResolution {
|
|
49
|
+
/** The matched route file (denied.tsx or default.tsx). */
|
|
50
|
+
file: RouteFile;
|
|
51
|
+
/** Slot name without @ prefix. */
|
|
52
|
+
slotName: string;
|
|
53
|
+
/** How the file was matched. */
|
|
54
|
+
kind: SlotDeniedKind;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Resolve the status-code file to render for a given HTTP status code.
|
|
58
|
+
*
|
|
59
|
+
* Walks the segment chain from leaf to root following the fallback chain
|
|
60
|
+
* defined in design/10-error-handling.md. Returns null if no file is found
|
|
61
|
+
* (caller should render the framework default).
|
|
62
|
+
*
|
|
63
|
+
* @param status - The HTTP status code (4xx or 5xx).
|
|
64
|
+
* @param segments - The matched segment chain from root (index 0) to leaf (last).
|
|
65
|
+
* @param format - The response format family ('component' or 'json'). Defaults to 'component'.
|
|
66
|
+
*/
|
|
67
|
+
export declare function resolveStatusFile(status: number, segments: ReadonlyArray<SegmentNode>, format?: StatusFileFormat): StatusFileResolution | null;
|
|
68
|
+
/**
|
|
69
|
+
* Resolve the denial file for a parallel route slot.
|
|
70
|
+
*
|
|
71
|
+
* Slot denial is graceful degradation — no HTTP status on the wire.
|
|
72
|
+
* Fallback chain: denied.tsx → default.tsx → null.
|
|
73
|
+
*
|
|
74
|
+
* @param slotNode - The segment node for the slot (segmentType === 'slot').
|
|
75
|
+
*/
|
|
76
|
+
export declare function resolveSlotDenied(slotNode: SegmentNode): SlotDeniedResolution | null;
|
|
77
|
+
//# sourceMappingURL=status-code-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-code-resolver.d.ts","sourceRoot":"","sources":["../../src/server/status-code-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAIjE,4CAA4C;AAC5C,MAAM,MAAM,cAAc,GACtB,OAAO,GACP,UAAU,GACV,QAAQ,GACR,OAAO,CAAC;AAEZ,yDAAyD;AACzD,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,MAAM,CAAC;AAEpD,kEAAkE;AAClE,MAAM,WAAW,oBAAoB;IACnC,8BAA8B;IAC9B,IAAI,EAAE,SAAS,CAAC;IAChB,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,IAAI,EAAE,cAAc,CAAC;IACrB,8DAA8D;IAC9D,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,0CAA0C;AAC1C,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,CAAC;AAElD,8CAA8C;AAC9C,MAAM,WAAW,oBAAoB;IACnC,0DAA0D;IAC1D,IAAI,EAAE,SAAS,CAAC;IAChB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,IAAI,EAAE,cAAc,CAAC;CACtB;AAgBD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,aAAa,CAAC,WAAW,CAAC,EACpC,MAAM,GAAE,gBAA8B,GACrC,oBAAoB,GAAG,IAAI,CAS7B;AA2JD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,WAAW,GAAG,oBAAoB,GAAG,IAAI,CAYpF"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tracing — per-request trace ID via AsyncLocalStorage, OTEL span helpers.
|
|
3
|
+
*
|
|
4
|
+
* traceId() is always available in server code (middleware, access, components, actions).
|
|
5
|
+
* Returns a 32-char lowercase hex string — the OTEL trace ID when an SDK is active,
|
|
6
|
+
* or a crypto.randomUUID()-derived fallback otherwise.
|
|
7
|
+
*
|
|
8
|
+
* See design/17-logging.md §"trace_id is Always Set"
|
|
9
|
+
*/
|
|
10
|
+
export interface TraceStore {
|
|
11
|
+
/** 32-char lowercase hex trace ID (OTEL or UUID fallback). */
|
|
12
|
+
traceId: string;
|
|
13
|
+
/** OTEL span ID if available, undefined otherwise. */
|
|
14
|
+
spanId?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Returns the current request's trace ID — always a 32-char lowercase hex string.
|
|
18
|
+
*
|
|
19
|
+
* With OTEL: the real OTEL trace ID (matches Jaeger/Honeycomb/Datadog).
|
|
20
|
+
* Without OTEL: crypto.randomUUID() with hyphens stripped.
|
|
21
|
+
*
|
|
22
|
+
* Throws if called outside a request context (no ALS store).
|
|
23
|
+
*/
|
|
24
|
+
export declare function traceId(): string;
|
|
25
|
+
/**
|
|
26
|
+
* Returns the current OTEL span ID if available, undefined otherwise.
|
|
27
|
+
*/
|
|
28
|
+
export declare function spanId(): string | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Generate a 32-char lowercase hex ID from crypto.randomUUID().
|
|
31
|
+
* Same format as OTEL trace IDs — zero-friction upgrade path.
|
|
32
|
+
*/
|
|
33
|
+
export declare function generateTraceId(): string;
|
|
34
|
+
/**
|
|
35
|
+
* Run a callback within a trace context. Used by the pipeline to establish
|
|
36
|
+
* per-request ALS scope.
|
|
37
|
+
*/
|
|
38
|
+
export declare function runWithTraceId<T>(id: string, fn: () => T): T;
|
|
39
|
+
/**
|
|
40
|
+
* Replace the trace ID in the current ALS store. Used when OTEL creates
|
|
41
|
+
* a root span and we want to switch from the UUID fallback to the real
|
|
42
|
+
* OTEL trace ID.
|
|
43
|
+
*/
|
|
44
|
+
export declare function replaceTraceId(newTraceId: string, newSpanId?: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* Update the span ID in the current ALS store. Used when entering a new
|
|
47
|
+
* OTEL span to keep log–trace correlation accurate.
|
|
48
|
+
*/
|
|
49
|
+
export declare function updateSpanId(newSpanId: string | undefined): void;
|
|
50
|
+
/**
|
|
51
|
+
* Get the current trace store, or undefined if outside a request context.
|
|
52
|
+
* Framework-internal — use traceId()/spanId() in user code.
|
|
53
|
+
*/
|
|
54
|
+
export declare function getTraceStore(): TraceStore | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* Initialize a minimal OTEL SDK in dev mode so spans are recorded and
|
|
57
|
+
* fed to the DevSpanProcessor for dev log output.
|
|
58
|
+
*
|
|
59
|
+
* If the user already configured an OTEL SDK in register(), we add
|
|
60
|
+
* our DevSpanProcessor alongside theirs. If no SDK is configured,
|
|
61
|
+
* we create a BasicTracerProvider with our processor.
|
|
62
|
+
*
|
|
63
|
+
* Only called in dev mode — zero overhead in production.
|
|
64
|
+
*/
|
|
65
|
+
export declare function initDevTracing(config: import('./dev-logger.js').DevLoggerConfig): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Get the timber.js OTEL tracer. Returns null if @opentelemetry/api is not available.
|
|
68
|
+
*/
|
|
69
|
+
export declare function getTracer(): Promise<import('@opentelemetry/api').Tracer | null>;
|
|
70
|
+
/**
|
|
71
|
+
* Run a function within an OTEL span. If OTEL is not available, runs the function
|
|
72
|
+
* directly without any span overhead.
|
|
73
|
+
*
|
|
74
|
+
* Automatically:
|
|
75
|
+
* - Creates the span as a child of the current context
|
|
76
|
+
* - Updates the ALS span ID for log–trace correlation
|
|
77
|
+
* - Ends the span when the function completes
|
|
78
|
+
* - Records exceptions on error
|
|
79
|
+
*/
|
|
80
|
+
export declare function withSpan<T>(name: string, attributes: Record<string, string | number | boolean>, fn: () => T | Promise<T>): Promise<T>;
|
|
81
|
+
/**
|
|
82
|
+
* Set an attribute on the current active span (if any).
|
|
83
|
+
* Used for setting span attributes after span creation (e.g. timber.result on access spans).
|
|
84
|
+
*/
|
|
85
|
+
export declare function setSpanAttribute(key: string, value: string | number | boolean): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Add a span event to the current active span (if any).
|
|
88
|
+
* Used for timber.cache HIT/MISS events — recorded as span events, not child spans.
|
|
89
|
+
*/
|
|
90
|
+
export declare function addSpanEvent(name: string, attributes?: Record<string, string | number | boolean>): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Try to extract the OTEL trace ID from the current active span context.
|
|
93
|
+
* Returns undefined if OTEL is not active or no span exists.
|
|
94
|
+
*/
|
|
95
|
+
export declare function getOtelTraceId(): Promise<{
|
|
96
|
+
traceId: string;
|
|
97
|
+
spanId: string;
|
|
98
|
+
} | undefined>;
|
|
99
|
+
//# sourceMappingURL=tracing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../../src/server/tracing.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,MAAM,WAAW,UAAU;IACzB,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAMD;;;;;;;GAOG;AACH,wBAAgB,OAAO,IAAI,MAAM,CAShC;AAED;;GAEG;AACH,wBAAgB,MAAM,IAAI,MAAM,GAAG,SAAS,CAE3C;AAID;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAM3E;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAKhE;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,UAAU,GAAG,SAAS,CAEtD;AAID;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,OAAO,iBAAiB,EAAE,eAAe,GAChD,OAAO,CAAC,IAAI,CAAC,CA4Bf;AA4BD;;GAEG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,OAAO,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC,CAUrF;AAED;;;;;;;;;GASG;AACH,wBAAsB,QAAQ,CAAC,CAAC,EAC9B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EACrD,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC,CAAC,CAAC,CAyBZ;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAC/B,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GACrD,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC,CAc/F"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Element tree construction for timber.js rendering.
|
|
3
|
+
*
|
|
4
|
+
* Builds a unified React element tree from a matched segment chain, bottom-up:
|
|
5
|
+
* page → status-code error boundaries → access gates → layout → repeat up segment chain
|
|
6
|
+
*
|
|
7
|
+
* The tree is rendered via a single `renderToReadableStream` call,
|
|
8
|
+
* giving one `React.cache` scope for the entire route.
|
|
9
|
+
*
|
|
10
|
+
* See design/02-rendering-pipeline.md §"Element Tree Construction"
|
|
11
|
+
*/
|
|
12
|
+
import type { SegmentNode, RouteFile } from '#/routing/types.js';
|
|
13
|
+
/** A loaded module for a route file convention. */
|
|
14
|
+
export interface LoadedModule {
|
|
15
|
+
/** The default export (component, access function, etc.) */
|
|
16
|
+
default?: unknown;
|
|
17
|
+
/** Named exports (for route.ts method handlers, metadata, etc.) */
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
/** Function that loads a route file's module. */
|
|
21
|
+
export type ModuleLoader = (file: RouteFile) => LoadedModule | Promise<LoadedModule>;
|
|
22
|
+
/** A React element — kept opaque to avoid a React dependency in this module. */
|
|
23
|
+
export type ReactElement = any;
|
|
24
|
+
/** Function that creates a React element. Matches React.createElement signature. */
|
|
25
|
+
export type CreateElement = (type: unknown, props: Record<string, unknown> | null, ...children: unknown[]) => ReactElement;
|
|
26
|
+
/**
|
|
27
|
+
* Resolved slot content for a layout.
|
|
28
|
+
* Key is slot name (without @), value is the element tree for that slot.
|
|
29
|
+
*/
|
|
30
|
+
export type SlotElements = Map<string, ReactElement>;
|
|
31
|
+
/** Configuration for the tree builder. */
|
|
32
|
+
export interface TreeBuilderConfig {
|
|
33
|
+
/** The matched segment chain from root to leaf. */
|
|
34
|
+
segments: SegmentNode[];
|
|
35
|
+
/** Route params extracted by the matcher (catch-all segments produce string[]). */
|
|
36
|
+
params: Record<string, string | string[]>;
|
|
37
|
+
/** Parsed search params (typed or URLSearchParams). */
|
|
38
|
+
searchParams: unknown;
|
|
39
|
+
/** Loads a route file's module. */
|
|
40
|
+
loadModule: ModuleLoader;
|
|
41
|
+
/** React.createElement or equivalent. */
|
|
42
|
+
createElement: CreateElement;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Framework-injected access gate component.
|
|
46
|
+
*
|
|
47
|
+
* When `verdict` is provided (from the pre-render pass), AccessGate replays
|
|
48
|
+
* the stored result synchronously — no re-execution, no async, immune to
|
|
49
|
+
* Suspense timing. When `verdict` is absent, falls back to calling `accessFn`
|
|
50
|
+
* (backward compat for tree-builder.ts which doesn't run a pre-render pass).
|
|
51
|
+
*/
|
|
52
|
+
export interface AccessGateProps {
|
|
53
|
+
accessFn: (ctx: {
|
|
54
|
+
params: Record<string, string | string[]>;
|
|
55
|
+
searchParams: unknown;
|
|
56
|
+
}) => unknown;
|
|
57
|
+
params: Record<string, string | string[]>;
|
|
58
|
+
searchParams: unknown;
|
|
59
|
+
/** Segment name for dev logging (e.g. "authenticated", "dashboard"). */
|
|
60
|
+
segmentName?: string;
|
|
61
|
+
/**
|
|
62
|
+
* Pre-computed verdict from the pre-render pass. When set, AccessGate
|
|
63
|
+
* replays this verdict synchronously instead of calling accessFn.
|
|
64
|
+
* - 'pass': render children
|
|
65
|
+
* - DenySignal/RedirectSignal: throw synchronously
|
|
66
|
+
*/
|
|
67
|
+
verdict?: 'pass' | import('./primitives.js').DenySignal | import('./primitives.js').RedirectSignal;
|
|
68
|
+
children: ReactElement;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Framework-injected slot access gate component.
|
|
72
|
+
* On denial, renders denied.tsx → default.tsx → null instead of failing the page.
|
|
73
|
+
*/
|
|
74
|
+
export interface SlotAccessGateProps {
|
|
75
|
+
accessFn: (ctx: {
|
|
76
|
+
params: Record<string, string | string[]>;
|
|
77
|
+
searchParams: unknown;
|
|
78
|
+
}) => unknown;
|
|
79
|
+
params: Record<string, string | string[]>;
|
|
80
|
+
searchParams: unknown;
|
|
81
|
+
deniedFallback: ReactElement | null;
|
|
82
|
+
defaultFallback: ReactElement | null;
|
|
83
|
+
children: ReactElement;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Framework-injected error boundary wrapper.
|
|
87
|
+
* Wraps content with status-code error boundary handling.
|
|
88
|
+
*/
|
|
89
|
+
export interface ErrorBoundaryProps {
|
|
90
|
+
fallbackComponent: ReactElement | null;
|
|
91
|
+
status?: number;
|
|
92
|
+
children: ReactElement;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Result of building the element tree.
|
|
96
|
+
*/
|
|
97
|
+
export interface TreeBuildResult {
|
|
98
|
+
/** The root React element tree ready for renderToReadableStream. */
|
|
99
|
+
tree: ReactElement;
|
|
100
|
+
/** Whether the leaf segment is a route.ts (API endpoint) rather than a page. */
|
|
101
|
+
isApiRoute: boolean;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Build the unified element tree from a matched segment chain.
|
|
105
|
+
*
|
|
106
|
+
* Construction is bottom-up:
|
|
107
|
+
* 1. Start with the page component (leaf segment)
|
|
108
|
+
* 2. Wrap in status-code error boundaries (fallback chain)
|
|
109
|
+
* 3. Wrap in AccessGate (if segment has access.ts)
|
|
110
|
+
* 4. Pass as children to the segment's layout
|
|
111
|
+
* 5. Repeat up the segment chain to root
|
|
112
|
+
*
|
|
113
|
+
* Parallel slots are resolved at each layout level and composed as named props.
|
|
114
|
+
*/
|
|
115
|
+
export declare function buildElementTree(config: TreeBuilderConfig): Promise<TreeBuildResult>;
|
|
116
|
+
//# sourceMappingURL=tree-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree-builder.d.ts","sourceRoot":"","sources":["../../src/server/tree-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAKjE,mDAAmD;AACnD,MAAM,WAAW,YAAY;IAC3B,4DAA4D;IAC5D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mEAAmE;IACnE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,iDAAiD;AACjD,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,SAAS,KAAK,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;AAErF,gFAAgF;AAEhF,MAAM,MAAM,YAAY,GAAG,GAAG,CAAC;AAE/B,oFAAoF;AACpF,MAAM,MAAM,aAAa,GAAG,CAC1B,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACrC,GAAG,QAAQ,EAAE,OAAO,EAAE,KACnB,YAAY,CAAC;AAElB;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AAErD,0CAA0C;AAC1C,MAAM,WAAW,iBAAiB;IAChC,mDAAmD;IACnD,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,uDAAuD;IACvD,YAAY,EAAE,OAAO,CAAC;IACtB,mCAAmC;IACnC,UAAU,EAAE,YAAY,CAAC;IACzB,yCAAyC;IACzC,aAAa,EAAE,aAAa,CAAC;CAC9B;AAID;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,CAAC,GAAG,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;QAAC,YAAY,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC;IACjG,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,YAAY,EAAE,OAAO,CAAC;IACtB,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,iBAAiB,EAAE,UAAU,GAAG,OAAO,iBAAiB,EAAE,cAAc,CAAC;IACnG,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,CAAC,GAAG,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;QAAC,YAAY,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC;IACjG,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,YAAY,EAAE,OAAO,CAAC;IACtB,cAAc,EAAE,YAAY,GAAG,IAAI,CAAC;IACpC,eAAe,EAAE,YAAY,GAAG,IAAI,CAAC;IACrC,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,iBAAiB,EAAE,YAAY,GAAG,IAAI,CAAC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,YAAY,CAAC;CACxB;AAID;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,oEAAoE;IACpE,IAAI,EAAE,YAAY,CAAC;IACnB,gFAAgF;IAChF,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,eAAe,CAAC,CAiF1F"}
|