@timber-js/app 0.2.0-alpha.157 → 0.2.0-alpha.159
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/dist/_chunks/{actions-CqE7SW7E.js → actions-CBbP1hHO.js} +22 -6
- package/dist/_chunks/actions-CBbP1hHO.js.map +1 -0
- package/dist/_chunks/{build-output-helper-C8q4Zpf5.js → build-output-helper-DF5uScqS.js} +4 -1
- package/dist/_chunks/{build-output-helper-C8q4Zpf5.js.map → build-output-helper-DF5uScqS.js.map} +1 -1
- package/dist/_chunks/cache-api-DsWEYwVZ.js +1120 -0
- package/dist/_chunks/cache-api-DsWEYwVZ.js.map +1 -0
- package/dist/_chunks/{cli-schema-sync-DcmQrzJG.js → cli-schema-sync-Bivx4Rn7.js} +4 -3
- package/dist/_chunks/{cli-schema-sync-DcmQrzJG.js.map → cli-schema-sync-Bivx4Rn7.js.map} +1 -1
- package/dist/_chunks/dist-BA3u1z3W.js +423 -0
- package/dist/_chunks/dist-BA3u1z3W.js.map +1 -0
- package/dist/_chunks/{logger-C5v1IMuh.js → logger-CrRmZMlo.js} +81 -56
- package/dist/_chunks/logger-CrRmZMlo.js.map +1 -0
- package/dist/_chunks/{plugin-context-DUl3dnCF.js → plugin-context-DeAxFRMq.js} +3 -36
- package/dist/_chunks/plugin-context-DeAxFRMq.js.map +1 -0
- package/dist/_chunks/sizeof-lXffQ1Vr.js +35 -0
- package/dist/_chunks/sizeof-lXffQ1Vr.js.map +1 -0
- package/dist/_chunks/{walkers-D5jCGPum.js → walkers-DXbJkeCY.js} +217 -19
- package/dist/_chunks/walkers-DXbJkeCY.js.map +1 -0
- package/dist/adapters/build-output-helper.d.ts.map +1 -1
- package/dist/adapters/cloudflare.d.ts +28 -0
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +143 -9
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/nitro.js +1 -1
- package/dist/cache/cache-api.d.ts +2 -0
- package/dist/cache/cache-api.d.ts.map +1 -1
- package/dist/cache/handler-store.d.ts +2 -0
- package/dist/cache/handler-store.d.ts.map +1 -1
- package/dist/cache/index.d.ts +2 -0
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +3 -186
- package/dist/cache/redis-handler.d.ts +17 -5
- package/dist/cache/redis-handler.d.ts.map +1 -1
- package/dist/cache/singleflight.d.ts +1 -1
- package/dist/cache/singleflight.d.ts.map +1 -1
- package/dist/cache/store.d.ts +53 -0
- package/dist/cache/store.d.ts.map +1 -0
- package/dist/cache/stores/cloudflare-kv.d.ts +38 -0
- package/dist/cache/stores/cloudflare-kv.d.ts.map +1 -0
- package/dist/cache/stores/cloudflare-kv.js +29 -0
- package/dist/cache/stores/cloudflare-kv.js.map +1 -0
- package/dist/cache/stores/memory.d.ts +42 -0
- package/dist/cache/stores/memory.d.ts.map +1 -0
- package/dist/cache/stores/memory.js +90 -0
- package/dist/cache/stores/memory.js.map +1 -0
- package/dist/cache/stores/redis.d.ts +69 -0
- package/dist/cache/stores/redis.d.ts.map +1 -0
- package/dist/cache/stores/redis.js +35 -0
- package/dist/cache/stores/redis.js.map +1 -0
- package/dist/cache/stores/vercel.d.ts +36 -0
- package/dist/cache/stores/vercel.d.ts.map +1 -0
- package/dist/cache/stores/vercel.js +33 -0
- package/dist/cache/stores/vercel.js.map +1 -0
- package/dist/cache/tag-aware-handler.d.ts +51 -0
- package/dist/cache/tag-aware-handler.d.ts.map +1 -0
- package/dist/cache/timber-cache.d.ts.map +1 -1
- package/dist/cdn/cloudflare-purge.d.ts +23 -0
- package/dist/cdn/cloudflare-purge.d.ts.map +1 -0
- package/dist/cdn/fastly-purge.d.ts +25 -0
- package/dist/cdn/fastly-purge.d.ts.map +1 -0
- package/dist/cdn/headers.d.ts +82 -0
- package/dist/cdn/headers.d.ts.map +1 -0
- package/dist/cdn/index.d.ts +5 -0
- package/dist/cdn/index.d.ts.map +1 -0
- package/dist/cdn/purge-store.d.ts +23 -0
- package/dist/cdn/purge-store.d.ts.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
- package/dist/client/browser-entry/post-hydration.d.ts.map +1 -1
- package/dist/client/browser-entry/router-init.d.ts.map +1 -1
- package/dist/client/history.d.ts +0 -3
- package/dist/client/history.d.ts.map +1 -1
- package/dist/client/index.js +0 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.js +11 -86
- package/dist/client/internal.js.map +1 -1
- package/dist/client/navigation-api.d.ts +1 -3
- package/dist/client/navigation-api.d.ts.map +1 -1
- package/dist/client/router.d.ts +1 -4
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +1 -11
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +1 -3
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/use-cookie.d.ts.map +1 -1
- package/dist/config-types.d.ts +3 -1
- package/dist/config-types.d.ts.map +1 -1
- package/dist/config-validation.d.ts.map +1 -1
- package/dist/cookies/index.js +15 -11
- package/dist/cookies/index.js.map +1 -1
- package/dist/dev-tools/browser-logs.d.ts +28 -72
- package/dist/dev-tools/browser-logs.d.ts.map +1 -1
- package/dist/dev-tools/index.d.ts +1 -1
- package/dist/dev-tools/index.d.ts.map +1 -1
- package/dist/dev-tools/logger.d.ts.map +1 -1
- package/dist/dev-tools/terminal.d.ts.map +1 -1
- package/dist/fonts/transform.d.ts +4 -0
- package/dist/fonts/transform.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1269 -359
- package/dist/index.js.map +1 -1
- package/dist/plugin-context.d.ts +36 -0
- package/dist/plugin-context.d.ts.map +1 -1
- package/dist/plugins/build-report.d.ts +21 -0
- package/dist/plugins/build-report.d.ts.map +1 -1
- package/dist/plugins/cache.d.ts +5 -14
- package/dist/plugins/cache.d.ts.map +1 -1
- package/dist/plugins/callsite-ast.d.ts +95 -0
- package/dist/plugins/callsite-ast.d.ts.map +1 -0
- package/dist/plugins/callsite-jsx.d.ts +35 -0
- package/dist/plugins/callsite-jsx.d.ts.map +1 -0
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts.map +1 -1
- package/dist/plugins/prebuilt-capture.d.ts +60 -0
- package/dist/plugins/prebuilt-capture.d.ts.map +1 -0
- package/dist/plugins/prebuilt.d.ts +82 -0
- package/dist/plugins/prebuilt.d.ts.map +1 -0
- package/dist/plugins/prerender-sugar.d.ts +42 -0
- package/dist/plugins/prerender-sugar.d.ts.map +1 -0
- package/dist/plugins/server-bundle.d.ts.map +1 -1
- package/dist/plugins/shims.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/convention-lint.d.ts.map +1 -1
- package/dist/routing/export-detect.d.ts +56 -0
- package/dist/routing/export-detect.d.ts.map +1 -0
- package/dist/routing/index.js +2 -2
- package/dist/routing/manifest-codegen.d.ts.map +1 -1
- package/dist/rsc-runtime/rsc.d.ts +1 -1
- package/dist/rsc-runtime/rsc.d.ts.map +1 -1
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/actions.d.ts +0 -3
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +7 -0
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/cookie-parsing.d.ts +15 -1
- package/dist/server/cookie-parsing.d.ts.map +1 -1
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/form-data.d.ts +12 -0
- package/dist/server/form-data.d.ts.map +1 -1
- package/dist/server/html-injectors.d.ts +1 -0
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/internal.d.ts +6 -1
- package/dist/server/internal.d.ts.map +1 -1
- package/dist/server/internal.js +563 -74
- package/dist/server/internal.js.map +1 -1
- package/dist/server/prebuilt/cache-key.d.ts +58 -0
- package/dist/server/prebuilt/cache-key.d.ts.map +1 -0
- package/dist/server/prebuilt/capture-state.d.ts +57 -0
- package/dist/server/prebuilt/capture-state.d.ts.map +1 -0
- package/dist/server/prebuilt/manifest-tag-index.d.ts +27 -0
- package/dist/server/prebuilt/manifest-tag-index.d.ts.map +1 -0
- package/dist/server/prebuilt/overlay.d.ts +100 -0
- package/dist/server/prebuilt/overlay.d.ts.map +1 -0
- package/dist/server/prebuilt/payload-source.d.ts +75 -0
- package/dist/server/prebuilt/payload-source.d.ts.map +1 -0
- package/dist/server/prebuilt/synthetic-store.d.ts +64 -0
- package/dist/server/prebuilt/synthetic-store.d.ts.map +1 -0
- package/dist/server/prebuilt-builder.d.ts +110 -0
- package/dist/server/prebuilt-builder.d.ts.map +1 -0
- package/dist/server/prebuilt-runtime.d.ts +101 -0
- package/dist/server/prebuilt-runtime.d.ts.map +1 -0
- package/dist/server/route-element-builder.d.ts +10 -8
- package/dist/server/route-element-builder.d.ts.map +1 -1
- package/dist/server/rsc-entry/helpers.d.ts +0 -5
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +10 -0
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
- package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-payload.d.ts +3 -4
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/sitemap-generator.d.ts +6 -6
- package/dist/server/sitemap-generator.d.ts.map +1 -1
- package/dist/server/tracing.d.ts +37 -3
- package/dist/server/tracing.d.ts.map +1 -1
- package/docs/api/32-api-cache.mdx +10 -4
- package/docs/learn/00-introduction.mdx +8 -13
- package/docs/learn/02-pages-and-layouts.mdx +9 -0
- package/docs/learn/06-forms-and-actions.mdx +0 -4
- package/docs/learn/07-typed-routes.mdx +127 -0
- package/docs/learn/09-caching.mdx +12 -1
- package/docs/learn/10-middleware.mdx +1 -0
- package/docs/learn/11-error-handling.mdx +9 -0
- package/docs/learn/13-configuration.mdx +28 -0
- package/docs/learn/14-deploying.mdx +52 -0
- package/docs/more/06-instrumentation.mdx +27 -1
- package/docs/more/07-security.mdx +8 -2
- package/docs/more/08-developer-experience.mdx +134 -0
- package/package.json +31 -2
- package/src/adapters/build-output-helper.ts +10 -0
- package/src/adapters/cloudflare.ts +178 -4
- package/src/cache/cache-api.ts +60 -0
- package/src/cache/handler-store.ts +8 -0
- package/src/cache/index.ts +4 -0
- package/src/cache/redis-handler.ts +25 -13
- package/src/cache/singleflight.ts +11 -11
- package/src/cache/store.ts +71 -0
- package/src/cache/stores/cloudflare-kv.ts +52 -0
- package/src/cache/stores/memory.ts +125 -0
- package/src/cache/stores/redis.ts +97 -0
- package/src/cache/stores/vercel.ts +59 -0
- package/src/cache/tag-aware-handler.ts +233 -0
- package/src/cache/timber-cache.ts +17 -7
- package/src/cdn/cloudflare-purge.ts +50 -0
- package/src/cdn/fastly-purge.ts +63 -0
- package/src/cdn/headers.ts +127 -0
- package/src/cdn/index.ts +16 -0
- package/src/cdn/purge-store.ts +34 -0
- package/src/client/browser-entry/action-dispatch.ts +1 -10
- package/src/client/browser-entry/post-hydration.ts +0 -1
- package/src/client/browser-entry/router-init.ts +0 -5
- package/src/client/history.ts +0 -4
- package/src/client/navigation-api.ts +5 -11
- package/src/client/router.ts +9 -43
- package/src/client/rsc-fetch.ts +5 -27
- package/src/client/segment-cache.ts +1 -4
- package/src/client/use-cookie.ts +18 -12
- package/src/config-types.ts +3 -1
- package/src/config-validation.ts +1 -0
- package/src/dev-tools/browser-logs.ts +37 -273
- package/src/dev-tools/index.ts +2 -2
- package/src/dev-tools/instrumentation.ts +1 -1
- package/src/dev-tools/logger.ts +33 -51
- package/src/dev-tools/terminal.ts +21 -22
- package/src/fonts/transform.ts +4 -43
- package/src/index.ts +16 -3
- package/src/plugin-context.ts +36 -0
- package/src/plugins/build-report.ts +133 -1
- package/src/plugins/cache.ts +32 -131
- package/src/plugins/callsite-ast.ts +167 -0
- package/src/plugins/callsite-jsx.ts +243 -0
- package/src/plugins/entries.ts +23 -4
- package/src/plugins/fonts.ts +16 -2
- package/src/plugins/prebuilt-capture.ts +208 -0
- package/src/plugins/prebuilt.ts +673 -0
- package/src/plugins/prerender-sugar.ts +329 -0
- package/src/plugins/server-bundle.ts +12 -0
- package/src/plugins/shims.ts +9 -0
- package/src/plugins/static-build.ts +0 -1
- package/src/routing/codegen.ts +1 -21
- package/src/routing/convention-lint.ts +85 -49
- package/src/routing/export-detect.ts +304 -0
- package/src/routing/manifest-codegen.ts +2 -11
- package/src/rsc-runtime/rsc.ts +7 -0
- package/src/server/action-handler.ts +11 -27
- package/src/server/actions.ts +3 -4
- package/src/server/als-registry.ts +7 -0
- package/src/server/cookie-parsing.ts +75 -59
- package/src/server/deny-renderer.ts +7 -15
- package/src/server/form-data.ts +23 -7
- package/src/server/html-injectors.ts +11 -3
- package/src/server/internal.ts +17 -1
- package/src/server/prebuilt/cache-key.ts +224 -0
- package/src/server/prebuilt/capture-state.ts +89 -0
- package/src/server/prebuilt/manifest-tag-index.ts +46 -0
- package/src/server/prebuilt/overlay.ts +256 -0
- package/src/server/prebuilt/payload-source.ts +192 -0
- package/src/server/prebuilt/synthetic-store.ts +108 -0
- package/src/server/prebuilt-builder.ts +640 -0
- package/src/server/prebuilt-runtime.ts +706 -0
- package/src/server/route-element-builder.ts +40 -12
- package/src/server/rsc-entry/helpers.ts +0 -17
- package/src/server/rsc-entry/index.ts +83 -0
- package/src/server/rsc-entry/render-route.ts +6 -33
- package/src/server/rsc-entry/revalidate-renderer.ts +16 -11
- package/src/server/rsc-entry/rsc-payload.ts +5 -11
- package/src/server/sitemap-generator.ts +16 -10
- package/src/server/tracing.ts +88 -3
- package/dist/_chunks/actions-CqE7SW7E.js.map +0 -1
- package/dist/_chunks/cache-api-Cbyh3RW4.js +0 -401
- package/dist/_chunks/cache-api-Cbyh3RW4.js.map +0 -1
- package/dist/_chunks/logger-C5v1IMuh.js.map +0 -1
- package/dist/_chunks/plugin-context-DUl3dnCF.js.map +0 -1
- package/dist/_chunks/validation-CnKhGJsp.js +0 -113
- package/dist/_chunks/validation-CnKhGJsp.js.map +0 -1
- package/dist/_chunks/walkers-D5jCGPum.js.map +0 -1
- package/dist/cache/index.js.map +0 -1
- package/dist/client/head.d.ts +0 -16
- package/dist/client/head.d.ts.map +0 -1
- package/dist/client/navigation-api-types.d.ts +0 -90
- package/dist/client/navigation-api-types.d.ts.map +0 -1
- package/dist/server/client-module-map.d.ts +0 -47
- package/dist/server/client-module-map.d.ts.map +0 -1
- package/dist/shared/head-header.d.ts +0 -54
- package/dist/shared/head-header.d.ts.map +0 -1
- package/src/client/head.ts +0 -61
- package/src/client/navigation-api-types.ts +0 -112
- package/src/server/client-module-map.ts +0 -58
- package/src/shared/head-header.ts +0 -69
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-build prebuilt capture — Node-side orchestration (TIM-1119).
|
|
3
|
+
*
|
|
4
|
+
* Runs from timber-prebuilt's `buildApp` post hook, after Vite's 5-step
|
|
5
|
+
* build sequence. Imports the BUILT `rsc/index.js` (the bundle carries
|
|
6
|
+
* the react-server condition resolved at build time, so a plain dynamic
|
|
7
|
+
* import works) and calls its `__timber_capturePrebuilt` export — the
|
|
8
|
+
* capture itself must run inside the bundle's module graph, where the
|
|
9
|
+
* component registry and flight renderer live. See
|
|
10
|
+
* server/prebuilt-builder.ts and design/44-render-at-build-time.md
|
|
11
|
+
* §Build Phase.
|
|
12
|
+
*
|
|
13
|
+
* This side owns PERSISTENCE: each captured payload is written to
|
|
14
|
+
* `.timber/dist/prebuilt/<componentId>/<cacheKey>.flight` atomically
|
|
15
|
+
* (temp file + rename — a crashed build never leaves a torn artifact
|
|
16
|
+
* under its final name), and `manifest.json` is written last, only after
|
|
17
|
+
* every payload it references is fully on disk. Keeping node:fs on the
|
|
18
|
+
* plugin side keeps it out of the server bundle, which must also run on
|
|
19
|
+
* Cloudflare Workers.
|
|
20
|
+
*
|
|
21
|
+
* NOTE: importing the built entry runs the app's production startup —
|
|
22
|
+
* instrumentation.ts register() and the configured cache handler load
|
|
23
|
+
* inside the build process. That is by design (prebuilt components may
|
|
24
|
+
* call timber.cache), and it only happens when the app actually declares
|
|
25
|
+
* prebuilt components.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import { existsSync } from 'node:fs';
|
|
29
|
+
import { mkdir, rename, rm, writeFile } from 'node:fs/promises';
|
|
30
|
+
import { dirname, join } from 'node:path';
|
|
31
|
+
import { pathToFileURL } from 'node:url';
|
|
32
|
+
|
|
33
|
+
import type { PluginContext } from '../plugin-context.js';
|
|
34
|
+
import type { CaptureOptions, CaptureSummary, CapturedEntry } from '../server/prebuilt-builder.js';
|
|
35
|
+
import type { PrebuiltManifest } from '../server/prebuilt/payload-source.js';
|
|
36
|
+
|
|
37
|
+
// ─── Artifact writer ──────────────────────────────────────────────────────
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Both patterns are framework-generated (plugins/prebuilt.ts assigns IDs,
|
|
41
|
+
* server/prebuilt/cache-key.ts hashes keys), so a mismatch is a framework
|
|
42
|
+
* bug or a tampered registry — either way it must never reach a path join.
|
|
43
|
+
*/
|
|
44
|
+
const COMPONENT_ID_RE = /^[a-z0-9]+_[0-9a-f]{16}$/;
|
|
45
|
+
const CACHE_KEY_RE = /^[0-9a-f]{16}$/;
|
|
46
|
+
|
|
47
|
+
export interface PrebuiltArtifactWriter {
|
|
48
|
+
write(entry: CapturedEntry): Promise<void>;
|
|
49
|
+
/** Write manifest.json (if any entries exist). Returns the entry count. */
|
|
50
|
+
finalize(): Promise<number>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Write a file atomically: temp sibling + rename. */
|
|
54
|
+
async function writeFileAtomic(path: string, data: Uint8Array | string): Promise<void> {
|
|
55
|
+
const tmp = `${path}.tmp`;
|
|
56
|
+
await writeFile(tmp, data);
|
|
57
|
+
await rename(tmp, path);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Create the writer for `.timber/dist/prebuilt/`. Storage layout per
|
|
62
|
+
* design/44 §Storage: one directory per component ID, one `.flight` file
|
|
63
|
+
* per cache key, one manifest.json mapping componentId + key → file +
|
|
64
|
+
* metadata.
|
|
65
|
+
*/
|
|
66
|
+
export function createPrebuiltArtifactWriter(prebuiltDir: string): PrebuiltArtifactWriter {
|
|
67
|
+
const manifest: PrebuiltManifest = {};
|
|
68
|
+
const buildTimestamp = Date.now();
|
|
69
|
+
let count = 0;
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
async write(entry: CapturedEntry): Promise<void> {
|
|
73
|
+
if (!COMPONENT_ID_RE.test(entry.componentId) || !CACHE_KEY_RE.test(entry.cacheKey)) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
`[timber] prebuilt artifact writer received a malformed identity ` +
|
|
76
|
+
`(componentId: ${JSON.stringify(entry.componentId)}, cacheKey: ` +
|
|
77
|
+
`${JSON.stringify(entry.cacheKey)}) — refusing to write`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
const relativeFile = `${entry.componentId}/${entry.cacheKey}.flight`;
|
|
81
|
+
const path = join(prebuiltDir, relativeFile);
|
|
82
|
+
await mkdir(dirname(path), { recursive: true });
|
|
83
|
+
await writeFileAtomic(path, entry.bytes);
|
|
84
|
+
|
|
85
|
+
manifest[entry.componentId] ??= { entries: {} };
|
|
86
|
+
manifest[entry.componentId].entries[entry.cacheKey] = {
|
|
87
|
+
params: entry.params,
|
|
88
|
+
file: relativeFile,
|
|
89
|
+
bytes: entry.bytes.byteLength,
|
|
90
|
+
buildTimestamp,
|
|
91
|
+
...(entry.tags ? { tags: entry.tags } : {}),
|
|
92
|
+
};
|
|
93
|
+
count++;
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
async finalize(): Promise<number> {
|
|
97
|
+
if (count === 0) return 0;
|
|
98
|
+
await writeFileAtomic(
|
|
99
|
+
join(prebuiltDir, 'manifest.json'),
|
|
100
|
+
JSON.stringify(manifest, null, 2) + '\n'
|
|
101
|
+
);
|
|
102
|
+
return count;
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Remove any `prebuilt/` output left by a previous build in this
|
|
109
|
+
* directory (watch mode, `emptyOutDir: false`). A stale manifest would
|
|
110
|
+
* make adapters ship payloads from an OLD build — reviving them serves
|
|
111
|
+
* outdated content with that build's chunk references instead of the
|
|
112
|
+
* intended miss → live render. Runs unconditionally at the start of the
|
|
113
|
+
* post-build hook, BEFORE the capture decision: a build whose app no
|
|
114
|
+
* longer declares any prebuilt components must also shed the artifacts
|
|
115
|
+
* (codex P2 on PR #836).
|
|
116
|
+
*/
|
|
117
|
+
export async function cleanPrebuiltDir(buildDir: string): Promise<void> {
|
|
118
|
+
await rm(join(buildDir, 'prebuilt'), { recursive: true, force: true });
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ─── Capture orchestration ────────────────────────────────────────────────
|
|
122
|
+
|
|
123
|
+
/** Shape of the built RSC entry's capture export. */
|
|
124
|
+
interface CaptureModule {
|
|
125
|
+
__timber_capturePrebuilt?: (options: CaptureOptions) => Promise<CaptureSummary>;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Load the built RSC entry and run the capture pass. Throws (failing the
|
|
130
|
+
* build) on infrastructure errors — missing/unloadable entry — and on
|
|
131
|
+
* dynamic-context hard errors (cookies()/headers() in a prerendered
|
|
132
|
+
* component). Per-entry data errors skip-and-report per design/44
|
|
133
|
+
* §Build-Phase Error Handling.
|
|
134
|
+
*/
|
|
135
|
+
export async function runPrebuiltCapture(ctx: PluginContext): Promise<CaptureSummary> {
|
|
136
|
+
const routeComponents = ctx.routePrebuiltComponents;
|
|
137
|
+
if (!routeComponents || routeComponents.size === 0) {
|
|
138
|
+
return { captured: 0, skipped: [], hardErrors: [], nestingWarnings: 0 };
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const entryPath = join(ctx.buildDir, 'rsc', 'index.js');
|
|
142
|
+
if (!existsSync(entryPath)) {
|
|
143
|
+
throw new Error(
|
|
144
|
+
`[timber] prebuilt capture: built RSC entry not found at ${entryPath} — ` +
|
|
145
|
+
`the app declares cache.component({ prerender: true }) call sites but the ` +
|
|
146
|
+
`RSC build output is missing`
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// The same globals the adapter entry sets before importing the handler
|
|
151
|
+
// (adapter-build.ts). The bundle's virtual:timber-build-manifest falls
|
|
152
|
+
// back to an empty manifest, but set the real values when available so
|
|
153
|
+
// capture-time behavior matches production startup.
|
|
154
|
+
const g = globalThis as Record<string, unknown>;
|
|
155
|
+
if (ctx.buildManifest) g.__TIMBER_BUILD_MANIFEST__ ??= ctx.buildManifest;
|
|
156
|
+
if (ctx.deploymentId) g.__TIMBER_DEPLOYMENT_ID__ ??= ctx.deploymentId;
|
|
157
|
+
|
|
158
|
+
console.log('[timber] cache.component: capturing prebuilt flight payloads…');
|
|
159
|
+
|
|
160
|
+
let mod: CaptureModule;
|
|
161
|
+
try {
|
|
162
|
+
// Cache-busting query: in a long-lived build process (vite build
|
|
163
|
+
// --watch), a bare file URL would return the FIRST build's module from
|
|
164
|
+
// the ESM cache — stale code and a stale (already-walked) registry.
|
|
165
|
+
const entryUrl = `${pathToFileURL(entryPath).href}?t=${Date.now()}`;
|
|
166
|
+
mod = (await import(/* @vite-ignore */ entryUrl)) as CaptureModule;
|
|
167
|
+
} catch (error) {
|
|
168
|
+
throw new Error(
|
|
169
|
+
`[timber] prebuilt capture: failed to load the built RSC entry (${entryPath}). ` +
|
|
170
|
+
`The capture pass runs the production server module inside the build process — ` +
|
|
171
|
+
`its startup must succeed for prerendering to work.`,
|
|
172
|
+
{ cause: error }
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
const capture = mod.__timber_capturePrebuilt;
|
|
176
|
+
if (typeof capture !== 'function') {
|
|
177
|
+
throw new Error(
|
|
178
|
+
`[timber] prebuilt capture: built RSC entry does not export __timber_capturePrebuilt — ` +
|
|
179
|
+
`the build output predates this framework version; rebuild from a clean .timber/dist`
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const writer = createPrebuiltArtifactWriter(join(ctx.buildDir, 'prebuilt'));
|
|
184
|
+
const summary = await capture({
|
|
185
|
+
fileComponentMap: Object.fromEntries(routeComponents),
|
|
186
|
+
callSiteProps: ctx.prebuiltCallSiteProps
|
|
187
|
+
? Object.fromEntries(ctx.prebuiltCallSiteProps)
|
|
188
|
+
: undefined,
|
|
189
|
+
onEntry: (entry) => writer.write(entry),
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
if (summary.hardErrors.length > 0) {
|
|
193
|
+
const details = summary.hardErrors.map((issue) => ` - ${issue.message}`).join('\n');
|
|
194
|
+
throw new Error(
|
|
195
|
+
`[timber] prebuilt capture failed: ${summary.hardErrors.length} component(s) read ` +
|
|
196
|
+
`per-request context at build time:\n${details}`
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
await writer.finalize();
|
|
201
|
+
|
|
202
|
+
const total = summary.captured + summary.skipped.length;
|
|
203
|
+
console.log(
|
|
204
|
+
`[timber] Prebuilt ${summary.captured}/${total} entries.` +
|
|
205
|
+
(summary.skipped.length > 0 ? ` ${summary.skipped.length} skipped due to errors.` : '')
|
|
206
|
+
);
|
|
207
|
+
return summary;
|
|
208
|
+
}
|