@thomas.f/prnext 0.1.0-alpha.1
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 +54 -0
- package/build/action-exports.mjs +107 -0
- package/build/actions.mjs +214 -0
- package/build/app-config.mjs +138 -0
- package/build/app-routing.mjs +119 -0
- package/build/app-static.mjs +158 -0
- package/build/app.mjs +536 -0
- package/build/cache-components.mjs +91 -0
- package/build/cache-handlers.mjs +54 -0
- package/build/check.mjs +40 -0
- package/build/compiler.mjs +222 -0
- package/build/config.mjs +193 -0
- package/build/css-modules.mjs +114 -0
- package/build/custom-routes.mjs +363 -0
- package/build/dev-worker.mjs +18 -0
- package/build/dev.mjs +76 -0
- package/build/directory-cache.mjs +29 -0
- package/build/dynamic.mjs +125 -0
- package/build/edge.mjs +141 -0
- package/build/font-data.LICENSE.txt +25 -0
- package/build/font-data.json +1 -0
- package/build/font-files.mjs +221 -0
- package/build/fonts.mjs +131 -0
- package/build/framework-imports.mjs +17 -0
- package/build/i18n.mjs +39 -0
- package/build/images-config.mjs +62 -0
- package/build/images.mjs +86 -0
- package/build/incremental.mjs +76 -0
- package/build/index.mjs +356 -0
- package/build/loader-cache.mjs +69 -0
- package/build/metadata-images.mjs +72 -0
- package/build/metadata-routes.mjs +77 -0
- package/build/middleware.mjs +231 -0
- package/build/migrate.mjs +289 -0
- package/build/module-resolution.mjs +78 -0
- package/build/native-discovery.mjs +134 -0
- package/build/native-packages.mjs +105 -0
- package/build/npm-packages.mjs +110 -0
- package/build/og.mjs +14 -0
- package/build/page-extensions.mjs +12 -0
- package/build/passthrough-loader.cjs +4 -0
- package/build/precompress.mjs +122 -0
- package/build/scan.mjs +178 -0
- package/build/script-workers.mjs +25 -0
- package/build/server-actions-config.mjs +27 -0
- package/build/source-maps.mjs +34 -0
- package/build/standalone-config.mjs +19 -0
- package/build/standalone-runner.mjs +21 -0
- package/build/standalone-worker.mjs +5 -0
- package/build/standalone.mjs +240 -0
- package/build/static-export.mjs +93 -0
- package/build/styles.mjs +174 -0
- package/build/transform-cache.mjs +50 -0
- package/build/transform.mjs +155 -0
- package/build/turbopack-conditions.mjs +59 -0
- package/build/webpack-bridge.cjs +3 -0
- package/build/webpack-graph.mjs +256 -0
- package/build/webpack-loader.cjs +9 -0
- package/cli.mjs +210 -0
- package/compat/app-client-page.cjs +32 -0
- package/compat/app-context.cjs +40 -0
- package/compat/app-context.d.cts +20 -0
- package/compat/app-dynamic.cjs +34 -0
- package/compat/app-error-boundary.cjs +53 -0
- package/compat/app-global-error-boundary.cjs +34 -0
- package/compat/app-layout-context.cjs +27 -0
- package/compat/app-navigation-boundary.cjs +47 -0
- package/compat/app.cjs +33 -0
- package/compat/app.d.cts +9 -0
- package/compat/cache-handlers.cjs +223 -0
- package/compat/cache-life.cjs +34 -0
- package/compat/cache.cjs +99 -0
- package/compat/cache.d.cts +36 -0
- package/compat/compat/router.d.cts +2 -0
- package/compat/compat-router.cjs +7 -0
- package/compat/constants.cjs +8 -0
- package/compat/constants.d.cts +7 -0
- package/compat/cookies.cjs +129 -0
- package/compat/data-cache.cjs +389 -0
- package/compat/dist/shared/lib/app-router-context.shared-runtime.d.cts +3 -0
- package/compat/dist/shared/lib/router-context.d.cts +1 -0
- package/compat/dist/shared/lib/router-context.shared-runtime.d.cts +3 -0
- package/compat/document.cjs +73 -0
- package/compat/document.d.cts +41 -0
- package/compat/draft.cjs +28 -0
- package/compat/dynamic-bailout.cjs +13 -0
- package/compat/dynamic.cjs +119 -0
- package/compat/dynamic.d.cts +32 -0
- package/compat/error.cjs +36 -0
- package/compat/error.d.cts +15 -0
- package/compat/fetch.d.cts +10 -0
- package/compat/font/google.d.cts +1 -0
- package/compat/font/local.d.cts +2 -0
- package/compat/font-google.cjs +2 -0
- package/compat/font-google.d.cts +1944 -0
- package/compat/font-local.cjs +5 -0
- package/compat/font-local.d.cts +3 -0
- package/compat/font-types.d.cts +25 -0
- package/compat/head.cjs +180 -0
- package/compat/head.d.cts +3 -0
- package/compat/headers.cjs +89 -0
- package/compat/headers.d.cts +26 -0
- package/compat/image-config.cjs +3 -0
- package/compat/image-imports.d.ts +12 -0
- package/compat/image-shared.cjs +62 -0
- package/compat/image.cjs +64 -0
- package/compat/image.d.cts +35 -0
- package/compat/incremental-cache.cjs +186 -0
- package/compat/index.d.ts +159 -0
- package/compat/instant-samples.cjs +39 -0
- package/compat/instant.cjs +13 -0
- package/compat/link.cjs +68 -0
- package/compat/link.d.cts +17 -0
- package/compat/locale.cjs +30 -0
- package/compat/metadata.d.cts +77 -0
- package/compat/navigation-controls.cjs +27 -0
- package/compat/navigation-server.cjs +25 -0
- package/compat/navigation.cjs +52 -0
- package/compat/navigation.d.cts +28 -0
- package/compat/next-app-router-context.cjs +6 -0
- package/compat/next-router-context.cjs +3 -0
- package/compat/og.cjs +32 -0
- package/compat/og.d.cts +1 -0
- package/compat/paths.cjs +33 -0
- package/compat/preview.cjs +41 -0
- package/compat/rewrite.cjs +41 -0
- package/compat/route-request.cjs +64 -0
- package/compat/router.cjs +137 -0
- package/compat/router.d.cts +58 -0
- package/compat/script-context.cjs +5 -0
- package/compat/script-loader.cjs +135 -0
- package/compat/script.cjs +69 -0
- package/compat/script.d.cts +17 -0
- package/compat/server-primitives.cjs +109 -0
- package/compat/server.cjs +13 -0
- package/compat/server.d.cts +37 -0
- package/compat/static-generation.cjs +108 -0
- package/compat/use-cache.cjs +129 -0
- package/index.mjs +1 -0
- package/native/platforms.json +6 -0
- package/native/resolve.mjs +81 -0
- package/package.json +127 -0
- package/release/verify.mjs +59 -0
- package/runtime/action-client.mjs +19 -0
- package/runtime/action-crypto.mjs +138 -0
- package/runtime/action-reference.mjs +2 -0
- package/runtime/action-server.mjs +161 -0
- package/runtime/action-ssr.mjs +5 -0
- package/runtime/api.mjs +326 -0
- package/runtime/app-client.mjs +539 -0
- package/runtime/app-content.mjs +8 -0
- package/runtime/app-errors.mjs +12 -0
- package/runtime/app-instant.mjs +30 -0
- package/runtime/app-metadata.mjs +410 -0
- package/runtime/app-partial-model.mjs +228 -0
- package/runtime/app-partial.mjs +130 -0
- package/runtime/app-prefetch.mjs +34 -0
- package/runtime/app-recovery.mjs +87 -0
- package/runtime/app-render.mjs +544 -0
- package/runtime/app-routing-access.mjs +143 -0
- package/runtime/app-routing-context.mjs +35 -0
- package/runtime/app-routing-state.mjs +61 -0
- package/runtime/app-routing.mjs +323 -0
- package/runtime/app-segments.mjs +22 -0
- package/runtime/app-static-params.mjs +120 -0
- package/runtime/app-static.mjs +86 -0
- package/runtime/app-stream-channel.mjs +92 -0
- package/runtime/app-stream-html.mjs +279 -0
- package/runtime/build-directory.mjs +48 -0
- package/runtime/cache-arguments.mjs +33 -0
- package/runtime/cache-components-rsc.mjs +64 -0
- package/runtime/cache-request.mjs +23 -0
- package/runtime/client-navigation.mjs +40 -0
- package/runtime/dev-client.mjs +129 -0
- package/runtime/dev-file-changes.mjs +110 -0
- package/runtime/document.mjs +96 -0
- package/runtime/edge.mjs +105 -0
- package/runtime/env.mjs +68 -0
- package/runtime/fetch-cache.mjs +379 -0
- package/runtime/font-preload.mjs +4 -0
- package/runtime/http.mjs +190 -0
- package/runtime/incremental-cache.mjs +83 -0
- package/runtime/metadata-route.mjs +83 -0
- package/runtime/middleware.mjs +186 -0
- package/runtime/module-loader.mjs +21 -0
- package/runtime/navigation.mjs +16 -0
- package/runtime/og-loader.mjs +17 -0
- package/runtime/pages-client.mjs +197 -0
- package/runtime/pages-error-props.mjs +6 -0
- package/runtime/pages-errors.mjs +85 -0
- package/runtime/pages-initial-props.mjs +43 -0
- package/runtime/pages-navigation.mjs +565 -0
- package/runtime/pages-paths.mjs +80 -0
- package/runtime/pages-revalidate.mjs +33 -0
- package/runtime/partial-artifact-cache.mjs +37 -0
- package/runtime/partial-template.mjs +174 -0
- package/runtime/profile.mjs +9 -0
- package/runtime/profiles.json +47 -0
- package/runtime/render.mjs +304 -0
- package/runtime/request-transport.mjs +41 -0
- package/runtime/request-work.mjs +7 -0
- package/runtime/route-static.mjs +117 -0
- package/runtime/rsc-worker.mjs +426 -0
- package/runtime/script-html.mjs +61 -0
- package/runtime/stream-select.mjs +25 -0
- package/runtime/stream-utils.mjs +127 -0
- package/runtime/transport.mjs +108 -0
- package/runtime/watch-project.mjs +130 -0
- package/runtime/worker-artifacts.mjs +22 -0
- package/runtime/worker-metadata.mjs +31 -0
- package/runtime/worker.mjs +197 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { writeFile } from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
5
|
+
import { staticPath } from '../runtime/pages-paths.mjs';
|
|
6
|
+
|
|
7
|
+
const MAX_STATIC_PATHS = 10_000;
|
|
8
|
+
const MAX_RESPONSE_BYTES = 16 * 1024 * 1024;
|
|
9
|
+
const parameter = /^\[(\[)?(\.\.\.)?([^\]]+)\]\]?$/;
|
|
10
|
+
|
|
11
|
+
export function appStaticEntries(pattern, generated) {
|
|
12
|
+
if (!Array.isArray(generated) || generated.length > MAX_STATIC_PATHS) throw new Error(`generateStaticParams for ${pattern} must return at most ${MAX_STATIC_PATHS} parameter objects.`);
|
|
13
|
+
const dynamic = pattern.split('/').map(segment => parameter.exec(segment)).filter(Boolean);
|
|
14
|
+
const entries = new Map();
|
|
15
|
+
for (const params of generated) {
|
|
16
|
+
if (!params || typeof params !== 'object' || Array.isArray(params)) throw new Error(`generateStaticParams for ${pattern} must return parameter objects.`);
|
|
17
|
+
let complete = true;
|
|
18
|
+
const validated = {};
|
|
19
|
+
const actual = {};
|
|
20
|
+
for (const match of dynamic) {
|
|
21
|
+
const name = match[3];
|
|
22
|
+
const value = Object.hasOwn(params, name) ? params[name] : undefined;
|
|
23
|
+
if (value === undefined && !match[1]) {
|
|
24
|
+
complete = false;
|
|
25
|
+
Object.defineProperty(validated, name, { value: match[2] ? ['__prnext_unbound__'] : '__prnext_unbound__', enumerable: true });
|
|
26
|
+
} else {
|
|
27
|
+
Object.defineProperty(validated, name, { value, enumerable: true });
|
|
28
|
+
if (value !== undefined) Object.defineProperty(actual, name, { value, enumerable: true });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// Validate supplied values even when another segment is still unbound.
|
|
32
|
+
try { staticPath(pattern, { params: validated }); }
|
|
33
|
+
catch (error) { throw new Error(error.message.replaceAll('getStaticPaths', 'generateStaticParams')); }
|
|
34
|
+
if (!complete) continue;
|
|
35
|
+
const entry = staticPath(pattern, { params: actual });
|
|
36
|
+
if (!entries.has(entry.path)) entries.set(entry.path, entry);
|
|
37
|
+
}
|
|
38
|
+
return [...entries.values()];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function prerenderApp(stage, manifest, dev) {
|
|
42
|
+
const routes = manifest.routes.filter(route => route.router === 'app');
|
|
43
|
+
if (!routes.length || dev) return;
|
|
44
|
+
const { closeAppRuntime } = await import(pathToFileURL(path.join(stage, 'runtime/app-render.mjs')).href);
|
|
45
|
+
const occupied = new Set(manifest.prerendered.map(page => page.path));
|
|
46
|
+
try {
|
|
47
|
+
const pages = routes.some(route => route.kind === 'page')
|
|
48
|
+
? await import(pathToFileURL(path.join(stage, 'runtime/app-static.mjs')).href) : null;
|
|
49
|
+
const handlers = routes.some(route => route.kind === 'api')
|
|
50
|
+
? await import(pathToFileURL(path.join(stage, 'runtime/route-static.mjs')).href) : null;
|
|
51
|
+
for (const route of routes) {
|
|
52
|
+
const handler = route.kind === 'api';
|
|
53
|
+
const options = { modulePath: path.join(stage, route.module), distDir: stage, manifest, route, production: true };
|
|
54
|
+
// This fixed internal entry shares the root layout, but its parameter
|
|
55
|
+
// generators belong to user routes and must never run for a global 404.
|
|
56
|
+
const inspected = route.id === manifest.appNotFound ? { generated: false, params: [{}] }
|
|
57
|
+
: handler ? await handlers.inspectAppRouteHandler(options) : await pages.inspectAppStatic(options);
|
|
58
|
+
route.hasStaticParams = inspected.generated;
|
|
59
|
+
if (handler) route.handlerMethods = inspected.methods;
|
|
60
|
+
const dynamic = route.pattern.includes('[');
|
|
61
|
+
const entries = appStaticEntries(route.pattern, dynamic ? inspected.params : [{}]);
|
|
62
|
+
const config = route.cacheConfig;
|
|
63
|
+
// Keep generated-path restrictions and method metadata for Edge routes,
|
|
64
|
+
// while separating dynamic rendering from the persistent Data Cache.
|
|
65
|
+
if (config.runtime === 'edge') {
|
|
66
|
+
if (dynamic && config.dynamicParams === false) route.allowedPaths = entries.map(entry => entry.path);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const partial = !handler && manifest.config?.cacheComponents === true && (!config.dynamic || config.dynamic === 'auto');
|
|
70
|
+
if (partial && dynamic && !inspected.generated) entries.length = 0;
|
|
71
|
+
if (partial && dynamic && inspected.generated && inspected.params.length === 0) {
|
|
72
|
+
throw new Error(`generateStaticParams for ${route.pattern} must return at least one parameter object when cacheComponents is enabled.`);
|
|
73
|
+
}
|
|
74
|
+
if (partial && dynamic) for (const supplied of inspected.params) {
|
|
75
|
+
if (inspected.generated && appStaticEntries(route.pattern, [supplied]).length) continue;
|
|
76
|
+
const params = { ...supplied }, unknown = [];
|
|
77
|
+
for (const segment of route.pattern.split('/')) {
|
|
78
|
+
const match = parameter.exec(segment);
|
|
79
|
+
if (!match || Object.hasOwn(supplied, match[3])) continue;
|
|
80
|
+
unknown.push(match[3]);
|
|
81
|
+
params[match[3]] = match[2] ? ['__prnext_unbound__'] : '__prnext_unbound__';
|
|
82
|
+
}
|
|
83
|
+
const fallback = staticPath(route.pattern, { params });
|
|
84
|
+
// Validate unknown parameter access and save its reusable build shell.
|
|
85
|
+
// Concrete Flight uses explicit framework key bindings; the opaque React
|
|
86
|
+
// continuation itself is never patched.
|
|
87
|
+
const rendered = await pages.prerenderAppRoute({ ...options, path: fallback.path, params, partialParams: unknown });
|
|
88
|
+
if (rendered.partial) {
|
|
89
|
+
const file = `static/generic-${createHash('sha256').update(route.id + JSON.stringify(supplied)).digest('hex').slice(0, 20)}.json`;
|
|
90
|
+
await writeFile(path.join(stage, file), JSON.stringify({ ...rendered.partial, ...rendered.metadata }));
|
|
91
|
+
(route.pprGeneric ||= []).push({ file, params: supplied, unknown });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (partial && route.instantBuild) {
|
|
95
|
+
const { validateInstantRoute } = await import(pathToFileURL(path.join(stage, 'runtime/app-instant.mjs')).href);
|
|
96
|
+
for (const entry of entries.length ? entries : [{ path: route.pattern.replace(/\[\[?(?:\.\.\.)?[^\]]+\]\]?/g, '__prnext_instant__'), params: Object.fromEntries(route.pattern.split('/').map(segment => parameter.exec(segment)).filter(Boolean).map(match => [match[3], match[2] ? ['__prnext_instant__'] : '__prnext_instant__'])) }]) await validateInstantRoute({ ...options, path: entry.path, params: entry.params });
|
|
97
|
+
}
|
|
98
|
+
if (partial) route.pprFallback = config.dynamicParams !== false;
|
|
99
|
+
if (dynamic && config.dynamicParams === false) route.allowedPaths = entries.map(entry => entry.path);
|
|
100
|
+
if (handler) {
|
|
101
|
+
if (!inspected.staticEligible) continue;
|
|
102
|
+
if (dynamic && !inspected.generated && !['force-static', 'error'].includes(config.dynamic)) continue;
|
|
103
|
+
} else {
|
|
104
|
+
if (config.dynamic === 'force-dynamic' || (config.dynamic !== 'force-static' && (config.revalidate === 0 || config.forceNoStore))) continue;
|
|
105
|
+
if (dynamic && !inspected.generated && !partial && !['force-static', 'error'].includes(config.dynamic)) continue;
|
|
106
|
+
}
|
|
107
|
+
route.ssg = true;
|
|
108
|
+
route.fallback = config.dynamicParams === false ? false : 'blocking';
|
|
109
|
+
for (const entry of entries) {
|
|
110
|
+
if (occupied.has(entry.path)) throw new Error(`Multiple pages prerender the same path: ${entry.path}.`);
|
|
111
|
+
const rendered = await (handler ? handlers.prerenderAppRouteHandler : pages.prerenderAppRoute)({ ...options, path: entry.path, params: entry.params });
|
|
112
|
+
if (rendered.partial) {
|
|
113
|
+
const file = `static/partial-${createHash('sha256').update(entry.path).digest('hex').slice(0, 20)}.json`;
|
|
114
|
+
await writeFile(path.join(stage, file), JSON.stringify({ ...rendered.partial, ...rendered.metadata }));
|
|
115
|
+
(route.ppr ||= {})[entry.path] = file;
|
|
116
|
+
if (!dynamic) { delete route.ssg; delete route.fallback; }
|
|
117
|
+
else (route.dynamicPaths ||= []).push(entry.path);
|
|
118
|
+
occupied.add(entry.path);
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (rendered.dynamic) {
|
|
122
|
+
if (!handler && config.dynamic === 'error') throw new Error(`App route ${entry.path} with dynamic='error' used dynamic data: ${rendered.reason || 'dynamic rendering required'}.`);
|
|
123
|
+
if (!dynamic) { delete route.ssg; delete route.fallback; delete route.pprFallback; }
|
|
124
|
+
else {
|
|
125
|
+
(route.dynamicPaths ||= []).push(entry.path);
|
|
126
|
+
// A failed handler export removes Next's dynamic prerender entry;
|
|
127
|
+
// successful seeds survive, while ungenerated paths stay dynamic.
|
|
128
|
+
if (handler && config.dynamicParams !== false) route.fallback = 'dynamic';
|
|
129
|
+
}
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const body = Buffer.isBuffer(rendered.body) ? rendered.body : Buffer.from(rendered.body);
|
|
133
|
+
const flight = handler ? null : Buffer.isBuffer(rendered.flight) ? rendered.flight : Buffer.from(rendered.flight);
|
|
134
|
+
if (body.byteLength > MAX_RESPONSE_BYTES || (flight && flight.byteLength > MAX_RESPONSE_BYTES)) throw new Error(`Static App route ${entry.path} exceeds the 16 MiB response limit.`);
|
|
135
|
+
const stem = `static/${handler ? 'route' : 'app'}-${createHash('sha256').update(entry.path).digest('hex').slice(0, 20)}`;
|
|
136
|
+
const file = `${stem}.${handler ? 'body' : 'html'}`;
|
|
137
|
+
// Flight is opaque text, not JSON; the native cache supplies text/x-component.
|
|
138
|
+
const dataFile = handler ? undefined : `${stem}.txt`;
|
|
139
|
+
await writeFile(path.join(stage, file), body);
|
|
140
|
+
if (dataFile) await writeFile(path.join(stage, dataFile), flight);
|
|
141
|
+
occupied.add(entry.path);
|
|
142
|
+
manifest.prerendered.push({ routeId: route.id, path: entry.path, file, ...(dataFile ? { dataFile } : {}), status: rendered.status ?? 200,
|
|
143
|
+
headers: rendered.headers || {}, revalidate: rendered.revalidate ?? config.revalidate,
|
|
144
|
+
generatedAt: rendered.generatedAt, tags: rendered.tags || [], paths: rendered.paths || [],
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
// Unseen Cache Components paths are generated by the PPR runtime, which
|
|
148
|
+
// handles either complete HTML/Flight or a resumable shell atomically.
|
|
149
|
+
if (partial && dynamic) {
|
|
150
|
+
if (manifest.prerendered.some(page => page.routeId === route.id)) {
|
|
151
|
+
// Concrete complete seeds use the native invalidation-aware cache.
|
|
152
|
+
// Other paths still reach the PPR runtime, including dynamic holes.
|
|
153
|
+
route.ssg = true; route.fallback = 'ppr';
|
|
154
|
+
} else { delete route.ssg; delete route.fallback; }
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
} finally { await closeAppRuntime(); }
|
|
158
|
+
}
|