feat: frontend PWA scaffolding with React and Tailwind

This commit is contained in:
Daniel Bedeleanu
2026-04-10 14:05:50 +03:00
parent 373652e8b8
commit 7f8b24aabb
33622 changed files with 4317382 additions and 0 deletions

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,181 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
const _picocolors = require("../../lib/picocolors");
const _workunitasyncstorageexternal = require("../app-render/work-unit-async-storage.external");
const isColorSupported = (0, _picocolors.dim)('test') !== 'test';
// 50% opacity for dimmed text
const dimStyle = 'color: color(from currentColor xyz x y z / 0.5);';
const reactBadgeFormat = '\x1b[0m\x1b[7m%c%s\x1b[0m%c ';
function dimmedConsoleArgs(...inputArgs) {
if (!isColorSupported) {
return inputArgs;
}
const newArgs = inputArgs.slice(0);
let template = '';
let argumentsPointer = 0;
if (typeof inputArgs[0] === 'string') {
const originalTemplateString = inputArgs[0];
// Remove the original template string from the args.
newArgs.splice(argumentsPointer, 1);
argumentsPointer += 1;
let i = 0;
if (originalTemplateString.startsWith(reactBadgeFormat)) {
i = reactBadgeFormat.length;
// for `format` we already moved the pointer earlier
// style, badge, reset style
argumentsPointer += 3;
template += reactBadgeFormat;
// React's badge reset styles, reapply dimming
template += '\x1b[2m%c';
// argumentsPointer includes template
newArgs.splice(argumentsPointer - 1, 0, dimStyle);
// dim the badge
newArgs[0] += `;${dimStyle}`;
}
for(i; i < originalTemplateString.length; i++){
const currentChar = originalTemplateString[i];
if (currentChar !== '%') {
template += currentChar;
continue;
}
const nextChar = originalTemplateString[i + 1];
++i;
switch(nextChar){
case 'f':
case 'O':
case 'o':
case 'd':
case 's':
case 'i':
case 'c':
++argumentsPointer;
template += `%${nextChar}`;
break;
default:
template += `%${nextChar}`;
}
}
}
for(argumentsPointer; argumentsPointer < inputArgs.length; ++argumentsPointer){
const arg = inputArgs[argumentsPointer];
const argType = typeof arg;
if (argumentsPointer > 0) {
template += ' ';
}
switch(argType){
case 'boolean':
case 'string':
template += '%s';
break;
case 'bigint':
template += '%s';
break;
case 'number':
if (arg % 0) {
template += '%f';
} else {
template += '%d';
}
break;
case 'object':
template += '%O';
break;
case 'symbol':
case 'undefined':
case 'function':
template += '%s';
break;
default:
// deopt to string for new, unknown types
template += '%s';
}
}
template += '\x1b[22m';
return [
(0, _picocolors.dim)(`%c${template}`),
dimStyle,
...newArgs
];
}
function dimConsoleCall(methodName, args) {
switch(methodName){
case 'dir':
case 'dirxml':
case 'group':
case 'groupCollapsed':
case 'groupEnd':
case 'table':
{
// These methods cannot be colorized because they don't take a formatting string.
return args;
}
case 'assert':
{
// assert takes formatting options as the second argument.
return [
args[0]
].concat(...dimmedConsoleArgs(args[1], ...args.slice(2)));
}
case 'error':
case 'debug':
case 'info':
case 'log':
case 'trace':
case 'warn':
return dimmedConsoleArgs(args[0], ...args.slice(1));
default:
return methodName;
}
}
// Based on https://github.com/facebook/react/blob/28dc0776be2e1370fe217549d32aee2519f0cf05/packages/react-server/src/ReactFlightServer.js#L248
function patchConsoleMethodDEV(methodName) {
const descriptor = Object.getOwnPropertyDescriptor(console, methodName);
if (descriptor && (descriptor.configurable || descriptor.writable) && typeof descriptor.value === 'function') {
const originalMethod = descriptor.value;
const originalName = Object.getOwnPropertyDescriptor(originalMethod, 'name');
const wrapperMethod = function(...args) {
const workUnitStore = _workunitasyncstorageexternal.workUnitAsyncStorage.getStore();
switch(workUnitStore == null ? void 0 : workUnitStore.type){
case 'prerender':
case 'prerender-client':
case 'prerender-runtime':
originalMethod.apply(this, dimConsoleCall(methodName, args));
break;
case 'prerender-ppr':
case 'prerender-legacy':
case 'request':
case 'cache':
case 'private-cache':
case 'unstable-cache':
case undefined:
originalMethod.apply(this, args);
break;
default:
workUnitStore;
}
};
if (originalName) {
Object.defineProperty(wrapperMethod, 'name', originalName);
}
Object.defineProperty(console, methodName, {
value: wrapperMethod
});
}
}
patchConsoleMethodDEV('error');
patchConsoleMethodDEV('assert');
patchConsoleMethodDEV('debug');
patchConsoleMethodDEV('dir');
patchConsoleMethodDEV('dirxml');
patchConsoleMethodDEV('group');
patchConsoleMethodDEV('groupCollapsed');
patchConsoleMethodDEV('groupEnd');
patchConsoleMethodDEV('info');
patchConsoleMethodDEV('log');
patchConsoleMethodDEV('table');
patchConsoleMethodDEV('trace');
patchConsoleMethodDEV('warn');
//# sourceMappingURL=console-dev.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,52 @@
/**
* We extend `Date` during builds and revalidates to ensure that prerenders don't observe the clock as a source of IO
* When cacheComponents is enabled. The current time is a form of IO even though it resolves synchronously. When cacheComponents is
* enabled we need to ensure that clock time is excluded from prerenders unless it is cached.
*
* There is tension here because time is used for both output and introspection. While arbitrary we intend to reserve
* `Date` for output use cases and `performance` for introspection use cases. If you want to measure
* how long something takes use `performance.timeOrigin` and `performance.now()` rather than `Date.now()` for instance.
*
* The extensions here never error nor alter the underlying Date objects, strings, and numbers created and thus should be transparent to callers.
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
const _utils = require("./utils");
function createNow(originalNow) {
return ({
now: function now() {
(0, _utils.io)('`Date.now()`', 'time');
return originalNow();
}
})['now'.slice()].bind(null);
}
function createDate(originalConstructor) {
const properties = Object.getOwnPropertyDescriptors(originalConstructor);
properties.now.value = createNow(originalConstructor.now);
const apply = Reflect.apply;
const construct = Reflect.construct;
const newConstructor = Object.defineProperties(// Ideally this should not minify the name.
function Date1() {
if (new.target === undefined) {
(0, _utils.io)('`Date()`', 'time');
return apply(originalConstructor, undefined, arguments);
}
if (arguments.length === 0) {
(0, _utils.io)('`new Date()`', 'time');
}
return construct(originalConstructor, arguments, new.target);
}, properties);
Object.defineProperty(originalConstructor.prototype, 'constructor', {
value: newConstructor
});
return newConstructor;
}
try {
// eslint-disable-next-line no-native-reassign
Date = createDate(Date);
} catch {
console.error('Failed to install `Date` class extension. When using `experimental.cacheComponents`, APIs that read the current time will not correctly trigger dynamic behavior.');
}
//# sourceMappingURL=date.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../src/server/node-environment-extensions/date.tsx"],"sourcesContent":["/**\n * We extend `Date` during builds and revalidates to ensure that prerenders don't observe the clock as a source of IO\n * When cacheComponents is enabled. The current time is a form of IO even though it resolves synchronously. When cacheComponents is\n * enabled we need to ensure that clock time is excluded from prerenders unless it is cached.\n *\n * There is tension here because time is used for both output and introspection. While arbitrary we intend to reserve\n * `Date` for output use cases and `performance` for introspection use cases. If you want to measure\n * how long something takes use `performance.timeOrigin` and `performance.now()` rather than `Date.now()` for instance.\n *\n * The extensions here never error nor alter the underlying Date objects, strings, and numbers created and thus should be transparent to callers.\n */\nimport { io } from './utils'\n\nfunction createNow(originalNow: typeof Date.now) {\n return {\n now: function now() {\n io('`Date.now()`', 'time')\n return originalNow()\n },\n }['now'.slice() as 'now'].bind(null)\n}\n\nfunction createDate(originalConstructor: typeof Date): typeof Date {\n const properties = Object.getOwnPropertyDescriptors(originalConstructor)\n properties.now.value = createNow(originalConstructor.now)\n\n const apply = Reflect.apply\n const construct = Reflect.construct\n\n const newConstructor = Object.defineProperties(\n // Ideally this should not minify the name.\n function Date() {\n if (new.target === undefined) {\n io('`Date()`', 'time')\n return apply(originalConstructor, undefined, arguments)\n }\n if (arguments.length === 0) {\n io('`new Date()`', 'time')\n }\n return construct(originalConstructor, arguments, new.target)\n },\n properties\n )\n Object.defineProperty(originalConstructor.prototype, 'constructor', {\n value: newConstructor,\n })\n return newConstructor as typeof Date\n}\n\ntry {\n // eslint-disable-next-line no-native-reassign\n Date = createDate(Date)\n} catch {\n console.error(\n 'Failed to install `Date` class extension. When using `experimental.cacheComponents`, APIs that read the current time will not correctly trigger dynamic behavior.'\n )\n}\n"],"names":["createNow","originalNow","now","io","slice","bind","createDate","originalConstructor","properties","Object","getOwnPropertyDescriptors","value","apply","Reflect","construct","newConstructor","defineProperties","Date","undefined","arguments","length","defineProperty","prototype","console","error"],"mappings":"AAAA;;;;;;;;;;CAUC;;;;uBACkB;AAEnB,SAASA,UAAUC,WAA4B;IAC7C,OAAO,CAAA;QACLC,KAAK,SAASA;YACZC,IAAAA,SAAE,EAAC,gBAAgB;YACnB,OAAOF;QACT;IACF,CAAA,CAAC,CAAC,MAAMG,KAAK,GAAY,CAACC,IAAI,CAAC;AACjC;AAEA,SAASC,WAAWC,mBAAgC;IAClD,MAAMC,aAAaC,OAAOC,yBAAyB,CAACH;IACpDC,WAAWN,GAAG,CAACS,KAAK,GAAGX,UAAUO,oBAAoBL,GAAG;IAExD,MAAMU,QAAQC,QAAQD,KAAK;IAC3B,MAAME,YAAYD,QAAQC,SAAS;IAEnC,MAAMC,iBAAiBN,OAAOO,gBAAgB,CAC5C,2CAA2C;IAC3C,SAASC;QACP,IAAI,eAAeC,WAAW;YAC5Bf,IAAAA,SAAE,EAAC,YAAY;YACf,OAAOS,MAAML,qBAAqBW,WAAWC;QAC/C;QACA,IAAIA,UAAUC,MAAM,KAAK,GAAG;YAC1BjB,IAAAA,SAAE,EAAC,gBAAgB;QACrB;QACA,OAAOW,UAAUP,qBAAqBY,WAAW;IACnD,GACAX;IAEFC,OAAOY,cAAc,CAACd,oBAAoBe,SAAS,EAAE,eAAe;QAClEX,OAAOI;IACT;IACA,OAAOA;AACT;AAEA,IAAI;IACF,8CAA8C;IAC9CE,OAAOX,WAAWW;AACpB,EAAE,OAAM;IACNM,QAAQC,KAAK,CACX;AAEJ","ignoreList":[0]}

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
const _patcherrorinspect = require("../patch-error-inspect");
(0, _patcherrorinspect.patchErrorInspectNodeJS)(globalThis.Error);
//# sourceMappingURL=error-inspect.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../src/server/node-environment-extensions/error-inspect.tsx"],"sourcesContent":["import { patchErrorInspectNodeJS } from '../patch-error-inspect'\n\npatchErrorInspectNodeJS(globalThis.Error)\n"],"names":["patchErrorInspectNodeJS","globalThis","Error"],"mappings":";;;;mCAAwC;AAExCA,IAAAA,0CAAuB,EAACC,WAAWC,KAAK","ignoreList":[0]}

View File

@@ -0,0 +1,9 @@
/**
* We extend node:crypto APIs during builds and revalidates to ensure that prerenders don't observe random bytes
* When cacheComponents is enabled. Random bytes are a form of IO even if they resolve synchronously. When cacheComponents is
* enabled we need to ensure that random bytes are excluded from prerenders unless they are cached.
*
*
* The extensions here never error nor alter the underlying return values and thus should be transparent to callers.
*/
export {};

View File

@@ -0,0 +1,103 @@
/**
* We extend node:crypto APIs during builds and revalidates to ensure that prerenders don't observe random bytes
* When cacheComponents is enabled. Random bytes are a form of IO even if they resolve synchronously. When cacheComponents is
* enabled we need to ensure that random bytes are excluded from prerenders unless they are cached.
*
*
* The extensions here never error nor alter the underlying return values and thus should be transparent to callers.
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
const _utils = require("./utils");
if (process.env.NEXT_RUNTIME === 'edge') {
// nothing to patch
} else {
const nodeCrypto = require('node:crypto');
// require('node:crypto').getRandomValues is an alias for
// crypto.getRandomValues which is extended in web-crypto.tsx
// require('node:crypto').randomUUID is not an alias for crypto.randomUUID
const randomUUIDExpression = "`require('node:crypto').randomUUID()`";
try {
const _randomUUID = nodeCrypto.randomUUID;
nodeCrypto.randomUUID = function randomUUID() {
(0, _utils.io)(randomUUIDExpression, 'random');
return _randomUUID.apply(this, arguments);
};
} catch {
console.error(`Failed to install ${randomUUIDExpression} extension. When using \`experimental.cacheComponents\` calling this function will not correctly trigger dynamic behavior.`);
}
const randomBytesExpression = "`require('node:crypto').randomBytes(size)`";
try {
const _randomBytes = nodeCrypto.randomBytes;
// @ts-expect-error -- TODO: tell TS the overloads are preserved
nodeCrypto.randomBytes = function randomBytes() {
if (typeof arguments[1] !== 'function') {
// randomBytes is sync if the second arg is undefined
(0, _utils.io)(randomBytesExpression, 'random');
}
return _randomBytes.apply(this, arguments);
};
} catch {
console.error(`Failed to install ${randomBytesExpression} extension. When using \`experimental.cacheComponents\` calling this function without a callback argument will not correctly trigger dynamic behavior.`);
}
const randomFillSyncExpression = "`require('node:crypto').randomFillSync(...)`";
try {
const _randomFillSync = nodeCrypto.randomFillSync;
// @ts-expect-error -- TODO: tell TS the overloads are preserved
nodeCrypto.randomFillSync = function randomFillSync() {
(0, _utils.io)(randomFillSyncExpression, 'random');
return _randomFillSync.apply(this, arguments);
};
} catch {
console.error(`Failed to install ${randomFillSyncExpression} extension. When using \`experimental.cacheComponents\` calling this function will not correctly trigger dynamic behavior.`);
}
const randomIntExpression = "`require('node:crypto').randomInt(min, max)`";
try {
const _randomInt = nodeCrypto.randomInt;
// @ts-expect-error -- TODO: tell TS the overloads are preserved
nodeCrypto.randomInt = function randomInt() {
if (typeof arguments[2] !== 'function') {
// randomInt is sync if the third arg is undefined
(0, _utils.io)(randomIntExpression, 'random');
}
return _randomInt.apply(this, arguments);
};
} catch {
console.error(`Failed to install ${randomBytesExpression} extension. When using \`experimental.cacheComponents\` calling this function without a callback argument will not correctly trigger dynamic behavior.`);
}
const generatePrimeSyncExpression = "`require('node:crypto').generatePrimeSync(...)`";
try {
const _generatePrimeSync = nodeCrypto.generatePrimeSync;
// @ts-expect-error -- TODO: tell TS the overloads are preserved
nodeCrypto.generatePrimeSync = function generatePrimeSync() {
(0, _utils.io)(generatePrimeSyncExpression, 'random');
return _generatePrimeSync.apply(this, arguments);
};
} catch {
console.error(`Failed to install ${generatePrimeSyncExpression} extension. When using \`experimental.cacheComponents\` calling this function will not correctly trigger dynamic behavior.`);
}
const generateKeyPairSyncExpression = "`require('node:crypto').generateKeyPairSync(...)`";
try {
const _generateKeyPairSync = nodeCrypto.generateKeyPairSync;
// @ts-expect-error -- TODO: tell TS the overloads are preserved
nodeCrypto.generateKeyPairSync = function generateKeyPairSync() {
(0, _utils.io)(generateKeyPairSyncExpression, 'random');
return _generateKeyPairSync.apply(this, arguments);
};
} catch {
console.error(`Failed to install ${generateKeyPairSyncExpression} extension. When using \`experimental.cacheComponents\` calling this function will not correctly trigger dynamic behavior.`);
}
const generateKeySyncExpression = "`require('node:crypto').generateKeySync(...)`";
try {
const _generateKeySync = nodeCrypto.generateKeySync;
nodeCrypto.generateKeySync = function generateKeySync() {
(0, _utils.io)(generateKeySyncExpression, 'random');
return _generateKeySync.apply(this, arguments);
};
} catch {
console.error(`Failed to install ${generateKeySyncExpression} extension. When using \`experimental.cacheComponents\` calling this function will not correctly trigger dynamic behavior.`);
}
}
//# sourceMappingURL=node-crypto.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
/**
* We extend Math.random() during builds and revalidates to ensure that prerenders don't observe randomness
* When cacheComponents is enabled. randomness is a form of IO even though it resolves synchronously. When cacheComponents is
* enabled we need to ensure that randomness is excluded from prerenders.
*
* The extensions here never error nor alter the random generation itself and thus should be transparent to callers.
*/
export {};

View File

@@ -0,0 +1,28 @@
/**
* We extend Math.random() during builds and revalidates to ensure that prerenders don't observe randomness
* When cacheComponents is enabled. randomness is a form of IO even though it resolves synchronously. When cacheComponents is
* enabled we need to ensure that randomness is excluded from prerenders.
*
* The extensions here never error nor alter the random generation itself and thus should be transparent to callers.
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
const _utils = require("./utils");
const expression = '`Math.random()`';
try {
const _random = Math.random;
Math.random = (function random() {
(0, _utils.io)(expression, 'random');
return _random.apply(null, arguments);
// We bind here to alter the `toString` printing to match `Math.random`'s native `toString`.
// eslint-disable-next-line no-extra-bind
}).bind(null);
Object.defineProperty(Math.random, 'name', {
value: 'random'
});
} catch {
console.error(`Failed to install ${expression} extension. When using \`experimental.cacheComponents\` calling this function will not correctly trigger dynamic behavior.`);
}
//# sourceMappingURL=random.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../src/server/node-environment-extensions/random.tsx"],"sourcesContent":["/**\n * We extend Math.random() during builds and revalidates to ensure that prerenders don't observe randomness\n * When cacheComponents is enabled. randomness is a form of IO even though it resolves synchronously. When cacheComponents is\n * enabled we need to ensure that randomness is excluded from prerenders.\n *\n * The extensions here never error nor alter the random generation itself and thus should be transparent to callers.\n */\n\nimport { io } from './utils'\n\nconst expression = '`Math.random()`'\ntry {\n const _random = Math.random\n Math.random = function random() {\n io(expression, 'random')\n return _random.apply(null, arguments as any)\n\n // We bind here to alter the `toString` printing to match `Math.random`'s native `toString`.\n // eslint-disable-next-line no-extra-bind\n }.bind(null)\n Object.defineProperty(Math.random, 'name', { value: 'random' })\n} catch {\n console.error(\n `Failed to install ${expression} extension. When using \\`experimental.cacheComponents\\` calling this function will not correctly trigger dynamic behavior.`\n )\n}\n"],"names":["expression","_random","Math","random","io","apply","arguments","bind","Object","defineProperty","value","console","error"],"mappings":"AAAA;;;;;;CAMC;;;;uBAEkB;AAEnB,MAAMA,aAAa;AACnB,IAAI;IACF,MAAMC,UAAUC,KAAKC,MAAM;IAC3BD,KAAKC,MAAM,GAAG,CAAA,SAASA;QACrBC,IAAAA,SAAE,EAACJ,YAAY;QACf,OAAOC,QAAQI,KAAK,CAAC,MAAMC;IAE3B,4FAA4F;IAC5F,yCAAyC;IAC3C,CAAA,EAAEC,IAAI,CAAC;IACPC,OAAOC,cAAc,CAACP,KAAKC,MAAM,EAAE,QAAQ;QAAEO,OAAO;IAAS;AAC/D,EAAE,OAAM;IACNC,QAAQC,KAAK,CACX,CAAC,kBAAkB,EAAEZ,WAAW,0HAA0H,CAAC;AAE/J","ignoreList":[0]}

View File

@@ -0,0 +1,3 @@
type ApiType = 'time' | 'random' | 'crypto';
export declare function io(expression: string, type: ApiType): void;
export {};

View File

@@ -0,0 +1,127 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "io", {
enumerable: true,
get: function() {
return io;
}
});
const _workasyncstorageexternal = require("../app-render/work-async-storage.external");
const _workunitasyncstorageexternal = require("../app-render/work-unit-async-storage.external");
const _dynamicrendering = require("../app-render/dynamic-rendering");
const _invarianterror = require("../../shared/lib/invariant-error");
function io(expression, type) {
const workUnitStore = _workunitasyncstorageexternal.workUnitAsyncStorage.getStore();
const workStore = _workasyncstorageexternal.workAsyncStorage.getStore();
if (!workUnitStore || !workStore) {
return;
}
switch(workUnitStore.type){
case 'prerender':
case 'prerender-runtime':
{
const prerenderSignal = workUnitStore.controller.signal;
if (prerenderSignal.aborted === false) {
// If the prerender signal is already aborted we don't need to construct
// any stacks because something else actually terminated the prerender.
let message;
switch(type){
case 'time':
message = `Route "${workStore.route}" used ${expression} instead of using \`performance\` or without explicitly calling \`await connection()\` beforehand. See more info here: https://nextjs.org/docs/messages/next-prerender-current-time`;
break;
case 'random':
message = `Route "${workStore.route}" used ${expression} outside of \`"use cache"\` and without explicitly calling \`await connection()\` beforehand. See more info here: https://nextjs.org/docs/messages/next-prerender-random`;
break;
case 'crypto':
message = `Route "${workStore.route}" used ${expression} outside of \`"use cache"\` and without explicitly calling \`await connection()\` beforehand. See more info here: https://nextjs.org/docs/messages/next-prerender-crypto`;
break;
default:
throw Object.defineProperty(new _invarianterror.InvariantError('Unknown expression type in abortOnSynchronousPlatformIOAccess.'), "__NEXT_ERROR_CODE", {
value: "E526",
enumerable: false,
configurable: true
});
}
(0, _dynamicrendering.abortOnSynchronousPlatformIOAccess)(workStore.route, expression, applyOwnerStack(Object.defineProperty(new Error(message), "__NEXT_ERROR_CODE", {
value: "E394",
enumerable: false,
configurable: true
}), workUnitStore), workUnitStore);
}
break;
}
case 'prerender-client':
{
const prerenderSignal = workUnitStore.controller.signal;
if (prerenderSignal.aborted === false) {
// If the prerender signal is already aborted we don't need to construct
// any stacks because something else actually terminated the prerender.
let message;
switch(type){
case 'time':
message = `Route "${workStore.route}" used ${expression} inside a Client Component without a Suspense boundary above it. See more info here: https://nextjs.org/docs/messages/next-prerender-current-time-client`;
break;
case 'random':
message = `Route "${workStore.route}" used ${expression} inside a Client Component without a Suspense boundary above it. See more info here: https://nextjs.org/docs/messages/next-prerender-random-client`;
break;
case 'crypto':
message = `Route "${workStore.route}" used ${expression} inside a Client Component without a Suspense boundary above it. See more info here: https://nextjs.org/docs/messages/next-prerender-crypto-client`;
break;
default:
throw Object.defineProperty(new _invarianterror.InvariantError('Unknown expression type in abortOnSynchronousPlatformIOAccess.'), "__NEXT_ERROR_CODE", {
value: "E526",
enumerable: false,
configurable: true
});
}
(0, _dynamicrendering.abortOnSynchronousPlatformIOAccess)(workStore.route, expression, applyOwnerStack(Object.defineProperty(new Error(message), "__NEXT_ERROR_CODE", {
value: "E394",
enumerable: false,
configurable: true
}), workUnitStore), workUnitStore);
}
break;
}
case 'request':
if (workUnitStore.prerenderPhase === true) {
(0, _dynamicrendering.trackSynchronousPlatformIOAccessInDev)(workUnitStore);
}
break;
case 'prerender-ppr':
case 'prerender-legacy':
case 'cache':
case 'private-cache':
case 'unstable-cache':
break;
default:
workUnitStore;
}
}
function applyOwnerStack(error, workUnitStore) {
// TODO: Instead of stitching the stacks here, we should log the original
// error as-is when it occurs, and let `patchErrorInspect` handle adding the
// owner stack, instead of logging it deferred in the `LogSafely` component
// via `throwIfDisallowedDynamic`.
if (process.env.NODE_ENV !== 'production' && workUnitStore.captureOwnerStack) {
const ownerStack = workUnitStore.captureOwnerStack();
if (ownerStack) {
let stack = ownerStack;
if (error.stack) {
const frames = [];
for (const frame of error.stack.split('\n').slice(1)){
if (frame.includes('react_stack_bottom_frame')) {
break;
}
frames.push(frame);
}
stack = '\n' + frames.join('\n') + stack;
}
error.stack = error.name + ': ' + error.message + stack;
}
}
return error;
}
//# sourceMappingURL=utils.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,9 @@
/**
* We extend Web Crypto APIs during builds and revalidates to ensure that prerenders don't observe random bytes
* When cacheComponents is enabled. Random bytes are a form of IO even if they resolve synchronously. When cacheComponents is
* enabled we need to ensure that random bytes are excluded from prerenders unless they are cached.
*
*
* The extensions here never error nor alter the underlying return values and thus should be transparent to callers.
*/
export {};

View File

@@ -0,0 +1,45 @@
/**
* We extend Web Crypto APIs during builds and revalidates to ensure that prerenders don't observe random bytes
* When cacheComponents is enabled. Random bytes are a form of IO even if they resolve synchronously. When cacheComponents is
* enabled we need to ensure that random bytes are excluded from prerenders unless they are cached.
*
*
* The extensions here never error nor alter the underlying return values and thus should be transparent to callers.
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
const _utils = require("./utils");
let webCrypto;
if (process.env.NEXT_RUNTIME === 'edge') {
webCrypto = crypto;
} else {
if (typeof crypto === 'undefined') {
// @ts-expect-error -- TODO: Is this actually safe?
webCrypto = require('node:crypto').webcrypto;
} else {
webCrypto = crypto;
}
}
const getRandomValuesExpression = '`crypto.getRandomValues()`';
try {
const _getRandomValues = webCrypto.getRandomValues;
webCrypto.getRandomValues = function getRandomValues() {
(0, _utils.io)(getRandomValuesExpression, 'crypto');
return _getRandomValues.apply(webCrypto, arguments);
};
} catch {
console.error(`Failed to install ${getRandomValuesExpression} extension. When using \`experimental.cacheComponents\` calling this function will not correctly trigger dynamic behavior.`);
}
const randomUUIDExpression = '`crypto.randomUUID()`';
try {
const _randomUUID = webCrypto.randomUUID;
webCrypto.randomUUID = function randomUUID() {
(0, _utils.io)(randomUUIDExpression, 'crypto');
return _randomUUID.apply(webCrypto, arguments);
};
} catch {
console.error(`Failed to install ${getRandomValuesExpression} extension. When using \`experimental.cacheComponents\` calling this function will not correctly trigger dynamic behavior.`);
}
//# sourceMappingURL=web-crypto.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../src/server/node-environment-extensions/web-crypto.tsx"],"sourcesContent":["/**\n * We extend Web Crypto APIs during builds and revalidates to ensure that prerenders don't observe random bytes\n * When cacheComponents is enabled. Random bytes are a form of IO even if they resolve synchronously. When cacheComponents is\n * enabled we need to ensure that random bytes are excluded from prerenders unless they are cached.\n *\n *\n * The extensions here never error nor alter the underlying return values and thus should be transparent to callers.\n */\n\nimport { io } from './utils'\n\nlet webCrypto: typeof crypto\nif (process.env.NEXT_RUNTIME === 'edge') {\n webCrypto = crypto\n} else {\n if (typeof crypto === 'undefined') {\n // @ts-expect-error -- TODO: Is this actually safe?\n webCrypto = (require('node:crypto') as typeof import('node:crypto'))\n .webcrypto\n } else {\n webCrypto = crypto\n }\n}\n\nconst getRandomValuesExpression = '`crypto.getRandomValues()`'\ntry {\n const _getRandomValues = webCrypto.getRandomValues\n webCrypto.getRandomValues = function getRandomValues() {\n io(getRandomValuesExpression, 'crypto')\n return _getRandomValues.apply(webCrypto, arguments as any)\n }\n} catch {\n console.error(\n `Failed to install ${getRandomValuesExpression} extension. When using \\`experimental.cacheComponents\\` calling this function will not correctly trigger dynamic behavior.`\n )\n}\n\nconst randomUUIDExpression = '`crypto.randomUUID()`'\ntry {\n const _randomUUID = webCrypto.randomUUID\n webCrypto.randomUUID = function randomUUID() {\n io(randomUUIDExpression, 'crypto')\n return _randomUUID.apply(webCrypto, arguments as any)\n } as typeof _randomUUID\n} catch {\n console.error(\n `Failed to install ${getRandomValuesExpression} extension. When using \\`experimental.cacheComponents\\` calling this function will not correctly trigger dynamic behavior.`\n )\n}\n"],"names":["webCrypto","process","env","NEXT_RUNTIME","crypto","require","webcrypto","getRandomValuesExpression","_getRandomValues","getRandomValues","io","apply","arguments","console","error","randomUUIDExpression","_randomUUID","randomUUID"],"mappings":"AAAA;;;;;;;CAOC;;;;uBAEkB;AAEnB,IAAIA;AACJ,IAAIC,QAAQC,GAAG,CAACC,YAAY,KAAK,QAAQ;IACvCH,YAAYI;AACd,OAAO;IACL,IAAI,OAAOA,WAAW,aAAa;QACjC,mDAAmD;QACnDJ,YAAY,AAACK,QAAQ,eAClBC,SAAS;IACd,OAAO;QACLN,YAAYI;IACd;AACF;AAEA,MAAMG,4BAA4B;AAClC,IAAI;IACF,MAAMC,mBAAmBR,UAAUS,eAAe;IAClDT,UAAUS,eAAe,GAAG,SAASA;QACnCC,IAAAA,SAAE,EAACH,2BAA2B;QAC9B,OAAOC,iBAAiBG,KAAK,CAACX,WAAWY;IAC3C;AACF,EAAE,OAAM;IACNC,QAAQC,KAAK,CACX,CAAC,kBAAkB,EAAEP,0BAA0B,0HAA0H,CAAC;AAE9K;AAEA,MAAMQ,uBAAuB;AAC7B,IAAI;IACF,MAAMC,cAAchB,UAAUiB,UAAU;IACxCjB,UAAUiB,UAAU,GAAG,SAASA;QAC9BP,IAAAA,SAAE,EAACK,sBAAsB;QACzB,OAAOC,YAAYL,KAAK,CAACX,WAAWY;IACtC;AACF,EAAE,OAAM;IACNC,QAAQC,KAAK,CACX,CAAC,kBAAkB,EAAEP,0BAA0B,0HAA0H,CAAC;AAE9K","ignoreList":[0]}