@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,135 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const ReactDOM = require('react-dom');
|
|
4
|
+
const registries = new WeakMap();
|
|
5
|
+
const ignored = new Set(['onLoad', 'onReady', 'onError', 'children', 'dangerouslySetInnerHTML', 'strategy', 'stylesheets']);
|
|
6
|
+
const attributeNames = { acceptCharset: 'accept-charset', className: 'class', htmlFor: 'for', httpEquiv: 'http-equiv', noModule: 'noModule' };
|
|
7
|
+
|
|
8
|
+
function registry() {
|
|
9
|
+
let value = registries.get(document);
|
|
10
|
+
if (!value) registries.set(document, value = { scripts: new Map(), loaded: new Set(), before: null });
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function setAttributes(element, props) {
|
|
15
|
+
for (const [name, value] of Object.entries(props)) {
|
|
16
|
+
if (ignored.has(name) || value === undefined) continue;
|
|
17
|
+
const attribute = attributeNames[name] || name.toLowerCase();
|
|
18
|
+
const boolean = element.tagName === 'SCRIPT' && ['async', 'defer', 'noModule'].includes(attribute);
|
|
19
|
+
if (boolean) element[attribute] = !!value;
|
|
20
|
+
else element.setAttribute(attribute, String(value));
|
|
21
|
+
// Setting then removing is significant: it overrides force-async for a
|
|
22
|
+
// dynamically created script even when async={false} is requested.
|
|
23
|
+
if (value === false || (boolean && (!value || value === 'false'))) {
|
|
24
|
+
element.setAttribute(attribute, '');
|
|
25
|
+
element.removeAttribute(attribute);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function insertStylesheets(stylesheets) {
|
|
31
|
+
if (ReactDOM.preinit) {
|
|
32
|
+
for (const href of stylesheets) ReactDOM.preinit(href, { as: 'style' });
|
|
33
|
+
} else {
|
|
34
|
+
for (const href of stylesheets) {
|
|
35
|
+
const link = document.createElement('link');
|
|
36
|
+
link.type = 'text/css'; link.rel = 'stylesheet'; link.href = href;
|
|
37
|
+
document.head.appendChild(link);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function isScriptLoaded(key) { return !!key && registry().loaded.has(key); }
|
|
43
|
+
function markScriptLoaded(key) { registry().loaded.add(key); }
|
|
44
|
+
|
|
45
|
+
function loadScript(props) {
|
|
46
|
+
const { src, id, onLoad = () => {}, onReady = null, onError, children = '', dangerouslySetInnerHTML,
|
|
47
|
+
strategy = 'afterInteractive', stylesheets } = props;
|
|
48
|
+
const { scripts, loaded } = registry();
|
|
49
|
+
const key = id || src;
|
|
50
|
+
if (key && loaded.has(key)) return;
|
|
51
|
+
if (scripts.has(src)) {
|
|
52
|
+
loaded.add(key);
|
|
53
|
+
scripts.get(src).then(onLoad, onError);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const afterLoad = () => { if (onReady) onReady(); loaded.add(key); };
|
|
57
|
+
const element = document.createElement('script');
|
|
58
|
+
const promise = new Promise((resolve, reject) => {
|
|
59
|
+
element.addEventListener('load', function (event) {
|
|
60
|
+
resolve();
|
|
61
|
+
if (onLoad) onLoad.call(this, event);
|
|
62
|
+
afterLoad();
|
|
63
|
+
});
|
|
64
|
+
element.addEventListener('error', reject);
|
|
65
|
+
}).catch(error => { if (onError) onError(error); });
|
|
66
|
+
if (dangerouslySetInnerHTML) {
|
|
67
|
+
element.innerHTML = dangerouslySetInnerHTML.__html || '';
|
|
68
|
+
afterLoad();
|
|
69
|
+
} else if (children) {
|
|
70
|
+
element.textContent = typeof children === 'string' ? children : Array.isArray(children) ? children.join('') : '';
|
|
71
|
+
afterLoad();
|
|
72
|
+
} else if (src) {
|
|
73
|
+
element.src = src;
|
|
74
|
+
scripts.set(src, promise);
|
|
75
|
+
}
|
|
76
|
+
setAttributes(element, props);
|
|
77
|
+
if (strategy === 'worker') element.setAttribute('type', 'text/partytown');
|
|
78
|
+
element.setAttribute('data-nscript', strategy);
|
|
79
|
+
if (stylesheets) insertStylesheets(stylesheets);
|
|
80
|
+
document.body.appendChild(element);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function idle(callback) {
|
|
84
|
+
if (window.requestIdleCallback) window.requestIdleCallback(callback);
|
|
85
|
+
else window.setTimeout(callback, 1);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function loadLazyScript(props) {
|
|
89
|
+
if (document.readyState === 'complete') idle(() => loadScript(props));
|
|
90
|
+
else window.addEventListener('load', () => idle(() => loadScript(props)), { once: true });
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function handleClientScriptLoad(props) {
|
|
94
|
+
if (props.strategy === 'lazyOnload') {
|
|
95
|
+
window.addEventListener('load', () => idle(() => loadScript(props)), { once: true });
|
|
96
|
+
} else loadScript(props);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function markBeforeInteractive() {
|
|
100
|
+
const { loaded } = registry();
|
|
101
|
+
for (const script of document.querySelectorAll('[data-nscript="beforeInteractive"], [data-nscript="beforePageRender"]')) {
|
|
102
|
+
loaded.add(script.id || script.getAttribute('src'));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function initScriptLoader(items = []) {
|
|
107
|
+
items.forEach(handleClientScriptLoad);
|
|
108
|
+
markBeforeInteractive();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function loadBeforeInteractive(queue = globalThis.__PRNEXT_SCRIPTS__) {
|
|
112
|
+
const state = registry();
|
|
113
|
+
if (state.before) return state.before;
|
|
114
|
+
state.before = (queue || []).reduce((previous, [src, props]) => previous.then(() => new Promise((resolve, reject) => {
|
|
115
|
+
const element = document.createElement('script');
|
|
116
|
+
if (props) setAttributes(element, props);
|
|
117
|
+
if (src) {
|
|
118
|
+
element.src = src;
|
|
119
|
+
element.onload = () => resolve();
|
|
120
|
+
element.onerror = reject;
|
|
121
|
+
} else if (props) {
|
|
122
|
+
element.innerHTML = props.children;
|
|
123
|
+
window.setTimeout(resolve, 0);
|
|
124
|
+
} else { resolve(); return; }
|
|
125
|
+
document.head.appendChild(element);
|
|
126
|
+
})), Promise.resolve()).catch(error => {
|
|
127
|
+
// As in Next, one failed blocking script stops the remaining queue but
|
|
128
|
+
// must not prevent the application itself from hydrating.
|
|
129
|
+
console.error(error);
|
|
130
|
+
});
|
|
131
|
+
return state.before;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
module.exports = { loadScript, loadLazyScript, isScriptLoaded, markScriptLoaded, setAttributes, insertStylesheets,
|
|
135
|
+
handleClientScriptLoad, initScriptLoader, markBeforeInteractive, loadBeforeInteractive };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const React = require('react');
|
|
5
|
+
const ReactDOM = require('react-dom');
|
|
6
|
+
const { ScriptContext } = require('./script-context.cjs');
|
|
7
|
+
const { loadScript, loadLazyScript, isScriptLoaded, markScriptLoaded, handleClientScriptLoad, initScriptLoader } = require('./script-loader.cjs');
|
|
8
|
+
|
|
9
|
+
function safeJSON(value) {
|
|
10
|
+
return JSON.stringify(value).replace(/[<>&\u2028\u2029]/g, character => ({
|
|
11
|
+
'<': '\\u003c', '>': '\\u003e', '&': '\\u0026', '\u2028': '\\u2028', '\u2029': '\\u2029',
|
|
12
|
+
})[character]);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function Script(props) {
|
|
16
|
+
const { id, src = '', onLoad = () => {}, onReady = null, onError, strategy = 'afterInteractive', stylesheets, ...attributes } = props;
|
|
17
|
+
const context = React.useContext(ScriptContext);
|
|
18
|
+
const nonce = attributes.nonce || context.nonce;
|
|
19
|
+
const readyCalled = React.useRef(false);
|
|
20
|
+
React.useEffect(() => {
|
|
21
|
+
if (!readyCalled.current) {
|
|
22
|
+
if (onReady && isScriptLoaded(id || src)) onReady();
|
|
23
|
+
readyCalled.current = true;
|
|
24
|
+
}
|
|
25
|
+
}, [onReady, id, src]);
|
|
26
|
+
const loadCalled = React.useRef(false);
|
|
27
|
+
React.useEffect(() => {
|
|
28
|
+
if (!loadCalled.current) {
|
|
29
|
+
if (strategy === 'afterInteractive') loadScript(props);
|
|
30
|
+
else if (strategy === 'lazyOnload') loadLazyScript(props);
|
|
31
|
+
loadCalled.current = true;
|
|
32
|
+
}
|
|
33
|
+
}, [props, strategy]);
|
|
34
|
+
|
|
35
|
+
if (!context.appDir && context.ssr) {
|
|
36
|
+
if (context.collect && (context.document || strategy === 'beforeInteractive' || strategy === 'worker')) {
|
|
37
|
+
context.collect({ ...props, nonce });
|
|
38
|
+
} else if (!context.collect && typeof window !== 'undefined' && (strategy === 'beforeInteractive' || strategy === 'worker')) {
|
|
39
|
+
markScriptLoaded(id || src);
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
if (!context.appDir && !context.ssr && typeof window !== 'undefined' && (strategy === 'beforeInteractive' || strategy === 'worker')) {
|
|
44
|
+
loadScript({ ...props, nonce });
|
|
45
|
+
}
|
|
46
|
+
if (context.appDir) {
|
|
47
|
+
if (stylesheets) for (const href of stylesheets) ReactDOM.preinit(href, { as: 'style' });
|
|
48
|
+
if (src && (strategy === 'beforeInteractive' || strategy === 'afterInteractive')) {
|
|
49
|
+
ReactDOM.preload(src, { as: 'script', nonce, crossOrigin: attributes.crossOrigin,
|
|
50
|
+
...(attributes.integrity ? { integrity: attributes.integrity } : {}) });
|
|
51
|
+
}
|
|
52
|
+
if (strategy === 'beforeInteractive') {
|
|
53
|
+
if (!src && attributes.dangerouslySetInnerHTML) {
|
|
54
|
+
attributes.children = attributes.dangerouslySetInnerHTML.__html;
|
|
55
|
+
delete attributes.dangerouslySetInnerHTML;
|
|
56
|
+
}
|
|
57
|
+
return React.createElement('script', { nonce, dangerouslySetInnerHTML: {
|
|
58
|
+
__html: `(self.__PRNEXT_SCRIPTS__=self.__PRNEXT_SCRIPTS__||[]).push(${safeJSON([src || 0, { ...attributes, id }])})`,
|
|
59
|
+
} });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
Object.defineProperty(Script, '__nextScript', { value: true });
|
|
66
|
+
module.exports = Script;
|
|
67
|
+
module.exports.default = Script;
|
|
68
|
+
module.exports.handleClientScriptLoad = handleClientScriptLoad;
|
|
69
|
+
module.exports.initScriptLoader = initScriptLoader;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { JSX, ReactNode, ScriptHTMLAttributes } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface ScriptProps extends ScriptHTMLAttributes<HTMLScriptElement> {
|
|
4
|
+
strategy?: 'afterInteractive' | 'lazyOnload' | 'beforeInteractive' | 'worker';
|
|
5
|
+
id?: string;
|
|
6
|
+
onLoad?: (event: any) => void;
|
|
7
|
+
onReady?: () => void | null;
|
|
8
|
+
onError?: (event: any) => void;
|
|
9
|
+
children?: ReactNode;
|
|
10
|
+
stylesheets?: string[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** @deprecated Use ScriptProps instead. */
|
|
14
|
+
export type Props = ScriptProps;
|
|
15
|
+
export declare function handleClientScriptLoad(props: ScriptProps): void;
|
|
16
|
+
export declare function initScriptLoader(scriptLoaderItems: ScriptProps[]): void;
|
|
17
|
+
export default function Script(props: ScriptProps): JSX.Element | null;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { CookieStore, ResponseCookieStore } = require('./cookies.cjs');
|
|
3
|
+
const { hasBasePath, addBasePath, removeBasePath } = require('./paths.cjs');
|
|
4
|
+
const { localePath, withLocale } = require('./locale.cjs');
|
|
5
|
+
|
|
6
|
+
function middlewareHeaders(init, headers) {
|
|
7
|
+
if (!init?.request?.headers) return;
|
|
8
|
+
if (!(init.request.headers instanceof Headers)) throw new TypeError('request.headers must be an instance of Headers');
|
|
9
|
+
const names = [];
|
|
10
|
+
for (const [name, value] of init.request.headers) {
|
|
11
|
+
headers.set(`x-middleware-request-${name}`, value);
|
|
12
|
+
names.push(name);
|
|
13
|
+
}
|
|
14
|
+
headers.set('x-middleware-override-headers', names.join(','));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
class NextURL extends URL {
|
|
18
|
+
constructor(input, baseOrOptions, options) {
|
|
19
|
+
const base = typeof baseOrOptions === 'string' || baseOrOptions instanceof URL ? baseOrOptions : undefined;
|
|
20
|
+
const config = options || (base ? {} : baseOrOptions) || {};
|
|
21
|
+
super(input, base || config.base);
|
|
22
|
+
this._nextConfig = config.nextConfig || {};
|
|
23
|
+
this._trailingSlash = super.pathname === '/' ? !!this._nextConfig.trailingSlash : super.pathname.endsWith('/');
|
|
24
|
+
this._basePath = hasBasePath(super.pathname, this._nextConfig.basePath) ? this._nextConfig.basePath || '' : '';
|
|
25
|
+
this._locale = this._nextConfig.i18n ? localePath(removeBasePath(super.pathname, this._basePath), {...this._nextConfig.i18n,defaultLocale:this.defaultLocale}).locale : '';
|
|
26
|
+
}
|
|
27
|
+
get pathname() { return localePath(removeBasePath(super.pathname, this._basePath), this._nextConfig.i18n).pathname; }
|
|
28
|
+
set pathname(value) { super.pathname = addBasePath(withLocale(String(value).startsWith('/') ? value : `/${value}`, this._locale, this.defaultLocale), this._basePath); }
|
|
29
|
+
get defaultLocale() { return this.domainLocale?.defaultLocale || this._nextConfig.i18n?.defaultLocale; }
|
|
30
|
+
get domainLocale() { return this._nextConfig.i18n?.domains?.find(value=>value.domain.toLowerCase()===this.host.toLowerCase()); }
|
|
31
|
+
get locale() { return this._locale; }
|
|
32
|
+
set locale(value) {
|
|
33
|
+
if (!this._nextConfig.i18n?.locales.includes(value)) throw new TypeError(`Unknown locale: ${value}`);
|
|
34
|
+
const pathname=this.pathname;this._locale=value;this.pathname=pathname;
|
|
35
|
+
}
|
|
36
|
+
get basePath() { return this._basePath; }
|
|
37
|
+
set basePath(value) {
|
|
38
|
+
const pathname = this.pathname;
|
|
39
|
+
this._basePath = value.startsWith('/') ? value : `/${value}`;
|
|
40
|
+
this.pathname = pathname;
|
|
41
|
+
}
|
|
42
|
+
get trailingSlash() { return this._trailingSlash; }
|
|
43
|
+
set trailingSlash(value) { this._trailingSlash = value; }
|
|
44
|
+
get href() {
|
|
45
|
+
const url = new URL(super.href);
|
|
46
|
+
if (this._nextConfig.i18n) url.pathname=addBasePath(withLocale(this.pathname,this._locale,this.defaultLocale),this._basePath);
|
|
47
|
+
if (this._trailingSlash) { if (!url.pathname.endsWith('/')) url.pathname += '/'; }
|
|
48
|
+
else if (url.pathname !== '/') url.pathname = url.pathname.replace(/\/$/, '');
|
|
49
|
+
return url.href;
|
|
50
|
+
}
|
|
51
|
+
toString() { return this.href; }
|
|
52
|
+
toJSON() { return this.href; }
|
|
53
|
+
set href(value) {
|
|
54
|
+
super.href = value;
|
|
55
|
+
this._trailingSlash = super.pathname === '/' ? !!this._nextConfig.trailingSlash : super.pathname.endsWith('/');
|
|
56
|
+
this._basePath = hasBasePath(super.pathname, this._nextConfig.basePath) ? this._nextConfig.basePath || '' : '';
|
|
57
|
+
this._locale = this._nextConfig.i18n ? localePath(removeBasePath(super.pathname, this._basePath), {...this._nextConfig.i18n,defaultLocale:this.defaultLocale}).locale : '';
|
|
58
|
+
}
|
|
59
|
+
clone() { return new NextURL(this.href, { nextConfig: this._nextConfig }); }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
class NextRequest extends Request {
|
|
63
|
+
constructor(input, init) {
|
|
64
|
+
super(input, init);
|
|
65
|
+
this.nextUrl = new NextURL(this.url, { nextConfig: init?.nextConfig || input?.nextUrl?._nextConfig });
|
|
66
|
+
this.cookies = new CookieStore(this.headers.get('cookie') || '', {
|
|
67
|
+
mutable: true,
|
|
68
|
+
onChange: () => this.headers.set('cookie', this.cookies.toString()),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
class NextResponse extends Response {
|
|
74
|
+
constructor(body, init) {
|
|
75
|
+
super(body, init);
|
|
76
|
+
this.cookies = new ResponseCookieStore(this.headers);
|
|
77
|
+
const update = this.cookies._onChange;
|
|
78
|
+
this.cookies._onChange = () => {
|
|
79
|
+
update();
|
|
80
|
+
this.headers.set('x-middleware-set-cookie', this.headers.getSetCookie().join(','));
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
static json(value, init) {
|
|
84
|
+
const response = Response.json(value, init);
|
|
85
|
+
return new NextResponse(response.body, { status: response.status, statusText: response.statusText, headers: response.headers });
|
|
86
|
+
}
|
|
87
|
+
static redirect(url, init = 307) {
|
|
88
|
+
const options = typeof init === 'number' ? { status: init } : { ...init };
|
|
89
|
+
const status = options.status ?? 307;
|
|
90
|
+
if (![301, 302, 303, 307, 308].includes(status)) throw new RangeError('Invalid redirect status');
|
|
91
|
+
const headers = new Headers(options.headers);
|
|
92
|
+
headers.set('location', new URL(url).href);
|
|
93
|
+
return new NextResponse(null, { ...options, status, headers });
|
|
94
|
+
}
|
|
95
|
+
static next(init) {
|
|
96
|
+
const headers = new Headers(init?.headers);
|
|
97
|
+
headers.set('x-middleware-next', '1');
|
|
98
|
+
middlewareHeaders(init, headers);
|
|
99
|
+
return new NextResponse(null, { ...init, headers });
|
|
100
|
+
}
|
|
101
|
+
static rewrite(destination, init) {
|
|
102
|
+
const headers = new Headers(init?.headers);
|
|
103
|
+
headers.set('x-middleware-rewrite', new URL(destination).href);
|
|
104
|
+
middlewareHeaders(init, headers);
|
|
105
|
+
return new NextResponse(null, { ...init, headers });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
module.exports = { NextRequest, NextResponse, NextURL };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { NextRequest, NextResponse, NextURL } = require('./server-primitives.cjs');
|
|
3
|
+
|
|
4
|
+
async function connection() {
|
|
5
|
+
const context = require('./headers.cjs').currentRequest();
|
|
6
|
+
const { forceStaticRender, dynamicUsage } = require('./static-generation.cjs');
|
|
7
|
+
if (forceStaticRender(context)) return;
|
|
8
|
+
if (require('./data-cache.cjs').inCacheScope()) throw new Error('connection() cannot be used inside unstable_cache');
|
|
9
|
+
if (context.operation === 'static-params') throw new Error('connection() cannot be used inside generateStaticParams');
|
|
10
|
+
dynamicUsage('connection()', context);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
module.exports = { NextRequest, NextResponse, NextURL, connection };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { CookieStore } from './headers.cjs';
|
|
2
|
+
export interface NextURLConfig { i18n?: import('./index.js').NextConfig['i18n']; basePath?: string; trailingSlash?: boolean; skipMiddlewareUrlNormalize?: boolean; skipProxyUrlNormalize?: boolean }
|
|
3
|
+
export class NextURL extends URL { constructor(input: string | URL, options?: { base?: string | URL; nextConfig?: NextURLConfig }); constructor(input: string | URL, base: string | URL, options?: { nextConfig?: NextURLConfig }); clone(): NextURL; locale: string; readonly defaultLocale?: string; readonly domainLocale?: NonNullable<NonNullable<import('./index.js').NextConfig['i18n']>['domains']>[number]; basePath: string; trailingSlash: boolean }
|
|
4
|
+
export class NextRequest extends Request { constructor(input: RequestInfo | URL, init?: RequestInit & { nextConfig?: NextURLConfig }); nextUrl: NextURL; cookies: CookieStore }
|
|
5
|
+
export interface MiddlewareResponseInit extends ResponseInit { request?: { headers?: Headers } }
|
|
6
|
+
export class NextResponse<Body = unknown> extends Response {
|
|
7
|
+
cookies: CookieStore;
|
|
8
|
+
static json<T>(body: T, init?: ResponseInit): NextResponse<T>;
|
|
9
|
+
static redirect(url: string | URL, init?: number | ResponseInit): NextResponse;
|
|
10
|
+
static next(init?: MiddlewareResponseInit): NextResponse;
|
|
11
|
+
static rewrite(destination: string | URL, init?: MiddlewareResponseInit): NextResponse;
|
|
12
|
+
}
|
|
13
|
+
export interface NextFetchEvent {
|
|
14
|
+
readonly sourcePage: string;
|
|
15
|
+
waitUntil(promise: Promise<unknown>): void;
|
|
16
|
+
passThroughOnException(): void;
|
|
17
|
+
/** @deprecated Read the handler's first argument instead. */
|
|
18
|
+
readonly request: never;
|
|
19
|
+
/** @deprecated Return a Response from the handler instead. */
|
|
20
|
+
respondWith(): never;
|
|
21
|
+
}
|
|
22
|
+
export type NextMiddlewareResult = NextResponse | Response | null | undefined | void;
|
|
23
|
+
export type NextMiddleware = (request: NextRequest, event: NextFetchEvent) => NextMiddlewareResult | Promise<NextMiddlewareResult>;
|
|
24
|
+
export type NextProxy = NextMiddleware;
|
|
25
|
+
export interface MiddlewareMatcher {
|
|
26
|
+
source: string;
|
|
27
|
+
locale?: false;
|
|
28
|
+
has?: import('./index.d.ts').RouteCondition[];
|
|
29
|
+
missing?: import('./index.d.ts').RouteCondition[];
|
|
30
|
+
}
|
|
31
|
+
export interface MiddlewareConfig {
|
|
32
|
+
matcher?: string | Array<string | MiddlewareMatcher>;
|
|
33
|
+
runtime?: 'nodejs' | 'edge' | 'experimental-edge';
|
|
34
|
+
}
|
|
35
|
+
export interface ProxyConfig { matcher?: MiddlewareConfig['matcher'] }
|
|
36
|
+
/** Exclude the following render from prerendering until a request is available. */
|
|
37
|
+
export function connection(): Promise<void>;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const {sampleObject} = require('./instant-samples.cjs');
|
|
3
|
+
let requestReader;
|
|
4
|
+
|
|
5
|
+
function context() {
|
|
6
|
+
// Resolve the circular dependency once. Repeated CJS resolution can stat
|
|
7
|
+
// package.json on every cookies()/params access. Retain the reader function,
|
|
8
|
+
// never the result belonging to a particular visitor.
|
|
9
|
+
try { requestReader ||= require('./headers.cjs').currentRequest; return requestReader?.(); } catch { return undefined; }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function createStaticState(options = {}, config = {}) {
|
|
13
|
+
return { mode: options.mode || config.dynamic || 'auto', partial: options.partial === true, revalidate: config.revalidate ?? false,
|
|
14
|
+
tags: new Set(), paths: new Set(), dynamicReasons: new Set(), error: null };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function forceStaticRender(request) {
|
|
18
|
+
return ['render', 'route'].includes(request?.phase) && (request.cacheConfig?.dynamic === 'force-static' || request.staticState?.mode === 'force-static');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function dynamicUsage(reason, request = context()) {
|
|
22
|
+
if (forceStaticRender(request)) return false;
|
|
23
|
+
return staticBailout(reason, request);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function staticBailout(reason, request = context()) {
|
|
27
|
+
const state = request?.staticState;
|
|
28
|
+
if (!state) return true;
|
|
29
|
+
if (state.partial && state.mode === 'auto') {
|
|
30
|
+
state.dynamicReasons.add(reason);
|
|
31
|
+
if (request.metadataRendering) {
|
|
32
|
+
// Unknown fallback params alone do not make an otherwise static metadata
|
|
33
|
+
// export request-dependent. They are postponed by framework resolution.
|
|
34
|
+
if (!reason.startsWith('params for a path')) state.metadataDynamic = true;
|
|
35
|
+
} else state.contentDynamic = true;
|
|
36
|
+
throw Object.assign(new Error(`Partial prerendering postponed ${reason}`), {
|
|
37
|
+
code: 'PRNEXT_PPR_DYNAMIC', digest: 'PRNEXT_PPR_DYNAMIC', dynamicReason: reason,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
const error = Object.assign(new Error(`Static rendering used ${reason}`), {
|
|
41
|
+
code: 'PRNEXT_DYNAMIC_SERVER_USAGE', staticMode: state.mode, dynamicReason: reason,
|
|
42
|
+
});
|
|
43
|
+
// A caught bailout must not silently turn private request data into a shared
|
|
44
|
+
// route. The render checks this state even if application code swallows it.
|
|
45
|
+
state.error ||= error;
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function trackStaticDependency({ tags = [], paths = [], revalidate, externalCache } = {}, request = context()) {
|
|
50
|
+
const state = request?.staticState;
|
|
51
|
+
if (!state) return;
|
|
52
|
+
if (externalCache) state.externalCache = true;
|
|
53
|
+
if (typeof revalidate === 'number' && Number.isFinite(revalidate) && revalidate >= 0) {
|
|
54
|
+
const seconds = Math.floor(revalidate);
|
|
55
|
+
state.revalidate = state.revalidate === false ? seconds : Math.min(state.revalidate, seconds);
|
|
56
|
+
}
|
|
57
|
+
for (const tag of tags) state.tags.add(tag);
|
|
58
|
+
for (const path of paths) state.paths.add(path);
|
|
59
|
+
if (state.tags.size > 128 || state.paths.size > 128 ||
|
|
60
|
+
Buffer.byteLength(JSON.stringify([[...state.tags], [...state.paths]])) > 48 * 1024) {
|
|
61
|
+
state.error ||= new Error('Static route cache dependencies exceed the PRNext metadata limit');
|
|
62
|
+
throw state.error;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function staticMetadata(request = context()) {
|
|
67
|
+
const state = request?.staticState;
|
|
68
|
+
if (!state) return undefined;
|
|
69
|
+
if (state.error) throw state.error;
|
|
70
|
+
return { revalidate: state.revalidate, tags: [...state.tags], paths: [...state.paths], ...(state.externalCache ? { externalCache: true } : {}),
|
|
71
|
+
...(state.partial ? { dynamicReasons: [...state.dynamicReasons], metadataDynamic: !!state.metadataDynamic, contentDynamic: !!state.contentDynamic } : {}) };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function staticParams(values, request = context()) {
|
|
75
|
+
if (request?.instantValidation && request.instantSample) return Promise.resolve(sampleObject(request, 'params', values));
|
|
76
|
+
const unknown = request?.partialParams;
|
|
77
|
+
if (!request?.staticState || !unknown?.some(name => Object.hasOwn(values, name) || Object.values(values).some(value => JSON.stringify(value) === JSON.stringify(request.params?.[name])))) return Promise.resolve(values);
|
|
78
|
+
// Do not assimilate this thenable while constructing the tree. React or the
|
|
79
|
+
// component which actually awaits params must encounter the dynamic access,
|
|
80
|
+
// inside that component's nearest Suspense boundary.
|
|
81
|
+
return { then(resolve, reject) {
|
|
82
|
+
try { dynamicUsage('params for a path not supplied by generateStaticParams', request); resolve(values); }
|
|
83
|
+
catch (error) { if (reject) reject(error); else throw error; }
|
|
84
|
+
} };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function staticSearchParams(values, request = context(), clientPage = false) {
|
|
88
|
+
if (request?.instantValidation && request.instantSample) return Promise.resolve(sampleObject(request, 'searchParams', values));
|
|
89
|
+
if (forceStaticRender(request)) return Promise.resolve({});
|
|
90
|
+
if (!request?.staticState || clientPage) return Promise.resolve(values);
|
|
91
|
+
let initializing = true;
|
|
92
|
+
const proxy = new Proxy(values, {
|
|
93
|
+
get(target, property, receiver) {
|
|
94
|
+
// Promise.resolve probes `then` once while constructing the wrapper.
|
|
95
|
+
// Afterwards it is an ordinary query key and reading it is dynamic too.
|
|
96
|
+
if (typeof property === 'string' && !(initializing && property === 'then')) dynamicUsage('searchParams', request);
|
|
97
|
+
return Reflect.get(target, property, receiver);
|
|
98
|
+
},
|
|
99
|
+
has(target, property) { dynamicUsage('searchParams', request); return Reflect.has(target, property); },
|
|
100
|
+
ownKeys(target) { dynamicUsage('searchParams', request); return Reflect.ownKeys(target); },
|
|
101
|
+
getOwnPropertyDescriptor(target, property) { dynamicUsage('searchParams', request); return Reflect.getOwnPropertyDescriptor(target, property); },
|
|
102
|
+
});
|
|
103
|
+
const promise = Promise.resolve(proxy);
|
|
104
|
+
initializing = false;
|
|
105
|
+
return promise;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
module.exports = { createStaticState, forceStaticRender, dynamicUsage, staticBailout, trackStaticDependency, staticMetadata, staticSearchParams, staticParams };
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { createHash } = require('node:crypto');
|
|
3
|
+
const { serialize, deserialize } = require('node:v8');
|
|
4
|
+
const { cachedValue, currentCacheScope, runCacheScope, optionalRequestContext, getCachePaths, validateTags } = require('./data-cache.cjs');
|
|
5
|
+
const { trackStaticDependency, dynamicUsage } = require('./static-generation.cjs');
|
|
6
|
+
const { defaults, validateLife } = require('./cache-life.cjs');
|
|
7
|
+
const { configured, customCachedValue } = require('./cache-handlers.cjs');
|
|
8
|
+
const codecSymbol = Symbol.for('prnext.cache-components-codec');
|
|
9
|
+
const MAX_BYTES = 2 * 1024 * 1024;
|
|
10
|
+
|
|
11
|
+
function scopeFor(name) {
|
|
12
|
+
const scope = currentCacheScope();
|
|
13
|
+
if (!scope || scope === true) throw new Error(`${name}() can only be called inside a 'use cache' function`);
|
|
14
|
+
return scope;
|
|
15
|
+
}
|
|
16
|
+
function cacheTag(...tags) {
|
|
17
|
+
const scope = scopeFor('cacheTag');
|
|
18
|
+
scope.tags = new Set(validateTags([...new Set([...scope.tags, ...validateTags(tags)])]));
|
|
19
|
+
}
|
|
20
|
+
function cacheLife(profile) {
|
|
21
|
+
const scope = scopeFor('cacheLife');
|
|
22
|
+
const value = typeof profile === 'string' ? scope.profiles[profile] : profile;
|
|
23
|
+
if (value === undefined) throw new TypeError(`Unknown cache lifetime profile: ${profile}`);
|
|
24
|
+
const valid = validateLife(value);
|
|
25
|
+
for (const [name, value] of Object.entries(valid)) {
|
|
26
|
+
scope.life[name] = scope.explicit.has(name) ? Math.min(scope.life[name], value) : value;
|
|
27
|
+
scope.explicit.add(name);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function recordCacheDependency({ tags = [], revalidate } = {}) {
|
|
31
|
+
const scope = currentCacheScope();
|
|
32
|
+
if (!scope || scope === true) return;
|
|
33
|
+
scope.tags = new Set(validateTags([...new Set([...scope.tags, ...validateTags(tags)])]));
|
|
34
|
+
if (typeof revalidate === 'number' && Number.isFinite(revalidate) && revalidate >= 0 && !scope.explicit.has('revalidate')) scope.life.revalidate = Math.min(scope.life.revalidate, revalidate);
|
|
35
|
+
}
|
|
36
|
+
function metadata(scope, context) { return { ...scope.life, revalidate: Math.min(scope.life.revalidate, scope.life.expire), tags: [...scope.tags], paths: getCachePaths(context), ...(scope.externalCache ? { externalCache: true } : {}) }; }
|
|
37
|
+
function propagate(info, parent, context) {
|
|
38
|
+
trackStaticDependency(info, context);
|
|
39
|
+
if (!parent || parent === true) return;
|
|
40
|
+
if (info.externalCache) parent.externalCache = true;
|
|
41
|
+
for (const tag of info.tags) parent.tags.add(tag);
|
|
42
|
+
validateTags([...parent.tags]);
|
|
43
|
+
for (const name of ['stale', 'revalidate', 'expire']) if (!parent.explicit.has(name)) parent.life[name] = Math.min(parent.life[name], info[name]);
|
|
44
|
+
}
|
|
45
|
+
function envelope(info, value) {
|
|
46
|
+
const header = Buffer.from(JSON.stringify(info));
|
|
47
|
+
const result = Buffer.allocUnsafe(4 + header.length + value.length);
|
|
48
|
+
result.writeUInt32BE(header.length); header.copy(result, 4); value.copy(result, 4 + header.length);
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
function unpack(bytes) {
|
|
52
|
+
if (bytes.length < 4 || bytes.readUInt32BE(0) > 64 * 1024 || 4 + bytes.readUInt32BE(0) > bytes.length) throw new Error('Invalid Cache Components entry');
|
|
53
|
+
const end = 4 + bytes.readUInt32BE(0);
|
|
54
|
+
return { metadata: JSON.parse(bytes.subarray(4, end).toString()), value: bytes.subarray(end) };
|
|
55
|
+
}
|
|
56
|
+
function serializeData(value) {
|
|
57
|
+
const seen = new Set();
|
|
58
|
+
function validate(value) {
|
|
59
|
+
if (!value || typeof value !== 'object' || seen.has(value)) return;
|
|
60
|
+
seen.add(value);
|
|
61
|
+
if (value instanceof Date || value instanceof ArrayBuffer || ArrayBuffer.isView(value)) return;
|
|
62
|
+
if (value instanceof Map) { for (const [key, item] of value) { validate(key); validate(item); } return; }
|
|
63
|
+
if (value instanceof Set) { for (const item of value) validate(item); return; }
|
|
64
|
+
const prototype = Object.getPrototypeOf(value);
|
|
65
|
+
if (!Array.isArray(value) && prototype !== Object.prototype && prototype !== null) throw new TypeError("'use cache' only supports serializable data; class instances are not supported");
|
|
66
|
+
for (const key of Object.keys(value)) validate(value[key]);
|
|
67
|
+
}
|
|
68
|
+
validate(value);
|
|
69
|
+
return serialize(value);
|
|
70
|
+
}
|
|
71
|
+
const plainCodec = {
|
|
72
|
+
async arguments(values) { const bytes = serializeData(values); return { key: bytes, values: deserialize(bytes) }; },
|
|
73
|
+
async render(callback) { return serializeData(await callback()); },
|
|
74
|
+
async decode(bytes) { return deserialize(bytes); },
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
async function invokeCache(id, kind, captures, args, callback, segment = '') {
|
|
78
|
+
const context = optionalRequestContext();
|
|
79
|
+
if (!context) throw new Error("'use cache' requires an active PRNext request or build render");
|
|
80
|
+
const parent = currentCacheScope();
|
|
81
|
+
if (kind === 'private' && parent && parent.kind !== 'private') throw new Error("'use cache: private' cannot be nested inside a shared cache");
|
|
82
|
+
if (kind === 'private') dynamicUsage("'use cache: private'", context);
|
|
83
|
+
const codec = globalThis[codecSymbol] || plainCodec;
|
|
84
|
+
if (segment === 'page' && kind !== 'private' && args[0]) {
|
|
85
|
+
const { searchParams: ignored, ...props } = args[0];
|
|
86
|
+
args = [props, ...args.slice(1)];
|
|
87
|
+
}
|
|
88
|
+
const encoded = await codec.arguments([captures, args], context);
|
|
89
|
+
if (segment === 'page' && kind !== 'private' && encoded.values[1][0]) encoded.values[1][0].searchParams = {
|
|
90
|
+
then(_resolve, reject) { reject(new Error("searchParams cannot be read inside 'use cache'; read them outside and pass their values as arguments")); },
|
|
91
|
+
};
|
|
92
|
+
if (encoded.key.length > MAX_BYTES) throw new Error("'use cache' arguments exceed 2 MiB");
|
|
93
|
+
const key = createHash('sha256').update(id).update(kind).update(codec === plainCodec ? ':v8:' : ':flight:').update(encoded.key).digest('hex');
|
|
94
|
+
const profiles = context.cacheLife || context.manifest?.config?.cacheLife || defaults;
|
|
95
|
+
const scope = { kind, profiles, life: { ...profiles.default }, explicit: new Set(), tags: new Set() };
|
|
96
|
+
let producedMetadata;
|
|
97
|
+
const producer = async () => runCacheScope(async () => {
|
|
98
|
+
const value = await codec.render(() => callback(...encoded.values), encoded, context);
|
|
99
|
+
producedMetadata = metadata(scope, context);
|
|
100
|
+
return envelope(producedMetadata, Buffer.from(value));
|
|
101
|
+
}, scope);
|
|
102
|
+
let bytes, handlerMetadata;
|
|
103
|
+
const custom = kind !== 'private' && !context.draftMode && Object.hasOwn(configured(context), kind);
|
|
104
|
+
if (custom) {
|
|
105
|
+
scope.externalCache = true;
|
|
106
|
+
if (context.staticState) context.staticState.externalCache = true;
|
|
107
|
+
bytes = await customCachedValue(key, kind, producer, { context, resolveMetadata: () => producedMetadata, onReadMetadata: value => { handlerMetadata = value; } });
|
|
108
|
+
} else if (kind === 'private' || context.draftMode || !process.env.PRNEXT_CACHE_URL) {
|
|
109
|
+
// Private entries are confined to this request, never persisted or shared.
|
|
110
|
+
const entries = context.privateCache ||= new Map();
|
|
111
|
+
if (!entries.has(key)) {
|
|
112
|
+
const pending = producer();
|
|
113
|
+
if (entries.size < 128) {
|
|
114
|
+
entries.set(key, pending);
|
|
115
|
+
void pending.then(bytes => {
|
|
116
|
+
const total = (context.privateCacheBytes || 0) + bytes.length;
|
|
117
|
+
if (total > 8 * 1024 * 1024) entries.delete(key); else context.privateCacheBytes = total;
|
|
118
|
+
}, () => entries.delete(key));
|
|
119
|
+
}
|
|
120
|
+
bytes = await pending;
|
|
121
|
+
} else bytes = await entries.get(key);
|
|
122
|
+
} else bytes = await cachedValue(key, producer, { context, tags: [], paths: getCachePaths(context),
|
|
123
|
+
signal: context.signal, resolveMetadata: () => producedMetadata, forceFresh: Boolean(context.staticState) });
|
|
124
|
+
const result = unpack(bytes);
|
|
125
|
+
if (handlerMetadata) Object.assign(result.metadata, handlerMetadata, { externalCache: true });
|
|
126
|
+
propagate(result.metadata, parent, context);
|
|
127
|
+
return codec.decode(result.value, encoded, context);
|
|
128
|
+
}
|
|
129
|
+
module.exports = { invokeCache, cacheTag, cacheLife, recordCacheDependency, codecSymbol };
|
package/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { build } from './build/index.mjs';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
[
|
|
2
|
+
{ "id": "darwin-arm64", "package": "prnext-darwin-arm64", "os": "darwin", "cpu": "arm64", "target": "aarch64-apple-darwin" },
|
|
3
|
+
{ "id": "darwin-x64", "package": "prnext-darwin-x64", "os": "darwin", "cpu": "x64", "target": "x86_64-apple-darwin" },
|
|
4
|
+
{ "id": "linux-arm64-gnu", "package": "prnext-linux-arm64-gnu", "os": "linux", "cpu": "arm64", "libc": "glibc", "target": "aarch64-unknown-linux-gnu" },
|
|
5
|
+
{ "id": "linux-x64-gnu", "package": "prnext-linux-x64-gnu", "os": "linux", "cpu": "x64", "libc": "glibc", "target": "x86_64-unknown-linux-gnu" }
|
|
6
|
+
]
|