feat(blog): add file-based blog with dynamic slugs, MDX content and layout shell

- Introduced blog routing using Next.js App Router
- Implemented dynamic [slug] pages for blog posts
- Added MDX-based content loading via lib/posts
- Integrated shared TopBar layout with navigation
- Established clear content, lib and component separation
This commit is contained in:
PascalSchattenburg
2026-01-22 14:14:15 +01:00
parent b717952234
commit d147843c76
10412 changed files with 2475583 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
export interface LogEntry {
timestamp: string;
source: 'Server' | 'Browser';
level: string;
message: string;
}
export declare class FileLogger {
private logFilePath;
private isInitialized;
private logQueue;
private flushTimer;
private mcpServerEnabled;
initialize(distDir: string, mcpServerEnabled: boolean): void;
private formatTimestamp;
private formatLogEntry;
private scheduleFlush;
getLogQueue(): string[];
private flush;
private enqueueLog;
log(source: 'Server' | 'Browser', level: string, message: string): void;
logServer(level: string, message: string): void;
logBrowser(level: string, message: string): void;
forceFlush(): void;
destroy(): void;
}
export declare function getFileLogger(): FileLogger;
export declare function test__resetFileLogger(): void;

View File

@@ -0,0 +1,183 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
FileLogger: null,
getFileLogger: null,
test__resetFileLogger: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
FileLogger: function() {
return FileLogger;
},
getFileLogger: function() {
return getFileLogger;
},
test__resetFileLogger: function() {
return test__resetFileLogger;
}
});
const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
class FileLogger {
initialize(distDir, mcpServerEnabled) {
this.logFilePath = _path.default.join(distDir, 'logs', `next-development.log`);
this.mcpServerEnabled = mcpServerEnabled;
if (this.isInitialized) {
return;
}
// Only initialize if mcpServer is enabled
if (!this.mcpServerEnabled) {
return;
}
try {
// Clean up the log file on each initialization
// ensure the directory exists
_fs.default.mkdirSync(_path.default.dirname(this.logFilePath), {
recursive: true
});
_fs.default.writeFileSync(this.logFilePath, '');
this.isInitialized = true;
} catch (error) {
console.error(error);
}
}
formatTimestamp() {
// Use performance.now() instead of Date.now() for avoid sync IO of cache components
const now = performance.now();
const hours = Math.floor(now / 3600000).toString().padStart(2, '0');
const minutes = Math.floor(now % 3600000 / 60000).toString().padStart(2, '0');
const seconds = Math.floor(now % 60000 / 1000).toString().padStart(2, '0');
const milliseconds = Math.floor(now % 1000).toString().padStart(3, '0');
return `${hours}:${minutes}:${seconds}.${milliseconds}`;
}
formatLogEntry(entry) {
const { timestamp, source, level, message } = entry;
const levelPadded = level.toUpperCase().padEnd(7, ' ') // Pad level to 7 characters for alignment
;
const sourcePadded = source === 'Browser' ? source : 'Server ';
return `[${timestamp}] ${sourcePadded} ${levelPadded} ${message}\n`;
}
scheduleFlush() {
// Debounce the flush
if (this.flushTimer) {
clearTimeout(this.flushTimer);
this.flushTimer = null;
}
// Delay the log flush to ensure more logs can be batched together asynchronously
this.flushTimer = setTimeout(()=>{
this.flush();
}, 100);
}
getLogQueue() {
return this.logQueue;
}
flush() {
if (this.logQueue.length === 0) {
return;
}
// Only flush to disk if mcpServer is enabled
if (!this.mcpServerEnabled) {
this.logQueue = [] // Clear the queue without writing
;
this.flushTimer = null;
return;
}
try {
// Ensure the directory exists before writing
const logDir = _path.default.dirname(this.logFilePath);
if (!_fs.default.existsSync(logDir)) {
_fs.default.mkdirSync(logDir, {
recursive: true
});
}
const logsToWrite = this.logQueue.join('');
// Writing logs to files synchronously to ensure they're written before returning
_fs.default.appendFileSync(this.logFilePath, logsToWrite);
this.logQueue = [];
} catch (error) {
console.error('Failed to flush logs to file:', error);
} finally{
this.flushTimer = null;
}
}
enqueueLog(formattedEntry) {
this.logQueue.push(formattedEntry);
// Cancel existing timer and start a new one to ensure all logs are flushed together
if (this.flushTimer) {
clearTimeout(this.flushTimer);
this.flushTimer = null;
}
this.scheduleFlush();
}
log(source, level, message) {
// Don't log anything if mcpServer is disabled
if (!this.mcpServerEnabled) {
return;
}
if (!this.isInitialized) {
return;
}
const logEntry = {
timestamp: this.formatTimestamp(),
source,
level,
message
};
const formattedEntry = this.formatLogEntry(logEntry);
this.enqueueLog(formattedEntry);
}
logServer(level, message) {
this.log('Server', level, message);
}
logBrowser(level, message) {
this.log('Browser', level, message);
}
// Force flush all queued logs immediately
forceFlush() {
if (this.flushTimer) {
clearTimeout(this.flushTimer);
this.flushTimer = null;
}
this.flush();
}
// Cleanup method to flush logs on process exit
destroy() {
this.forceFlush();
}
constructor(){
this.logFilePath = '';
this.isInitialized = false;
this.logQueue = [];
this.flushTimer = null;
this.mcpServerEnabled = false;
}
}
// Singleton instance
let fileLogger = null;
function getFileLogger() {
if (!fileLogger || process.env.NODE_ENV === 'test') {
fileLogger = new FileLogger();
}
return fileLogger;
}
function test__resetFileLogger() {
if (fileLogger) {
fileLogger.destroy();
}
fileLogger = null;
}
//# sourceMappingURL=file-logger.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,40 @@
import type { Project } from '../../../build/swc/types';
import { type MappingContext } from './source-map';
import { type ServerLogEntry } from '../../../next-devtools/shared/forward-logs-shared';
export declare function restoreUndefined(x: any): any;
export declare function stripFormatSpecifiers(args: any[]): any[];
export declare function handleLog(entries: ServerLogEntry[], ctx: MappingContext, distDir: string, config: boolean | {
logDepth?: number;
showSourceLocation?: boolean;
}): Promise<void>;
export declare function receiveBrowserLogsWebpack(opts: {
entries: ServerLogEntry[];
router: 'app' | 'pages';
sourceType?: 'server' | 'edge-server';
clientStats: () => any;
serverStats: () => any;
edgeServerStats: () => any;
rootDirectory: string;
distDir: string;
config: boolean | {
logDepth?: number;
showSourceLocation?: boolean;
};
}): Promise<void>;
export declare function receiveBrowserLogsTurbopack(opts: {
entries: ServerLogEntry[];
router: 'app' | 'pages';
sourceType?: 'server' | 'edge-server';
project: Project;
projectPath: string;
distDir: string;
config: boolean | {
logDepth?: number;
showSourceLocation?: boolean;
};
}): Promise<void>;
export declare function handleClientFileLogs(logs: Array<{
timestamp: string;
level: string;
message: string;
}>): Promise<void>;

View File

@@ -0,0 +1,512 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
handleClientFileLogs: null,
handleLog: null,
receiveBrowserLogsTurbopack: null,
receiveBrowserLogsWebpack: null,
restoreUndefined: null,
stripFormatSpecifiers: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
handleClientFileLogs: function() {
return handleClientFileLogs;
},
handleLog: function() {
return handleLog;
},
receiveBrowserLogsTurbopack: function() {
return receiveBrowserLogsTurbopack;
},
receiveBrowserLogsWebpack: function() {
return receiveBrowserLogsWebpack;
},
restoreUndefined: function() {
return restoreUndefined;
},
stripFormatSpecifiers: function() {
return stripFormatSpecifiers;
}
});
const _picocolors = require("../../../lib/picocolors");
const _util = /*#__PURE__*/ _interop_require_default(require("util"));
const _sourcemap = require("./source-map");
const _forwardlogsshared = require("../../../next-devtools/shared/forward-logs-shared");
const _console = require("../../../client/lib/console");
const _filelogger = require("./file-logger");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function restoreUndefined(x) {
if (x === _forwardlogsshared.UNDEFINED_MARKER) return undefined;
if (Array.isArray(x)) return x.map(restoreUndefined);
if (x && typeof x === 'object') {
for(let k in x){
x[k] = restoreUndefined(x[k]);
}
}
return x;
}
function cleanConsoleArgsForFileLogging(args) {
/**
* Use formatConsoleArgs to strip out background and color format specifiers
* and keep only the original string content for file logging
*/ try {
return (0, _console.formatConsoleArgs)(args);
} catch {
// Fallback to simple string conversion if formatting fails
return args.map((arg)=>typeof arg === 'string' ? arg : _util.default.inspect(arg, {
depth: 2
})).join(' ');
}
}
const methods = [
'log',
'info',
'warn',
'debug',
'table',
'error',
'assert',
'dir',
'dirxml',
'group',
'groupCollapsed',
'groupEnd'
];
const methodsToSkipInspect = new Set([
'table',
'dir',
'dirxml',
'group',
'groupCollapsed',
'groupEnd'
]);
// we aren't overriding console, we're just making a (slightly convoluted) helper for replaying user console methods
const forwardConsole = {
...console,
...Object.fromEntries(methods.map((method)=>[
method,
(...args)=>console[method](...args.map((arg)=>methodsToSkipInspect.has(method) || typeof arg !== 'object' || arg === null ? arg : _util.default.inspect(arg, {
depth: Infinity,
colors: true
})))
]))
};
async function deserializeArgData(arg) {
try {
// we want undefined to be represented as it would be in the browser from the user's perspective (otherwise it would be stripped away/shown as null)
if (arg === _forwardlogsshared.UNDEFINED_MARKER) {
return restoreUndefined(arg);
}
return restoreUndefined(JSON.parse(arg));
} catch {
return arg;
}
}
const colorError = (mapped, config)=>{
const colorFn = (config == null ? void 0 : config.applyColor) === undefined || config.applyColor ? _picocolors.red : (x)=>x;
switch(mapped.kind){
case 'mapped-stack':
case 'stack':
{
return ((config == null ? void 0 : config.prefix) ? colorFn(config == null ? void 0 : config.prefix) : '') + `\n${colorFn(mapped.stack)}`;
}
case 'with-frame-code':
{
return ((config == null ? void 0 : config.prefix) ? colorFn(config == null ? void 0 : config.prefix) : '') + `\n${colorFn(mapped.stack)}\n${mapped.frameCode}`;
}
// a more sophisticated version of this allows the user to config if they want ignored frames (but we need to be sure to source map them)
case 'all-ignored':
{
return (config == null ? void 0 : config.prefix) ? colorFn(config == null ? void 0 : config.prefix) : '';
}
default:
{}
}
mapped;
};
function processConsoleFormatStrings(args) {
/**
* this handles the case formatting is applied to the console log
* otherwise we will see the format specifier directly in the terminal output
*/ if (args.length > 0 && typeof args[0] === 'string') {
const formatString = args[0];
if (formatString.includes('%s') || formatString.includes('%d') || formatString.includes('%i') || formatString.includes('%f') || formatString.includes('%o') || formatString.includes('%O') || formatString.includes('%c')) {
try {
const formatted = _util.default.format(...args);
return [
formatted
];
} catch {
return args;
}
}
}
return args;
}
function stripFormatSpecifiers(args) {
if (args.length === 0 || typeof args[0] !== 'string') return args;
const fmtIn = String(args[0]);
const rest = args.slice(1);
if (!fmtIn.includes('%')) return args;
let fmtOut = '';
let argPtr = 0;
for(let i = 0; i < fmtIn.length; i++){
if (fmtIn[i] !== '%') {
fmtOut += fmtIn[i];
continue;
}
if (fmtIn[i + 1] === '%') {
fmtOut += '%';
i++;
continue;
}
const token = fmtIn[++i];
if (!token) {
fmtOut += '%';
continue;
}
if ('csdifoOj'.includes(token) || token === 'O') {
if (argPtr < rest.length) {
if (token === 'c') {
argPtr++;
} else if (token === 'o' || token === 'O' || token === 'j') {
const obj = rest[argPtr++];
fmtOut += _util.default.inspect(obj, {
depth: 2,
colors: false
});
} else {
// string(...) is safe for remaining specifiers
fmtOut += String(rest[argPtr++]);
}
}
continue;
}
fmtOut += '%' + token;
}
const result = [
fmtOut
];
if (argPtr < rest.length) {
result.push(...rest.slice(argPtr));
}
return result;
}
async function prepareFormattedErrorArgs(entry, ctx, distDir) {
const mapped = await (0, _sourcemap.getSourceMappedStackFrames)(entry.stack, ctx, distDir);
return [
colorError(mapped, {
prefix: entry.prefix
})
];
}
async function prepareConsoleArgs(entry, ctx, distDir) {
const deserialized = await Promise.all(entry.args.map(async (arg)=>{
if (arg.kind === 'arg') {
const data = await deserializeArgData(arg.data);
if (entry.method === 'warn' && typeof data === 'string') {
return (0, _picocolors.yellow)(data);
}
return data;
}
if (!arg.stack) return (0, _picocolors.red)(arg.prefix);
const mapped = await (0, _sourcemap.getSourceMappedStackFrames)(arg.stack, ctx, distDir);
return colorError(mapped, {
prefix: arg.prefix,
applyColor: false
});
}));
return processConsoleFormatStrings(deserialized);
}
async function prepareConsoleErrorArgs(entry, ctx, distDir) {
const deserialized = await Promise.all(entry.args.map(async (arg)=>{
if (arg.kind === 'arg') {
if (arg.isRejectionMessage) return (0, _picocolors.red)(arg.data);
return deserializeArgData(arg.data);
}
if (!arg.stack) return (0, _picocolors.red)(arg.prefix);
const mapped = await (0, _sourcemap.getSourceMappedStackFrames)(arg.stack, ctx, distDir);
return colorError(mapped, {
prefix: arg.prefix
});
}));
const mappedStack = await (0, _sourcemap.getSourceMappedStackFrames)(entry.consoleErrorStack, ctx, distDir);
/**
* don't show the stack + codeblock when there are errors present, since:
* - it will look overwhelming to see 2 stacks and 2 code blocks
* - the user already knows where the console.error is at because we append the location
*/ const location = (0, _sourcemap.getConsoleLocation)(mappedStack);
if (entry.args.some((a)=>a.kind === 'formatted-error-arg')) {
const result = stripFormatSpecifiers(deserialized);
if (location) {
result.push((0, _picocolors.dim)(`(${location})`));
}
return result;
}
const result = [
...processConsoleFormatStrings(deserialized),
colorError(mappedStack)
];
if (location) {
result.push((0, _picocolors.dim)(`(${location})`));
}
return result;
}
async function handleTable(entry, browserPrefix, ctx, distDir) {
const deserializedArgs = await Promise.all(entry.args.map(async (arg)=>{
if (arg.kind === 'formatted-error-arg') {
return {
stack: arg.stack
};
}
return deserializeArgData(arg.data);
}));
const location = await (async ()=>{
if (!entry.consoleMethodStack) {
return;
}
const frames = await (0, _sourcemap.getSourceMappedStackFrames)(entry.consoleMethodStack, ctx, distDir);
return (0, _sourcemap.getConsoleLocation)(frames);
})();
// we can't inline pass browser prefix, but it looks better multiline for table anyways
forwardConsole.log(browserPrefix);
forwardConsole.table(...deserializedArgs);
if (location) {
forwardConsole.log((0, _picocolors.dim)(`(${location})`));
}
}
async function handleTrace(entry, browserPrefix, ctx, distDir) {
const deserializedArgs = await Promise.all(entry.args.map(async (arg)=>{
if (arg.kind === 'formatted-error-arg') {
if (!arg.stack) return (0, _picocolors.red)(arg.prefix);
const mapped = await (0, _sourcemap.getSourceMappedStackFrames)(arg.stack, ctx, distDir);
return colorError(mapped, {
prefix: arg.prefix
});
}
return deserializeArgData(arg.data);
}));
if (!entry.consoleMethodStack) {
forwardConsole.log(browserPrefix, ...deserializedArgs, '[Trace unavailable]');
return;
}
// TODO(rob): refactor so we can re-use result and not re-run the entire source map to avoid trivial post processing
const [mapped, mappedIgnored] = await Promise.all([
(0, _sourcemap.getSourceMappedStackFrames)(entry.consoleMethodStack, ctx, distDir, false),
(0, _sourcemap.getSourceMappedStackFrames)(entry.consoleMethodStack, ctx, distDir)
]);
const location = (0, _sourcemap.getConsoleLocation)(mappedIgnored);
forwardConsole.log(browserPrefix, ...deserializedArgs, `\n${mapped.stack}`, ...location ? [
`\n${(0, _picocolors.dim)(`(${location})`)}`
] : []);
}
async function handleDir(entry, browserPrefix, ctx, distDir) {
const loggableEntry = await prepareConsoleArgs(entry, ctx, distDir);
const consoleMethod = forwardConsole[entry.method] || forwardConsole.log;
if (entry.consoleMethodStack) {
const mapped = await (0, _sourcemap.getSourceMappedStackFrames)(entry.consoleMethodStack, ctx, distDir);
const location = (0, _picocolors.dim)(`(${(0, _sourcemap.getConsoleLocation)(mapped)})`);
const originalWrite = process.stdout.write.bind(process.stdout);
let captured = '';
process.stdout.write = (chunk)=>{
captured += chunk;
return true;
};
try {
consoleMethod(...loggableEntry);
} finally{
process.stdout.write = originalWrite;
}
const preserved = captured.replace(/\r?\n$/, '');
originalWrite(`${browserPrefix}${preserved} ${location}\n`);
return;
}
consoleMethod(browserPrefix, ...loggableEntry);
}
async function handleDefaultConsole(entry, browserPrefix, ctx, distDir, config, isServerLog) {
const consoleArgs = await prepareConsoleArgs(entry, ctx, distDir);
const withStackEntry = await (0, _sourcemap.withLocation)({
original: consoleArgs,
stack: entry.consoleMethodStack || null
}, ctx, distDir, config);
const consoleMethod = forwardConsole[entry.method] || forwardConsole.log;
consoleMethod(browserPrefix, ...withStackEntry);
// Process enqueued logs and write to file
// Log to file with correct source based on context
const fileLogger = (0, _filelogger.getFileLogger)();
// Use cleaned console args to strip out background and color format specifiers
const message = cleanConsoleArgsForFileLogging(consoleArgs);
if (isServerLog) {
fileLogger.logServer(entry.method.toUpperCase(), message);
} else {
fileLogger.logBrowser(entry.method.toUpperCase(), message);
}
}
async function handleLog(entries, ctx, distDir, config) {
// Determine the source based on the context
const isServerLog = ctx.isServer || ctx.isEdgeServer;
const browserPrefix = isServerLog ? (0, _picocolors.cyan)('[server]') : (0, _picocolors.cyan)('[browser]');
const fileLogger = (0, _filelogger.getFileLogger)();
for (const entry of entries){
try {
switch(entry.kind){
case 'console':
{
switch(entry.method){
case 'table':
{
// timeout based abort on source mapping result
await handleTable(entry, browserPrefix, ctx, distDir);
break;
}
// ignore frames
case 'trace':
{
await handleTrace(entry, browserPrefix, ctx, distDir);
break;
}
case 'dir':
{
await handleDir(entry, browserPrefix, ctx, distDir);
break;
}
case 'dirxml':
{
// xml log thing maybe needs an impl
// fallthrough
}
case 'group':
case 'groupCollapsed':
case 'groupEnd':
{
// [browser] undefined (app/page.tsx:8:11) console.group
// fallthrough
}
case 'assert':
{
// check console assert
// fallthrough
}
case 'log':
case 'info':
case 'debug':
case 'error':
case 'warn':
{
await handleDefaultConsole(entry, browserPrefix, ctx, distDir, config, isServerLog);
break;
}
default:
{
entry;
}
}
break;
}
// any logged errors are anything that are logged as "red" in the browser but aren't only an Error (console.error, Promise.reject(100))
case 'any-logged-error':
{
const consoleArgs = await prepareConsoleErrorArgs(entry, ctx, distDir);
forwardConsole.error(browserPrefix, ...consoleArgs);
// Process enqueued logs and write to file
fileLogger.logBrowser('ERROR', cleanConsoleArgsForFileLogging(consoleArgs));
break;
}
// formatted error is an explicit error event (rejections, uncaught errors)
case 'formatted-error':
{
const formattedArgs = await prepareFormattedErrorArgs(entry, ctx, distDir);
forwardConsole.error(browserPrefix, ...formattedArgs);
// Process enqueued logs and write to file
fileLogger.logBrowser('ERROR', cleanConsoleArgsForFileLogging(formattedArgs));
break;
}
default:
{}
}
} catch {
switch(entry.kind){
case 'any-logged-error':
{
const consoleArgs = await prepareConsoleErrorArgs(entry, ctx, distDir);
forwardConsole.error(browserPrefix, ...consoleArgs);
// Process enqueued logs and write to file
fileLogger.logBrowser('ERROR', cleanConsoleArgsForFileLogging(consoleArgs));
break;
}
case 'console':
{
const consoleMethod = forwardConsole[entry.method] || forwardConsole.log;
const consoleArgs = await prepareConsoleArgs(entry, ctx, distDir);
consoleMethod(browserPrefix, ...consoleArgs);
// Process enqueued logs and write to file
fileLogger.logBrowser('ERROR', cleanConsoleArgsForFileLogging(consoleArgs));
break;
}
case 'formatted-error':
{
forwardConsole.error(browserPrefix, `${entry.prefix}\n`, entry.stack);
// Process enqueued logs and write to file
fileLogger.logBrowser('ERROR', cleanConsoleArgsForFileLogging([
`${entry.prefix}\n${entry.stack}`
]));
break;
}
default:
{}
}
}
}
}
async function receiveBrowserLogsWebpack(opts) {
const { entries, router, sourceType, clientStats, serverStats, edgeServerStats, rootDirectory, distDir } = opts;
const isAppDirectory = router === 'app';
const isServer = sourceType === 'server';
const isEdgeServer = sourceType === 'edge-server';
const ctx = {
bundler: 'webpack',
isServer,
isEdgeServer,
isAppDirectory,
clientStats,
serverStats,
edgeServerStats,
rootDirectory
};
await handleLog(entries, ctx, distDir, opts.config);
}
async function receiveBrowserLogsTurbopack(opts) {
const { entries, router, sourceType, project, projectPath, distDir } = opts;
const isAppDirectory = router === 'app';
const isServer = sourceType === 'server';
const isEdgeServer = sourceType === 'edge-server';
const ctx = {
bundler: 'turbopack',
project,
projectPath,
isServer,
isEdgeServer,
isAppDirectory
};
await handleLog(entries, ctx, distDir, opts.config);
}
async function handleClientFileLogs(logs) {
const fileLogger = (0, _filelogger.getFileLogger)();
for (const log of logs){
fileLogger.logBrowser(log.level, log.message);
}
}
//# sourceMappingURL=receive-logs.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,68 @@
import type { Project } from '../../../build/swc/types';
import { type StackFrame } from '../../lib/parse-stack';
type WebpackMappingContext = {
bundler: 'webpack';
isServer: boolean;
isEdgeServer: boolean;
isAppDirectory: boolean;
clientStats: () => any;
serverStats: () => any;
edgeServerStats: () => any;
rootDirectory: string;
};
type TurbopackMappingContext = {
bundler: 'turbopack';
isServer: boolean;
isEdgeServer: boolean;
isAppDirectory: boolean;
project: Project;
projectPath: string;
};
export type MappingContext = WebpackMappingContext | TurbopackMappingContext;
export declare function mapFramesUsingBundler(frames: StackFrame[], ctx: MappingContext): Promise<import("../../../next-devtools/server/shared").OriginalStackFramesResponse>;
export declare function getSourceMappedStackFrames(stackTrace: string, ctx: MappingContext, distDir: string, ignore?: boolean): Promise<{
kind: "stack";
stack: string;
frameCode?: undefined;
frames?: undefined;
} | {
kind: "all-ignored";
stack?: undefined;
frameCode?: undefined;
frames?: undefined;
} | {
kind: "with-frame-code";
frameCode: string;
stack: string;
frames: ({
kind: "rejected";
frameText: string;
codeFrame: null;
} | {
kind: "success";
frameText: string;
codeFrame: string | null;
})[];
} | {
kind: "mapped-stack";
stack: string;
frames: ({
kind: "rejected";
frameText: string;
codeFrame: null;
} | {
kind: "success";
frameText: string;
codeFrame: string | null;
})[];
frameCode?: undefined;
}>;
export declare const withLocation: ({ original, stack, }: {
original: Array<any>;
stack: string | null;
}, ctx: MappingContext, distDir: string, config: boolean | {
logDepth?: number;
showSourceLocation?: boolean;
}) => Promise<any[]>;
export declare const getConsoleLocation: (mapped: Awaited<ReturnType<typeof getSourceMappedStackFrames>>) => string | null;
export {};

View File

@@ -0,0 +1,225 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
getConsoleLocation: null,
getSourceMappedStackFrames: null,
mapFramesUsingBundler: null,
withLocation: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
getConsoleLocation: function() {
return getConsoleLocation;
},
getSourceMappedStackFrames: function() {
return getSourceMappedStackFrames;
},
mapFramesUsingBundler: function() {
return mapFramesUsingBundler;
},
withLocation: function() {
return withLocation;
}
});
const _middlewarewebpack = require("../middleware-webpack");
const _middlewareturbopack = require("../middleware-turbopack");
const _picocolors = require("../../../lib/picocolors");
const _parsestack = require("../../lib/parse-stack");
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _lrucache = require("../../lib/lru-cache");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
async function mapFramesUsingBundler(frames, ctx) {
switch(ctx.bundler){
case 'webpack':
{
const { isServer, isEdgeServer, isAppDirectory, clientStats, serverStats, edgeServerStats, rootDirectory } = ctx;
const res = await (0, _middlewarewebpack.getOriginalStackFrames)({
isServer,
isEdgeServer,
isAppDirectory,
frames,
clientStats,
serverStats,
edgeServerStats,
rootDirectory
});
return res;
}
case 'turbopack':
{
const { project, projectPath, isServer, isEdgeServer, isAppDirectory } = ctx;
const res = await (0, _middlewareturbopack.getOriginalStackFrames)({
project,
projectPath,
frames,
isServer,
isEdgeServer,
isAppDirectory
});
return res;
}
default:
{
return null;
}
}
}
// converts _next/static/chunks/... to file:///.next/static/chunks/... for parseStack
// todo: where does next dev overlay handle this case and re-use that logic
function preprocessStackTrace(stackTrace, distDir) {
return stackTrace.split('\n').map((line)=>{
const match = line.match(/^(\s*at\s+.*?)\s+\(([^)]+)\)$/);
if (match) {
const [, prefix, location] = match;
if (location.startsWith('_next/static/') && distDir) {
const normalizedDistDir = distDir.replace(/\\/g, '/').replace(/\/$/, '');
const absolutePath = normalizedDistDir + '/' + location.slice('_next/'.length);
const fileUrl = `file://${_path.default.resolve(absolutePath)}`;
return `${prefix} (${fileUrl})`;
}
}
return line;
}).join('\n');
}
const cache = new _lrucache.LRUCache(25);
async function getSourceMappedStackFramesInternal(stackTrace, ctx, distDir, ignore = true) {
try {
var _filteredFrames_find;
const normalizedStack = preprocessStackTrace(stackTrace, distDir);
const frames = (0, _parsestack.parseStack)(normalizedStack, distDir);
if (frames.length === 0) {
return {
kind: 'stack',
stack: stackTrace
};
}
const mappingResults = await mapFramesUsingBundler(frames, ctx);
const processedFrames = mappingResults.map((result, index)=>({
result,
originalFrame: frames[index]
})).map(({ result, originalFrame })=>{
var _originalStackFrame_file;
if (result.status === 'rejected') {
return {
kind: 'rejected',
frameText: formatStackFrame(originalFrame),
codeFrame: null
};
}
const { originalStackFrame, originalCodeFrame } = result.value;
if ((originalStackFrame == null ? void 0 : originalStackFrame.ignored) && ignore) {
return {
kind: 'ignored'
};
}
// should we apply this generally to dev overlay (dev overlay does not ignore chrome-extension://)
if (originalStackFrame == null ? void 0 : (_originalStackFrame_file = originalStackFrame.file) == null ? void 0 : _originalStackFrame_file.startsWith('chrome-extension://')) {
return {
kind: 'ignored'
};
}
return {
kind: 'success',
// invariant: if result is not rejected and not ignored, then original stack frame exists
// verifiable by tracing `getOriginalStackFrame`. The invariant exists because of bad types
frameText: formatStackFrame(originalStackFrame),
codeFrame: originalCodeFrame
};
});
const allIgnored = processedFrames.every((frame)=>frame.kind === 'ignored');
// we want to handle **all** ignored vs all/some rejected differently
// if all are ignored we should show no frames
// if all are rejected, we want to fallback to showing original stack frames
if (allIgnored) {
return {
kind: 'all-ignored'
};
}
const filteredFrames = processedFrames.filter((frame)=>frame.kind !== 'ignored');
if (filteredFrames.length === 0) {
return {
kind: 'stack',
stack: stackTrace
};
}
const stackOutput = filteredFrames.map((frame)=>frame.frameText).join('\n');
const firstFrameCode = (_filteredFrames_find = filteredFrames.find((frame)=>frame.codeFrame)) == null ? void 0 : _filteredFrames_find.codeFrame;
if (firstFrameCode) {
return {
kind: 'with-frame-code',
frameCode: firstFrameCode,
stack: stackOutput,
frames: filteredFrames
};
}
// i don't think this a real case, but good for exhaustion
return {
kind: 'mapped-stack',
stack: stackOutput,
frames: filteredFrames
};
} catch (error) {
return {
kind: 'stack',
stack: stackTrace
};
}
}
async function getSourceMappedStackFrames(stackTrace, ctx, distDir, ignore = true) {
const cacheKey = `sm_${stackTrace}-${ctx.bundler}-${ctx.isAppDirectory}-${ctx.isEdgeServer}-${ctx.isServer}-${distDir}-${ignore}`;
const cacheItem = cache.get(cacheKey);
if (cacheItem) {
return cacheItem;
}
const result = await getSourceMappedStackFramesInternal(stackTrace, ctx, distDir, ignore);
cache.set(cacheKey, result);
return result;
}
function formatStackFrame(frame) {
const functionName = frame.methodName || '<anonymous>';
const location = frame.file && frame.line1 ? `${frame.file}:${frame.line1}${frame.column1 ? `:${frame.column1}` : ''}` : frame.file || '<unknown>';
return ` at ${functionName} (${location})`;
}
const withLocation = async ({ original, stack }, ctx, distDir, config)=>{
if (typeof config === 'object' && config.showSourceLocation === false) {
return original;
}
if (!stack) {
return original;
}
const res = await getSourceMappedStackFrames(stack, ctx, distDir);
const location = getConsoleLocation(res);
if (!location) {
return original;
}
return [
...original,
(0, _picocolors.dim)(`(${location})`)
];
};
const getConsoleLocation = (mapped)=>{
if (mapped.kind !== 'mapped-stack' && mapped.kind !== 'with-frame-code') {
return null;
}
const first = mapped.frames.at(0);
if (!first) {
return null;
}
// we don't want to show the name of parent function (at <fn> thing in stack), just source location for minimal noise
const match = first.frameText.match(/\(([^)]+)\)/);
const locationText = match ? match[1] : first.frameText;
return locationText;
};
//# sourceMappingURL=source-map.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
import { type HmrMessageSentToBrowser } from './hot-reloader-types';
export interface ReactDebugChannelForBrowser {
readonly readable: ReadableStream<Uint8Array>;
}
export declare function connectReactDebugChannel(requestId: string, debugChannel: ReactDebugChannelForBrowser, sendToClient: (message: HmrMessageSentToBrowser) => void): void;
export declare function connectReactDebugChannelForHtmlRequest(htmlRequestId: string, sendToClient: (message: HmrMessageSentToBrowser) => void): void;
export declare function setReactDebugChannelForHtmlRequest(htmlRequestId: string, debugChannel: ReactDebugChannelForBrowser): void;
export declare function deleteReactDebugChannelForHtmlRequest(htmlRequestId: string): void;

View File

@@ -0,0 +1,87 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
connectReactDebugChannel: null,
connectReactDebugChannelForHtmlRequest: null,
deleteReactDebugChannelForHtmlRequest: null,
setReactDebugChannelForHtmlRequest: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
connectReactDebugChannel: function() {
return connectReactDebugChannel;
},
connectReactDebugChannelForHtmlRequest: function() {
return connectReactDebugChannelForHtmlRequest;
},
deleteReactDebugChannelForHtmlRequest: function() {
return deleteReactDebugChannelForHtmlRequest;
},
setReactDebugChannelForHtmlRequest: function() {
return setReactDebugChannelForHtmlRequest;
}
});
const _nodewebstreamshelper = require("../stream-utils/node-web-streams-helper");
const _hotreloadertypes = require("./hot-reloader-types");
const reactDebugChannelsByHtmlRequestId = new Map();
function connectReactDebugChannel(requestId, debugChannel, sendToClient) {
const reader = debugChannel.readable.pipeThrough(// We're sending the chunks in batches to reduce overhead in the browser.
(0, _nodewebstreamshelper.createBufferedTransformStream)({
maxBufferByteLength: 128 * 1024
})).getReader();
const stop = ()=>{
sendToClient({
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.REACT_DEBUG_CHUNK,
requestId,
chunk: null
});
};
const onError = (err)=>{
console.error(Object.defineProperty(new Error('React debug channel stream error', {
cause: err
}), "__NEXT_ERROR_CODE", {
value: "E810",
enumerable: false,
configurable: true
}));
stop();
};
const progress = (entry)=>{
if (entry.done) {
stop();
} else {
sendToClient({
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.REACT_DEBUG_CHUNK,
requestId,
chunk: entry.value
});
reader.read().then(progress, onError);
}
};
reader.read().then(progress, onError);
}
function connectReactDebugChannelForHtmlRequest(htmlRequestId, sendToClient) {
const debugChannel = reactDebugChannelsByHtmlRequestId.get(htmlRequestId);
if (!debugChannel) {
return;
}
reactDebugChannelsByHtmlRequestId.delete(htmlRequestId);
connectReactDebugChannel(htmlRequestId, debugChannel, sendToClient);
}
function setReactDebugChannelForHtmlRequest(htmlRequestId, debugChannel) {
// TODO: Clean up after a timeout, in case the client never connects, e.g.
// when CURL'ing the page, or loading the page with JavaScript disabled etc.
reactDebugChannelsByHtmlRequestId.set(htmlRequestId, debugChannel);
}
function deleteReactDebugChannelForHtmlRequest(htmlRequestId) {
reactDebugChannelsByHtmlRequestId.delete(htmlRequestId);
}
//# sourceMappingURL=debug-channel.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../src/server/dev/debug-channel.ts"],"sourcesContent":["import { createBufferedTransformStream } from '../stream-utils/node-web-streams-helper'\nimport {\n HMR_MESSAGE_SENT_TO_BROWSER,\n type HmrMessageSentToBrowser,\n} from './hot-reloader-types'\n\nexport interface ReactDebugChannelForBrowser {\n readonly readable: ReadableStream<Uint8Array>\n // Might also get a writable stream as return channel in the future.\n}\n\nconst reactDebugChannelsByHtmlRequestId = new Map<\n string,\n ReactDebugChannelForBrowser\n>()\n\nexport function connectReactDebugChannel(\n requestId: string,\n debugChannel: ReactDebugChannelForBrowser,\n sendToClient: (message: HmrMessageSentToBrowser) => void\n) {\n const reader = debugChannel.readable\n .pipeThrough(\n // We're sending the chunks in batches to reduce overhead in the browser.\n createBufferedTransformStream({ maxBufferByteLength: 128 * 1024 })\n )\n .getReader()\n\n const stop = () => {\n sendToClient({\n type: HMR_MESSAGE_SENT_TO_BROWSER.REACT_DEBUG_CHUNK,\n requestId,\n chunk: null,\n })\n }\n\n const onError = (err: unknown) => {\n console.error(new Error('React debug channel stream error', { cause: err }))\n stop()\n }\n\n const progress = (entry: ReadableStreamReadResult<Uint8Array>) => {\n if (entry.done) {\n stop()\n } else {\n sendToClient({\n type: HMR_MESSAGE_SENT_TO_BROWSER.REACT_DEBUG_CHUNK,\n requestId,\n chunk: entry.value,\n })\n\n reader.read().then(progress, onError)\n }\n }\n\n reader.read().then(progress, onError)\n}\n\nexport function connectReactDebugChannelForHtmlRequest(\n htmlRequestId: string,\n sendToClient: (message: HmrMessageSentToBrowser) => void\n) {\n const debugChannel = reactDebugChannelsByHtmlRequestId.get(htmlRequestId)\n\n if (!debugChannel) {\n return\n }\n\n reactDebugChannelsByHtmlRequestId.delete(htmlRequestId)\n\n connectReactDebugChannel(htmlRequestId, debugChannel, sendToClient)\n}\n\nexport function setReactDebugChannelForHtmlRequest(\n htmlRequestId: string,\n debugChannel: ReactDebugChannelForBrowser\n) {\n // TODO: Clean up after a timeout, in case the client never connects, e.g.\n // when CURL'ing the page, or loading the page with JavaScript disabled etc.\n reactDebugChannelsByHtmlRequestId.set(htmlRequestId, debugChannel)\n}\n\nexport function deleteReactDebugChannelForHtmlRequest(htmlRequestId: string) {\n reactDebugChannelsByHtmlRequestId.delete(htmlRequestId)\n}\n"],"names":["connectReactDebugChannel","connectReactDebugChannelForHtmlRequest","deleteReactDebugChannelForHtmlRequest","setReactDebugChannelForHtmlRequest","reactDebugChannelsByHtmlRequestId","Map","requestId","debugChannel","sendToClient","reader","readable","pipeThrough","createBufferedTransformStream","maxBufferByteLength","getReader","stop","type","HMR_MESSAGE_SENT_TO_BROWSER","REACT_DEBUG_CHUNK","chunk","onError","err","console","error","Error","cause","progress","entry","done","value","read","then","htmlRequestId","get","delete","set"],"mappings":";;;;;;;;;;;;;;;;;IAgBgBA,wBAAwB;eAAxBA;;IA0CAC,sCAAsC;eAAtCA;;IAwBAC,qCAAqC;eAArCA;;IATAC,kCAAkC;eAAlCA;;;sCAzE8B;kCAIvC;AAOP,MAAMC,oCAAoC,IAAIC;AAKvC,SAASL,yBACdM,SAAiB,EACjBC,YAAyC,EACzCC,YAAwD;IAExD,MAAMC,SAASF,aAAaG,QAAQ,CACjCC,WAAW,CACV,yEAAyE;IACzEC,IAAAA,mDAA6B,EAAC;QAAEC,qBAAqB,MAAM;IAAK,IAEjEC,SAAS;IAEZ,MAAMC,OAAO;QACXP,aAAa;YACXQ,MAAMC,6CAA2B,CAACC,iBAAiB;YACnDZ;YACAa,OAAO;QACT;IACF;IAEA,MAAMC,UAAU,CAACC;QACfC,QAAQC,KAAK,CAAC,qBAA6D,CAA7D,IAAIC,MAAM,oCAAoC;YAAEC,OAAOJ;QAAI,IAA3D,qBAAA;mBAAA;wBAAA;0BAAA;QAA4D;QAC1EN;IACF;IAEA,MAAMW,WAAW,CAACC;QAChB,IAAIA,MAAMC,IAAI,EAAE;YACdb;QACF,OAAO;YACLP,aAAa;gBACXQ,MAAMC,6CAA2B,CAACC,iBAAiB;gBACnDZ;gBACAa,OAAOQ,MAAME,KAAK;YACpB;YAEApB,OAAOqB,IAAI,GAAGC,IAAI,CAACL,UAAUN;QAC/B;IACF;IAEAX,OAAOqB,IAAI,GAAGC,IAAI,CAACL,UAAUN;AAC/B;AAEO,SAASnB,uCACd+B,aAAqB,EACrBxB,YAAwD;IAExD,MAAMD,eAAeH,kCAAkC6B,GAAG,CAACD;IAE3D,IAAI,CAACzB,cAAc;QACjB;IACF;IAEAH,kCAAkC8B,MAAM,CAACF;IAEzChC,yBAAyBgC,eAAezB,cAAcC;AACxD;AAEO,SAASL,mCACd6B,aAAqB,EACrBzB,YAAyC;IAEzC,0EAA0E;IAC1E,4EAA4E;IAC5EH,kCAAkC+B,GAAG,CAACH,eAAezB;AACvD;AAEO,SAASL,sCAAsC8B,aAAqB;IACzE5B,kCAAkC8B,MAAM,CAACF;AAC3C","ignoreList":[0]}

View File

@@ -0,0 +1,4 @@
export type DevIndicatorServerState = typeof devIndicatorServerState;
export declare const devIndicatorServerState: {
disabledUntil: number;
};

View File

@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "devIndicatorServerState", {
enumerable: true,
get: function() {
return devIndicatorServerState;
}
});
const devIndicatorServerState = {
disabledUntil: 0
};
//# sourceMappingURL=dev-indicator-server-state.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../src/server/dev/dev-indicator-server-state.ts"],"sourcesContent":["export type DevIndicatorServerState = typeof devIndicatorServerState\n\nexport const devIndicatorServerState = {\n disabledUntil: 0,\n}\n"],"names":["devIndicatorServerState","disabledUntil"],"mappings":";;;;+BAEaA;;;eAAAA;;;AAAN,MAAMA,0BAA0B;IACrCC,eAAe;AACjB","ignoreList":[0]}

View File

@@ -0,0 +1,2 @@
import type { RawSourceMap } from 'next/dist/compiled/source-map08';
export declare function getSourceMapFromFile(filename: string): Promise<RawSourceMap | undefined>;

View File

@@ -0,0 +1,100 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "getSourceMapFromFile", {
enumerable: true,
get: function() {
return getSourceMapFromFile;
}
});
const _promises = /*#__PURE__*/ _interop_require_default(require("fs/promises"));
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _url = /*#__PURE__*/ _interop_require_default(require("url"));
const _datauritobuffer = /*#__PURE__*/ _interop_require_default(require("next/dist/compiled/data-uri-to-buffer"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function getSourceMapUrl(fileContents) {
const regex = /\/\/[#@] ?sourceMappingURL=([^\s'"]+)\s*$/gm;
let match = null;
for(;;){
let next = regex.exec(fileContents);
if (next == null) {
break;
}
match = next;
}
if (!(match && match[1])) {
return null;
}
return match[1].toString();
}
async function getSourceMapFromFile(filename) {
filename = filename.startsWith('file://') ? _url.default.fileURLToPath(filename) : filename;
let fileContents;
try {
fileContents = await _promises.default.readFile(filename, 'utf-8');
} catch (error) {
throw Object.defineProperty(new Error(`Failed to read file contents of ${filename}.`, {
cause: error
}), "__NEXT_ERROR_CODE", {
value: "E466",
enumerable: false,
configurable: true
});
}
const sourceUrl = getSourceMapUrl(fileContents);
if (!sourceUrl) {
return undefined;
}
if (sourceUrl.startsWith('data:')) {
let buffer;
try {
buffer = (0, _datauritobuffer.default)(sourceUrl);
} catch (error) {
throw Object.defineProperty(new Error(`Failed to parse source map URL for ${filename}.`, {
cause: error
}), "__NEXT_ERROR_CODE", {
value: "E199",
enumerable: false,
configurable: true
});
}
if (buffer.type !== 'application/json') {
throw Object.defineProperty(new Error(`Unknown source map type for ${filename}: ${buffer.typeFull}.`), "__NEXT_ERROR_CODE", {
value: "E113",
enumerable: false,
configurable: true
});
}
try {
return JSON.parse(buffer.toString());
} catch (error) {
throw Object.defineProperty(new Error(`Failed to parse source map for ${filename}.`, {
cause: error
}), "__NEXT_ERROR_CODE", {
value: "E318",
enumerable: false,
configurable: true
});
}
}
const sourceMapFilename = _path.default.resolve(_path.default.dirname(filename), decodeURIComponent(sourceUrl));
try {
const sourceMapContents = await _promises.default.readFile(sourceMapFilename, 'utf-8');
return JSON.parse(sourceMapContents.toString());
} catch (error) {
throw Object.defineProperty(new Error(`Failed to parse source map ${sourceMapFilename}.`, {
cause: error
}), "__NEXT_ERROR_CODE", {
value: "E220",
enumerable: false,
configurable: true
});
}
}
//# sourceMappingURL=get-source-map-from-file.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../src/server/dev/get-source-map-from-file.ts"],"sourcesContent":["import fs from 'fs/promises'\nimport path from 'path'\nimport url from 'url'\nimport type { RawSourceMap } from 'next/dist/compiled/source-map08'\nimport dataUriToBuffer from 'next/dist/compiled/data-uri-to-buffer'\n\nfunction getSourceMapUrl(fileContents: string): string | null {\n const regex = /\\/\\/[#@] ?sourceMappingURL=([^\\s'\"]+)\\s*$/gm\n let match = null\n for (;;) {\n let next = regex.exec(fileContents)\n if (next == null) {\n break\n }\n match = next\n }\n if (!(match && match[1])) {\n return null\n }\n return match[1].toString()\n}\n\nexport async function getSourceMapFromFile(\n filename: string\n): Promise<RawSourceMap | undefined> {\n filename = filename.startsWith('file://')\n ? url.fileURLToPath(filename)\n : filename\n\n let fileContents: string\n\n try {\n fileContents = await fs.readFile(filename, 'utf-8')\n } catch (error) {\n throw new Error(`Failed to read file contents of ${filename}.`, {\n cause: error,\n })\n }\n\n const sourceUrl = getSourceMapUrl(fileContents)\n\n if (!sourceUrl) {\n return undefined\n }\n\n if (sourceUrl.startsWith('data:')) {\n let buffer: dataUriToBuffer.MimeBuffer\n\n try {\n buffer = dataUriToBuffer(sourceUrl)\n } catch (error) {\n throw new Error(`Failed to parse source map URL for ${filename}.`, {\n cause: error,\n })\n }\n\n if (buffer.type !== 'application/json') {\n throw new Error(\n `Unknown source map type for ${filename}: ${buffer.typeFull}.`\n )\n }\n\n try {\n return JSON.parse(buffer.toString())\n } catch (error) {\n throw new Error(`Failed to parse source map for ${filename}.`, {\n cause: error,\n })\n }\n }\n\n const sourceMapFilename = path.resolve(\n path.dirname(filename),\n decodeURIComponent(sourceUrl)\n )\n\n try {\n const sourceMapContents = await fs.readFile(sourceMapFilename, 'utf-8')\n\n return JSON.parse(sourceMapContents.toString())\n } catch (error) {\n throw new Error(`Failed to parse source map ${sourceMapFilename}.`, {\n cause: error,\n })\n }\n}\n"],"names":["getSourceMapFromFile","getSourceMapUrl","fileContents","regex","match","next","exec","toString","filename","startsWith","url","fileURLToPath","fs","readFile","error","Error","cause","sourceUrl","undefined","buffer","dataUriToBuffer","type","typeFull","JSON","parse","sourceMapFilename","path","resolve","dirname","decodeURIComponent","sourceMapContents"],"mappings":";;;;+BAsBsBA;;;eAAAA;;;iEAtBP;6DACE;4DACD;wEAEY;;;;;;AAE5B,SAASC,gBAAgBC,YAAoB;IAC3C,MAAMC,QAAQ;IACd,IAAIC,QAAQ;IACZ,OAAS;QACP,IAAIC,OAAOF,MAAMG,IAAI,CAACJ;QACtB,IAAIG,QAAQ,MAAM;YAChB;QACF;QACAD,QAAQC;IACV;IACA,IAAI,CAAED,CAAAA,SAASA,KAAK,CAAC,EAAE,AAAD,GAAI;QACxB,OAAO;IACT;IACA,OAAOA,KAAK,CAAC,EAAE,CAACG,QAAQ;AAC1B;AAEO,eAAeP,qBACpBQ,QAAgB;IAEhBA,WAAWA,SAASC,UAAU,CAAC,aAC3BC,YAAG,CAACC,aAAa,CAACH,YAClBA;IAEJ,IAAIN;IAEJ,IAAI;QACFA,eAAe,MAAMU,iBAAE,CAACC,QAAQ,CAACL,UAAU;IAC7C,EAAE,OAAOM,OAAO;QACd,MAAM,qBAEJ,CAFI,IAAIC,MAAM,CAAC,gCAAgC,EAAEP,SAAS,CAAC,CAAC,EAAE;YAC9DQ,OAAOF;QACT,IAFM,qBAAA;mBAAA;wBAAA;0BAAA;QAEL;IACH;IAEA,MAAMG,YAAYhB,gBAAgBC;IAElC,IAAI,CAACe,WAAW;QACd,OAAOC;IACT;IAEA,IAAID,UAAUR,UAAU,CAAC,UAAU;QACjC,IAAIU;QAEJ,IAAI;YACFA,SAASC,IAAAA,wBAAe,EAACH;QAC3B,EAAE,OAAOH,OAAO;YACd,MAAM,qBAEJ,CAFI,IAAIC,MAAM,CAAC,mCAAmC,EAAEP,SAAS,CAAC,CAAC,EAAE;gBACjEQ,OAAOF;YACT,IAFM,qBAAA;uBAAA;4BAAA;8BAAA;YAEL;QACH;QAEA,IAAIK,OAAOE,IAAI,KAAK,oBAAoB;YACtC,MAAM,qBAEL,CAFK,IAAIN,MACR,CAAC,4BAA4B,EAAEP,SAAS,EAAE,EAAEW,OAAOG,QAAQ,CAAC,CAAC,CAAC,GAD1D,qBAAA;uBAAA;4BAAA;8BAAA;YAEN;QACF;QAEA,IAAI;YACF,OAAOC,KAAKC,KAAK,CAACL,OAAOZ,QAAQ;QACnC,EAAE,OAAOO,OAAO;YACd,MAAM,qBAEJ,CAFI,IAAIC,MAAM,CAAC,+BAA+B,EAAEP,SAAS,CAAC,CAAC,EAAE;gBAC7DQ,OAAOF;YACT,IAFM,qBAAA;uBAAA;4BAAA;8BAAA;YAEL;QACH;IACF;IAEA,MAAMW,oBAAoBC,aAAI,CAACC,OAAO,CACpCD,aAAI,CAACE,OAAO,CAACpB,WACbqB,mBAAmBZ;IAGrB,IAAI;QACF,MAAMa,oBAAoB,MAAMlB,iBAAE,CAACC,QAAQ,CAACY,mBAAmB;QAE/D,OAAOF,KAAKC,KAAK,CAACM,kBAAkBvB,QAAQ;IAC9C,EAAE,OAAOO,OAAO;QACd,MAAM,qBAEJ,CAFI,IAAIC,MAAM,CAAC,2BAA2B,EAAEU,kBAAkB,CAAC,CAAC,EAAE;YAClET,OAAOF;QACT,IAFM,qBAAA;mBAAA;wBAAA;0BAAA;QAEL;IACH;AACF","ignoreList":[0]}

View File

@@ -0,0 +1,42 @@
import type { webpack } from 'next/dist/compiled/webpack/webpack';
import type ws from 'next/dist/compiled/ws';
import type { DevToolsConfig } from '../../next-devtools/dev-overlay/shared';
import type { VersionInfo } from './parse-version-info';
import type { HmrMessageSentToBrowser } from './hot-reloader-types';
import type { NextConfigComplete } from '../config-shared';
export declare class WebpackHotMiddleware {
private versionInfo;
private devtoolsFrontendUrl;
private config;
private devToolsConfig;
private clientsWithoutHtmlRequestId;
private clientsByHtmlRequestId;
private closed;
private clientLatestStats;
private middlewareLatestStats;
private serverLatestStats;
constructor(compilers: webpack.Compiler[], versionInfo: VersionInfo, devtoolsFrontendUrl: string | undefined, config: NextConfigComplete, devToolsConfig: DevToolsConfig);
onClientInvalid: () => void;
onClientDone: (statsResult: webpack.Stats) => void;
onServerInvalid: () => void;
onServerDone: (statsResult: webpack.Stats) => void;
onEdgeServerInvalid: () => void;
onEdgeServerDone: (statsResult: webpack.Stats) => void;
updateDevToolsConfig(newConfig: DevToolsConfig): void;
/**
* To sync we use the most recent stats but also we append middleware
* errors. This is because it is possible that middleware fails to compile
* and we still want to show the client overlay with the error while
* the error page should be rendered just fine.
*/
onHMR: (client: ws, htmlRequestId: string | null) => void;
publishStats: (statsResult: webpack.Stats) => void;
getClient: (htmlRequestId: string) => ws | undefined;
publishToClient: (client: ws, message: HmrMessageSentToBrowser) => void;
publish: (message: HmrMessageSentToBrowser) => void;
publishToLegacyClients: (message: HmrMessageSentToBrowser) => void;
close: () => void;
deleteClient: (client: ws, htmlRequestId: string | null) => void;
hasClients: () => boolean;
getClientCount: () => number;
}

View File

@@ -0,0 +1,274 @@
// Based on https://github.com/webpack-contrib/webpack-hot-middleware/blob/9708d781ae0e46179cf8ea1a94719de4679aaf53/middleware.js
// Included License below
// Copyright JS Foundation and other contributors
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// 'Software'), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "WebpackHotMiddleware", {
enumerable: true,
get: function() {
return WebpackHotMiddleware;
}
});
const _utils = require("../../build/utils");
const _hotreloadertypes = require("./hot-reloader-types");
const _devindicatorserverstate = require("./dev-indicator-server-state");
const _messages = require("./messages");
function isMiddlewareStats(stats) {
for (const key of stats.compilation.entrypoints.keys()){
if ((0, _utils.isMiddlewareFilename)(key)) {
return true;
}
}
return false;
}
function statsToJson(stats) {
if (!stats) return {};
return stats.toJson({
all: false,
errors: true,
hash: true,
warnings: true
});
}
function getStatsForSyncEvent(clientStats, serverStats) {
if (!clientStats) return serverStats == null ? void 0 : serverStats.stats;
if (!serverStats) return clientStats == null ? void 0 : clientStats.stats;
// Prefer the server compiler stats if it has errors.
// Otherwise we may end up in a state where the client compilation is the latest but without errors.
// This causes the error overlay to not display the build error.
if (serverStats.stats.hasErrors()) {
return serverStats.stats;
}
// Return the latest stats
return serverStats.ts > clientStats.ts ? serverStats.stats : clientStats.stats;
}
class WebpackHotMiddleware {
constructor(compilers, versionInfo, devtoolsFrontendUrl, config, devToolsConfig){
this.versionInfo = versionInfo;
this.devtoolsFrontendUrl = devtoolsFrontendUrl;
this.config = config;
this.devToolsConfig = devToolsConfig;
this.clientsWithoutHtmlRequestId = new Set();
this.clientsByHtmlRequestId = new Map();
this.closed = false;
this.clientLatestStats = null;
this.middlewareLatestStats = null;
this.serverLatestStats = null;
this.onClientInvalid = ()=>{
var _this_serverLatestStats;
if (this.closed || ((_this_serverLatestStats = this.serverLatestStats) == null ? void 0 : _this_serverLatestStats.stats.hasErrors())) return;
this.publish({
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.BUILDING
});
};
this.onClientDone = (statsResult)=>{
var _this_serverLatestStats;
this.clientLatestStats = {
ts: Date.now(),
stats: statsResult
};
if (this.closed || ((_this_serverLatestStats = this.serverLatestStats) == null ? void 0 : _this_serverLatestStats.stats.hasErrors())) return;
this.publishStats(statsResult);
};
this.onServerInvalid = ()=>{
var _this_serverLatestStats, _this_clientLatestStats;
if (!((_this_serverLatestStats = this.serverLatestStats) == null ? void 0 : _this_serverLatestStats.stats.hasErrors())) return;
this.serverLatestStats = null;
if ((_this_clientLatestStats = this.clientLatestStats) == null ? void 0 : _this_clientLatestStats.stats) {
this.publishStats(this.clientLatestStats.stats);
}
};
this.onServerDone = (statsResult)=>{
if (this.closed) return;
if (statsResult.hasErrors()) {
this.serverLatestStats = {
ts: Date.now(),
stats: statsResult
};
this.publishStats(statsResult);
}
};
this.onEdgeServerInvalid = ()=>{
var _this_middlewareLatestStats, _this_clientLatestStats;
if (!((_this_middlewareLatestStats = this.middlewareLatestStats) == null ? void 0 : _this_middlewareLatestStats.stats.hasErrors())) return;
this.middlewareLatestStats = null;
if ((_this_clientLatestStats = this.clientLatestStats) == null ? void 0 : _this_clientLatestStats.stats) {
this.publishStats(this.clientLatestStats.stats);
}
};
this.onEdgeServerDone = (statsResult)=>{
if (this.closed) return;
if (!isMiddlewareStats(statsResult)) {
this.onServerInvalid();
this.onServerDone(statsResult);
}
if (statsResult.hasErrors()) {
this.middlewareLatestStats = {
ts: Date.now(),
stats: statsResult
};
this.publishStats(statsResult);
}
};
this./**
* To sync we use the most recent stats but also we append middleware
* errors. This is because it is possible that middleware fails to compile
* and we still want to show the client overlay with the error while
* the error page should be rendered just fine.
*/ onHMR = (client, htmlRequestId)=>{
if (this.closed) return;
if (htmlRequestId) {
this.clientsByHtmlRequestId.set(htmlRequestId, client);
} else {
this.clientsWithoutHtmlRequestId.add(client);
}
client.addEventListener('close', ()=>{
if (htmlRequestId) {
this.clientsByHtmlRequestId.delete(htmlRequestId);
} else {
this.clientsWithoutHtmlRequestId.delete(client);
}
});
const syncStats = getStatsForSyncEvent(this.clientLatestStats, this.serverLatestStats);
if (syncStats) {
var _this_middlewareLatestStats;
const stats = statsToJson(syncStats);
const middlewareStats = statsToJson((_this_middlewareLatestStats = this.middlewareLatestStats) == null ? void 0 : _this_middlewareLatestStats.stats);
if (_devindicatorserverstate.devIndicatorServerState.disabledUntil < Date.now()) {
_devindicatorserverstate.devIndicatorServerState.disabledUntil = 0;
}
this.publish({
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.SYNC,
hash: stats.hash,
errors: [
...stats.errors || [],
...middlewareStats.errors || []
],
warnings: [
...stats.warnings || [],
...middlewareStats.warnings || []
],
versionInfo: this.versionInfo,
debug: {
devtoolsFrontendUrl: this.devtoolsFrontendUrl
},
devIndicator: _devindicatorserverstate.devIndicatorServerState,
devToolsConfig: this.devToolsConfig
});
}
};
this.publishStats = (statsResult)=>{
const stats = statsResult.toJson({
all: false,
hash: true,
warnings: true,
errors: true,
moduleTrace: true
});
this.publish({
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.BUILT,
hash: stats.hash,
warnings: stats.warnings || [],
errors: stats.errors || []
});
};
this.getClient = (htmlRequestId)=>{
return this.clientsByHtmlRequestId.get(htmlRequestId);
};
this.publishToClient = (client, message)=>{
if (this.closed) {
return;
}
const data = typeof message.type === 'number' ? (0, _messages.createBinaryHmrMessageData)(message) : JSON.stringify(message);
client.send(data);
};
this.publish = (message)=>{
if (this.closed) {
return;
}
for (const wsClient of [
...this.clientsWithoutHtmlRequestId,
...this.clientsByHtmlRequestId.values()
]){
this.publishToClient(wsClient, message);
}
};
this.publishToLegacyClients = (message)=>{
if (this.closed) {
return;
}
// Clients with a request ID are inferred App Router clients. If Cache
// Components is not enabled, we consider those legacy clients. Pages
// Router clients are also considered legacy clients. TODO: Maybe mark
// clients as App Router / Pages Router clients explicitly, instead of
// inferring it from the presence of a request ID.
if (!this.config.cacheComponents) {
for (const wsClient of this.clientsByHtmlRequestId.values()){
this.publishToClient(wsClient, message);
}
}
for (const wsClient of this.clientsWithoutHtmlRequestId){
this.publishToClient(wsClient, message);
}
};
this.close = ()=>{
if (this.closed) {
return;
}
// Can't remove compiler plugins, so we just set a flag and noop if closed
// https://github.com/webpack/tapable/issues/32#issuecomment-350644466
this.closed = true;
for (const wsClient of [
...this.clientsWithoutHtmlRequestId,
...this.clientsByHtmlRequestId.values()
]){
// it's okay to not cleanly close these websocket connections, this is dev
wsClient.terminate();
}
this.clientsWithoutHtmlRequestId.clear();
this.clientsByHtmlRequestId.clear();
};
this.deleteClient = (client, htmlRequestId)=>{
if (htmlRequestId) {
this.clientsByHtmlRequestId.delete(htmlRequestId);
} else {
this.clientsWithoutHtmlRequestId.delete(client);
}
};
this.hasClients = ()=>{
return this.clientsWithoutHtmlRequestId.size + this.clientsByHtmlRequestId.size > 0;
};
this.getClientCount = ()=>{
return this.clientsWithoutHtmlRequestId.size + this.clientsByHtmlRequestId.size;
};
compilers[0].hooks.invalid.tap('webpack-hot-middleware', this.onClientInvalid);
compilers[0].hooks.done.tap('webpack-hot-middleware', this.onClientDone);
compilers[1].hooks.invalid.tap('webpack-hot-middleware', this.onServerInvalid);
compilers[1].hooks.done.tap('webpack-hot-middleware', this.onServerDone);
compilers[2].hooks.done.tap('webpack-hot-middleware', this.onEdgeServerDone);
compilers[2].hooks.invalid.tap('webpack-hot-middleware', this.onEdgeServerInvalid);
}
updateDevToolsConfig(newConfig) {
this.devToolsConfig = newConfig;
}
}
//# sourceMappingURL=hot-middleware.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,36 @@
import HotReloaderWebpack from './hot-reloader-webpack';
import type { RouteDefinition } from '../route-definitions/route-definition';
import type { MultiCompiler } from 'webpack';
/**
* Rspack Persistent Cache Strategy for Next.js Development
*
* Rspack's persistent caching differs from Webpack in how it manages module graphs.
* While Webpack incrementally updates modules, Rspack operates on complete module
* graph snapshots for cache restoration.
*
* Problem:
* - Next.js dev server starts with no page modules in the initial entry points
* - When Rspack restores from persistent cache, it finds no modules and purges
* the entire module graph
* - Later page requests find no cached module information, preventing cache reuse
*
* Solution:
* - Track successfully built page entries after each compilation
* - Restore these entries on dev server restart to maintain module graph continuity
* - This ensures previously compiled pages can leverage persistent cache for faster builds
*/
export default class HotReloaderRspack extends HotReloaderWebpack {
private builtEntriesCachePath?;
private isClientCacheEnabled;
private isServerCacheEnabled;
private isEdgeServerCacheEnabled;
afterCompile(multiCompiler: MultiCompiler): Promise<void>;
ensurePage({ page, clientOnly, appPaths, definition, isApp, url, }: {
page: string;
clientOnly: boolean;
appPaths?: ReadonlyArray<string> | null;
isApp?: boolean;
definition?: RouteDefinition;
url?: string;
}): Promise<void>;
}

View File

@@ -0,0 +1,171 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, /**
* Rspack Persistent Cache Strategy for Next.js Development
*
* Rspack's persistent caching differs from Webpack in how it manages module graphs.
* While Webpack incrementally updates modules, Rspack operates on complete module
* graph snapshots for cache restoration.
*
* Problem:
* - Next.js dev server starts with no page modules in the initial entry points
* - When Rspack restores from persistent cache, it finds no modules and purges
* the entire module graph
* - Later page requests find no cached module information, preventing cache reuse
*
* Solution:
* - Track successfully built page entries after each compilation
* - Restore these entries on dev server restart to maintain module graph continuity
* - This ensures previously compiled pages can leverage persistent cache for faster builds
*/ "default", {
enumerable: true,
get: function() {
return HotReloaderRspack;
}
});
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _promises = /*#__PURE__*/ _interop_require_default(require("fs/promises"));
const _crypto = require("crypto");
const _hotreloaderwebpack = /*#__PURE__*/ _interop_require_default(require("./hot-reloader-webpack"));
const _ondemandentryhandler = require("./on-demand-entry-handler");
const _constants = require("../../shared/lib/constants");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
class HotReloaderRspack extends _hotreloaderwebpack.default {
async afterCompile(multiCompiler) {
// Always initialize the fallback error watcher for Rspack.
// Rspack may restore/retain the previous build's error state, so without this
// a page that previously failed to build might not be rebuilt on the next request.
await super.buildFallbackError();
const rspackStartSpan = this.hotReloaderSpan.traceChild('rspack-after-compile');
await rspackStartSpan.traceAsyncFn(async ()=>{
const hash = (0, _crypto.createHash)('sha1');
multiCompiler.compilers.forEach((compiler)=>{
const cache = compiler.options.cache;
if (typeof cache === 'object' && 'version' in cache && cache.version) {
hash.update(cache.version);
if (compiler.name === _constants.COMPILER_NAMES.client) {
this.isClientCacheEnabled = true;
} else if (compiler.name === _constants.COMPILER_NAMES.server) {
this.isServerCacheEnabled = true;
} else if (compiler.name === _constants.COMPILER_NAMES.edgeServer) {
this.isEdgeServerCacheEnabled = true;
}
} else {
hash.update('-');
}
return undefined;
});
this.builtEntriesCachePath = _path.default.join(this.distDir, 'cache', 'rspack', hash.digest('hex').substring(0, 16), 'built-entries.json');
const hasBuiltEntriesCache = await _promises.default.access(this.builtEntriesCachePath).then(()=>true, ()=>false);
if (hasBuiltEntriesCache) {
try {
const builtEntries = JSON.parse(await _promises.default.readFile(this.builtEntriesCachePath, 'utf-8') || '{}');
await Promise.all(Object.keys(builtEntries).map(async (entryKey)=>{
const entryData = builtEntries[entryKey];
const isEntry = entryData.type === _ondemandentryhandler.EntryTypes.ENTRY;
const isChildEntry = entryData.type === _ondemandentryhandler.EntryTypes.CHILD_ENTRY;
// Check if the page was removed or disposed and remove it
if (isEntry) {
const pageExists = !entryData.dispose && await _promises.default.access(entryData.absolutePagePath).then(()=>true, ()=>false);
if (!pageExists) {
delete builtEntries[entryKey];
return;
} else if (!('hash' in builtEntries[entryKey]) || builtEntries[entryKey].hash !== await calculateFileHash(entryData.absolutePagePath)) {
delete builtEntries[entryKey];
return;
}
}
// For child entries, if it has an entry file and it's gone, remove it
if (isChildEntry) {
if (entryData.absoluteEntryFilePath) {
const pageExists = !entryData.dispose && await _promises.default.access(entryData.absoluteEntryFilePath).then(()=>true, ()=>false);
if (!pageExists) {
delete builtEntries[entryKey];
return;
} else {
if (!('hash' in builtEntries[entryKey]) || builtEntries[entryKey].hash !== await calculateFileHash(entryData.absoluteEntryFilePath)) {
delete builtEntries[entryKey];
return;
}
}
}
}
}));
Object.assign((0, _ondemandentryhandler.getEntries)(multiCompiler.outputPath), builtEntries);
} catch (error) {
console.error('Rspack failed to read built entries cache: ', error);
}
}
});
}
async ensurePage({ page, clientOnly, appPaths, definition, isApp, url }) {
await super.ensurePage({
page,
clientOnly,
appPaths,
definition,
isApp,
url
});
const entries = (0, _ondemandentryhandler.getEntries)(this.multiCompiler.outputPath);
const builtEntries = {};
await Promise.all(Object.keys(entries).map(async (entryName)=>{
const entry = entries[entryName];
if (entry.status !== _ondemandentryhandler.BUILT) return;
const result = /^(client|server|edge-server)@(app|pages|root)@(.*)/g.exec(entryName);
const [, key /* pageType */ , , ] = result// this match should always happen
;
if (key === 'client' && !this.isClientCacheEnabled) return;
if (key === 'server' && !this.isServerCacheEnabled) return;
if (key === 'edge-server' && !this.isEdgeServerCacheEnabled) return;
// TODO: Rspack does not store middleware entries in persistent cache, causing
// test/integration/middleware-src/test/index.test.ts to fail. This is a temporary
// workaround to skip middleware entry caching until Rspack properly supports it.
if (page === '/middleware') {
return;
}
let hash;
if (entry.type === _ondemandentryhandler.EntryTypes.ENTRY) {
hash = await calculateFileHash(entry.absolutePagePath);
} else if (entry.absoluteEntryFilePath) {
hash = await calculateFileHash(entry.absoluteEntryFilePath);
}
if (!hash) {
return;
}
builtEntries[entryName] = entry;
builtEntries[entryName].hash = hash;
}));
const hasBuitEntriesCache = await _promises.default.access(this.builtEntriesCachePath).then(()=>true, ()=>false);
try {
if (!hasBuitEntriesCache) {
await _promises.default.mkdir(_path.default.dirname(this.builtEntriesCachePath), {
recursive: true
});
}
await _promises.default.writeFile(this.builtEntriesCachePath, JSON.stringify(builtEntries, null, 2));
} catch (error) {
console.error('Rspack failed to write built entries cache: ', error);
}
}
constructor(...args){
super(...args), this.isClientCacheEnabled = false, this.isServerCacheEnabled = false, this.isEdgeServerCacheEnabled = false;
}
}
async function calculateFileHash(filePath, algorithm = 'sha256') {
if (!await _promises.default.access(filePath).then(()=>true, ()=>false)) {
return;
}
const fileBuffer = await _promises.default.readFile(filePath);
const hash = (0, _crypto.createHash)(algorithm);
hash.update(fileBuffer);
return hash.digest('hex');
}
//# sourceMappingURL=hot-reloader-rspack.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
import { type VersionInfo } from './parse-version-info';
export declare const matchNextPageBundleRequest: import("../../shared/lib/router/utils/path-match").PatchMatcher;
export declare function getVersionInfo(): Promise<VersionInfo>;

View File

@@ -0,0 +1,56 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
getVersionInfo: null,
matchNextPageBundleRequest: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
getVersionInfo: function() {
return getVersionInfo;
},
matchNextPageBundleRequest: function() {
return matchNextPageBundleRequest;
}
});
const _pathmatch = require("../../shared/lib/router/utils/path-match");
const _parseversioninfo = require("./parse-version-info");
const matchNextPageBundleRequest = (0, _pathmatch.getPathMatch)('/_next/static/chunks/pages/:path*.js(\\.map|)');
async function getVersionInfo() {
let installed = '0.0.0';
try {
installed = require('next/package.json').version;
let res;
try {
// use NPM registry regardless user using Yarn
res = await fetch('https://registry.npmjs.org/-/package/next/dist-tags');
} catch {
// ignore fetch errors
}
if (!res || !res.ok) return {
installed,
staleness: 'unknown'
};
const { latest, canary } = await res.json();
return (0, _parseversioninfo.parseVersionInfo)({
installed,
latest,
canary
});
} catch (e) {
console.error(e);
return {
installed,
staleness: 'unknown'
};
}
}
//# sourceMappingURL=hot-reloader-shared-utils.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../src/server/dev/hot-reloader-shared-utils.ts"],"sourcesContent":["import { getPathMatch } from '../../shared/lib/router/utils/path-match'\nimport { parseVersionInfo, type VersionInfo } from './parse-version-info'\n\nexport const matchNextPageBundleRequest = getPathMatch(\n '/_next/static/chunks/pages/:path*.js(\\\\.map|)'\n)\nexport async function getVersionInfo(): Promise<VersionInfo> {\n let installed = '0.0.0'\n\n try {\n installed = require('next/package.json').version\n\n let res\n\n try {\n // use NPM registry regardless user using Yarn\n res = await fetch('https://registry.npmjs.org/-/package/next/dist-tags')\n } catch {\n // ignore fetch errors\n }\n\n if (!res || !res.ok) return { installed, staleness: 'unknown' }\n\n const { latest, canary } = await res.json()\n\n return parseVersionInfo({ installed, latest, canary })\n } catch (e: any) {\n console.error(e)\n return { installed, staleness: 'unknown' }\n }\n}\n"],"names":["getVersionInfo","matchNextPageBundleRequest","getPathMatch","installed","require","version","res","fetch","ok","staleness","latest","canary","json","parseVersionInfo","e","console","error"],"mappings":";;;;;;;;;;;;;;;IAMsBA,cAAc;eAAdA;;IAHTC,0BAA0B;eAA1BA;;;2BAHgB;kCACsB;AAE5C,MAAMA,6BAA6BC,IAAAA,uBAAY,EACpD;AAEK,eAAeF;IACpB,IAAIG,YAAY;IAEhB,IAAI;QACFA,YAAYC,QAAQ,qBAAqBC,OAAO;QAEhD,IAAIC;QAEJ,IAAI;YACF,8CAA8C;YAC9CA,MAAM,MAAMC,MAAM;QACpB,EAAE,OAAM;QACN,sBAAsB;QACxB;QAEA,IAAI,CAACD,OAAO,CAACA,IAAIE,EAAE,EAAE,OAAO;YAAEL;YAAWM,WAAW;QAAU;QAE9D,MAAM,EAAEC,MAAM,EAAEC,MAAM,EAAE,GAAG,MAAML,IAAIM,IAAI;QAEzC,OAAOC,IAAAA,kCAAgB,EAAC;YAAEV;YAAWO;YAAQC;QAAO;IACtD,EAAE,OAAOG,GAAQ;QACfC,QAAQC,KAAK,CAACF;QACd,OAAO;YAAEX;YAAWM,WAAW;QAAU;IAC3C;AACF","ignoreList":[0]}

View File

@@ -0,0 +1,6 @@
import type { NextJsHotReloaderInterface } from './hot-reloader-types';
import { type ServerFields, type SetupOpts } from '../lib/router-utils/setup-dev-bundler';
import type { Lockfile } from '../../build/lockfile';
export declare function createHotReloaderTurbopack(opts: SetupOpts & {
isSrcDir: boolean;
}, serverFields: ServerFields, distDir: string, resetFetch: () => void, lockfile: Lockfile | undefined): Promise<NextJsHotReloaderInterface>;

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,205 @@
import type { IncomingMessage, ServerResponse } from 'http';
import type { UrlObject } from 'url';
import type { Duplex } from 'stream';
import type { webpack } from 'next/dist/compiled/webpack/webpack';
import type getBaseWebpackConfig from '../../build/webpack-config';
import type { RouteDefinition } from '../route-definitions/route-definition';
import type { Project, Update as TurbopackUpdate } from '../../build/swc/types';
import type { VersionInfo } from './parse-version-info';
import type { DebugInfo } from '../../next-devtools/shared/types';
import type { DevIndicatorServerState } from './dev-indicator-server-state';
import type { CacheIndicatorState, ServerCacheStatus } from '../../next-devtools/dev-overlay/cache-indicator';
import type { DevToolsConfig } from '../../next-devtools/dev-overlay/shared';
import type { ReactDebugChannelForBrowser } from './debug-channel';
export declare const enum HMR_MESSAGE_SENT_TO_BROWSER {
ADDED_PAGE = "addedPage",
REMOVED_PAGE = "removedPage",
RELOAD_PAGE = "reloadPage",
SERVER_COMPONENT_CHANGES = "serverComponentChanges",
MIDDLEWARE_CHANGES = "middlewareChanges",
CLIENT_CHANGES = "clientChanges",
SERVER_ONLY_CHANGES = "serverOnlyChanges",
SYNC = "sync",
BUILT = "built",
BUILDING = "building",
DEV_PAGES_MANIFEST_UPDATE = "devPagesManifestUpdate",
TURBOPACK_MESSAGE = "turbopack-message",
SERVER_ERROR = "serverError",
TURBOPACK_CONNECTED = "turbopack-connected",
ISR_MANIFEST = "isrManifest",
CACHE_INDICATOR = "cacheIndicator",
DEV_INDICATOR = "devIndicator",
DEVTOOLS_CONFIG = "devtoolsConfig",
REQUEST_CURRENT_ERROR_STATE = "requestCurrentErrorState",
REQUEST_PAGE_METADATA = "requestPageMetadata",
REACT_DEBUG_CHUNK = 0,
ERRORS_TO_SHOW_IN_BROWSER = 1
}
export declare const enum HMR_MESSAGE_SENT_TO_SERVER {
MCP_ERROR_STATE_RESPONSE = "mcp-error-state-response",
MCP_PAGE_METADATA_RESPONSE = "mcp-page-metadata-response",
PING = "ping"
}
export interface ServerErrorMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.SERVER_ERROR;
errorJSON: string;
}
export interface TurbopackMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.TURBOPACK_MESSAGE;
data: TurbopackUpdate | TurbopackUpdate[];
}
export interface BuildingMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.BUILDING;
}
export interface CompilationError {
moduleName?: string;
message: string;
details?: string;
moduleTrace?: Array<{
moduleName?: string;
}>;
stack?: string;
}
export interface SyncMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.SYNC;
hash: string;
errors: ReadonlyArray<CompilationError>;
warnings: ReadonlyArray<CompilationError>;
versionInfo: VersionInfo;
updatedModules?: ReadonlyArray<string>;
debug?: DebugInfo;
devIndicator: DevIndicatorServerState;
devToolsConfig?: DevToolsConfig;
}
export interface BuiltMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.BUILT;
hash: string;
errors: ReadonlyArray<CompilationError>;
warnings: ReadonlyArray<CompilationError>;
updatedModules?: ReadonlyArray<string>;
}
export interface AddedPageMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.ADDED_PAGE;
data: [page: string | null];
}
export interface RemovedPageMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.REMOVED_PAGE;
data: [page: string | null];
}
export interface ReloadPageMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.RELOAD_PAGE;
data: string;
}
export interface ServerComponentChangesMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.SERVER_COMPONENT_CHANGES;
hash: string;
}
export interface MiddlewareChangesMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.MIDDLEWARE_CHANGES;
}
export interface ClientChangesMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.CLIENT_CHANGES;
}
export interface ServerOnlyChangesMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.SERVER_ONLY_CHANGES;
pages: ReadonlyArray<string>;
}
export interface DevPagesManifestUpdateMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.DEV_PAGES_MANIFEST_UPDATE;
data: [
{
devPagesManifest: true;
}
];
}
export interface TurbopackConnectedMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.TURBOPACK_CONNECTED;
data: {
sessionId: number;
};
}
export interface AppIsrManifestMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.ISR_MANIFEST;
data: Record<string, boolean>;
}
export interface DevToolsConfigMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.DEVTOOLS_CONFIG;
data: DevToolsConfig;
}
export interface ReactDebugChunkMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.REACT_DEBUG_CHUNK;
requestId: string;
/**
* A null chunk signals to the browser that no more chunks will be sent.
*/
chunk: Uint8Array | null;
}
export interface ErrorsToShowInBrowserMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.ERRORS_TO_SHOW_IN_BROWSER;
serializedErrors: Uint8Array;
}
export interface RequestCurrentErrorStateMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.REQUEST_CURRENT_ERROR_STATE;
requestId: string;
}
export interface RequestPageMetadataMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.REQUEST_PAGE_METADATA;
requestId: string;
}
export interface CacheIndicatorMessage {
type: HMR_MESSAGE_SENT_TO_BROWSER.CACHE_INDICATOR;
state: CacheIndicatorState;
}
export type HmrMessageSentToBrowser = TurbopackMessage | TurbopackConnectedMessage | BuildingMessage | SyncMessage | BuiltMessage | AddedPageMessage | RemovedPageMessage | ReloadPageMessage | ServerComponentChangesMessage | ClientChangesMessage | MiddlewareChangesMessage | ServerOnlyChangesMessage | DevPagesManifestUpdateMessage | ServerErrorMessage | AppIsrManifestMessage | DevToolsConfigMessage | ErrorsToShowInBrowserMessage | ReactDebugChunkMessage | RequestCurrentErrorStateMessage | RequestPageMetadataMessage | CacheIndicatorMessage;
export type BinaryHmrMessageSentToBrowser = Extract<HmrMessageSentToBrowser, {
type: number;
}>;
export type TurbopackMessageSentToBrowser = {
type: HMR_MESSAGE_SENT_TO_BROWSER.TURBOPACK_MESSAGE;
data: any;
} | {
type: HMR_MESSAGE_SENT_TO_BROWSER.TURBOPACK_CONNECTED;
data: {
sessionId: number;
};
};
export interface NextJsHotReloaderInterface {
turbopackProject?: Project;
activeWebpackConfigs?: Array<Awaited<ReturnType<typeof getBaseWebpackConfig>>>;
serverStats: webpack.Stats | null;
edgeServerStats: webpack.Stats | null;
run(req: IncomingMessage, res: ServerResponse, parsedUrl: UrlObject): Promise<{
finished?: true;
}>;
setHmrServerError(error: Error | null): void;
clearHmrServerError(): void;
start(): Promise<void>;
send(action: HmrMessageSentToBrowser): void;
/**
* Send the given action only to legacy clients, i.e. Pages Router clients,
* and App Router clients that don't have Cache Components enabled.
*/
sendToLegacyClients(action: HmrMessageSentToBrowser): void;
setCacheStatus(status: ServerCacheStatus, htmlRequestId: string): void;
setReactDebugChannel(debugChannel: ReactDebugChannelForBrowser, htmlRequestId: string, requestId: string): void;
sendErrorsToBrowser(errorsRscStream: ReadableStream<Uint8Array>, htmlRequestId: string): void;
getCompilationErrors(page: string): Promise<any[]>;
onHMR(req: IncomingMessage, _socket: Duplex, head: Buffer, onUpgrade: (client: {
send(data: string): void;
}, context: {
isLegacyClient: boolean;
}) => void): void;
invalidate({ reloadAfterInvalidation, }: {
reloadAfterInvalidation: boolean;
}): Promise<void> | void;
buildFallbackError(): Promise<void>;
ensurePage({ page, clientOnly, appPaths, definition, isApp, url, }: {
page: string;
clientOnly: boolean;
appPaths?: ReadonlyArray<string> | null;
isApp?: boolean;
definition: RouteDefinition | undefined;
url?: string;
}): Promise<void>;
close(): void;
}

View File

@@ -0,0 +1,58 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
HMR_MESSAGE_SENT_TO_BROWSER: null,
HMR_MESSAGE_SENT_TO_SERVER: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
HMR_MESSAGE_SENT_TO_BROWSER: function() {
return HMR_MESSAGE_SENT_TO_BROWSER;
},
HMR_MESSAGE_SENT_TO_SERVER: function() {
return HMR_MESSAGE_SENT_TO_SERVER;
}
});
var HMR_MESSAGE_SENT_TO_BROWSER = /*#__PURE__*/ function(HMR_MESSAGE_SENT_TO_BROWSER) {
// JSON messages:
HMR_MESSAGE_SENT_TO_BROWSER["ADDED_PAGE"] = "addedPage";
HMR_MESSAGE_SENT_TO_BROWSER["REMOVED_PAGE"] = "removedPage";
HMR_MESSAGE_SENT_TO_BROWSER["RELOAD_PAGE"] = "reloadPage";
HMR_MESSAGE_SENT_TO_BROWSER["SERVER_COMPONENT_CHANGES"] = "serverComponentChanges";
HMR_MESSAGE_SENT_TO_BROWSER["MIDDLEWARE_CHANGES"] = "middlewareChanges";
HMR_MESSAGE_SENT_TO_BROWSER["CLIENT_CHANGES"] = "clientChanges";
HMR_MESSAGE_SENT_TO_BROWSER["SERVER_ONLY_CHANGES"] = "serverOnlyChanges";
HMR_MESSAGE_SENT_TO_BROWSER["SYNC"] = "sync";
HMR_MESSAGE_SENT_TO_BROWSER["BUILT"] = "built";
HMR_MESSAGE_SENT_TO_BROWSER["BUILDING"] = "building";
HMR_MESSAGE_SENT_TO_BROWSER["DEV_PAGES_MANIFEST_UPDATE"] = "devPagesManifestUpdate";
HMR_MESSAGE_SENT_TO_BROWSER["TURBOPACK_MESSAGE"] = "turbopack-message";
HMR_MESSAGE_SENT_TO_BROWSER["SERVER_ERROR"] = "serverError";
HMR_MESSAGE_SENT_TO_BROWSER["TURBOPACK_CONNECTED"] = "turbopack-connected";
HMR_MESSAGE_SENT_TO_BROWSER["ISR_MANIFEST"] = "isrManifest";
HMR_MESSAGE_SENT_TO_BROWSER["CACHE_INDICATOR"] = "cacheIndicator";
HMR_MESSAGE_SENT_TO_BROWSER["DEV_INDICATOR"] = "devIndicator";
HMR_MESSAGE_SENT_TO_BROWSER["DEVTOOLS_CONFIG"] = "devtoolsConfig";
HMR_MESSAGE_SENT_TO_BROWSER["REQUEST_CURRENT_ERROR_STATE"] = "requestCurrentErrorState";
HMR_MESSAGE_SENT_TO_BROWSER["REQUEST_PAGE_METADATA"] = "requestPageMetadata";
// Binary messages:
HMR_MESSAGE_SENT_TO_BROWSER[HMR_MESSAGE_SENT_TO_BROWSER["REACT_DEBUG_CHUNK"] = 0] = "REACT_DEBUG_CHUNK";
HMR_MESSAGE_SENT_TO_BROWSER[HMR_MESSAGE_SENT_TO_BROWSER["ERRORS_TO_SHOW_IN_BROWSER"] = 1] = "ERRORS_TO_SHOW_IN_BROWSER";
return HMR_MESSAGE_SENT_TO_BROWSER;
}({});
var HMR_MESSAGE_SENT_TO_SERVER = /*#__PURE__*/ function(HMR_MESSAGE_SENT_TO_SERVER) {
// JSON messages:
HMR_MESSAGE_SENT_TO_SERVER["MCP_ERROR_STATE_RESPONSE"] = "mcp-error-state-response";
HMR_MESSAGE_SENT_TO_SERVER["MCP_PAGE_METADATA_RESPONSE"] = "mcp-page-metadata-response";
HMR_MESSAGE_SENT_TO_SERVER["PING"] = "ping";
return HMR_MESSAGE_SENT_TO_SERVER;
}({});
//# sourceMappingURL=hot-reloader-types.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,111 @@
import type { NextConfigComplete } from '../config-shared';
import type { CustomRoutes } from '../../lib/load-custom-routes';
import type { Duplex } from 'stream';
import type { Telemetry } from '../../telemetry/storage';
import type { IncomingMessage, ServerResponse } from 'http';
import type { UrlObject } from 'url';
import type { RouteDefinition } from '../route-definitions/route-definition';
import { type webpack } from 'next/dist/compiled/webpack/webpack';
import getBaseWebpackConfig from '../../build/webpack-config';
import type { __ApiPreviewProps } from '../api-utils';
import { type Span } from '../../trace';
import ws from 'next/dist/compiled/ws';
import type { UnwrapPromise } from '../../lib/coalesced-function';
import { type NextJsHotReloaderInterface } from './hot-reloader-types';
import type { HmrMessageSentToBrowser } from './hot-reloader-types';
import { type ReactDebugChannelForBrowser } from './debug-channel';
import type { ServerCacheStatus } from '../../next-devtools/dev-overlay/cache-indicator';
import type { Lockfile } from '../../build/lockfile';
export declare function renderScriptError(res: ServerResponse, error: Error, { verbose }?: {
verbose?: boolean | undefined;
}): Promise<{
finished: true | undefined;
}>;
export default class HotReloaderWebpack implements NextJsHotReloaderInterface {
private hasAppRouterEntrypoints;
private hasPagesRouterEntrypoints;
protected dir: string;
protected buildId: string;
private encryptionKey;
protected middlewares: ((req: IncomingMessage, res: ServerResponse, next: () => void) => Promise<void>)[];
protected pagesDir?: string;
protected distDir: string;
private webpackHotMiddleware?;
protected config: NextConfigComplete;
private clientStats;
private clientError;
private serverError;
private hmrServerError;
private serverPrevDocumentHash;
private serverChunkNames?;
private prevChunkNames?;
private onDemandEntries?;
protected previewProps: __ApiPreviewProps;
private watcher;
private rewrites;
private fallbackWatcher;
protected hotReloaderSpan: Span;
private pagesMapping;
protected appDir?: string;
private telemetry;
private resetFetch;
private lockfile;
private versionInfo;
private devtoolsFrontendUrl;
private reloadAfterInvalidation;
private isSrcDir;
private cacheStatusesByRequestId;
serverStats: webpack.Stats | null;
edgeServerStats: webpack.Stats | null;
multiCompiler?: webpack.MultiCompiler;
activeWebpackConfigs?: Array<UnwrapPromise<ReturnType<typeof getBaseWebpackConfig>>>;
constructor(dir: string, { config, isSrcDir, pagesDir, distDir, buildId, encryptionKey, previewProps, rewrites, appDir, telemetry, resetFetch, lockfile, onDevServerCleanup, }: {
config: NextConfigComplete;
isSrcDir: boolean;
pagesDir?: string;
distDir: string;
buildId: string;
encryptionKey: string;
previewProps: __ApiPreviewProps;
rewrites: CustomRoutes['rewrites'];
appDir?: string;
telemetry: Telemetry;
resetFetch: () => void;
lockfile: Lockfile | undefined;
onDevServerCleanup: ((listener: () => Promise<void>) => void) | undefined;
});
run(req: IncomingMessage, res: ServerResponse, parsedUrl: UrlObject): Promise<{
finished?: true;
}>;
setHmrServerError(error: Error | null): void;
clearHmrServerError(): void;
protected refreshServerComponents(hash: string): Promise<void>;
onHMR(req: IncomingMessage, _socket: Duplex, head: Buffer, callback: (client: ws.WebSocket, context: {
isLegacyClient: boolean;
}) => void): void;
private clean;
private getWebpackConfig;
buildFallbackError(): Promise<void>;
private tracedGetVersionInfo;
start(): Promise<void>;
protected afterCompile(_multiCompiler: webpack.MultiCompiler): Promise<void>;
invalidate({ reloadAfterInvalidation }?: {
reloadAfterInvalidation: boolean;
}): void;
getCompilationErrors(page: string): Promise<Error[]>;
send(message: HmrMessageSentToBrowser): void;
sendToClient(client: ws, message: HmrMessageSentToBrowser): void;
sendToLegacyClients(message: HmrMessageSentToBrowser): void;
setCacheStatus(status: ServerCacheStatus, htmlRequestId: string): void;
setReactDebugChannel(debugChannel: ReactDebugChannelForBrowser, htmlRequestId: string, requestId: string): void;
sendErrorsToBrowser(errorsRscStream: ReadableStream<Uint8Array>, htmlRequestId: string): void;
ensurePage({ page, clientOnly, appPaths, definition, isApp, url, }: {
page: string;
clientOnly: boolean;
appPaths?: ReadonlyArray<string> | null;
isApp?: boolean;
definition?: RouteDefinition;
url?: string;
}): Promise<void>;
close(): void;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,7 @@
import type { NodeNextRequest, NodeNextResponse } from '../base-http/node';
import type { LoggingConfig } from '../config-shared';
/**
* Returns true if the incoming request should be ignored for logging.
*/
export declare function ignoreLoggingIncomingRequests(request: NodeNextRequest, loggingConfig: LoggingConfig | undefined): boolean;
export declare function logRequests(request: NodeNextRequest, response: NodeNextResponse, loggingConfig: LoggingConfig, requestStartTime: bigint, requestEndTime: bigint, devRequestTimingMiddlewareStart: bigint | undefined, devRequestTimingMiddlewareEnd: bigint | undefined, devRequestTimingInternalsEnd: bigint | undefined, devGenerateStaticParamsDuration: bigint | undefined): void;

View File

@@ -0,0 +1,141 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
ignoreLoggingIncomingRequests: null,
logRequests: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
ignoreLoggingIncomingRequests: function() {
return ignoreLoggingIncomingRequests;
},
logRequests: function() {
return logRequests;
}
});
const _durationtostring = require("../../build/duration-to-string");
const _picocolors = require("../../lib/picocolors");
const _url = require("../../lib/url");
const _requestmeta = require("../request-meta");
function ignoreLoggingIncomingRequests(request, loggingConfig) {
var _loggingConfig_incomingRequests;
// If it's boolean use the boolean value
if (typeof (loggingConfig == null ? void 0 : loggingConfig.incomingRequests) === 'boolean') {
return !loggingConfig.incomingRequests;
}
// Any of the value on the chain is falsy, will not ignore the request.
const ignore = loggingConfig == null ? void 0 : (_loggingConfig_incomingRequests = loggingConfig.incomingRequests) == null ? void 0 : _loggingConfig_incomingRequests.ignore;
// If ignore is not set, don't ignore anything
if (!ignore) {
return false;
}
// If array of RegExp, ignore if any pattern matches
return ignore.some((pattern)=>pattern.test(request.url));
}
function logRequests(request, response, loggingConfig, requestStartTime, requestEndTime, devRequestTimingMiddlewareStart, devRequestTimingMiddlewareEnd, devRequestTimingInternalsEnd, devGenerateStaticParamsDuration) {
if (!ignoreLoggingIncomingRequests(request, loggingConfig)) {
logIncomingRequests(request, requestStartTime, requestEndTime, response.statusCode, devRequestTimingMiddlewareStart, devRequestTimingMiddlewareEnd, devRequestTimingInternalsEnd, devGenerateStaticParamsDuration);
}
if (request.fetchMetrics) {
for (const fetchMetric of request.fetchMetrics){
logFetchMetric(fetchMetric, loggingConfig);
}
}
}
function logIncomingRequests(request, requestStartTime, requestEndTime, statusCode, devRequestTimingMiddlewareStart, devRequestTimingMiddlewareEnd, devRequestTimingInternalsEnd, devGenerateStaticParamsDuration) {
const isRSC = (0, _requestmeta.getRequestMeta)(request, 'isRSCRequest');
const url = isRSC ? (0, _url.stripNextRscUnionQuery)(request.url) : request.url;
const statusCodeColor = statusCode < 200 ? _picocolors.white : statusCode < 300 ? _picocolors.green : statusCode < 400 ? _picocolors.blue : statusCode < 500 ? _picocolors.yellow : _picocolors.red;
const coloredStatus = statusCodeColor(statusCode.toString());
const totalRequestTime = requestEndTime - requestStartTime;
const times = [];
let middlewareTime;
if (devRequestTimingMiddlewareStart && devRequestTimingMiddlewareEnd) {
middlewareTime = devRequestTimingMiddlewareEnd - devRequestTimingMiddlewareStart;
times.push([
'proxy.ts',
middlewareTime
]);
}
if (devRequestTimingInternalsEnd) {
let frameworkTime = devRequestTimingInternalsEnd - requestStartTime;
/* Middleware runs during the internals so we have to subtract it from the framework time */ if (middlewareTime) {
frameworkTime -= middlewareTime;
}
// Insert as the first item to be rendered in the list
times.unshift([
'compile',
frameworkTime
]);
// Insert after compile, before render based on the execution order.
if (devGenerateStaticParamsDuration) {
// Pages Router getStaticPaths are technically "generate params" as well.
times.push([
'generate-params',
devGenerateStaticParamsDuration
]);
}
times.push([
'render',
requestEndTime - devRequestTimingInternalsEnd
]);
}
return writeLine(`${request.method} ${url} ${coloredStatus} in ${(0, _durationtostring.hrtimeBigIntDurationToString)(totalRequestTime)}${times.length > 0 ? (0, _picocolors.dim)(` (${times.map(([label, time])=>`${label}: ${(0, _durationtostring.hrtimeBigIntDurationToString)(time)}`).join(', ')})`) : ''}`);
}
function logFetchMetric(fetchMetric, loggingConfig) {
var _loggingConfig_fetches;
let { cacheReason, cacheStatus, cacheWarning, end, method, start, status, url } = fetchMetric;
if (cacheStatus === 'hmr' && !(loggingConfig == null ? void 0 : (_loggingConfig_fetches = loggingConfig.fetches) == null ? void 0 : _loggingConfig_fetches.hmrRefreshes)) {
// Cache hits during HMR refreshes are intentionally not logged, unless
// explicitly enabled in the logging config.
return;
}
if (loggingConfig == null ? void 0 : loggingConfig.fetches) {
if (url.length > 48 && !loggingConfig.fetches.fullUrl) {
url = truncateUrl(url);
}
writeLine((0, _picocolors.white)(`${method} ${url} ${status} in ${Math.round(end - start)}ms ${formatCacheStatus(cacheStatus)}`), 1);
if (cacheStatus === 'skip' || cacheStatus === 'miss') {
writeLine((0, _picocolors.gray)(`Cache ${cacheStatus === 'skip' ? 'skipped' : 'missed'} reason: (${(0, _picocolors.white)(cacheReason)})`), 2);
}
} else if (cacheWarning) {
// When logging for fetches is not enabled, we still want to print any
// associated warnings, so we print the request first to provide context.
writeLine((0, _picocolors.white)(`${method} ${url}`), 1);
}
if (cacheWarning) {
writeLine(`${(0, _picocolors.yellow)((0, _picocolors.bold)('⚠'))} ${(0, _picocolors.white)(cacheWarning)}`, 2);
}
}
function writeLine(text, indentationLevel = 0) {
process.stdout.write(` ${'│ '.repeat(indentationLevel)}${text}\n`);
}
function truncate(text, maxLength) {
return maxLength !== undefined && text.length > maxLength ? text.substring(0, maxLength) + '..' : text;
}
function truncateUrl(url) {
const { protocol, host, pathname, search } = new URL(url);
return protocol + '//' + truncate(host, 16) + truncate(pathname, 24) + truncate(search, 16);
}
function formatCacheStatus(cacheStatus) {
switch(cacheStatus){
case 'hmr':
return (0, _picocolors.green)('(HMR cache)');
case 'hit':
return (0, _picocolors.green)('(cache hit)');
case 'miss':
case 'skip':
return (0, _picocolors.yellow)(`(cache ${cacheStatus})`);
default:
return cacheStatus;
}
}
//# sourceMappingURL=log-requests.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
import { type BinaryHmrMessageSentToBrowser } from './hot-reloader-types';
export declare const FAST_REFRESH_RUNTIME_RELOAD = "Fast Refresh had to perform a full reload due to a runtime error.";
export declare function createBinaryHmrMessageData(message: BinaryHmrMessageSentToBrowser): Uint8Array;

View File

@@ -0,0 +1,74 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
FAST_REFRESH_RUNTIME_RELOAD: null,
createBinaryHmrMessageData: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
FAST_REFRESH_RUNTIME_RELOAD: function() {
return FAST_REFRESH_RUNTIME_RELOAD;
},
createBinaryHmrMessageData: function() {
return createBinaryHmrMessageData;
}
});
const _invarianterror = require("../../shared/lib/invariant-error");
const _hotreloadertypes = require("./hot-reloader-types");
const FAST_REFRESH_RUNTIME_RELOAD = 'Fast Refresh had to perform a full reload due to a runtime error.';
const textEncoder = new TextEncoder();
function createBinaryHmrMessageData(message) {
switch(message.type){
case _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.ERRORS_TO_SHOW_IN_BROWSER:
{
const { serializedErrors } = message;
const totalLength = 1 + serializedErrors.length;
const data = new Uint8Array(totalLength);
const view = new DataView(data.buffer);
view.setUint8(0, _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.ERRORS_TO_SHOW_IN_BROWSER);
data.set(serializedErrors, 1);
return data;
}
case _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.REACT_DEBUG_CHUNK:
{
const { requestId, chunk } = message;
const requestIdBytes = textEncoder.encode(requestId);
const requestIdLength = requestIdBytes.length;
if (requestIdLength > 255) {
throw Object.defineProperty(new _invarianterror.InvariantError('Request ID is too long for the binary HMR message.'), "__NEXT_ERROR_CODE", {
value: "E805",
enumerable: false,
configurable: true
});
}
const chunkLength = chunk ? chunk.length : 0;
const totalLength = 2 + requestIdLength + chunkLength;
const data = new Uint8Array(totalLength);
const view = new DataView(data.buffer);
view.setUint8(0, _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.REACT_DEBUG_CHUNK);
view.setUint8(1, requestIdLength);
textEncoder.encodeInto(requestId, data.subarray(2, 2 + requestIdLength));
if (chunk) {
data.set(chunk, 2 + requestIdLength);
}
return data;
}
default:
{
throw Object.defineProperty(new _invarianterror.InvariantError(`Invalid binary HMR message of type ${message.type}`), "__NEXT_ERROR_CODE", {
value: "E809",
enumerable: false,
configurable: true
});
}
}
}
//# sourceMappingURL=messages.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../src/server/dev/messages.ts"],"sourcesContent":["import { InvariantError } from '../../shared/lib/invariant-error'\nimport {\n HMR_MESSAGE_SENT_TO_BROWSER,\n type BinaryHmrMessageSentToBrowser,\n} from './hot-reloader-types'\n\nexport const FAST_REFRESH_RUNTIME_RELOAD =\n 'Fast Refresh had to perform a full reload due to a runtime error.'\n\nconst textEncoder = new TextEncoder()\n\nexport function createBinaryHmrMessageData(\n message: BinaryHmrMessageSentToBrowser\n): Uint8Array {\n switch (message.type) {\n case HMR_MESSAGE_SENT_TO_BROWSER.ERRORS_TO_SHOW_IN_BROWSER: {\n const { serializedErrors } = message\n const totalLength = 1 + serializedErrors.length\n const data = new Uint8Array(totalLength)\n const view = new DataView(data.buffer)\n\n view.setUint8(0, HMR_MESSAGE_SENT_TO_BROWSER.ERRORS_TO_SHOW_IN_BROWSER)\n data.set(serializedErrors, 1)\n\n return data\n }\n case HMR_MESSAGE_SENT_TO_BROWSER.REACT_DEBUG_CHUNK: {\n const { requestId, chunk } = message\n const requestIdBytes = textEncoder.encode(requestId)\n const requestIdLength = requestIdBytes.length\n\n if (requestIdLength > 255) {\n throw new InvariantError(\n 'Request ID is too long for the binary HMR message.'\n )\n }\n\n const chunkLength = chunk ? chunk.length : 0\n const totalLength = 2 + requestIdLength + chunkLength\n const data = new Uint8Array(totalLength)\n const view = new DataView(data.buffer)\n\n view.setUint8(0, HMR_MESSAGE_SENT_TO_BROWSER.REACT_DEBUG_CHUNK)\n view.setUint8(1, requestIdLength)\n textEncoder.encodeInto(requestId, data.subarray(2, 2 + requestIdLength))\n\n if (chunk) {\n data.set(chunk, 2 + requestIdLength)\n }\n\n return data\n }\n default: {\n throw new InvariantError(\n `Invalid binary HMR message of type ${(message as any).type}`\n )\n }\n }\n}\n"],"names":["FAST_REFRESH_RUNTIME_RELOAD","createBinaryHmrMessageData","textEncoder","TextEncoder","message","type","HMR_MESSAGE_SENT_TO_BROWSER","ERRORS_TO_SHOW_IN_BROWSER","serializedErrors","totalLength","length","data","Uint8Array","view","DataView","buffer","setUint8","set","REACT_DEBUG_CHUNK","requestId","chunk","requestIdBytes","encode","requestIdLength","InvariantError","chunkLength","encodeInto","subarray"],"mappings":";;;;;;;;;;;;;;;IAMaA,2BAA2B;eAA3BA;;IAKGC,0BAA0B;eAA1BA;;;gCAXe;kCAIxB;AAEA,MAAMD,8BACX;AAEF,MAAME,cAAc,IAAIC;AAEjB,SAASF,2BACdG,OAAsC;IAEtC,OAAQA,QAAQC,IAAI;QAClB,KAAKC,6CAA2B,CAACC,yBAAyB;YAAE;gBAC1D,MAAM,EAAEC,gBAAgB,EAAE,GAAGJ;gBAC7B,MAAMK,cAAc,IAAID,iBAAiBE,MAAM;gBAC/C,MAAMC,OAAO,IAAIC,WAAWH;gBAC5B,MAAMI,OAAO,IAAIC,SAASH,KAAKI,MAAM;gBAErCF,KAAKG,QAAQ,CAAC,GAAGV,6CAA2B,CAACC,yBAAyB;gBACtEI,KAAKM,GAAG,CAACT,kBAAkB;gBAE3B,OAAOG;YACT;QACA,KAAKL,6CAA2B,CAACY,iBAAiB;YAAE;gBAClD,MAAM,EAAEC,SAAS,EAAEC,KAAK,EAAE,GAAGhB;gBAC7B,MAAMiB,iBAAiBnB,YAAYoB,MAAM,CAACH;gBAC1C,MAAMI,kBAAkBF,eAAeX,MAAM;gBAE7C,IAAIa,kBAAkB,KAAK;oBACzB,MAAM,qBAEL,CAFK,IAAIC,8BAAc,CACtB,uDADI,qBAAA;+BAAA;oCAAA;sCAAA;oBAEN;gBACF;gBAEA,MAAMC,cAAcL,QAAQA,MAAMV,MAAM,GAAG;gBAC3C,MAAMD,cAAc,IAAIc,kBAAkBE;gBAC1C,MAAMd,OAAO,IAAIC,WAAWH;gBAC5B,MAAMI,OAAO,IAAIC,SAASH,KAAKI,MAAM;gBAErCF,KAAKG,QAAQ,CAAC,GAAGV,6CAA2B,CAACY,iBAAiB;gBAC9DL,KAAKG,QAAQ,CAAC,GAAGO;gBACjBrB,YAAYwB,UAAU,CAACP,WAAWR,KAAKgB,QAAQ,CAAC,GAAG,IAAIJ;gBAEvD,IAAIH,OAAO;oBACTT,KAAKM,GAAG,CAACG,OAAO,IAAIG;gBACtB;gBAEA,OAAOZ;YACT;QACA;YAAS;gBACP,MAAM,qBAEL,CAFK,IAAIa,8BAAc,CACtB,CAAC,mCAAmC,EAAE,AAACpB,QAAgBC,IAAI,EAAE,GADzD,qBAAA;2BAAA;gCAAA;kCAAA;gBAEN;YACF;IACF;AACF","ignoreList":[0]}

View File

@@ -0,0 +1,17 @@
import type { IncomingMessage, ServerResponse } from 'http';
import { type OriginalStackFramesResponse, type StackFrame } from '../../next-devtools/server/shared';
import type { Project } from '../../build/swc/types';
export declare function getOverlayMiddleware({ project, projectPath, isSrcDir, }: {
project: Project;
projectPath: string;
isSrcDir: boolean;
}): (req: IncomingMessage, res: ServerResponse, next: () => void) => Promise<void>;
export declare function getSourceMapMiddleware(project: Project): (req: IncomingMessage, res: ServerResponse, next: () => void) => Promise<void>;
export declare function getOriginalStackFrames({ project, projectPath, frames, isServer, isEdgeServer, isAppDirectory, }: {
project: Project;
projectPath: string;
frames: readonly StackFrame[];
isServer: boolean;
isEdgeServer: boolean;
isAppDirectory: boolean;
}): Promise<OriginalStackFramesResponse>;

View File

@@ -0,0 +1,393 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
getOriginalStackFrames: null,
getOverlayMiddleware: null,
getSourceMapMiddleware: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
getOriginalStackFrames: function() {
return getOriginalStackFrames;
},
getOverlayMiddleware: function() {
return getOverlayMiddleware;
},
getSourceMapMiddleware: function() {
return getSourceMapMiddleware;
}
});
const _shared = require("../../next-devtools/server/shared");
const _middlewareresponse = require("../../next-devtools/server/middleware-response");
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _launcheditor = require("../../next-devtools/server/launch-editor");
const _sourcemap08 = require("next/dist/compiled/source-map08");
const _sourcemaps = require("../lib/source-maps");
const _nodemodule = require("node:module");
const _nodeurl = require("node:url");
const _nodeutil = require("node:util");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function shouldIgnorePath(modulePath) {
return modulePath.includes('node_modules') || // Only relevant for when Next.js is symlinked e.g. in the Next.js monorepo
modulePath.includes('next/dist') || modulePath.startsWith('node:');
}
const currentSourcesByFile = new Map();
/**
* @returns 1-based lines and 1-based columns
*/ async function batchedTraceSource(project, frame) {
const file = frame.file ? decodeURIComponent(frame.file) : undefined;
if (!file) return;
// For node internals they cannot traced the actual source code with project.traceSource,
// we need an early return to indicate it's ignored to avoid the unknown scheme error from `project.traceSource`.
if (file.startsWith('node:')) {
return {
frame: {
file,
line1: frame.line ?? null,
column1: frame.column ?? null,
methodName: frame.methodName ?? '<unknown>',
ignored: true,
arguments: []
},
source: null
};
}
const currentDirectoryFileUrl = (0, _nodeurl.pathToFileURL)(process.cwd()).href;
const sourceFrame = await project.traceSource(frame, currentDirectoryFileUrl);
if (!sourceFrame) {
return {
frame: {
file,
line1: frame.line ?? null,
column1: frame.column ?? null,
methodName: frame.methodName ?? '<unknown>',
ignored: shouldIgnorePath(file),
arguments: []
},
source: null
};
}
let source = null;
const originalFile = sourceFrame.originalFile;
// Don't look up source for node_modules or internals. These can often be large bundled files.
const ignored = shouldIgnorePath(originalFile ?? sourceFrame.file) || // isInternal means resource starts with turbopack:///[turbopack]
!!sourceFrame.isInternal;
if (originalFile && !ignored) {
let sourcePromise = currentSourcesByFile.get(originalFile);
if (!sourcePromise) {
sourcePromise = project.getSourceForAsset(originalFile);
currentSourcesByFile.set(originalFile, sourcePromise);
setTimeout(()=>{
// Cache file reads for 100ms, as frames will often reference the same
// files and can be large.
currentSourcesByFile.delete(originalFile);
}, 100);
}
source = await sourcePromise;
}
// TODO: get ignoredList from turbopack source map
const ignorableFrame = {
file: sourceFrame.file,
line1: sourceFrame.line ?? null,
column1: sourceFrame.column ?? null,
methodName: // We ignore the sourcemapped name since it won't be the correct name.
// The callsite will point to the column of the variable name instead of the
// name of the enclosing function.
// TODO(NDX-531): Spy on prepareStackTrace to get the enclosing line number for method name mapping.
frame.methodName ?? '<unknown>',
ignored,
arguments: []
};
return {
frame: ignorableFrame,
source
};
}
function parseFile(fileParam) {
if (!fileParam) {
return undefined;
}
return (0, _sourcemaps.devirtualizeReactServerURL)(fileParam);
}
function createStackFrames(body) {
const { frames, isServer } = body;
return frames.map((frame)=>{
const file = parseFile(frame.file);
if (!file) {
return undefined;
}
return {
file,
methodName: frame.methodName ?? '<unknown>',
line: frame.line1 ?? undefined,
column: frame.column1 ?? undefined,
isServer
};
}).filter((f)=>f !== undefined);
}
function createStackFrame(searchParams) {
const file = parseFile(searchParams.get('file'));
if (!file) {
return undefined;
}
return {
file,
methodName: searchParams.get('methodName') ?? '<unknown>',
line: parseInt(searchParams.get('line1') ?? '0', 10) || undefined,
column: parseInt(searchParams.get('column1') ?? '0', 10) || undefined,
isServer: searchParams.get('isServer') === 'true'
};
}
/**
* @returns 1-based lines and 1-based columns
*/ async function nativeTraceSource(frame) {
const sourceURL = frame.file;
let sourceMapPayload;
try {
var _findSourceMap;
sourceMapPayload = (_findSourceMap = (0, _nodemodule.findSourceMap)(sourceURL)) == null ? void 0 : _findSourceMap.payload;
} catch (cause) {
throw Object.defineProperty(new Error(`${sourceURL}: Invalid source map. Only conformant source maps can be used to find the original code.`, {
cause
}), "__NEXT_ERROR_CODE", {
value: "E635",
enumerable: false,
configurable: true
});
}
if (sourceMapPayload !== undefined) {
let consumer;
try {
consumer = await new _sourcemap08.SourceMapConsumer(sourceMapPayload);
} catch (cause) {
throw Object.defineProperty(new Error(`${sourceURL}: Invalid source map. Only conformant source maps can be used to find the original code.`, {
cause
}), "__NEXT_ERROR_CODE", {
value: "E635",
enumerable: false,
configurable: true
});
}
let traced;
try {
const originalPosition = consumer.originalPositionFor({
line: frame.line ?? 1,
// 0-based columns out requires 0-based columns in.
column: (frame.column ?? 1) - 1
});
if (originalPosition.source === null) {
traced = null;
} else {
const sourceContent = consumer.sourceContentFor(originalPosition.source, /* returnNullOnMissing */ true) ?? null;
traced = {
originalPosition,
sourceContent
};
}
} finally{
consumer.destroy();
}
if (traced !== null) {
var // We ignore the sourcemapped name since it won't be the correct name.
// The callsite will point to the column of the variable name instead of the
// name of the enclosing function.
// TODO(NDX-531): Spy on prepareStackTrace to get the enclosing line number for method name mapping.
_frame_methodName_replace, _frame_methodName;
const { originalPosition, sourceContent } = traced;
const applicableSourceMap = (0, _sourcemaps.findApplicableSourceMapPayload)((frame.line ?? 1) - 1, (frame.column ?? 1) - 1, sourceMapPayload);
// TODO(veil): Upstream a method to sourcemap consumer that immediately says if a frame is ignored or not.
let ignored = false;
if (applicableSourceMap === undefined) {
console.error('No applicable source map found in sections for frame', frame);
} else {
var _applicableSourceMap_ignoreList;
// TODO: O(n^2). Consider moving `ignoreList` into a Set
const sourceIndex = applicableSourceMap.sources.indexOf(originalPosition.source);
ignored = ((_applicableSourceMap_ignoreList = applicableSourceMap.ignoreList) == null ? void 0 : _applicableSourceMap_ignoreList.includes(sourceIndex)) ?? // When sourcemap is not available, fallback to checking `frame.file`.
// e.g. In pages router, nextjs server code is not bundled into the page.
shouldIgnorePath(frame.file);
}
const originalStackFrame = {
methodName: ((_frame_methodName = frame.methodName) == null ? void 0 : (_frame_methodName_replace = _frame_methodName.replace('__WEBPACK_DEFAULT_EXPORT__', 'default')) == null ? void 0 : _frame_methodName_replace.replace('__webpack_exports__.', '')) || '<unknown>',
file: originalPosition.source,
line1: originalPosition.line,
column1: originalPosition.column === null ? null : originalPosition.column + 1,
// TODO: c&p from async createOriginalStackFrame but why not frame.arguments?
arguments: [],
ignored
};
return {
frame: originalStackFrame,
source: sourceContent
};
}
}
return undefined;
}
async function createOriginalStackFrame(project, projectPath, frame) {
const traced = await nativeTraceSource(frame) ?? // TODO(veil): When would the bundler know more than native?
// If it's faster, try the bundler first and fall back to native later.
await batchedTraceSource(project, frame);
if (!traced) {
return null;
}
let normalizedStackFrameLocation = traced.frame.file;
if (normalizedStackFrameLocation !== null && normalizedStackFrameLocation.startsWith('file://')) {
normalizedStackFrameLocation = _path.default.relative(projectPath, (0, _nodeurl.fileURLToPath)(normalizedStackFrameLocation));
}
return {
originalStackFrame: {
arguments: traced.frame.arguments,
file: normalizedStackFrameLocation,
line1: traced.frame.line1,
column1: traced.frame.column1,
ignored: traced.frame.ignored,
methodName: traced.frame.methodName
},
originalCodeFrame: (0, _shared.getOriginalCodeFrame)(traced.frame, traced.source)
};
}
function getOverlayMiddleware({ project, projectPath, isSrcDir }) {
return async function(req, res, next) {
const { pathname, searchParams } = new URL(req.url, 'http://n');
if (pathname === '/__nextjs_original-stack-frames') {
if (req.method !== 'POST') {
return _middlewareresponse.middlewareResponse.badRequest(res);
}
const body = await new Promise((resolve, reject)=>{
let data = '';
req.on('data', (chunk)=>{
data += chunk;
});
req.on('end', ()=>resolve(data));
req.on('error', reject);
});
const request = JSON.parse(body);
const result = await getOriginalStackFrames({
project,
projectPath,
frames: request.frames,
isServer: request.isServer,
isEdgeServer: request.isEdgeServer,
isAppDirectory: request.isAppDirectory
});
(0, _shared.ignoreListAnonymousStackFramesIfSandwiched)(result);
return _middlewareresponse.middlewareResponse.json(res, result);
} else if (pathname === '/__nextjs_launch-editor') {
const isAppRelativePath = searchParams.get('isAppRelativePath') === '1';
let openEditorResult;
if (isAppRelativePath) {
const relativeFilePath = searchParams.get('file') || '';
const appPath = _path.default.join('app', isSrcDir ? 'src' : '', relativeFilePath);
openEditorResult = await (0, _launcheditor.openFileInEditor)(appPath, 1, 1, projectPath);
} else {
const frame = createStackFrame(searchParams);
if (!frame) return _middlewareresponse.middlewareResponse.badRequest(res);
openEditorResult = await (0, _launcheditor.openFileInEditor)(frame.file, frame.line ?? 1, frame.column ?? 1, projectPath);
}
if (openEditorResult.error) {
return _middlewareresponse.middlewareResponse.internalServerError(res, openEditorResult.error);
}
if (!openEditorResult.found) {
return _middlewareresponse.middlewareResponse.notFound(res);
}
return _middlewareresponse.middlewareResponse.noContent(res);
}
return next();
};
}
function getSourceMapMiddleware(project) {
return async function(req, res, next) {
const { pathname, searchParams } = new URL(req.url, 'http://n');
if (pathname !== '/__nextjs_source-map') {
return next();
}
let filename = searchParams.get('filename');
if (!filename) {
return _middlewareresponse.middlewareResponse.badRequest(res);
}
let nativeSourceMap;
try {
nativeSourceMap = (0, _nodemodule.findSourceMap)(filename);
} catch (cause) {
return _middlewareresponse.middlewareResponse.internalServerError(res, Object.defineProperty(new Error(`${filename}: Invalid source map. Only conformant source maps can be used to find the original code.`, {
cause
}), "__NEXT_ERROR_CODE", {
value: "E635",
enumerable: false,
configurable: true
}));
}
if (nativeSourceMap !== undefined) {
const sourceMapPayload = nativeSourceMap.payload;
return _middlewareresponse.middlewareResponse.json(res, sourceMapPayload);
}
try {
// Turbopack chunk filenames might be URL-encoded.
filename = decodeURI(filename);
} catch {
return _middlewareresponse.middlewareResponse.badRequest(res);
}
if (_path.default.isAbsolute(filename)) {
filename = (0, _nodeurl.pathToFileURL)(filename).href;
}
try {
const sourceMapString = await project.getSourceMap(filename);
if (sourceMapString) {
return _middlewareresponse.middlewareResponse.jsonString(res, sourceMapString);
}
} catch (cause) {
return _middlewareresponse.middlewareResponse.internalServerError(res, Object.defineProperty(new Error(`Failed to get source map for '${filename}'. This is a bug in Next.js`, {
cause
}), "__NEXT_ERROR_CODE", {
value: "E719",
enumerable: false,
configurable: true
}));
}
_middlewareresponse.middlewareResponse.noContent(res);
};
}
async function getOriginalStackFrames({ project, projectPath, frames, isServer, isEdgeServer, isAppDirectory }) {
const stackFrames = createStackFrames({
frames,
isServer,
isEdgeServer,
isAppDirectory
});
return Promise.all(stackFrames.map(async (frame)=>{
try {
const stackFrame = await createOriginalStackFrame(project, projectPath, frame);
if (stackFrame === null) {
return {
status: 'rejected',
reason: 'Failed to create original stack frame'
};
}
return {
status: 'fulfilled',
value: stackFrame
};
} catch (error) {
return {
status: 'rejected',
reason: (0, _nodeutil.inspect)(error, {
colors: false
})
};
}
}));
}
//# sourceMappingURL=middleware-turbopack.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,56 @@
import { type BasicSourceMapPayload } from '../lib/source-maps';
import { type StackFrame, type OriginalStackFrameResponse, type OriginalStackFramesResponse } from '../../next-devtools/server/shared';
import type { IncomingMessage, ServerResponse } from 'http';
import type webpack from 'webpack';
import type { RawSourceMap } from 'next/dist/compiled/source-map08';
type IgnoredSources = Array<{
url: string;
ignored: boolean;
}>;
type Source = {
type: 'file';
sourceMap: BasicSourceMapPayload;
ignoredSources: IgnoredSources;
moduleURL: string;
} | {
type: 'bundle';
sourceMap: BasicSourceMapPayload;
ignoredSources: IgnoredSources;
compilation: webpack.Compilation;
moduleId: string;
moduleURL: string;
};
export declare function getIgnoredSources(sourceMap: RawSourceMap & {
ignoreList?: number[];
}): IgnoredSources;
export declare function createOriginalStackFrame({ ignoredByDefault, source, rootDirectory, frame, errorMessage, }: {
/** setting this to true will not consult ignoreList */
ignoredByDefault: boolean;
source: Source;
rootDirectory: string;
frame: StackFrame;
errorMessage?: string;
}): Promise<OriginalStackFrameResponse | null>;
export declare function getOriginalStackFrames({ isServer, isEdgeServer, isAppDirectory, frames, clientStats, serverStats, edgeServerStats, rootDirectory, }: {
isServer: boolean;
isEdgeServer: boolean;
isAppDirectory: boolean;
frames: readonly StackFrame[];
clientStats: () => webpack.Stats | null;
serverStats: () => webpack.Stats | null;
edgeServerStats: () => webpack.Stats | null;
rootDirectory: string;
}): Promise<OriginalStackFramesResponse>;
export declare function getOverlayMiddleware(options: {
rootDirectory: string;
isSrcDir: boolean;
clientStats: () => webpack.Stats | null;
serverStats: () => webpack.Stats | null;
edgeServerStats: () => webpack.Stats | null;
}): (req: IncomingMessage, res: ServerResponse, next: () => void) => Promise<void>;
export declare function getSourceMapMiddleware(options: {
clientStats: () => webpack.Stats | null;
serverStats: () => webpack.Stats | null;
edgeServerStats: () => webpack.Stats | null;
}): (req: IncomingMessage, res: ServerResponse, next: () => void) => Promise<void>;
export {};

View File

@@ -0,0 +1,473 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
createOriginalStackFrame: null,
getIgnoredSources: null,
getOriginalStackFrames: null,
getOverlayMiddleware: null,
getSourceMapMiddleware: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
createOriginalStackFrame: function() {
return createOriginalStackFrame;
},
getIgnoredSources: function() {
return getIgnoredSources;
},
getOriginalStackFrames: function() {
return getOriginalStackFrames;
},
getOverlayMiddleware: function() {
return getOverlayMiddleware;
},
getSourceMapMiddleware: function() {
return getSourceMapMiddleware;
}
});
const _module = require("module");
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _url = require("url");
const _sourcemap08 = require("next/dist/compiled/source-map08");
const _getsourcemapfromfile = require("./get-source-map-from-file");
const _sourcemaps = require("../lib/source-maps");
const _launcheditor = require("../../next-devtools/server/launch-editor");
const _shared = require("../../next-devtools/server/shared");
const _middlewareresponse = require("../../next-devtools/server/middleware-response");
const _webpackmodulepath = require("../../next-devtools/shared/webpack-module-path");
const _util = require("util");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function shouldIgnoreSource(sourceURL) {
return sourceURL.includes('node_modules') || // Only relevant for when Next.js is symlinked e.g. in the Next.js monorepo
sourceURL.includes('next/dist') || sourceURL.startsWith('node:');
}
function getModuleById(id, compilation) {
const { chunkGraph, modules } = compilation;
return [
...modules
].find((module1)=>chunkGraph.getModuleId(module1) === id);
}
function findModuleNotFoundFromError(errorMessage) {
var _errorMessage_match;
return errorMessage == null ? void 0 : (_errorMessage_match = errorMessage.match(/'([^']+)' module/)) == null ? void 0 : _errorMessage_match[1];
}
function getSourcePath(source) {
if (source.startsWith('file://')) {
return (0, _url.fileURLToPath)(source);
}
return source.replace(/^(webpack:\/\/\/|webpack:\/\/|webpack:\/\/_N_E\/)/, '');
}
/**
* @returns 1-based lines and 0-based columns
*/ async function findOriginalSourcePositionAndContent(sourceMap, position) {
let consumer;
try {
consumer = await new _sourcemap08.SourceMapConsumer(sourceMap);
} catch (cause) {
console.error(Object.defineProperty(new Error(`${sourceMap.file}: Invalid source map. Only conformant source maps can be used to find the original code.`, {
cause
}), "__NEXT_ERROR_CODE", {
value: "E635",
enumerable: false,
configurable: true
}));
return null;
}
try {
const sourcePosition = consumer.originalPositionFor({
line: position.line1 ?? 1,
// 0-based columns out requires 0-based columns in.
column: (position.column1 ?? 1) - 1
});
if (!sourcePosition.source) {
return null;
}
const sourceContent = consumer.sourceContentFor(sourcePosition.source, /* returnNullOnMissing */ true) ?? null;
return {
sourcePosition,
sourceContent
};
} finally{
consumer.destroy();
}
}
function getIgnoredSources(sourceMap) {
const ignoreList = new Set(sourceMap.ignoreList ?? []);
const moduleFilenames = (sourceMap == null ? void 0 : sourceMap.sources) ?? [];
for(let index = 0; index < moduleFilenames.length; index++){
// bundlerFilePath case: webpack://./app/page.tsx
const webpackSourceURL = moduleFilenames[index];
// Format the path to the normal file path
const formattedFilePath = (0, _webpackmodulepath.formatFrameSourceFile)(webpackSourceURL);
if (shouldIgnoreSource(formattedFilePath)) {
ignoreList.add(index);
}
}
const ignoredSources = sourceMap.sources.map((source, index)=>{
var _sourceMap_sourcesContent;
return {
url: source,
ignored: ignoreList.has(sourceMap.sources.indexOf(source)),
content: ((_sourceMap_sourcesContent = sourceMap.sourcesContent) == null ? void 0 : _sourceMap_sourcesContent[index]) ?? null
};
});
return ignoredSources;
}
function isIgnoredSource(source, sourcePosition) {
if (sourcePosition.source == null) {
return true;
}
for (const ignoredSource of source.ignoredSources){
if (ignoredSource.ignored && ignoredSource.url === sourcePosition.source) {
return true;
}
}
return false;
}
function findOriginalSourcePositionAndContentFromCompilation(moduleId, importedModule, compilation) {
var _module_buildInfo_importLocByPath, _module_buildInfo;
const module1 = getModuleById(moduleId, compilation);
return (module1 == null ? void 0 : (_module_buildInfo = module1.buildInfo) == null ? void 0 : (_module_buildInfo_importLocByPath = _module_buildInfo.importLocByPath) == null ? void 0 : _module_buildInfo_importLocByPath.get(importedModule)) ?? null;
}
async function createOriginalStackFrame({ ignoredByDefault, source, rootDirectory, frame, errorMessage }) {
var // We ignore the sourcemapped name since it won't be the correct name.
// The callsite will point to the column of the variable name instead of the
// name of the enclosing function.
// TODO(NDX-531): Spy on prepareStackTrace to get the enclosing line number for method name mapping.
// default is not a valid identifier in JS so webpack uses a custom variable when it's an unnamed default export
// Resolve it back to `default` for the method name if the source position didn't have the method.
_frame_methodName_replace, _frame_methodName;
const moduleNotFound = findModuleNotFoundFromError(errorMessage);
const result = await (()=>{
if (moduleNotFound) {
if (source.type === 'file') {
return undefined;
}
return findOriginalSourcePositionAndContentFromCompilation(source.moduleId, moduleNotFound, source.compilation);
}
return findOriginalSourcePositionAndContent(source.sourceMap, frame);
})();
if (!result) {
return null;
}
const { sourcePosition, sourceContent } = result;
if (!sourcePosition.source) {
return null;
}
const ignored = ignoredByDefault || isIgnoredSource(source, sourcePosition) || // If the source file is externals, should be excluded even it's not ignored source.
// e.g. webpack://next/dist/.. needs to be ignored
shouldIgnoreSource(source.moduleURL);
const sourcePath = getSourcePath(// When sourcePosition.source is the loader path the modulePath is generally better.
(sourcePosition.source.includes('|') ? source.moduleURL : sourcePosition.source) || source.moduleURL);
const filePath = _path.default.resolve(rootDirectory, sourcePath);
const resolvedFilePath = _path.default.relative(rootDirectory, filePath);
const traced = {
file: resolvedFilePath,
line1: sourcePosition.line,
column1: sourcePosition.column === null ? null : sourcePosition.column + 1,
methodName: (_frame_methodName = frame.methodName) == null ? void 0 : (_frame_methodName_replace = _frame_methodName.replace('__WEBPACK_DEFAULT_EXPORT__', 'default')) == null ? void 0 : _frame_methodName_replace.replace('__webpack_exports__.', ''),
arguments: [],
ignored
};
return {
originalStackFrame: traced,
originalCodeFrame: (0, _shared.getOriginalCodeFrame)(traced, sourceContent)
};
}
async function getSourceMapFromCompilation(id, compilation) {
try {
const module1 = getModuleById(id, compilation);
if (!module1) {
return undefined;
}
// @ts-expect-error The types for `CodeGenerationResults.get` require a
// runtime to be passed as second argument, but apparently it also works
// without it.
const codeGenerationResult = compilation.codeGenerationResults.get(module1);
const source = codeGenerationResult == null ? void 0 : codeGenerationResult.sources.get('javascript');
return (source == null ? void 0 : source.map()) ?? undefined;
} catch (err) {
console.error(`Failed to lookup module by ID ("${id}"):`, err);
return undefined;
}
}
async function getSource(frame, options) {
let sourceURL = frame.file ?? '';
const { getCompilations } = options;
sourceURL = (0, _sourcemaps.devirtualizeReactServerURL)(sourceURL);
let nativeSourceMap;
try {
nativeSourceMap = (0, _module.findSourceMap)(sourceURL);
} catch (cause) {
throw Object.defineProperty(new Error(`${sourceURL}: Invalid source map. Only conformant source maps can be used to find the original code.`, {
cause
}), "__NEXT_ERROR_CODE", {
value: "E635",
enumerable: false,
configurable: true
});
}
if (nativeSourceMap !== undefined) {
const sourceMapPayload = nativeSourceMap.payload;
return {
type: 'file',
sourceMap: (0, _sourcemaps.findApplicableSourceMapPayload)((frame.line1 ?? 1) - 1, (frame.column1 ?? 1) - 1, sourceMapPayload),
ignoredSources: getIgnoredSources(// @ts-expect-error -- TODO: Support IndexSourceMap
sourceMapPayload),
moduleURL: sourceURL
};
}
if (_path.default.isAbsolute(sourceURL)) {
sourceURL = (0, _url.pathToFileURL)(sourceURL).href;
}
if (sourceURL.startsWith('file:')) {
const sourceMap = await (0, _getsourcemapfromfile.getSourceMapFromFile)(sourceURL);
return sourceMap ? {
type: 'file',
sourceMap,
ignoredSources: getIgnoredSources(sourceMap),
moduleURL: sourceURL
} : undefined;
}
// webpack-internal:///./src/hello.tsx => ./src/hello.tsx
// webpack://_N_E/./src/hello.tsx => ./src/hello.tsx
const moduleId = sourceURL.replace(/^(webpack-internal:\/\/\/|webpack:\/\/(_N_E\/)?)/, '').replace(/\?\d+$/, '');
// (rsc)/./src/hello.tsx => ./src/hello.tsx
const moduleURL = moduleId.replace(/^(\(.*\)\/?)/, '');
for (const compilation of getCompilations()){
const sourceMap = await getSourceMapFromCompilation(moduleId, compilation);
if (sourceMap) {
const ignoredSources = getIgnoredSources(sourceMap);
return {
type: 'bundle',
sourceMap,
compilation,
moduleId,
moduleURL,
ignoredSources
};
}
}
return undefined;
}
async function getOriginalStackFrames({ isServer, isEdgeServer, isAppDirectory, frames, clientStats, serverStats, edgeServerStats, rootDirectory }) {
const frameResponses = await Promise.all(frames.map((frame)=>getOriginalStackFrame({
isServer,
isEdgeServer,
isAppDirectory,
frame,
clientStats,
serverStats,
edgeServerStats,
rootDirectory
}).then((value)=>{
return {
status: 'fulfilled',
value
};
}, (reason)=>{
return {
status: 'rejected',
reason: (0, _util.inspect)(reason, {
colors: false
})
};
})));
(0, _shared.ignoreListAnonymousStackFramesIfSandwiched)(frameResponses);
return frameResponses;
}
async function getOriginalStackFrame({ isServer, isEdgeServer, isAppDirectory, frame, clientStats, serverStats, edgeServerStats, rootDirectory }) {
const filename = frame.file ?? '';
const source = await getSource(frame, {
getCompilations: ()=>{
const compilations = [];
// Try Client Compilation first. In `pages` we leverage
// `isClientError` to check. In `app` it depends on if it's a server
// / client component and when the code throws. E.g. during HTML
// rendering it's the server/edge compilation.
if (!isEdgeServer && !isServer || isAppDirectory) {
var _clientStats;
const compilation = (_clientStats = clientStats()) == null ? void 0 : _clientStats.compilation;
if (compilation) {
compilations.push(compilation);
}
}
// Try Server Compilation. In `pages` this could be something
// imported in getServerSideProps/getStaticProps as the code for
// those is tree-shaken. In `app` this finds server components and
// code that was imported from a server component. It also covers
// when client component code throws during HTML rendering.
if (isServer || isAppDirectory) {
var _serverStats;
const compilation = (_serverStats = serverStats()) == null ? void 0 : _serverStats.compilation;
if (compilation) {
compilations.push(compilation);
}
}
// Try Edge Server Compilation. Both cases are the same as Server
// Compilation, main difference is that it covers `runtime: 'edge'`
// pages/app routes.
if (isEdgeServer || isAppDirectory) {
var _edgeServerStats;
const compilation = (_edgeServerStats = edgeServerStats()) == null ? void 0 : _edgeServerStats.compilation;
if (compilation) {
compilations.push(compilation);
}
}
return compilations;
}
});
let defaultNormalizedStackFrameLocation = frame.file;
if (defaultNormalizedStackFrameLocation !== null && defaultNormalizedStackFrameLocation.startsWith('file://')) {
defaultNormalizedStackFrameLocation = _path.default.relative(rootDirectory, (0, _url.fileURLToPath)(defaultNormalizedStackFrameLocation));
}
// This stack frame is used for the one that couldn't locate the source or source mapped frame
const defaultStackFrame = {
file: defaultNormalizedStackFrameLocation,
line1: frame.line1,
column1: frame.column1,
methodName: frame.methodName,
ignored: shouldIgnoreSource(filename),
arguments: []
};
if (!source) {
// return original stack frame with no source map
return {
originalStackFrame: defaultStackFrame,
originalCodeFrame: null
};
}
defaultStackFrame.ignored ||= (0, _sourcemaps.sourceMapIgnoreListsEverything)(source.sourceMap);
const originalStackFrameResponse = await createOriginalStackFrame({
ignoredByDefault: defaultStackFrame.ignored,
frame,
source,
rootDirectory
});
if (!originalStackFrameResponse) {
return {
originalStackFrame: defaultStackFrame,
originalCodeFrame: null
};
}
return originalStackFrameResponse;
}
function getOverlayMiddleware(options) {
const { rootDirectory, isSrcDir, clientStats, serverStats, edgeServerStats } = options;
return async function(req, res, next) {
const { pathname, searchParams } = new URL(`http://n${req.url}`);
if (pathname === '/__nextjs_original-stack-frames') {
if (req.method !== 'POST') {
return _middlewareresponse.middlewareResponse.badRequest(res);
}
const body = await new Promise((resolve, reject)=>{
let data = '';
req.on('data', (chunk)=>{
data += chunk;
});
req.on('end', ()=>resolve(data));
req.on('error', reject);
});
try {
const { frames, isServer, isEdgeServer, isAppDirectory } = JSON.parse(body);
return _middlewareresponse.middlewareResponse.json(res, await getOriginalStackFrames({
isServer,
isEdgeServer,
isAppDirectory,
frames,
clientStats,
serverStats,
edgeServerStats,
rootDirectory
}));
} catch (err) {
return _middlewareresponse.middlewareResponse.badRequest(res);
}
} else if (pathname === '/__nextjs_launch-editor') {
const frame = {
file: searchParams.get('file'),
methodName: searchParams.get('methodName'),
line1: parseInt(searchParams.get('line1') ?? '1', 10) || 1,
column1: parseInt(searchParams.get('column1') ?? '1', 10) || 1,
arguments: searchParams.getAll('arguments').filter(Boolean)
};
if (!frame.file) return _middlewareresponse.middlewareResponse.badRequest(res);
let openEditorResult;
const isAppRelativePath = searchParams.get('isAppRelativePath') === '1';
if (isAppRelativePath) {
const relativeFilePath = searchParams.get('file') || '';
const appPath = _path.default.join('app', isSrcDir ? 'src' : '', relativeFilePath);
openEditorResult = await (0, _launcheditor.openFileInEditor)(appPath, 1, 1, rootDirectory);
} else {
// TODO: How do we differentiate layers and actual file paths with round brackets?
// frame files may start with their webpack layer, like (middleware)/middleware.js
const filePath = frame.file.replace(/^\([^)]+\)\//, '');
openEditorResult = await (0, _launcheditor.openFileInEditor)(filePath, frame.line1, frame.column1 ?? 1, rootDirectory);
}
if (openEditorResult.error) {
console.error('Failed to launch editor:', openEditorResult.error);
return _middlewareresponse.middlewareResponse.internalServerError(res, openEditorResult.error);
}
if (!openEditorResult.found) {
return _middlewareresponse.middlewareResponse.notFound(res);
}
return _middlewareresponse.middlewareResponse.noContent(res);
}
return next();
};
}
function getSourceMapMiddleware(options) {
const { clientStats, serverStats, edgeServerStats } = options;
return async function(req, res, next) {
const { pathname, searchParams } = new URL(`http://n${req.url}`);
if (pathname !== '/__nextjs_source-map') {
return next();
}
const filename = searchParams.get('filename');
if (!filename) {
return _middlewareresponse.middlewareResponse.badRequest(res);
}
let source;
try {
source = await getSource({
file: filename,
// Webpack doesn't use Index Source Maps
line1: null,
column1: null
}, {
getCompilations: ()=>{
const compilations = [];
for (const stats of [
clientStats(),
serverStats(),
edgeServerStats()
]){
if (stats == null ? void 0 : stats.compilation) {
compilations.push(stats.compilation);
}
}
return compilations;
}
});
} catch (error) {
return _middlewareresponse.middlewareResponse.internalServerError(res, error);
}
if (!source) {
return _middlewareresponse.middlewareResponse.noContent(res);
}
return _middlewareresponse.middlewareResponse.json(res, source.sourceMap);
};
}
//# sourceMappingURL=middleware-webpack.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,137 @@
import type { FindComponentsResult, NodeRequestHandler } from '../next-server';
import type { LoadComponentsReturnType } from '../load-components';
import type { Options as ServerOptions } from '../next-server';
import type { Params } from '../request/params';
import type { ParsedUrl } from '../../shared/lib/router/utils/parse-url';
import type { ParsedUrlQuery } from 'querystring';
import type { UrlWithParsedQuery } from 'url';
import type { MiddlewareRoutingItem } from '../base-server';
import type { RouteDefinition } from '../route-definitions/route-definition';
import type { RouteMatcherManager } from '../route-matcher-managers/route-matcher-manager';
import { type NextParsedUrlQuery, type NextUrlWithParsedQuery } from '../request-meta';
import type { DevBundlerService } from '../lib/dev-bundler-service';
import type { IncrementalCache } from '../lib/incremental-cache';
import type { NodeNextResponse, NodeNextRequest } from '../base-http/node';
import type { PagesManifest } from '../../build/webpack/plugins/pages-manifest-plugin';
import Server from '../next-server';
import { type Span } from '../../trace';
import { type ErrorModule } from '../load-default-error-components';
import { type NextConfigComplete } from '../config-shared';
import type { ServerOnInstrumentationRequestError } from '../app-render/types';
import type { ServerComponentsHmrCache } from '../response-cache';
import { FallbackMode } from '../../lib/fallback';
import type { PrerenderedRoute } from '../../build/static-paths/types';
export interface Options extends ServerOptions {
conf: NextConfigComplete;
/**
* Tells of Next.js is running from the `next dev` command
*/
isNextDevCommand?: boolean;
/**
* Interface to the development bundler.
*/
bundlerService: DevBundlerService;
/**
* Trace span for server startup.
*/
startServerSpan: Span;
}
export default class DevServer extends Server {
protected readonly nextConfig: NextConfigComplete;
/**
* The promise that resolves when the server is ready. When this is unset
* the server is ready.
*/
private ready?;
protected sortedRoutes?: string[];
private pagesDir?;
private appDir?;
private actualMiddlewareFile?;
private actualInstrumentationHookFile?;
private middleware?;
private readonly bundlerService;
private staticPathsCache;
private startServerSpan;
private readonly serverComponentsHmrCache;
protected staticPathsWorker?: {
[key: string]: any;
} & {
loadStaticPaths: typeof import('./static-paths-worker').loadStaticPaths;
};
private getStaticPathsWorker;
constructor(options: Options);
protected getServerComponentsHmrCache(): ServerComponentsHmrCache | undefined;
protected getRouteMatchers(): RouteMatcherManager;
protected getBuildId(): string;
protected prepareImpl(): Promise<void>;
protected hasPage(pathname: string): Promise<boolean>;
runMiddleware(params: {
request: NodeNextRequest;
response: NodeNextResponse;
parsedUrl: ParsedUrl;
parsed: UrlWithParsedQuery;
middlewareList: MiddlewareRoutingItem[];
}): Promise<import("../web/types").FetchEventResult | {
finished: boolean;
}>;
runEdgeFunction(params: {
req: NodeNextRequest;
res: NodeNextResponse;
query: ParsedUrlQuery;
params: Params | undefined;
page: string;
appPaths: string[] | null;
isAppPath: boolean;
}): Promise<import("../web/types").FetchEventResult | null>;
getRequestHandler(): NodeRequestHandler;
handleRequest(req: NodeNextRequest, res: NodeNextResponse, parsedUrl?: NextUrlWithParsedQuery): Promise<void>;
run(req: NodeNextRequest, res: NodeNextResponse, parsedUrl: UrlWithParsedQuery): Promise<void>;
protected logErrorWithOriginalStack(err?: unknown, type?: 'unhandledRejection' | 'uncaughtException' | 'warning' | 'app-dir'): void;
protected getPagesManifest(): PagesManifest | undefined;
protected getAppPathsManifest(): PagesManifest | undefined;
protected getinterceptionRoutePatterns(): RegExp[];
protected getMiddleware(): Promise<MiddlewareRoutingItem | undefined>;
protected getNextFontManifest(): undefined;
protected hasMiddleware(): Promise<boolean>;
protected ensureMiddleware(url: string): Promise<void>;
protected loadInstrumentationModule(): Promise<any>;
protected runInstrumentationHookIfAvailable(): Promise<void>;
protected ensureEdgeFunction({ page, appPaths, url, }: {
page: string;
appPaths: string[] | null;
url: string;
}): Promise<void>;
generateRoutes(_dev?: boolean): void;
protected getStaticPaths({ pathname, urlPathname, requestHeaders, page, isAppPath, }: {
pathname: string;
urlPathname: string;
requestHeaders: IncrementalCache['requestHeaders'];
page: string;
isAppPath: boolean;
}): Promise<{
prerenderedRoutes?: PrerenderedRoute[];
staticPaths?: string[];
fallbackMode?: FallbackMode;
}>;
protected ensurePage(opts: {
page: string;
clientOnly: boolean;
appPaths?: ReadonlyArray<string> | null;
definition: RouteDefinition | undefined;
url?: string;
}): Promise<void>;
protected findPageComponents({ locale, page, query, params, isAppPath, appPaths, shouldEnsure, url, }: {
locale: string | undefined;
page: string;
query: NextParsedUrlQuery;
params: Params;
isAppPath: boolean;
sriEnabled?: boolean;
appPaths?: ReadonlyArray<string> | null;
shouldEnsure: boolean;
url?: string;
}): Promise<FindComponentsResult | null>;
protected getFallbackErrorComponents(url?: string): Promise<LoadComponentsReturnType<ErrorModule> | null>;
getCompilationError(page: string): Promise<any>;
protected instrumentationOnRequestError(...args: Parameters<ServerOnInstrumentationRequestError>): Promise<void>;
}

View File

@@ -0,0 +1,717 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return DevServer;
}
});
const _requestmeta = require("../request-meta");
const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
const _jestworker = require("next/dist/compiled/jest-worker");
const _path = require("path");
const _constants = require("../../lib/constants");
const _findpagesdir = require("../../lib/find-pages-dir");
const _constants1 = require("../../shared/lib/constants");
const _nextserver = /*#__PURE__*/ _interop_require_wildcard(require("../next-server"));
const _normalizepagepath = require("../../shared/lib/page-path/normalize-page-path");
const _pathhasprefix = require("../../shared/lib/router/utils/path-has-prefix");
const _removepathprefix = require("../../shared/lib/router/utils/remove-path-prefix");
const _storage = require("../../telemetry/storage");
const _trace = require("../../trace");
const _shared = require("../../trace/shared");
const _findpagefile = require("../lib/find-page-file");
const _utils = require("../lib/utils");
const _coalescedfunction = require("../../lib/coalesced-function");
const _loaddefaulterrorcomponents = require("../load-default-error-components");
const _utils1 = require("../../shared/lib/utils");
const _log = /*#__PURE__*/ _interop_require_wildcard(require("../../build/output/log"));
const _iserror = /*#__PURE__*/ _interop_require_wildcard(require("../../lib/is-error"));
const _configshared = require("../config-shared");
const _utils2 = require("../../build/utils");
const _formatservererror = require("../../lib/format-server-error");
const _devroutematchermanager = require("../route-matcher-managers/dev-route-matcher-manager");
const _devpagesroutematcherprovider = require("../route-matcher-providers/dev/dev-pages-route-matcher-provider");
const _devpagesapiroutematcherprovider = require("../route-matcher-providers/dev/dev-pages-api-route-matcher-provider");
const _devapppageroutematcherprovider = require("../route-matcher-providers/dev/dev-app-page-route-matcher-provider");
const _devapprouteroutematcherprovider = require("../route-matcher-providers/dev/dev-app-route-route-matcher-provider");
const _nodemanifestloader = require("../route-matcher-providers/helpers/manifest-loaders/node-manifest-loader");
const _batchedfilereader = require("../route-matcher-providers/dev/helpers/file-reader/batched-file-reader");
const _defaultfilereader = require("../route-matcher-providers/dev/helpers/file-reader/default-file-reader");
const _lrucache = require("../lib/lru-cache");
const _middlewareroutematcher = require("../../shared/lib/router/utils/middleware-route-matcher");
const _detachedpromise = require("../../lib/detached-promise");
const _ispostpone = require("../lib/router-utils/is-postpone");
const _generateinterceptionroutesrewrites = require("../../lib/generate-interception-routes-rewrites");
const _buildcustomroute = require("../../lib/build-custom-route");
const _errorsource = require("../../shared/lib/error-source");
const _logrequests = require("./log-requests");
const _fallback = require("../../lib/fallback");
const _instrumentationglobalsexternal = require("../lib/router-utils/instrumentation-globals.external");
const _routeregex = require("../../shared/lib/router/utils/route-regex");
const _hotreloadertypes = require("./hot-reloader-types");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== "function") return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function(nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interop_require_wildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
}
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
return {
default: obj
};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {
__proto__: null
};
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
for(var key in obj){
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
// Load ReactDevOverlay only when needed
let PagesDevOverlayBridgeImpl;
const ReactDevOverlay = (props)=>{
if (PagesDevOverlayBridgeImpl === undefined) {
PagesDevOverlayBridgeImpl = require('../../next-devtools/userspace/pages/pages-dev-overlay-setup').PagesDevOverlayBridge;
}
return _react.createElement(PagesDevOverlayBridgeImpl, props);
};
class DevServer extends _nextserver.default {
getStaticPathsWorker() {
const worker = new _jestworker.Worker(require.resolve('./static-paths-worker'), {
maxRetries: 1,
// For dev server, it's not necessary to spin up too many workers as long as you are not doing a load test.
// This helps reusing the memory a lot.
numWorkers: 1,
enableWorkerThreads: this.nextConfig.experimental.workerThreads,
forkOptions: {
env: {
...process.env,
// discard --inspect/--inspect-brk flags from process.env.NODE_OPTIONS. Otherwise multiple Node.js debuggers
// would be started if user launch Next.js in debugging mode. The number of debuggers is linked to
// the number of workers Next.js tries to launch. The only worker users are interested in debugging
// is the main Next.js one
NODE_OPTIONS: (0, _utils.getFormattedNodeOptionsWithoutInspect)()
}
}
});
worker.getStdout().pipe(process.stdout);
worker.getStderr().pipe(process.stderr);
return worker;
}
constructor(options){
try {
// Increase the number of stack frames on the server
Error.stackTraceLimit = 50;
} catch {}
super({
...options,
dev: true
}), /**
* The promise that resolves when the server is ready. When this is unset
* the server is ready.
*/ this.ready = new _detachedpromise.DetachedPromise();
this.nextConfig = options.conf;
this.bundlerService = options.bundlerService;
this.startServerSpan = options.startServerSpan ?? (0, _trace.trace)('start-next-dev-server');
this.renderOpts.dev = true;
this.renderOpts.ErrorDebug = ReactDevOverlay;
this.staticPathsCache = new _lrucache.LRUCache(// 5MB
5 * 1024 * 1024, function length(value) {
var _JSON_stringify;
return ((_JSON_stringify = JSON.stringify(value.staticPaths)) == null ? void 0 : _JSON_stringify.length) ?? 0;
});
const { pagesDir, appDir } = (0, _findpagesdir.findPagesDir)(this.dir);
this.pagesDir = pagesDir;
this.appDir = appDir;
if (this.nextConfig.experimental.serverComponentsHmrCache) {
// Ensure HMR cache has a minimum size equal to the default cacheMaxMemorySize,
// but allow it to grow if the user has configured a larger value.
const hmrCacheSize = Math.max(this.nextConfig.cacheMaxMemorySize, _configshared.defaultConfig.cacheMaxMemorySize);
this.serverComponentsHmrCache = new _lrucache.LRUCache(hmrCacheSize, function length(value) {
return JSON.stringify(value).length;
});
}
}
getServerComponentsHmrCache() {
return this.serverComponentsHmrCache;
}
getRouteMatchers() {
const { pagesDir, appDir } = (0, _findpagesdir.findPagesDir)(this.dir);
const ensurer = {
ensure: async (match, pathname)=>{
await this.ensurePage({
definition: match.definition,
page: match.definition.page,
clientOnly: false,
url: pathname
});
}
};
const matchers = new _devroutematchermanager.DevRouteMatcherManager(super.getRouteMatchers(), ensurer, this.dir);
const extensions = this.nextConfig.pageExtensions;
const extensionsExpression = new RegExp(`\\.(?:${extensions.join('|')})$`);
// If the pages directory is available, then configure those matchers.
if (pagesDir) {
const fileReader = new _batchedfilereader.BatchedFileReader(new _defaultfilereader.DefaultFileReader({
// Only allow files that have the correct extensions.
pathnameFilter: (pathname)=>extensionsExpression.test(pathname)
}));
matchers.push(new _devpagesroutematcherprovider.DevPagesRouteMatcherProvider(pagesDir, extensions, fileReader, this.localeNormalizer));
matchers.push(new _devpagesapiroutematcherprovider.DevPagesAPIRouteMatcherProvider(pagesDir, extensions, fileReader, this.localeNormalizer));
}
if (appDir) {
// We create a new file reader for the app directory because we don't want
// to include any folders or files starting with an underscore. This will
// prevent the reader from wasting time reading files that we know we
// don't care about.
const fileReader = new _batchedfilereader.BatchedFileReader(new _defaultfilereader.DefaultFileReader({
// Ignore any directory prefixed with an underscore.
ignorePartFilter: (part)=>part.startsWith('_')
}));
// TODO: Improve passing of "is running with Turbopack"
const isTurbopack = !!process.env.TURBOPACK;
matchers.push(new _devapppageroutematcherprovider.DevAppPageRouteMatcherProvider(appDir, extensions, fileReader, isTurbopack));
matchers.push(new _devapprouteroutematcherprovider.DevAppRouteRouteMatcherProvider(appDir, extensions, fileReader, isTurbopack));
}
return matchers;
}
getBuildId() {
return 'development';
}
async prepareImpl() {
var _this_ready;
(0, _trace.setGlobal)('distDir', this.distDir);
(0, _trace.setGlobal)('phase', _constants1.PHASE_DEVELOPMENT_SERVER);
// Use existing telemetry instance from traceGlobals instead of creating a new one.
// Creating a new instance would overwrite the existing one, causing any telemetry
// events recorded to the original instance to be lost during cleanup/flush.
const existingTelemetry = _shared.traceGlobals.get('telemetry');
const telemetry = existingTelemetry || new _storage.Telemetry({
distDir: this.distDir
});
await super.prepareImpl();
await this.matchers.reload();
(_this_ready = this.ready) == null ? void 0 : _this_ready.resolve();
this.ready = undefined;
// In dev, this needs to be called after prepare because the build entries won't be known in the constructor
this.interceptionRoutePatterns = this.getinterceptionRoutePatterns();
// This is required by the tracing subsystem.
(0, _trace.setGlobal)('appDir', this.appDir);
(0, _trace.setGlobal)('pagesDir', this.pagesDir);
// Only set telemetry if it wasn't already set
if (!existingTelemetry) {
(0, _trace.setGlobal)('telemetry', telemetry);
}
process.on('unhandledRejection', (reason)=>{
if ((0, _ispostpone.isPostpone)(reason)) {
// React postpones that are unhandled might end up logged here but they're
// not really errors. They're just part of rendering.
return;
}
this.logErrorWithOriginalStack(reason, 'unhandledRejection');
});
process.on('uncaughtException', (err)=>{
this.logErrorWithOriginalStack(err, 'uncaughtException');
});
}
async hasPage(pathname) {
let normalizedPath;
try {
normalizedPath = (0, _normalizepagepath.normalizePagePath)(pathname);
} catch (err) {
console.error(err);
// if normalizing the page fails it means it isn't valid
// so it doesn't exist so don't throw and return false
// to ensure we return 404 instead of 500
return false;
}
if ((0, _utils2.isMiddlewareFile)(normalizedPath)) {
return (0, _findpagefile.findPageFile)(this.dir, normalizedPath, this.nextConfig.pageExtensions, false).then(Boolean);
}
let appFile = null;
let pagesFile = null;
if (this.appDir) {
appFile = await (0, _findpagefile.findPageFile)(this.appDir, normalizedPath + '/page', this.nextConfig.pageExtensions, true);
}
if (this.pagesDir) {
pagesFile = await (0, _findpagefile.findPageFile)(this.pagesDir, normalizedPath, this.nextConfig.pageExtensions, false);
}
if (appFile && pagesFile) {
return false;
}
return Boolean(appFile || pagesFile);
}
async runMiddleware(params) {
try {
const result = await super.runMiddleware({
...params,
onWarning: (warn)=>{
this.logErrorWithOriginalStack(warn, 'warning');
}
});
if ('finished' in result) {
return result;
}
result.waitUntil.catch((error)=>{
this.logErrorWithOriginalStack(error, 'unhandledRejection');
});
return result;
} catch (error) {
if (error instanceof _utils1.DecodeError) {
throw error;
}
/**
* We only log the error when it is not a MiddlewareNotFound error as
* in that case we should be already displaying a compilation error
* which is what makes the module not found.
*/ if (!(error instanceof _utils1.MiddlewareNotFoundError)) {
this.logErrorWithOriginalStack(error);
}
const err = (0, _iserror.getProperError)(error);
(0, _errorsource.decorateServerError)(err, _constants1.COMPILER_NAMES.edgeServer);
const { request, response, parsedUrl } = params;
/**
* When there is a failure for an internal Next.js request from
* middleware we bypass the error without finishing the request
* so we can serve the required chunks to render the error.
*/ if (request.url.includes('/_next/static') || request.url.includes('/__nextjs_attach-nodejs-inspector') || request.url.includes('/__nextjs_original-stack-frame') || request.url.includes('/__nextjs_source-map') || request.url.includes('/__nextjs_error_feedback')) {
return {
finished: false
};
}
response.statusCode = 500;
await this.renderError(err, request, response, parsedUrl.pathname);
return {
finished: true
};
}
}
async runEdgeFunction(params) {
try {
return super.runEdgeFunction({
...params,
onError: (err)=>this.logErrorWithOriginalStack(err, 'app-dir'),
onWarning: (warn)=>{
this.logErrorWithOriginalStack(warn, 'warning');
}
});
} catch (error) {
if (error instanceof _utils1.DecodeError) {
throw error;
}
this.logErrorWithOriginalStack(error, 'warning');
const err = (0, _iserror.getProperError)(error);
const { req, res, page } = params;
res.statusCode = 500;
await this.renderError(err, req, res, page);
return null;
}
}
getRequestHandler() {
const handler = super.getRequestHandler();
return (req, res, parsedUrl)=>{
const request = this.normalizeReq(req);
const response = this.normalizeRes(res);
const loggingConfig = this.nextConfig.logging;
if (loggingConfig !== false) {
// The closure variable is not used here because the request handler may be invoked twice for one request when middleware is added in the application.
// By setting the start time we can ensure that the middleware timing is correctly included.
if (!(0, _requestmeta.getRequestMeta)(req, 'devRequestTimingStart')) {
const requestStart = process.hrtime.bigint();
(0, _requestmeta.addRequestMeta)(req, 'devRequestTimingStart', requestStart);
}
const isMiddlewareRequest = (0, _requestmeta.getRequestMeta)(req, 'middlewareInvoke') ?? false;
if (!isMiddlewareRequest) {
response.originalResponse.once('close', ()=>{
// NOTE: The route match is only attached to the request's meta data
// after the request handler is created, so we need to check it in the
// close handler and not before.
const routeMatch = (0, _requestmeta.getRequestMeta)(req).match;
if (!routeMatch) {
return;
}
// The closure variable is not used here because the request handler may be invoked twice for one request when middleware is added in the application.
// By setting the start time we can ensure that the middleware timing is correctly included.
const requestStart = (0, _requestmeta.getRequestMeta)(req, 'devRequestTimingStart');
if (!requestStart) {
return;
}
const requestEnd = process.hrtime.bigint();
(0, _logrequests.logRequests)(request, response, loggingConfig, requestStart, requestEnd, (0, _requestmeta.getRequestMeta)(req, 'devRequestTimingMiddlewareStart'), (0, _requestmeta.getRequestMeta)(req, 'devRequestTimingMiddlewareEnd'), (0, _requestmeta.getRequestMeta)(req, 'devRequestTimingInternalsEnd'), (0, _requestmeta.getRequestMeta)(req, 'devGenerateStaticParamsDuration'));
});
}
}
return handler(request, response, parsedUrl);
};
}
async handleRequest(req, res, parsedUrl) {
const span = (0, _trace.trace)('handle-request', undefined, {
url: req.url
});
const result = await span.traceAsyncFn(async ()=>{
var _this_ready;
await ((_this_ready = this.ready) == null ? void 0 : _this_ready.promise);
(0, _requestmeta.addRequestMeta)(req, 'PagesErrorDebug', this.renderOpts.ErrorDebug);
return await super.handleRequest(req, res, parsedUrl);
});
const memoryUsage = process.memoryUsage();
span.traceChild('memory-usage', {
url: req.url,
'memory.rss': String(memoryUsage.rss),
'memory.heapUsed': String(memoryUsage.heapUsed),
'memory.heapTotal': String(memoryUsage.heapTotal)
}).stop();
return result;
}
async run(req, res, parsedUrl) {
var _this_ready;
await ((_this_ready = this.ready) == null ? void 0 : _this_ready.promise);
const { basePath } = this.nextConfig;
let originalPathname = null;
// TODO: see if we can remove this in the future
if (basePath && (0, _pathhasprefix.pathHasPrefix)(parsedUrl.pathname || '/', basePath)) {
// strip basePath before handling dev bundles
// If replace ends up replacing the full url it'll be `undefined`, meaning we have to default it to `/`
originalPathname = parsedUrl.pathname;
parsedUrl.pathname = (0, _removepathprefix.removePathPrefix)(parsedUrl.pathname || '/', basePath);
}
const { pathname } = parsedUrl;
if (pathname.startsWith('/_next')) {
if (_fs.default.existsSync((0, _path.join)(this.publicDir, '_next'))) {
throw Object.defineProperty(new Error(_constants.PUBLIC_DIR_MIDDLEWARE_CONFLICT), "__NEXT_ERROR_CODE", {
value: "E394",
enumerable: false,
configurable: true
});
}
}
if (originalPathname) {
// restore the path before continuing so that custom-routes can accurately determine
// if they should match against the basePath or not
parsedUrl.pathname = originalPathname;
}
try {
return await super.run(req, res, parsedUrl);
} catch (error) {
const err = (0, _iserror.getProperError)(error);
(0, _formatservererror.formatServerError)(err);
this.logErrorWithOriginalStack(err);
if (!res.sent) {
res.statusCode = 500;
try {
return await this.renderError(err, req, res, pathname, {
__NEXT_PAGE: (0, _iserror.default)(err) && err.page || pathname || ''
});
} catch (internalErr) {
console.error(internalErr);
res.body('Internal Server Error').send();
}
}
}
}
logErrorWithOriginalStack(err, type) {
this.bundlerService.logErrorWithOriginalStack(err, type);
}
getPagesManifest() {
return _nodemanifestloader.NodeManifestLoader.require((0, _path.join)(this.serverDistDir, _constants1.PAGES_MANIFEST)) ?? undefined;
}
getAppPathsManifest() {
if (!this.enabledDirectories.app) return undefined;
return _nodemanifestloader.NodeManifestLoader.require((0, _path.join)(this.serverDistDir, _constants1.APP_PATHS_MANIFEST)) ?? undefined;
}
getinterceptionRoutePatterns() {
const rewrites = (0, _generateinterceptionroutesrewrites.generateInterceptionRoutesRewrites)(Object.keys(this.appPathRoutes ?? {}), this.nextConfig.basePath).map((route)=>new RegExp((0, _buildcustomroute.buildCustomRoute)('rewrite', route).regex));
if (this.nextConfig.output === 'export' && rewrites.length > 0) {
_log.error('Intercepting routes are not supported with static export.\nRead more: https://nextjs.org/docs/app/building-your-application/deploying/static-exports#unsupported-features');
process.exit(1);
}
return rewrites ?? [];
}
async getMiddleware() {
var _this_middleware;
// We need to populate the match
// field as it isn't serializable
if (((_this_middleware = this.middleware) == null ? void 0 : _this_middleware.match) === null) {
this.middleware.match = (0, _middlewareroutematcher.getMiddlewareRouteMatcher)(this.middleware.matchers || []);
}
return this.middleware;
}
getNextFontManifest() {
return undefined;
}
async hasMiddleware() {
return this.hasPage(this.actualMiddlewareFile);
}
async ensureMiddleware(url) {
return this.ensurePage({
page: this.actualMiddlewareFile,
clientOnly: false,
definition: undefined,
url
});
}
async loadInstrumentationModule() {
let instrumentationModule;
if (this.actualInstrumentationHookFile && await this.ensurePage({
page: this.actualInstrumentationHookFile,
clientOnly: false,
definition: undefined
}).then(()=>true).catch(()=>false)) {
try {
instrumentationModule = await (0, _instrumentationglobalsexternal.getInstrumentationModule)(this.dir, this.nextConfig.distDir);
} catch (err) {
err.message = `An error occurred while loading instrumentation hook: ${err.message}`;
throw err;
}
}
return instrumentationModule;
}
async runInstrumentationHookIfAvailable() {
await (0, _instrumentationglobalsexternal.ensureInstrumentationRegistered)(this.dir, this.nextConfig.distDir);
}
async ensureEdgeFunction({ page, appPaths, url }) {
return this.ensurePage({
page,
appPaths,
clientOnly: false,
definition: undefined,
url
});
}
generateRoutes(_dev) {
// In development we expose all compiled files for react-error-overlay's line show feature
// We use unshift so that we're sure the routes is defined before Next's default routes
// routes.unshift({
// match: getPathMatch('/_next/development/:path*'),
// type: 'route',
// name: '_next/development catchall',
// fn: async (req, res, params) => {
// const p = pathJoin(this.distDir, ...(params.path || []))
// await this.serveStatic(req, res, p)
// return {
// finished: true,
// }
// },
// })
}
async getStaticPaths({ pathname, urlPathname, requestHeaders, page, isAppPath }) {
// we lazy load the staticPaths to prevent the user
// from waiting on them for the page to load in dev mode
const __getStaticPaths = async ()=>{
const { configFileName, httpAgentOptions } = this.nextConfig;
const { locales, defaultLocale } = this.nextConfig.i18n || {};
const staticPathsWorker = this.getStaticPathsWorker();
try {
var _this_nextConfig_experimental_sri;
const pathsResult = await staticPathsWorker.loadStaticPaths({
dir: this.dir,
distDir: this.distDir,
pathname,
config: {
pprConfig: this.nextConfig.experimental.ppr,
configFileName,
cacheComponents: Boolean(this.nextConfig.cacheComponents)
},
httpAgentOptions,
locales,
defaultLocale,
page,
isAppPath,
requestHeaders,
cacheHandler: this.nextConfig.cacheHandler,
cacheHandlers: this.nextConfig.cacheHandlers,
cacheLifeProfiles: this.nextConfig.cacheLife,
fetchCacheKeyPrefix: this.nextConfig.experimental.fetchCacheKeyPrefix,
isrFlushToDisk: this.nextConfig.experimental.isrFlushToDisk,
cacheMaxMemorySize: this.nextConfig.cacheMaxMemorySize,
nextConfigOutput: this.nextConfig.output,
buildId: this.buildId,
authInterrupts: Boolean(this.nextConfig.experimental.authInterrupts),
sriEnabled: Boolean((_this_nextConfig_experimental_sri = this.nextConfig.experimental.sri) == null ? void 0 : _this_nextConfig_experimental_sri.algorithm)
});
return pathsResult;
} finally{
// we don't re-use workers so destroy the used one
staticPathsWorker.end();
}
};
const result = this.staticPathsCache.get(pathname);
const nextInvoke = (0, _coalescedfunction.withCoalescedInvoke)(__getStaticPaths)(`staticPaths-${pathname}`, []).then(async (res)=>{
var _res_value;
const { prerenderedRoutes, fallbackMode: fallback } = res.value;
if (isAppPath) {
var // Ideally, we would want to compare the whole objects, but that is too expensive.
_result_prerenderedRoutes;
if (this.nextConfig.output === 'export') {
if (!prerenderedRoutes) {
throw Object.defineProperty(new Error(`Page "${page}" is missing exported function "generateStaticParams()", which is required with "output: export" config.`), "__NEXT_ERROR_CODE", {
value: "E353",
enumerable: false,
configurable: true
});
}
if (!prerenderedRoutes.some((item)=>item.pathname === urlPathname)) {
throw Object.defineProperty(new Error(`Page "${page}" is missing param "${pathname}" in "generateStaticParams()", which is required with "output: export" config.`), "__NEXT_ERROR_CODE", {
value: "E443",
enumerable: false,
configurable: true
});
}
}
// Since generateStaticParams run on the background, when accessing the
// devFallbackParams during the render, it is still set to the previous
// result from the cache. Therefore when the result has changed, re-render
// the Server Component to sync the devFallbackParams with the new result.
if (isAppPath && this.nextConfig.cacheComponents && // Ensure this is not the first invocation.
result && ((_result_prerenderedRoutes = result.prerenderedRoutes) == null ? void 0 : _result_prerenderedRoutes.length) !== (prerenderedRoutes == null ? void 0 : prerenderedRoutes.length)) {
this.bundlerService.sendHmrMessage({
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.SERVER_COMPONENT_CHANGES,
hash: `generateStaticParams-${Date.now()}`
});
}
}
if (!isAppPath && this.nextConfig.output === 'export') {
if (fallback === _fallback.FallbackMode.BLOCKING_STATIC_RENDER) {
throw Object.defineProperty(new Error('getStaticPaths with "fallback: blocking" cannot be used with "output: export". See more info here: https://nextjs.org/docs/advanced-features/static-html-export'), "__NEXT_ERROR_CODE", {
value: "E11",
enumerable: false,
configurable: true
});
} else if (fallback === _fallback.FallbackMode.PRERENDER) {
throw Object.defineProperty(new Error('getStaticPaths with "fallback: true" cannot be used with "output: export". See more info here: https://nextjs.org/docs/advanced-features/static-html-export'), "__NEXT_ERROR_CODE", {
value: "E210",
enumerable: false,
configurable: true
});
}
}
const value = {
staticPaths: prerenderedRoutes == null ? void 0 : prerenderedRoutes.map((route)=>route.pathname),
prerenderedRoutes,
fallbackMode: fallback
};
if (((_res_value = res.value) == null ? void 0 : _res_value.fallbackMode) !== undefined && // This matches the hasGenerateStaticParams logic we do during build.
(!isAppPath || prerenderedRoutes && prerenderedRoutes.length > 0)) {
// we write the static paths to partial manifest for
// fallback handling inside of entry handler's
const rawExistingManifest = await _fs.default.promises.readFile((0, _path.join)(this.distDir, _constants1.PRERENDER_MANIFEST), 'utf8');
const existingManifest = JSON.parse(rawExistingManifest);
for (const staticPath of value.staticPaths || []){
existingManifest.routes[staticPath] = {};
}
existingManifest.dynamicRoutes[pathname] = {
dataRoute: null,
dataRouteRegex: null,
fallback: (0, _fallback.fallbackModeToFallbackField)(res.value.fallbackMode, page),
fallbackRevalidate: false,
fallbackExpire: undefined,
fallbackHeaders: undefined,
fallbackStatus: undefined,
fallbackRootParams: undefined,
fallbackRouteParams: undefined,
fallbackSourceRoute: pathname,
prefetchDataRoute: undefined,
prefetchDataRouteRegex: undefined,
routeRegex: (0, _routeregex.getRouteRegex)(pathname).re.source,
experimentalPPR: undefined,
renderingMode: undefined,
allowHeader: []
};
const updatedManifest = JSON.stringify(existingManifest);
if (updatedManifest !== rawExistingManifest) {
await _fs.default.promises.writeFile((0, _path.join)(this.distDir, _constants1.PRERENDER_MANIFEST), updatedManifest);
}
}
this.staticPathsCache.set(pathname, value);
return value;
}).catch((err)=>{
this.staticPathsCache.remove(pathname);
if (!result) throw err;
_log.error(`Failed to generate static paths for ${pathname}:`);
console.error(err);
});
if (result) {
return result;
}
return nextInvoke;
}
async ensurePage(opts) {
await this.bundlerService.ensurePage(opts);
}
async findPageComponents({ locale, page, query, params, isAppPath, appPaths = null, shouldEnsure, url }) {
var _this_ready;
await ((_this_ready = this.ready) == null ? void 0 : _this_ready.promise);
const compilationErr = await this.getCompilationError(page);
if (compilationErr) {
// Wrap build errors so that they don't get logged again
throw new _nextserver.WrappedBuildError(compilationErr);
}
if (shouldEnsure || this.serverOptions.customServer) {
await this.ensurePage({
page,
appPaths,
clientOnly: false,
definition: undefined,
url
});
}
this.nextFontManifest = super.getNextFontManifest();
return await super.findPageComponents({
page,
query,
params,
locale,
isAppPath,
shouldEnsure,
url
});
}
async getFallbackErrorComponents(url) {
await this.bundlerService.getFallbackErrorComponents(url);
return await (0, _loaddefaulterrorcomponents.loadDefaultErrorComponents)(this.distDir);
}
async getCompilationError(page) {
return await this.bundlerService.getCompilationError(page);
}
async instrumentationOnRequestError(...args) {
await super.instrumentationOnRequestError(...args);
const [err, , , silenceLog] = args;
if (!silenceLog) {
this.logErrorWithOriginalStack(err, 'app-dir');
}
}
}
//# sourceMappingURL=next-dev-server.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
import { type ErrorSourceType } from '../../shared/lib/error-source';
export declare function getServerError(error: Error, type: ErrorSourceType): Error;

View File

@@ -0,0 +1,72 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "getServerError", {
enumerable: true,
get: function() {
return getServerError;
}
});
const _stacktraceparser = require("next/dist/compiled/stacktrace-parser");
const _errorsource = require("../../shared/lib/error-source");
function getFilesystemFrame(frame) {
const f = {
...frame
};
if (typeof f.file === 'string') {
if (// Posix:
f.file.startsWith('/') || // Win32:
/^[a-z]:\\/i.test(f.file) || // Win32 UNC:
f.file.startsWith('\\\\')) {
f.file = `file://${f.file}`;
}
}
return f;
}
function getServerError(error, type) {
if (error.name === 'TurbopackInternalError') {
// If this is an internal Turbopack error we shouldn't show internal details
// to the user. These are written to a log file instead.
const turbopackInternalError = Object.defineProperty(new Error('An unexpected Turbopack error occurred. Please see the output of `next dev` for more details.'), "__NEXT_ERROR_CODE", {
value: "E167",
enumerable: false,
configurable: true
});
(0, _errorsource.decorateServerError)(turbopackInternalError, type);
return turbopackInternalError;
}
let n;
try {
throw Object.defineProperty(new Error(error.message), "__NEXT_ERROR_CODE", {
value: "E394",
enumerable: false,
configurable: true
});
} catch (e) {
n = e;
}
n.name = error.name;
try {
n.stack = `${n.toString()}\n${(0, _stacktraceparser.parse)(error.stack).map(getFilesystemFrame).map((f)=>{
let str = ` at ${f.methodName}`;
if (f.file) {
let loc = f.file;
if (f.lineNumber) {
loc += `:${f.lineNumber}`;
if (f.column) {
loc += `:${f.column}`;
}
}
str += ` (${loc})`;
}
return str;
}).join('\n')}`;
} catch {
n.stack = error.stack;
}
(0, _errorsource.decorateServerError)(n, type);
return n;
}
//# sourceMappingURL=node-stack-frames.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../src/server/dev/node-stack-frames.ts"],"sourcesContent":["import { parse } from 'next/dist/compiled/stacktrace-parser'\nimport type { StackFrame } from 'next/dist/compiled/stacktrace-parser'\nimport {\n decorateServerError,\n type ErrorSourceType,\n} from '../../shared/lib/error-source'\n\nfunction getFilesystemFrame(frame: StackFrame): StackFrame {\n const f: StackFrame = { ...frame }\n\n if (typeof f.file === 'string') {\n if (\n // Posix:\n f.file.startsWith('/') ||\n // Win32:\n /^[a-z]:\\\\/i.test(f.file) ||\n // Win32 UNC:\n f.file.startsWith('\\\\\\\\')\n ) {\n f.file = `file://${f.file}`\n }\n }\n\n return f\n}\n\nexport function getServerError(error: Error, type: ErrorSourceType): Error {\n if (error.name === 'TurbopackInternalError') {\n // If this is an internal Turbopack error we shouldn't show internal details\n // to the user. These are written to a log file instead.\n const turbopackInternalError = new Error(\n 'An unexpected Turbopack error occurred. Please see the output of `next dev` for more details.'\n )\n decorateServerError(turbopackInternalError, type)\n return turbopackInternalError\n }\n\n let n: Error\n try {\n throw new Error(error.message)\n } catch (e) {\n n = e as Error\n }\n\n n.name = error.name\n try {\n n.stack = `${n.toString()}\\n${parse(error.stack!)\n .map(getFilesystemFrame)\n .map((f) => {\n let str = ` at ${f.methodName}`\n if (f.file) {\n let loc = f.file\n if (f.lineNumber) {\n loc += `:${f.lineNumber}`\n if (f.column) {\n loc += `:${f.column}`\n }\n }\n str += ` (${loc})`\n }\n return str\n })\n .join('\\n')}`\n } catch {\n n.stack = error.stack\n }\n\n decorateServerError(n, type)\n return n\n}\n"],"names":["getServerError","getFilesystemFrame","frame","f","file","startsWith","test","error","type","name","turbopackInternalError","Error","decorateServerError","n","message","e","stack","toString","parse","map","str","methodName","loc","lineNumber","column","join"],"mappings":";;;;+BA0BgBA;;;eAAAA;;;kCA1BM;6BAKf;AAEP,SAASC,mBAAmBC,KAAiB;IAC3C,MAAMC,IAAgB;QAAE,GAAGD,KAAK;IAAC;IAEjC,IAAI,OAAOC,EAAEC,IAAI,KAAK,UAAU;QAC9B,IACE,SAAS;QACTD,EAAEC,IAAI,CAACC,UAAU,CAAC,QAClB,SAAS;QACT,aAAaC,IAAI,CAACH,EAAEC,IAAI,KACxB,aAAa;QACbD,EAAEC,IAAI,CAACC,UAAU,CAAC,SAClB;YACAF,EAAEC,IAAI,GAAG,CAAC,OAAO,EAAED,EAAEC,IAAI,EAAE;QAC7B;IACF;IAEA,OAAOD;AACT;AAEO,SAASH,eAAeO,KAAY,EAAEC,IAAqB;IAChE,IAAID,MAAME,IAAI,KAAK,0BAA0B;QAC3C,4EAA4E;QAC5E,wDAAwD;QACxD,MAAMC,yBAAyB,qBAE9B,CAF8B,IAAIC,MACjC,kGAD6B,qBAAA;mBAAA;wBAAA;0BAAA;QAE/B;QACAC,IAAAA,gCAAmB,EAACF,wBAAwBF;QAC5C,OAAOE;IACT;IAEA,IAAIG;IACJ,IAAI;QACF,MAAM,qBAAwB,CAAxB,IAAIF,MAAMJ,MAAMO,OAAO,GAAvB,qBAAA;mBAAA;wBAAA;0BAAA;QAAuB;IAC/B,EAAE,OAAOC,GAAG;QACVF,IAAIE;IACN;IAEAF,EAAEJ,IAAI,GAAGF,MAAME,IAAI;IACnB,IAAI;QACFI,EAAEG,KAAK,GAAG,GAAGH,EAAEI,QAAQ,GAAG,EAAE,EAAEC,IAAAA,uBAAK,EAACX,MAAMS,KAAK,EAC5CG,GAAG,CAAClB,oBACJkB,GAAG,CAAC,CAAChB;YACJ,IAAIiB,MAAM,CAAC,OAAO,EAAEjB,EAAEkB,UAAU,EAAE;YAClC,IAAIlB,EAAEC,IAAI,EAAE;gBACV,IAAIkB,MAAMnB,EAAEC,IAAI;gBAChB,IAAID,EAAEoB,UAAU,EAAE;oBAChBD,OAAO,CAAC,CAAC,EAAEnB,EAAEoB,UAAU,EAAE;oBACzB,IAAIpB,EAAEqB,MAAM,EAAE;wBACZF,OAAO,CAAC,CAAC,EAAEnB,EAAEqB,MAAM,EAAE;oBACvB;gBACF;gBACAJ,OAAO,CAAC,EAAE,EAAEE,IAAI,CAAC,CAAC;YACpB;YACA,OAAOF;QACT,GACCK,IAAI,CAAC,OAAO;IACjB,EAAE,OAAM;QACNZ,EAAEG,KAAK,GAAGT,MAAMS,KAAK;IACvB;IAEAJ,IAAAA,gCAAmB,EAACC,GAAGL;IACvB,OAAOK;AACT","ignoreList":[0]}

View File

@@ -0,0 +1,129 @@
import type ws from 'next/dist/compiled/ws';
import type { webpack } from 'next/dist/compiled/webpack/webpack';
import type { NextConfigComplete } from '../config-shared';
import type { CompilerNameValues } from '../../shared/lib/constants';
import type { RouteDefinition } from '../route-definitions/route-definition';
import { COMPILER_INDEXES } from '../../shared/lib/constants';
import { type NextJsHotReloaderInterface } from './hot-reloader-types';
import { PAGE_TYPES } from '../../lib/page-types';
declare const COMPILER_KEYS: CompilerNameValues[];
/**
* format: {compiler type}@{page type}@{page path}
* e.g. client@pages@/index
* e.g. server@app@app/page
*
* This guarantees the uniqueness for each page, to avoid conflicts between app/ and pages/
*/
export declare function getEntryKey(compilerType: CompilerNameValues, pageBundleType: PAGE_TYPES, page: string): string;
export declare const ADDED: unique symbol;
export declare const BUILDING: unique symbol;
export declare const BUILT: unique symbol;
interface EntryType {
/**
* Tells if a page is scheduled to be disposed.
*/
dispose?: boolean;
/**
* Timestamp with the last time the page was active.
*/
lastActiveTime?: number;
/**
* Page build status.
*/
status?: typeof ADDED | typeof BUILDING | typeof BUILT;
/**
* Path to the page file relative to the dist folder with no extension.
* For example: `pages/about/index`
*/
bundlePath: string;
/**
* Webpack request to create a dependency for.
*/
request: string;
}
export declare const enum EntryTypes {
ENTRY = 0,
CHILD_ENTRY = 1
}
interface Entry extends EntryType {
type: EntryTypes.ENTRY;
/**
* The absolute page to the page file. Used for detecting if the file was removed. For example:
* `/Users/Rick/project/pages/about/index.js`
*/
absolutePagePath: string;
/**
* All parallel pages that match the same entry, for example:
* ['/parallel/@bar/nested/@a/page', '/parallel/@bar/nested/@b/page', '/parallel/@foo/nested/@a/page', '/parallel/@foo/nested/@b/page']
*/
appPaths: ReadonlyArray<string> | null;
}
interface ChildEntry extends EntryType {
type: EntryTypes.CHILD_ENTRY;
/**
* Which parent entries use this childEntry.
*/
parentEntries: Set<string>;
/**
* The absolute page to the entry file. Used for detecting if the file was removed. For example:
* `/Users/Rick/project/app/about/layout.js`
*/
absoluteEntryFilePath?: string;
}
declare const entriesMap: Map<string, {
/**
* The key composed of the compiler name and the page. For example:
* `edge-server/about`
*/
[entryName: string]: Entry | ChildEntry;
}>;
export declare const getEntries: (dir: string) => NonNullable<ReturnType<(typeof entriesMap)["get"]>>;
export declare const getInvalidator: (dir: string) => Invalidator | undefined;
declare class Invalidator {
private multiCompiler;
private building;
private rebuildAgain;
constructor(multiCompiler: webpack.MultiCompiler);
shouldRebuildAll(): boolean;
invalidate(compilerKeys?: typeof COMPILER_KEYS): void;
startBuilding(compilerKey: keyof typeof COMPILER_INDEXES): void;
doneBuilding(compilerKeys?: typeof COMPILER_KEYS): void;
willRebuild(compilerKey: keyof typeof COMPILER_INDEXES): boolean;
}
interface PagePathData {
filename: string;
bundlePath: string;
page: string;
}
/**
* Attempts to find a page file path from the given pages absolute directory,
* a page and allowed extensions. If the page can't be found it will throw an
* error. It defaults the `/_error` page to Next.js internal error page.
*
* @param rootDir Absolute path to the project root.
* @param page The page normalized (it will be denormalized).
* @param extensions Array of page extensions.
* @param pagesDir Absolute path to the pages folder with trailing `/pages`.
* @param appDir Absolute path to the app folder with trailing `/app`.
*/
export declare function findPagePathData(rootDir: string, page: string, extensions: string[], pagesDir: string | undefined, appDir: string | undefined, isGlobalNotFoundEnabled: boolean): Promise<PagePathData>;
export declare function onDemandEntryHandler({ hotReloader, maxInactiveAge, multiCompiler, nextConfig, pagesBufferLength, pagesDir, rootDir, appDir, }: {
hotReloader: NextJsHotReloaderInterface;
maxInactiveAge: number;
multiCompiler: webpack.MultiCompiler;
nextConfig: NextConfigComplete;
pagesBufferLength: number;
pagesDir?: string;
rootDir: string;
appDir?: string;
}): {
ensurePage({ page, appPaths, definition, isApp, url, }: {
page: string;
appPaths?: ReadonlyArray<string> | null;
definition?: RouteDefinition;
isApp?: boolean;
url?: string;
}): Promise<void>;
onHMR(client: ws, getHmrServerError: () => Error | null): void;
};
export {};

View File

@@ -0,0 +1,704 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
ADDED: null,
BUILDING: null,
BUILT: null,
EntryTypes: null,
findPagePathData: null,
getEntries: null,
getEntryKey: null,
getInvalidator: null,
onDemandEntryHandler: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
ADDED: function() {
return ADDED;
},
BUILDING: function() {
return BUILDING;
},
BUILT: function() {
return BUILT;
},
EntryTypes: function() {
return EntryTypes;
},
findPagePathData: function() {
return findPagePathData;
},
getEntries: function() {
return getEntries;
},
getEntryKey: function() {
return getEntryKey;
},
getInvalidator: function() {
return getInvalidator;
},
onDemandEntryHandler: function() {
return onDemandEntryHandler;
}
});
const _debug = /*#__PURE__*/ _interop_require_default(require("next/dist/compiled/debug"));
const _events = require("events");
const _findpagefile = require("../lib/find-page-file");
const _entries = require("../../build/entries");
const _getstaticinfoincludinglayouts = require("../../build/get-static-info-including-layouts");
const _path = require("path");
const _normalizepathsep = require("../../shared/lib/page-path/normalize-path-sep");
const _normalizepagepath = require("../../shared/lib/page-path/normalize-page-path");
const _ensureleadingslash = require("../../shared/lib/page-path/ensure-leading-slash");
const _removepagepathtail = require("../../shared/lib/page-path/remove-page-path-tail");
const _output = require("../../build/output");
const _getroutefromentrypoint = /*#__PURE__*/ _interop_require_default(require("../get-route-from-entrypoint"));
const _utils = require("../../build/utils");
const _utils1 = require("../../shared/lib/utils");
const _constants = require("../../shared/lib/constants");
const _segment = require("../../shared/lib/segment");
const _hotreloadertypes = require("./hot-reloader-types");
const _apppageroutedefinition = require("../route-definitions/app-page-route-definition");
const _scheduler = require("../../lib/scheduler");
const _batcher = require("../../lib/batcher");
const _apppaths = require("../../shared/lib/router/utils/app-paths");
const _pagetypes = require("../../lib/page-types");
const _flightdatahelpers = require("../../client/flight-data-helpers");
const _geterrors = require("../mcp/tools/get-errors");
const _getpagemetadata = require("../mcp/tools/get-page-metadata");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
const debug = (0, _debug.default)('next:on-demand-entry-handler');
/**
* Returns object keys with type inferred from the object key
*/ const keys = Object.keys;
const COMPILER_KEYS = keys(_constants.COMPILER_INDEXES);
function treePathToEntrypoint(segmentPath, parentPath) {
const [parallelRouteKey, segment] = segmentPath;
// TODO-APP: modify this path to cover parallelRouteKey convention
const path = (parentPath ? parentPath + '/' : '') + (parallelRouteKey !== 'children' && !segment.startsWith('@') ? `@${parallelRouteKey}/` : '') + (segment === '' ? 'page' : segment);
// Last segment
if (segmentPath.length === 2) {
return path;
}
const childSegmentPath = (0, _flightdatahelpers.getNextFlightSegmentPath)(segmentPath);
return treePathToEntrypoint(childSegmentPath, path);
}
function convertDynamicParamTypeToSyntax(dynamicParamTypeShort, param) {
switch(dynamicParamTypeShort){
case 'c':
case 'ci(..)(..)':
case 'ci(.)':
case 'ci(..)':
case 'ci(...)':
return `[...${param}]`;
case 'oc':
return `[[...${param}]]`;
case 'd':
case 'di(..)(..)':
case 'di(.)':
case 'di(..)':
case 'di(...)':
return `[${param}]`;
default:
throw Object.defineProperty(new Error('Unknown dynamic param type'), "__NEXT_ERROR_CODE", {
value: "E378",
enumerable: false,
configurable: true
});
}
}
function getEntryKey(compilerType, pageBundleType, page) {
// TODO: handle the /children slot better
// this is a quick hack to handle when children is provided as children/page instead of /page
const pageKey = page.replace(/(@[^/]+)\/children/g, '$1');
return `${compilerType}@${pageBundleType}@${pageKey}`;
}
function getPageBundleType(pageBundlePath) {
// Handle special case for /_error
if (pageBundlePath === '/_error') return _pagetypes.PAGE_TYPES.PAGES;
if ((0, _utils.isMiddlewareFilename)(pageBundlePath)) return _pagetypes.PAGE_TYPES.ROOT;
return pageBundlePath.startsWith('pages/') ? _pagetypes.PAGE_TYPES.PAGES : pageBundlePath.startsWith('app/') ? _pagetypes.PAGE_TYPES.APP : _pagetypes.PAGE_TYPES.ROOT;
}
function getEntrypointsFromTree(tree, isFirst, parentPath = []) {
const [segment, parallelRoutes] = tree;
const currentSegment = Array.isArray(segment) ? convertDynamicParamTypeToSyntax(segment[2], segment[0]) : segment;
const isPageSegment = currentSegment.startsWith(_segment.PAGE_SEGMENT_KEY);
const currentPath = [
...parentPath,
isPageSegment ? '' : currentSegment
];
if (!isFirst && isPageSegment) {
// TODO get rid of '' at the start of tree
return [
treePathToEntrypoint(currentPath.slice(1))
];
}
return Object.keys(parallelRoutes).reduce((paths, key)=>{
const childTree = parallelRoutes[key];
const childPages = getEntrypointsFromTree(childTree, false, [
...currentPath,
key
]);
return [
...paths,
...childPages
];
}, []);
}
const ADDED = Symbol('added');
const BUILDING = Symbol('building');
const BUILT = Symbol('built');
var EntryTypes = /*#__PURE__*/ function(EntryTypes) {
EntryTypes[EntryTypes["ENTRY"] = 0] = "ENTRY";
EntryTypes[EntryTypes["CHILD_ENTRY"] = 1] = "CHILD_ENTRY";
return EntryTypes;
}({});
const entriesMap = new Map();
// remove /server from end of output for server compiler
const normalizeOutputPath = (dir)=>dir.replace(/[/\\]server$/, '');
const getEntries = (dir)=>{
dir = normalizeOutputPath(dir);
const entries = entriesMap.get(dir) || {};
entriesMap.set(dir, entries);
return entries;
};
const invalidators = new Map();
const getInvalidator = (dir)=>{
dir = normalizeOutputPath(dir);
return invalidators.get(dir);
};
const doneCallbacks = new _events.EventEmitter();
const lastClientAccessPages = [
''
];
const lastServerAccessPagesForAppDir = [
''
];
// Make sure only one invalidation happens at a time
// Otherwise, webpack hash gets changed and it'll force the client to reload.
class Invalidator {
constructor(multiCompiler){
this.building = new Set();
this.rebuildAgain = new Set();
this.multiCompiler = multiCompiler;
}
shouldRebuildAll() {
return this.rebuildAgain.size > 0;
}
invalidate(compilerKeys = COMPILER_KEYS) {
for (const key of compilerKeys){
var _this_multiCompiler_compilers_COMPILER_INDEXES_key_watching;
// If there's a current build is processing, we won't abort it by invalidating.
// (If aborted, it'll cause a client side hard reload)
// But let it to invalidate just after the completion.
// So, it can re-build the queued pages at once.
if (this.building.has(key)) {
this.rebuildAgain.add(key);
continue;
}
this.building.add(key);
(_this_multiCompiler_compilers_COMPILER_INDEXES_key_watching = this.multiCompiler.compilers[_constants.COMPILER_INDEXES[key]].watching) == null ? void 0 : _this_multiCompiler_compilers_COMPILER_INDEXES_key_watching.invalidate();
}
}
startBuilding(compilerKey) {
this.building.add(compilerKey);
}
doneBuilding(compilerKeys = []) {
const rebuild = [];
for (const key of compilerKeys){
this.building.delete(key);
if (this.rebuildAgain.has(key)) {
rebuild.push(key);
this.rebuildAgain.delete(key);
}
}
if (rebuild.length > 0) {
this.invalidate(rebuild);
}
}
willRebuild(compilerKey) {
return this.rebuildAgain.has(compilerKey);
}
}
function disposeInactiveEntries(entries, maxInactiveAge) {
Object.keys(entries).forEach((entryKey)=>{
const entryData = entries[entryKey];
const { lastActiveTime, status, dispose, bundlePath } = entryData;
// TODO-APP: implement disposing of CHILD_ENTRY
if (entryData.type === 1) {
return;
}
// For the root middleware and the instrumentation hook files,
// we don't dispose them periodically as it's needed for every request.
if ((0, _utils.isMiddlewareFilename)(bundlePath) || (0, _utils.isInstrumentationHookFilename)(bundlePath)) {
return;
}
if (dispose) // Skip pages already scheduled for disposing
return;
// This means this entry is currently building or just added
// We don't need to dispose those entries.
if (status !== BUILT) return;
// We should not build the last accessed page even we didn't get any pings
// Sometimes, it's possible our XHR ping to wait before completing other requests.
// In that case, we should not dispose the current viewing page
if (lastClientAccessPages.includes(entryKey) || lastServerAccessPagesForAppDir.includes(entryKey)) return;
if (lastActiveTime && Date.now() - lastActiveTime > maxInactiveAge) {
entries[entryKey].dispose = true;
}
});
}
// Normalize both app paths and page paths
function tryToNormalizePagePath(page) {
try {
return (0, _normalizepagepath.normalizePagePath)(page);
} catch (err) {
console.error(err);
throw new _utils1.PageNotFoundError(page);
}
}
async function findPagePathData(rootDir, page, extensions, pagesDir, appDir, isGlobalNotFoundEnabled) {
const normalizedPagePath = tryToNormalizePagePath(page);
let pagePath = null;
const isInstrumentation = (0, _utils.isInstrumentationHookFile)(normalizedPagePath);
if ((0, _utils.isMiddlewareFile)(normalizedPagePath) || isInstrumentation) {
pagePath = await (0, _findpagefile.findPageFile)(rootDir, normalizedPagePath, extensions, false);
if (!pagePath) {
throw new _utils1.PageNotFoundError(normalizedPagePath);
}
const pageUrl = (0, _ensureleadingslash.ensureLeadingSlash)((0, _removepagepathtail.removePagePathTail)((0, _normalizepathsep.normalizePathSep)(pagePath), {
extensions
}));
let bundlePath = normalizedPagePath;
let pageKey = _path.posix.normalize(pageUrl);
if (isInstrumentation || (0, _utils.isMiddlewareFile)(normalizedPagePath)) {
bundlePath = bundlePath.replace('/src', '');
pageKey = page.replace('/src', '');
}
return {
filename: (0, _path.join)(rootDir, pagePath),
bundlePath: bundlePath.slice(1),
page: pageKey
};
}
// Check appDir first falling back to pagesDir
if (appDir) {
if (page === _constants.UNDERSCORE_NOT_FOUND_ROUTE_ENTRY) {
// Load `global-not-found` when global-not-found is enabled.
// Prefer to load it when both `global-not-found` and root `not-found` present.
if (isGlobalNotFoundEnabled) {
const globalNotFoundPath = await (0, _findpagefile.findPageFile)(appDir, 'global-not-found', extensions, true);
if (globalNotFoundPath) {
return {
filename: (0, _path.join)(appDir, globalNotFoundPath),
bundlePath: `app${_constants.UNDERSCORE_NOT_FOUND_ROUTE_ENTRY}`,
page: _constants.UNDERSCORE_NOT_FOUND_ROUTE_ENTRY
};
}
} else {
// Then if global-not-found.js doesn't exist then load not-found.js
const notFoundPath = await (0, _findpagefile.findPageFile)(appDir, 'not-found', extensions, true);
if (notFoundPath) {
return {
filename: (0, _path.join)(appDir, notFoundPath),
bundlePath: `app${_constants.UNDERSCORE_NOT_FOUND_ROUTE_ENTRY}`,
page: _constants.UNDERSCORE_NOT_FOUND_ROUTE_ENTRY
};
}
}
// If they're not presented, then fallback to global-not-found
return {
filename: require.resolve('next/dist/client/components/builtin/global-not-found'),
bundlePath: `app${_constants.UNDERSCORE_NOT_FOUND_ROUTE_ENTRY}`,
page: _constants.UNDERSCORE_NOT_FOUND_ROUTE_ENTRY
};
}
pagePath = await (0, _findpagefile.findPageFile)(appDir, normalizedPagePath, extensions, true);
if (pagePath) {
const pageUrl = (0, _ensureleadingslash.ensureLeadingSlash)((0, _removepagepathtail.removePagePathTail)((0, _normalizepathsep.normalizePathSep)(pagePath), {
keepIndex: true,
extensions
}));
return {
filename: (0, _path.join)(appDir, pagePath),
bundlePath: _path.posix.join('app', pageUrl),
page: _path.posix.normalize(pageUrl)
};
}
}
if (!pagePath && pagesDir) {
pagePath = await (0, _findpagefile.findPageFile)(pagesDir, normalizedPagePath, extensions, false);
}
if (pagePath !== null && pagesDir) {
const pageUrl = (0, _ensureleadingslash.ensureLeadingSlash)((0, _removepagepathtail.removePagePathTail)((0, _normalizepathsep.normalizePathSep)(pagePath), {
extensions
}));
return {
filename: (0, _path.join)(pagesDir, pagePath),
bundlePath: _path.posix.join('pages', (0, _normalizepagepath.normalizePagePath)(pageUrl)),
page: _path.posix.normalize(pageUrl)
};
}
if (page === '/_error') {
return {
filename: require.resolve('next/dist/pages/_error'),
bundlePath: page,
page: (0, _normalizepathsep.normalizePathSep)(page)
};
} else {
throw new _utils1.PageNotFoundError(normalizedPagePath);
}
}
function onDemandEntryHandler({ hotReloader, maxInactiveAge, multiCompiler, nextConfig, pagesBufferLength, pagesDir, rootDir, appDir }) {
const hasAppDir = !!appDir;
let curInvalidator = getInvalidator(multiCompiler.outputPath);
const curEntries = getEntries(multiCompiler.outputPath);
if (!curInvalidator) {
curInvalidator = new Invalidator(multiCompiler);
invalidators.set(multiCompiler.outputPath, curInvalidator);
}
const startBuilding = (compilation)=>{
const compilationName = compilation.name;
curInvalidator.startBuilding(compilationName);
};
for (const compiler of multiCompiler.compilers){
compiler.hooks.make.tap('NextJsOnDemandEntries', startBuilding);
}
function getPagePathsFromEntrypoints(type, entrypoints) {
const pagePaths = [];
for (const entrypoint of entrypoints.values()){
const page = (0, _getroutefromentrypoint.default)(entrypoint.name, hasAppDir);
if (page) {
var _entrypoint_name;
const pageBundleType = ((_entrypoint_name = entrypoint.name) == null ? void 0 : _entrypoint_name.startsWith('app/')) ? _pagetypes.PAGE_TYPES.APP : _pagetypes.PAGE_TYPES.PAGES;
pagePaths.push(getEntryKey(type, pageBundleType, page));
} else if ((0, _utils.isMiddlewareFilename)(entrypoint.name) || (0, _utils.isInstrumentationHookFilename)(entrypoint.name)) {
pagePaths.push(getEntryKey(type, _pagetypes.PAGE_TYPES.ROOT, `/${entrypoint.name}`));
}
}
return pagePaths;
}
for (const compiler of multiCompiler.compilers){
compiler.hooks.done.tap('NextJsOnDemandEntries', ()=>{
var _getInvalidator;
return (_getInvalidator = getInvalidator(compiler.outputPath)) == null ? void 0 : _getInvalidator.doneBuilding([
compiler.name
]);
});
}
multiCompiler.hooks.done.tap('NextJsOnDemandEntries', (multiStats)=>{
var _getInvalidator;
const [clientStats, serverStats, edgeServerStats] = multiStats.stats;
const entryNames = [
...getPagePathsFromEntrypoints(_constants.COMPILER_NAMES.client, clientStats.compilation.entrypoints),
...getPagePathsFromEntrypoints(_constants.COMPILER_NAMES.server, serverStats.compilation.entrypoints),
...edgeServerStats ? getPagePathsFromEntrypoints(_constants.COMPILER_NAMES.edgeServer, edgeServerStats.compilation.entrypoints) : []
];
for (const name of entryNames){
const entry = curEntries[name];
if (!entry) {
continue;
}
if (entry.status !== BUILDING) {
continue;
}
entry.status = BUILT;
doneCallbacks.emit(name);
}
(_getInvalidator = getInvalidator(multiCompiler.outputPath)) == null ? void 0 : _getInvalidator.doneBuilding([
...COMPILER_KEYS
]);
});
const pingIntervalTime = Math.max(1000, Math.min(5000, maxInactiveAge));
setInterval(function() {
disposeInactiveEntries(curEntries, maxInactiveAge);
}, pingIntervalTime + 1000).unref();
function handleAppDirPing(tree) {
const pages = getEntrypointsFromTree(tree, true);
for (const page of pages){
for (const compilerType of [
_constants.COMPILER_NAMES.client,
_constants.COMPILER_NAMES.server,
_constants.COMPILER_NAMES.edgeServer
]){
const entryKey = getEntryKey(compilerType, _pagetypes.PAGE_TYPES.APP, `/${page}`);
const entryInfo = curEntries[entryKey];
// If there's no entry, it may have been invalidated and needs to be re-built.
if (!entryInfo) {
continue;
}
// We don't need to maintain active state of anything other than BUILT entries
if (entryInfo.status !== BUILT) continue;
// If there's an entryInfo
if (!lastServerAccessPagesForAppDir.includes(entryKey)) {
lastServerAccessPagesForAppDir.unshift(entryKey);
// Maintain the buffer max length
// TODO: verify that the current pageKey is not at the end of the array as multiple entrypoints can exist
if (lastServerAccessPagesForAppDir.length > pagesBufferLength) {
lastServerAccessPagesForAppDir.pop();
}
}
entryInfo.lastActiveTime = Date.now();
entryInfo.dispose = false;
}
}
}
function handlePing(pg) {
const page = (0, _normalizepathsep.normalizePathSep)(pg);
for (const compilerType of [
_constants.COMPILER_NAMES.client,
_constants.COMPILER_NAMES.server,
_constants.COMPILER_NAMES.edgeServer
]){
const entryKey = getEntryKey(compilerType, _pagetypes.PAGE_TYPES.PAGES, page);
const entryInfo = curEntries[entryKey];
// If there's no entry, it may have been invalidated and needs to be re-built.
if (!entryInfo) {
// if (page !== lastEntry) client pings, but there's no entry for page
if (compilerType === _constants.COMPILER_NAMES.client) {
return;
}
continue;
}
// We don't need to maintain active state of anything other than BUILT entries
if (entryInfo.status !== BUILT) continue;
// If there's an entryInfo
if (!lastClientAccessPages.includes(entryKey)) {
lastClientAccessPages.unshift(entryKey);
// Maintain the buffer max length
if (lastClientAccessPages.length > pagesBufferLength) {
lastClientAccessPages.pop();
}
}
entryInfo.lastActiveTime = Date.now();
entryInfo.dispose = false;
}
return;
}
async function ensurePageImpl({ page, appPaths, definition, isApp, url }) {
const stalledTime = 60;
const stalledEnsureTimeout = setTimeout(()=>{
debug(`Ensuring ${page} has taken longer than ${stalledTime}s, if this continues to stall this may be a bug`);
}, stalledTime * 1000);
try {
let route;
if (definition) {
route = definition;
} else {
route = await findPagePathData(rootDir, page, nextConfig.pageExtensions, pagesDir, appDir, !!nextConfig.experimental.globalNotFound);
}
const isInsideAppDir = !!appDir && route.filename.startsWith(appDir);
if (typeof isApp === 'boolean' && isApp !== isInsideAppDir) {
Error.stackTraceLimit = 15;
throw Object.defineProperty(new Error(`Ensure bailed, found path "${route.page}" does not match ensure type (${isApp ? 'app' : 'pages'})`), "__NEXT_ERROR_CODE", {
value: "E419",
enumerable: false,
configurable: true
});
}
const pageBundleType = getPageBundleType(route.bundlePath);
const addEntry = (compilerType)=>{
const entryKey = getEntryKey(compilerType, pageBundleType, route.page);
if (curEntries[entryKey] && // there can be an overlap in the entryKey for the instrumentation hook file and a page named the same
// this is a quick fix to support this scenario by overwriting the instrumentation hook entry, since we only use it one time
// any changes to the instrumentation hook file will require a restart of the dev server anyway
!(0, _utils.isInstrumentationHookFilename)(curEntries[entryKey].bundlePath)) {
curEntries[entryKey].dispose = false;
curEntries[entryKey].lastActiveTime = Date.now();
if (curEntries[entryKey].status === BUILT) {
return {
entryKey,
newEntry: false,
shouldInvalidate: false
};
}
return {
entryKey,
newEntry: false,
shouldInvalidate: true
};
}
curEntries[entryKey] = {
type: 0,
appPaths,
absolutePagePath: route.filename,
request: route.filename,
bundlePath: route.bundlePath,
dispose: false,
lastActiveTime: Date.now(),
status: ADDED
};
return {
entryKey: entryKey,
newEntry: true,
shouldInvalidate: true
};
};
const staticInfo = await (0, _getstaticinfoincludinglayouts.getStaticInfoIncludingLayouts)({
page,
pageFilePath: route.filename,
isInsideAppDir,
pageExtensions: nextConfig.pageExtensions,
isDev: true,
config: nextConfig,
appDir
});
const added = new Map();
const isServerComponent = isInsideAppDir && staticInfo.rsc !== _constants.RSC_MODULE_TYPES.client;
let pageRuntime = staticInfo.runtime;
(0, _entries.runDependingOnPageType)({
page: route.page,
pageRuntime,
pageType: pageBundleType,
onClient: ()=>{
// Skip adding the client entry for app / Server Components.
if (isServerComponent || isInsideAppDir) {
return;
}
added.set(_constants.COMPILER_NAMES.client, addEntry(_constants.COMPILER_NAMES.client));
},
onServer: ()=>{
added.set(_constants.COMPILER_NAMES.server, addEntry(_constants.COMPILER_NAMES.server));
const edgeServerEntry = getEntryKey(_constants.COMPILER_NAMES.edgeServer, pageBundleType, route.page);
if (curEntries[edgeServerEntry] && !(0, _utils.isInstrumentationHookFile)(route.page)) {
// Runtime switched from edge to server
delete curEntries[edgeServerEntry];
}
},
onEdgeServer: ()=>{
added.set(_constants.COMPILER_NAMES.edgeServer, addEntry(_constants.COMPILER_NAMES.edgeServer));
const serverEntry = getEntryKey(_constants.COMPILER_NAMES.server, pageBundleType, route.page);
if (curEntries[serverEntry] && !(0, _utils.isInstrumentationHookFile)(route.page)) {
// Runtime switched from server to edge
delete curEntries[serverEntry];
}
}
});
const addedValues = [
...added.values()
];
const entriesThatShouldBeInvalidated = [
...added.entries()
].filter(([, entry])=>entry.shouldInvalidate);
const hasNewEntry = addedValues.some((entry)=>entry.newEntry);
if (hasNewEntry) {
const routePage = isApp ? route.page : (0, _apppaths.normalizeAppPath)(route.page);
// If proxy file, remove the leading slash from "/proxy" to "proxy".
(0, _output.reportTrigger)((0, _utils.isMiddlewareFile)(routePage) ? routePage.slice(1) : routePage, url);
}
if (entriesThatShouldBeInvalidated.length > 0) {
const invalidatePromise = Promise.all(entriesThatShouldBeInvalidated.map(([compilerKey, { entryKey }])=>{
return new Promise((resolve, reject)=>{
doneCallbacks.once(entryKey, (err)=>{
if (err) {
return reject(err);
}
// If the invalidation also triggers a rebuild, we need to
// wait for that additional build to prevent race conditions.
const needsRebuild = curInvalidator.willRebuild(compilerKey);
if (needsRebuild) {
doneCallbacks.once(entryKey, (rebuildErr)=>{
if (rebuildErr) {
return reject(rebuildErr);
}
resolve();
});
} else {
resolve();
}
});
});
}));
curInvalidator.invalidate([
...added.keys()
]);
await invalidatePromise;
}
} finally{
clearTimeout(stalledEnsureTimeout);
}
}
// Make sure that we won't have multiple invalidations ongoing concurrently.
const batcher = _batcher.Batcher.create({
// The cache key here is composed of the elements that affect the
// compilation, namely, the page, whether it's client only, and whether
// it's an app page. This ensures that we don't have multiple compilations
// for the same page happening concurrently.
//
// We don't include the whole match because it contains match specific
// parameters (like route params) that would just bust this cache. Any
// details that would possibly bust the cache should be listed here.
cacheKeyFn: (options)=>JSON.stringify(options),
// Schedule the invocation of the ensurePageImpl function on the next tick.
schedulerFn: _scheduler.scheduleOnNextTick
});
return {
async ensurePage ({ page, appPaths = null, definition, isApp, url }) {
// If the route is actually an app page route, then we should have access
// to the app route definition, and therefore, the appPaths from it.
if (!appPaths && definition && (0, _apppageroutedefinition.isAppPageRouteDefinition)(definition)) {
appPaths = definition.appPaths;
}
// Wrap the invocation of the ensurePageImpl function in the pending
// wrapper, which will ensure that we don't have multiple compilations
// for the same page happening concurrently.
return batcher.batch({
page,
appPaths,
definition,
isApp
}, async ()=>{
await ensurePageImpl({
page,
appPaths,
definition,
isApp,
url
});
});
},
onHMR (client, getHmrServerError) {
let bufferedHmrServerError = null;
client.addEventListener('close', ()=>{
bufferedHmrServerError = null;
});
client.addEventListener('message', ({ data })=>{
try {
const error = getHmrServerError();
// New error occurred: buffered error is flushed and new error occurred
if (!bufferedHmrServerError && error) {
hotReloader.send({
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.SERVER_ERROR,
errorJSON: (0, _utils1.stringifyError)(error)
});
bufferedHmrServerError = null;
}
const parsedData = JSON.parse(typeof data !== 'string' ? data.toString() : data);
if (parsedData.event === _hotreloadertypes.HMR_MESSAGE_SENT_TO_SERVER.PING) {
if (parsedData.appDirRoute) {
handleAppDirPing(parsedData.tree);
} else {
handlePing(parsedData.page);
}
} else if (parsedData.event === _hotreloadertypes.HMR_MESSAGE_SENT_TO_SERVER.MCP_ERROR_STATE_RESPONSE) {
(0, _geterrors.handleErrorStateResponse)(parsedData.requestId, parsedData.errorState, parsedData.url);
} else if (parsedData.event === _hotreloadertypes.HMR_MESSAGE_SENT_TO_SERVER.MCP_PAGE_METADATA_RESPONSE) {
(0, _getpagemetadata.handlePageMetadataResponse)(parsedData.requestId, parsedData.segmentTrieData, parsedData.url);
}
} catch {}
});
}
};
}
//# sourceMappingURL=on-demand-entry-handler.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
export interface VersionInfo {
installed: string;
staleness: 'fresh' | 'stale-patch' | 'stale-minor' | 'stale-major' | 'stale-prerelease' | 'newer-than-npm' | 'unknown';
expected?: string;
}
export declare function parseVersionInfo(o: {
installed: string;
latest: string;
canary: string;
}): VersionInfo;

View File

@@ -0,0 +1,108 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "parseVersionInfo", {
enumerable: true,
get: function() {
return parseVersionInfo;
}
});
const _semver = /*#__PURE__*/ _interop_require_wildcard(require("next/dist/compiled/semver"));
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== "function") return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function(nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interop_require_wildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
}
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
return {
default: obj
};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {
__proto__: null
};
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
for(var key in obj){
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
function parseVersionInfo(o) {
const latest = _semver.parse(o.latest);
const canary = _semver.parse(o.canary);
const installedParsed = _semver.parse(o.installed);
const installed = o.installed;
if (installedParsed && latest && canary) {
if (installedParsed.major < latest.major) {
// Old major version
return {
staleness: 'stale-major',
expected: latest.raw,
installed
};
} else if (installedParsed.prerelease[0] === 'canary' && _semver.lt(installedParsed, canary)) {
// Matching major, but old canary
return {
staleness: 'stale-prerelease',
expected: canary.raw,
installed
};
} else if (!installedParsed.prerelease.length && _semver.lt(installedParsed, latest)) {
// Stable, but not the latest
if (installedParsed.minor === latest.minor) {
// Same major and minor, but not the latest patch
return {
staleness: 'stale-patch',
expected: latest.raw,
installed
};
}
return {
staleness: 'stale-minor',
expected: latest.raw,
installed
};
} else if (_semver.gt(installedParsed, latest) && installedParsed.version !== canary.version) {
// Newer major version
return {
staleness: 'newer-than-npm',
installed
};
} else {
// Latest and greatest
return {
staleness: 'fresh',
installed
};
}
}
return {
installed: (installedParsed == null ? void 0 : installedParsed.raw) ?? '0.0.0',
staleness: 'unknown'
};
}
//# sourceMappingURL=parse-version-info.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../src/server/dev/parse-version-info.ts"],"sourcesContent":["import * as semver from 'next/dist/compiled/semver'\n\nexport interface VersionInfo {\n installed: string\n staleness:\n | 'fresh'\n | 'stale-patch'\n | 'stale-minor'\n | 'stale-major'\n | 'stale-prerelease'\n | 'newer-than-npm'\n | 'unknown'\n expected?: string\n}\n\nexport function parseVersionInfo(o: {\n installed: string\n latest: string\n canary: string\n}): VersionInfo {\n const latest = semver.parse(o.latest)\n const canary = semver.parse(o.canary)\n const installedParsed = semver.parse(o.installed)\n const installed = o.installed\n if (installedParsed && latest && canary) {\n if (installedParsed.major < latest.major) {\n // Old major version\n return { staleness: 'stale-major', expected: latest.raw, installed }\n } else if (\n installedParsed.prerelease[0] === 'canary' &&\n semver.lt(installedParsed, canary)\n ) {\n // Matching major, but old canary\n return {\n staleness: 'stale-prerelease',\n expected: canary.raw,\n installed,\n }\n } else if (\n !installedParsed.prerelease.length &&\n semver.lt(installedParsed, latest)\n ) {\n // Stable, but not the latest\n if (installedParsed.minor === latest.minor) {\n // Same major and minor, but not the latest patch\n return {\n staleness: 'stale-patch',\n expected: latest.raw,\n installed,\n }\n }\n return { staleness: 'stale-minor', expected: latest.raw, installed }\n } else if (\n semver.gt(installedParsed, latest) &&\n installedParsed.version !== canary.version\n ) {\n // Newer major version\n return { staleness: 'newer-than-npm', installed }\n } else {\n // Latest and greatest\n return { staleness: 'fresh', installed }\n }\n }\n\n return {\n installed: installedParsed?.raw ?? '0.0.0',\n staleness: 'unknown',\n }\n}\n"],"names":["parseVersionInfo","o","latest","semver","parse","canary","installedParsed","installed","major","staleness","expected","raw","prerelease","lt","length","minor","gt","version"],"mappings":";;;;+BAegBA;;;eAAAA;;;gEAfQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAejB,SAASA,iBAAiBC,CAIhC;IACC,MAAMC,SAASC,QAAOC,KAAK,CAACH,EAAEC,MAAM;IACpC,MAAMG,SAASF,QAAOC,KAAK,CAACH,EAAEI,MAAM;IACpC,MAAMC,kBAAkBH,QAAOC,KAAK,CAACH,EAAEM,SAAS;IAChD,MAAMA,YAAYN,EAAEM,SAAS;IAC7B,IAAID,mBAAmBJ,UAAUG,QAAQ;QACvC,IAAIC,gBAAgBE,KAAK,GAAGN,OAAOM,KAAK,EAAE;YACxC,oBAAoB;YACpB,OAAO;gBAAEC,WAAW;gBAAeC,UAAUR,OAAOS,GAAG;gBAAEJ;YAAU;QACrE,OAAO,IACLD,gBAAgBM,UAAU,CAAC,EAAE,KAAK,YAClCT,QAAOU,EAAE,CAACP,iBAAiBD,SAC3B;YACA,iCAAiC;YACjC,OAAO;gBACLI,WAAW;gBACXC,UAAUL,OAAOM,GAAG;gBACpBJ;YACF;QACF,OAAO,IACL,CAACD,gBAAgBM,UAAU,CAACE,MAAM,IAClCX,QAAOU,EAAE,CAACP,iBAAiBJ,SAC3B;YACA,6BAA6B;YAC7B,IAAII,gBAAgBS,KAAK,KAAKb,OAAOa,KAAK,EAAE;gBAC1C,iDAAiD;gBACjD,OAAO;oBACLN,WAAW;oBACXC,UAAUR,OAAOS,GAAG;oBACpBJ;gBACF;YACF;YACA,OAAO;gBAAEE,WAAW;gBAAeC,UAAUR,OAAOS,GAAG;gBAAEJ;YAAU;QACrE,OAAO,IACLJ,QAAOa,EAAE,CAACV,iBAAiBJ,WAC3BI,gBAAgBW,OAAO,KAAKZ,OAAOY,OAAO,EAC1C;YACA,sBAAsB;YACtB,OAAO;gBAAER,WAAW;gBAAkBF;YAAU;QAClD,OAAO;YACL,sBAAsB;YACtB,OAAO;gBAAEE,WAAW;gBAASF;YAAU;QACzC;IACF;IAEA,OAAO;QACLA,WAAWD,CAAAA,mCAAAA,gBAAiBK,GAAG,KAAI;QACnCF,WAAW;IACb;AACF","ignoreList":[0]}

View File

@@ -0,0 +1 @@
export declare function deleteCache(filePath: string): void;

View File

@@ -0,0 +1,49 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "deleteCache", {
enumerable: true,
get: function() {
return deleteCache;
}
});
const _iserror = /*#__PURE__*/ _interop_require_default(require("../../lib/is-error"));
const _realpath = require("../../lib/realpath");
const _loadmanifestexternal = require("../load-manifest.external");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function deleteFromRequireCache(filePath) {
try {
filePath = (0, _realpath.realpathSync)(filePath);
} catch (e) {
if ((0, _iserror.default)(e) && e.code !== 'ENOENT') throw e;
}
const mod = require.cache[filePath];
if (mod) {
// remove the child reference from all parent modules
for (const parent of Object.values(require.cache)){
if (parent == null ? void 0 : parent.children) {
const idx = parent.children.indexOf(mod);
if (idx >= 0) parent.children.splice(idx, 1);
}
}
// remove parent references from external modules
for (const child of mod.children){
child.parent = null;
}
delete require.cache[filePath];
return true;
}
return false;
}
function deleteCache(filePath) {
// try to clear it from the fs cache
(0, _loadmanifestexternal.clearManifestCache)(filePath);
deleteFromRequireCache(filePath);
}
//# sourceMappingURL=require-cache.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../src/server/dev/require-cache.ts"],"sourcesContent":["import isError from '../../lib/is-error'\nimport { realpathSync } from '../../lib/realpath'\nimport { clearManifestCache } from '../load-manifest.external'\n\nfunction deleteFromRequireCache(filePath: string) {\n try {\n filePath = realpathSync(filePath)\n } catch (e) {\n if (isError(e) && e.code !== 'ENOENT') throw e\n }\n const mod = require.cache[filePath]\n if (mod) {\n // remove the child reference from all parent modules\n for (const parent of Object.values(require.cache)) {\n if (parent?.children) {\n const idx = parent.children.indexOf(mod)\n if (idx >= 0) parent.children.splice(idx, 1)\n }\n }\n // remove parent references from external modules\n for (const child of mod.children) {\n child.parent = null\n }\n delete require.cache[filePath]\n return true\n }\n return false\n}\n\nexport function deleteCache(filePath: string) {\n // try to clear it from the fs cache\n clearManifestCache(filePath)\n\n deleteFromRequireCache(filePath)\n}\n"],"names":["deleteCache","deleteFromRequireCache","filePath","realpathSync","e","isError","code","mod","require","cache","parent","Object","values","children","idx","indexOf","splice","child","clearManifestCache"],"mappings":";;;;+BA6BgBA;;;eAAAA;;;gEA7BI;0BACS;sCACM;;;;;;AAEnC,SAASC,uBAAuBC,QAAgB;IAC9C,IAAI;QACFA,WAAWC,IAAAA,sBAAY,EAACD;IAC1B,EAAE,OAAOE,GAAG;QACV,IAAIC,IAAAA,gBAAO,EAACD,MAAMA,EAAEE,IAAI,KAAK,UAAU,MAAMF;IAC/C;IACA,MAAMG,MAAMC,QAAQC,KAAK,CAACP,SAAS;IACnC,IAAIK,KAAK;QACP,qDAAqD;QACrD,KAAK,MAAMG,UAAUC,OAAOC,MAAM,CAACJ,QAAQC,KAAK,EAAG;YACjD,IAAIC,0BAAAA,OAAQG,QAAQ,EAAE;gBACpB,MAAMC,MAAMJ,OAAOG,QAAQ,CAACE,OAAO,CAACR;gBACpC,IAAIO,OAAO,GAAGJ,OAAOG,QAAQ,CAACG,MAAM,CAACF,KAAK;YAC5C;QACF;QACA,iDAAiD;QACjD,KAAK,MAAMG,SAASV,IAAIM,QAAQ,CAAE;YAChCI,MAAMP,MAAM,GAAG;QACjB;QACA,OAAOF,QAAQC,KAAK,CAACP,SAAS;QAC9B,OAAO;IACT;IACA,OAAO;AACT;AAEO,SAASF,YAAYE,QAAgB;IAC1C,oCAAoC;IACpCgB,IAAAA,wCAAkB,EAAChB;IAEnBD,uBAAuBC;AACzB","ignoreList":[0]}

View File

@@ -0,0 +1,5 @@
import { type HmrMessageSentToBrowser } from './hot-reloader-types';
export declare function sendSerializedErrorsToClient(errorsRscStream: ReadableStream<Uint8Array>, sendToClient: (message: HmrMessageSentToBrowser) => void): void;
export declare function sendSerializedErrorsToClientForHtmlRequest(htmlRequestId: string, sendToClient: (message: HmrMessageSentToBrowser) => void): void;
export declare function setErrorsRscStreamForHtmlRequest(htmlRequestId: string, errorsRscStream: ReadableStream<Uint8Array>): void;
export declare function deleteErrorsRscStreamForHtmlRequest(htmlRequestId: string): void;

View File

@@ -0,0 +1,67 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
deleteErrorsRscStreamForHtmlRequest: null,
sendSerializedErrorsToClient: null,
sendSerializedErrorsToClientForHtmlRequest: null,
setErrorsRscStreamForHtmlRequest: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
deleteErrorsRscStreamForHtmlRequest: function() {
return deleteErrorsRscStreamForHtmlRequest;
},
sendSerializedErrorsToClient: function() {
return sendSerializedErrorsToClient;
},
sendSerializedErrorsToClientForHtmlRequest: function() {
return sendSerializedErrorsToClientForHtmlRequest;
},
setErrorsRscStreamForHtmlRequest: function() {
return setErrorsRscStreamForHtmlRequest;
}
});
const _nodewebstreamshelper = require("../stream-utils/node-web-streams-helper");
const _hotreloadertypes = require("./hot-reloader-types");
const errorsRscStreamsByHtmlRequestId = new Map();
function sendSerializedErrorsToClient(errorsRscStream, sendToClient) {
(0, _nodewebstreamshelper.streamToUint8Array)(errorsRscStream).then((serializedErrors)=>{
sendToClient({
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.ERRORS_TO_SHOW_IN_BROWSER,
serializedErrors
});
}, (err)=>{
console.error(Object.defineProperty(new Error('Failed to serialize errors.', {
cause: err
}), "__NEXT_ERROR_CODE", {
value: "E948",
enumerable: false,
configurable: true
}));
});
}
function sendSerializedErrorsToClientForHtmlRequest(htmlRequestId, sendToClient) {
const errorsRscStream = errorsRscStreamsByHtmlRequestId.get(htmlRequestId);
if (!errorsRscStream) {
return;
}
errorsRscStreamsByHtmlRequestId.delete(htmlRequestId);
sendSerializedErrorsToClient(errorsRscStream, sendToClient);
}
function setErrorsRscStreamForHtmlRequest(htmlRequestId, errorsRscStream) {
// TODO: Clean up after a timeout, in case the client never connects, e.g.
// when CURL'ing the page, or loading the page with JavaScript disabled etc.
errorsRscStreamsByHtmlRequestId.set(htmlRequestId, errorsRscStream);
}
function deleteErrorsRscStreamForHtmlRequest(htmlRequestId) {
errorsRscStreamsByHtmlRequestId.delete(htmlRequestId);
}
//# sourceMappingURL=serialized-errors.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../src/server/dev/serialized-errors.ts"],"sourcesContent":["import { streamToUint8Array } from '../stream-utils/node-web-streams-helper'\nimport {\n HMR_MESSAGE_SENT_TO_BROWSER,\n type HmrMessageSentToBrowser,\n} from './hot-reloader-types'\n\nconst errorsRscStreamsByHtmlRequestId = new Map<\n string,\n ReadableStream<Uint8Array>\n>()\n\nexport function sendSerializedErrorsToClient(\n errorsRscStream: ReadableStream<Uint8Array>,\n sendToClient: (message: HmrMessageSentToBrowser) => void\n) {\n streamToUint8Array(errorsRscStream).then(\n (serializedErrors) => {\n sendToClient({\n type: HMR_MESSAGE_SENT_TO_BROWSER.ERRORS_TO_SHOW_IN_BROWSER,\n serializedErrors,\n })\n },\n (err) => {\n console.error(new Error('Failed to serialize errors.', { cause: err }))\n }\n )\n}\n\nexport function sendSerializedErrorsToClientForHtmlRequest(\n htmlRequestId: string,\n sendToClient: (message: HmrMessageSentToBrowser) => void\n) {\n const errorsRscStream = errorsRscStreamsByHtmlRequestId.get(htmlRequestId)\n\n if (!errorsRscStream) {\n return\n }\n\n errorsRscStreamsByHtmlRequestId.delete(htmlRequestId)\n\n sendSerializedErrorsToClient(errorsRscStream, sendToClient)\n}\n\nexport function setErrorsRscStreamForHtmlRequest(\n htmlRequestId: string,\n errorsRscStream: ReadableStream<Uint8Array>\n) {\n // TODO: Clean up after a timeout, in case the client never connects, e.g.\n // when CURL'ing the page, or loading the page with JavaScript disabled etc.\n errorsRscStreamsByHtmlRequestId.set(htmlRequestId, errorsRscStream)\n}\n\nexport function deleteErrorsRscStreamForHtmlRequest(htmlRequestId: string) {\n errorsRscStreamsByHtmlRequestId.delete(htmlRequestId)\n}\n"],"names":["deleteErrorsRscStreamForHtmlRequest","sendSerializedErrorsToClient","sendSerializedErrorsToClientForHtmlRequest","setErrorsRscStreamForHtmlRequest","errorsRscStreamsByHtmlRequestId","Map","errorsRscStream","sendToClient","streamToUint8Array","then","serializedErrors","type","HMR_MESSAGE_SENT_TO_BROWSER","ERRORS_TO_SHOW_IN_BROWSER","err","console","error","Error","cause","htmlRequestId","get","delete","set"],"mappings":";;;;;;;;;;;;;;;;;IAoDgBA,mCAAmC;eAAnCA;;IAzCAC,4BAA4B;eAA5BA;;IAiBAC,0CAA0C;eAA1CA;;IAeAC,gCAAgC;eAAhCA;;;sCA3CmB;kCAI5B;AAEP,MAAMC,kCAAkC,IAAIC;AAKrC,SAASJ,6BACdK,eAA2C,EAC3CC,YAAwD;IAExDC,IAAAA,wCAAkB,EAACF,iBAAiBG,IAAI,CACtC,CAACC;QACCH,aAAa;YACXI,MAAMC,6CAA2B,CAACC,yBAAyB;YAC3DH;QACF;IACF,GACA,CAACI;QACCC,QAAQC,KAAK,CAAC,qBAAwD,CAAxD,IAAIC,MAAM,+BAA+B;YAAEC,OAAOJ;QAAI,IAAtD,qBAAA;mBAAA;wBAAA;0BAAA;QAAuD;IACvE;AAEJ;AAEO,SAASZ,2CACdiB,aAAqB,EACrBZ,YAAwD;IAExD,MAAMD,kBAAkBF,gCAAgCgB,GAAG,CAACD;IAE5D,IAAI,CAACb,iBAAiB;QACpB;IACF;IAEAF,gCAAgCiB,MAAM,CAACF;IAEvClB,6BAA6BK,iBAAiBC;AAChD;AAEO,SAASJ,iCACdgB,aAAqB,EACrBb,eAA2C;IAE3C,0EAA0E;IAC1E,4EAA4E;IAC5EF,gCAAgCkB,GAAG,CAACH,eAAeb;AACrD;AAEO,SAASN,oCAAoCmB,aAAqB;IACvEf,gCAAgCiB,MAAM,CAACF;AACzC","ignoreList":[0]}

View File

@@ -0,0 +1,36 @@
import type { NextConfigComplete } from '../config-shared';
import '../require-hook';
import '../node-environment';
import type { StaticPathsResult } from '../../build/static-paths/types';
import type { IncrementalCache } from '../lib/incremental-cache';
import { type ExperimentalPPRConfig } from '../lib/experimental/ppr';
type RuntimeConfig = {
pprConfig: ExperimentalPPRConfig | undefined;
configFileName: string;
cacheComponents: boolean;
};
export declare function loadStaticPaths({ dir, distDir, pathname, config, httpAgentOptions, locales, defaultLocale, isAppPath, page, isrFlushToDisk, fetchCacheKeyPrefix, cacheMaxMemorySize, requestHeaders, cacheHandler, cacheHandlers, cacheLifeProfiles, nextConfigOutput, buildId, authInterrupts, sriEnabled, }: {
dir: string;
distDir: string;
pathname: string;
config: RuntimeConfig;
httpAgentOptions: NextConfigComplete['httpAgentOptions'];
locales?: readonly string[];
defaultLocale?: string;
isAppPath: boolean;
page: string;
isrFlushToDisk?: boolean;
fetchCacheKeyPrefix?: string;
cacheMaxMemorySize: number;
requestHeaders: IncrementalCache['requestHeaders'];
cacheHandler?: string;
cacheHandlers?: NextConfigComplete['cacheHandlers'];
cacheLifeProfiles?: {
[profile: string]: import('../../server/use-cache/cache-life').CacheLife;
};
nextConfigOutput: 'standalone' | 'export' | undefined;
buildId: string;
authInterrupts: boolean;
sriEnabled: boolean;
}): Promise<StaticPathsResult>;
export {};

View File

@@ -0,0 +1,103 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "loadStaticPaths", {
enumerable: true,
get: function() {
return loadStaticPaths;
}
});
require("../require-hook");
require("../node-environment");
const _appsegments = require("../../build/segment-config/app/app-segments");
const _loadcomponents = require("../load-components");
const _setuphttpagentenv = require("../setup-http-agent-env");
const _checks = require("../route-modules/checks");
const _ppr = require("../lib/experimental/ppr");
const _invarianterror = require("../../shared/lib/invariant-error");
const _collectrootparamkeys = require("../../build/segment-config/app/collect-root-param-keys");
const _app = require("../../build/static-paths/app");
const _pages = require("../../build/static-paths/pages");
const _createincrementalcache = require("../../export/helpers/create-incremental-cache");
const _app1 = require("../../shared/lib/router/routes/app");
async function loadStaticPaths({ dir, distDir, pathname, config, httpAgentOptions, locales, defaultLocale, isAppPath, page, isrFlushToDisk, fetchCacheKeyPrefix, cacheMaxMemorySize, requestHeaders, cacheHandler, cacheHandlers, cacheLifeProfiles, nextConfigOutput, buildId, authInterrupts, sriEnabled }) {
// this needs to be initialized before loadComponents otherwise
// "use cache" could be missing it's cache handlers
await (0, _createincrementalcache.createIncrementalCache)({
dir,
distDir,
cacheHandler,
cacheHandlers,
requestHeaders,
fetchCacheKeyPrefix,
flushToDisk: isrFlushToDisk,
cacheMaxMemorySize
});
// update work memory runtime-config
(0, _setuphttpagentenv.setHttpClientAndAgentOptions)({
httpAgentOptions
});
const components = await (0, _loadcomponents.loadComponents)({
distDir,
// In `pages/`, the page is the same as the pathname.
page: page || pathname,
isAppPath,
isDev: true,
sriEnabled,
needsManifestsForLegacyReasons: true
});
if (isAppPath) {
const routeModule = components.routeModule;
const segments = await (0, _appsegments.collectSegments)(// We know this is an app page or app route module because we checked
// above that the page type is 'app'.
routeModule);
const route = (0, _app1.parseAppRoute)(pathname, true);
if (route.dynamicSegments.length === 0) {
throw Object.defineProperty(new _invarianterror.InvariantError(`Expected a dynamic route, but got a static route: ${pathname}`), "__NEXT_ERROR_CODE", {
value: "E930",
enumerable: false,
configurable: true
});
}
const isRoutePPREnabled = (0, _checks.isAppPageRouteModule)(routeModule) && (0, _ppr.checkIsRoutePPREnabled)(config.pprConfig);
const rootParamKeys = (0, _collectrootparamkeys.collectRootParamKeys)(routeModule);
return (0, _app.buildAppStaticPaths)({
dir,
page: pathname,
route,
cacheComponents: config.cacheComponents,
segments,
distDir,
requestHeaders,
cacheHandler,
cacheLifeProfiles,
isrFlushToDisk,
fetchCacheKeyPrefix,
cacheMaxMemorySize,
ComponentMod: components.ComponentMod,
nextConfigOutput,
isRoutePPREnabled,
buildId,
authInterrupts,
rootParamKeys
});
} else if (!components.getStaticPaths) {
// We shouldn't get to this point since the worker should only be called for
// SSG pages with getStaticPaths.
throw Object.defineProperty(new _invarianterror.InvariantError(`Failed to load page with getStaticPaths for ${pathname}`), "__NEXT_ERROR_CODE", {
value: "E605",
enumerable: false,
configurable: true
});
}
return (0, _pages.buildPagesStaticPaths)({
page: pathname,
getStaticPaths: components.getStaticPaths,
configFileName: config.configFileName,
locales,
defaultLocale
});
}
//# sourceMappingURL=static-paths-worker.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,110 @@
import type { ServerFields, SetupOpts } from '../lib/router-utils/setup-dev-bundler';
import type { Issue, TurbopackResult, Endpoint, RawEntrypoints, Update as TurbopackUpdate, WrittenEndpoint } from '../../build/swc/types';
import { type HmrMessageSentToBrowser } from './hot-reloader-types';
import type { PropagateToWorkersField } from '../lib/router-utils/types';
import type { TurbopackManifestLoader } from '../../shared/lib/turbopack/manifest-loader';
import type { AppRoute, Entrypoints, PageRoute } from '../../build/swc/types';
import { type EntryKey } from '../../shared/lib/turbopack/entry-key';
import type ws from 'next/dist/compiled/ws';
import type { CustomRoutes } from '../../lib/load-custom-routes';
import { type EntryIssuesMap, type TopLevelIssuesMap } from '../../shared/lib/turbopack/utils';
export declare function printNonFatalIssue(issue: Issue): void;
export declare function processTopLevelIssues(currentTopLevelIssues: TopLevelIssuesMap, result: TurbopackResult): void;
export declare function msToNs(ms: number): bigint;
export type ChangeSubscriptions = Map<EntryKey, Promise<AsyncIterableIterator<TurbopackResult>>>;
export type HandleWrittenEndpoint = (key: EntryKey, result: TurbopackResult<WrittenEndpoint>, forceDeleteCache: boolean) => boolean;
export type StartChangeSubscription = (key: EntryKey, includeIssues: boolean, endpoint: Endpoint, createMessage: (change: TurbopackResult, hash: string) => Promise<HmrMessageSentToBrowser> | HmrMessageSentToBrowser | void, onError?: (e: Error) => Promise<HmrMessageSentToBrowser> | HmrMessageSentToBrowser | void) => Promise<void>;
export type StopChangeSubscription = (key: EntryKey) => Promise<void>;
export type SendHmr = (id: string, message: HmrMessageSentToBrowser) => void;
export type StartBuilding = (id: string, requestUrl: string | undefined, forceRebuild: boolean) => () => void;
export type ReadyIds = Set<string>;
export type ClientState = {
clientIssues: EntryIssuesMap;
messages: Map<string, HmrMessageSentToBrowser>;
turbopackUpdates: TurbopackUpdate[];
subscriptions: Map<string, AsyncIterator<any>>;
};
export type ClientStateMap = WeakMap<ws, ClientState>;
type HandleRouteTypeHooks = {
handleWrittenEndpoint: HandleWrittenEndpoint;
subscribeToChanges: StartChangeSubscription;
};
export declare function handleRouteType({ dev, page, pathname, route, currentEntryIssues, entrypoints, manifestLoader, readyIds, devRewrites, productionRewrites, hooks, logErrors, }: {
dev: boolean;
page: string;
pathname: string;
route: PageRoute | AppRoute;
currentEntryIssues: EntryIssuesMap;
entrypoints: Entrypoints;
manifestLoader: TurbopackManifestLoader;
devRewrites: SetupOpts['fsChecker']['rewrites'] | undefined;
productionRewrites: CustomRoutes['rewrites'] | undefined;
logErrors: boolean;
readyIds?: ReadyIds;
hooks?: HandleRouteTypeHooks;
}): Promise<void>;
/**
* Maintains a mapping between entrypoins and the corresponding client asset paths.
*/
export declare class AssetMapper {
private entryMap;
private assetMap;
/**
* Overrides asset paths for a key and updates the mapping from path to key.
*
* @param key
* @param assetPaths asset paths relative to the .next directory
*/
setPathsForKey(key: EntryKey, assetPaths: string[]): void;
/**
* Deletes the key and any asset only referenced by this key.
*
* @param key
*/
delete(key: EntryKey): void;
getAssetPathsByKey(key: EntryKey): string[];
getKeysByAsset(path: string): EntryKey[];
keys(): IterableIterator<EntryKey>;
}
export declare function hasEntrypointForKey(entrypoints: Entrypoints, key: EntryKey, assetMapper: AssetMapper | undefined): boolean;
type HandleEntrypointsHooks = {
handleWrittenEndpoint: HandleWrittenEndpoint;
propagateServerField: (field: PropagateToWorkersField, args: any) => Promise<void>;
sendHmr: SendHmr;
startBuilding: StartBuilding;
subscribeToChanges: StartChangeSubscription;
unsubscribeFromChanges: StopChangeSubscription;
unsubscribeFromHmrEvents: (client: ws, id: string) => void;
};
type HandleEntrypointsDevOpts = {
assetMapper: AssetMapper;
changeSubscriptions: ChangeSubscriptions;
clients: Array<ws>;
clientStates: ClientStateMap;
serverFields: ServerFields;
hooks: HandleEntrypointsHooks;
};
export declare function handleEntrypoints({ entrypoints, currentEntrypoints, currentEntryIssues, manifestLoader, devRewrites, logErrors, dev, }: {
entrypoints: TurbopackResult<RawEntrypoints>;
currentEntrypoints: Entrypoints;
currentEntryIssues: EntryIssuesMap;
manifestLoader: TurbopackManifestLoader;
devRewrites: SetupOpts['fsChecker']['rewrites'] | undefined;
productionRewrites: CustomRoutes['rewrites'] | undefined;
logErrors: boolean;
dev: HandleEntrypointsDevOpts;
}): Promise<void>;
export declare function handlePagesErrorRoute({ currentEntryIssues, entrypoints, manifestLoader, devRewrites, productionRewrites, logErrors, hooks, }: {
currentEntryIssues: EntryIssuesMap;
entrypoints: Entrypoints;
manifestLoader: TurbopackManifestLoader;
devRewrites: SetupOpts['fsChecker']['rewrites'] | undefined;
productionRewrites: CustomRoutes['rewrites'] | undefined;
logErrors: boolean;
hooks: HandleRouteTypeHooks;
}): Promise<void>;
export declare function removeRouteSuffix(route: string): string;
export declare function addRouteSuffix(route: string): string;
export declare function addMetadataIdToRoute(route: string): string;
export declare function normalizedPageToTurbopackStructureRoute(route: string, ext: string | false): string;
export {};

View File

@@ -0,0 +1,696 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
AssetMapper: null,
addMetadataIdToRoute: null,
addRouteSuffix: null,
handleEntrypoints: null,
handlePagesErrorRoute: null,
handleRouteType: null,
hasEntrypointForKey: null,
msToNs: null,
normalizedPageToTurbopackStructureRoute: null,
printNonFatalIssue: null,
processTopLevelIssues: null,
removeRouteSuffix: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
AssetMapper: function() {
return AssetMapper;
},
addMetadataIdToRoute: function() {
return addMetadataIdToRoute;
},
addRouteSuffix: function() {
return addRouteSuffix;
},
handleEntrypoints: function() {
return handleEntrypoints;
},
handlePagesErrorRoute: function() {
return handlePagesErrorRoute;
},
handleRouteType: function() {
return handleRouteType;
},
hasEntrypointForKey: function() {
return hasEntrypointForKey;
},
msToNs: function() {
return msToNs;
},
normalizedPageToTurbopackStructureRoute: function() {
return normalizedPageToTurbopackStructureRoute;
},
printNonFatalIssue: function() {
return printNonFatalIssue;
},
processTopLevelIssues: function() {
return processTopLevelIssues;
},
removeRouteSuffix: function() {
return removeRouteSuffix;
}
});
const _hotreloadertypes = require("./hot-reloader-types");
const _log = /*#__PURE__*/ _interop_require_wildcard(require("../../build/output/log"));
const _entrykey = require("../../shared/lib/turbopack/entry-key");
const _ismetadataroute = require("../../lib/metadata/is-metadata-route");
const _utils = require("../../shared/lib/turbopack/utils");
const _constants = require("../../lib/constants");
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== "function") return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function(nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interop_require_wildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
}
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
return {
default: obj
};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {
__proto__: null
};
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
for(var key in obj){
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
const onceErrorSet = new Set();
/**
* Check if given issue is a warning to be display only once.
* This mimics behavior of get-page-static-info's warnOnce.
* @param issue
* @returns
*/ function shouldEmitOnceWarning(issue) {
const { severity, title, stage } = issue;
if (severity === 'warning' && title.value === 'Invalid page configuration') {
if (onceErrorSet.has(issue)) {
return false;
}
onceErrorSet.add(issue);
}
if (severity === 'warning' && stage === 'config' && (0, _utils.renderStyledStringToErrorAnsi)(issue.title).includes("can't be external")) {
if (onceErrorSet.has(issue)) {
return false;
}
onceErrorSet.add(issue);
}
return true;
}
function printNonFatalIssue(issue) {
if ((0, _utils.isRelevantWarning)(issue) && shouldEmitOnceWarning(issue)) {
_log.warn((0, _utils.formatIssue)(issue));
}
}
function processTopLevelIssues(currentTopLevelIssues, result) {
currentTopLevelIssues.clear();
for (const issue of result.issues){
const issueKey = (0, _utils.getIssueKey)(issue);
currentTopLevelIssues.set(issueKey, issue);
}
}
const MILLISECONDS_IN_NANOSECOND = BigInt(1000000);
function msToNs(ms) {
return BigInt(Math.floor(ms)) * MILLISECONDS_IN_NANOSECOND;
}
async function handleRouteType({ dev, page, pathname, route, currentEntryIssues, entrypoints, manifestLoader, readyIds, devRewrites, productionRewrites, hooks, logErrors }) {
const shouldCreateWebpackStats = process.env.TURBOPACK_STATS != null;
switch(route.type){
case 'page':
{
const clientKey = (0, _entrykey.getEntryKey)('pages', 'client', page);
const serverKey = (0, _entrykey.getEntryKey)('pages', 'server', page);
try {
// In the best case scenario, Turbopack chunks document, app, page separately in that order,
// so it can happen that the chunks of document change, but the chunks of app and page
// don't. We still need to reload the page chunks in that case though, otherwise the version
// of the document or app component export from the pages template is stale.
let documentOrAppChanged = false;
if (entrypoints.global.app) {
const key = (0, _entrykey.getEntryKey)('pages', 'server', '_app');
const writtenEndpoint = await entrypoints.global.app.writeToDisk();
documentOrAppChanged ||= (hooks == null ? void 0 : hooks.handleWrittenEndpoint(key, writtenEndpoint, false)) ?? false;
(0, _utils.processIssues)(currentEntryIssues, key, writtenEndpoint, false, logErrors);
}
await manifestLoader.loadBuildManifest('_app');
await manifestLoader.loadPagesManifest('_app');
if (entrypoints.global.document) {
const key = (0, _entrykey.getEntryKey)('pages', 'server', '_document');
const writtenEndpoint = await entrypoints.global.document.writeToDisk();
documentOrAppChanged ||= (hooks == null ? void 0 : hooks.handleWrittenEndpoint(key, writtenEndpoint, false)) ?? false;
(0, _utils.processIssues)(currentEntryIssues, key, writtenEndpoint, false, logErrors);
}
await manifestLoader.loadPagesManifest('_document');
const writtenEndpoint = await route.htmlEndpoint.writeToDisk();
hooks == null ? void 0 : hooks.handleWrittenEndpoint(serverKey, writtenEndpoint, documentOrAppChanged);
const type = writtenEndpoint == null ? void 0 : writtenEndpoint.type;
await manifestLoader.loadClientBuildManifest(page);
await manifestLoader.loadBuildManifest(page);
await manifestLoader.loadPagesManifest(page);
if (type === 'edge') {
await manifestLoader.loadMiddlewareManifest(page, 'pages');
} else {
manifestLoader.deleteMiddlewareManifest(serverKey);
}
await manifestLoader.loadFontManifest('/_app', 'pages');
await manifestLoader.loadFontManifest(page, 'pages');
if (shouldCreateWebpackStats) {
await manifestLoader.loadWebpackStats(page, 'pages');
}
manifestLoader.writeManifests({
devRewrites,
productionRewrites,
entrypoints
});
(0, _utils.processIssues)(currentEntryIssues, serverKey, writtenEndpoint, false, logErrors);
} finally{
if (dev) {
// TODO subscriptions should only be caused by the WebSocket connections
// otherwise we don't known when to unsubscribe and this leaking
hooks == null ? void 0 : hooks.subscribeToChanges(serverKey, false, route.dataEndpoint, ()=>{
// Report the next compilation again
readyIds == null ? void 0 : readyIds.delete(pathname);
return {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.SERVER_ONLY_CHANGES,
pages: [
page
]
};
}, (e)=>{
return {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.RELOAD_PAGE,
data: `error in ${page} data subscription: ${e}`
};
});
hooks == null ? void 0 : hooks.subscribeToChanges(clientKey, false, route.htmlEndpoint, ()=>{
return {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.CLIENT_CHANGES
};
}, (e)=>{
return {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.RELOAD_PAGE,
data: `error in ${page} html subscription: ${e}`
};
});
if (entrypoints.global.document) {
hooks == null ? void 0 : hooks.subscribeToChanges((0, _entrykey.getEntryKey)('pages', 'server', '_document'), false, entrypoints.global.document, ()=>{
return {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.RELOAD_PAGE,
data: '_document has changed (page route)'
};
}, (e)=>{
return {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.RELOAD_PAGE,
data: `error in _document subscription (page route): ${e}`
};
});
}
}
}
break;
}
case 'page-api':
{
const key = (0, _entrykey.getEntryKey)('pages', 'server', page);
const writtenEndpoint = await route.endpoint.writeToDisk();
hooks == null ? void 0 : hooks.handleWrittenEndpoint(key, writtenEndpoint, false);
const type = writtenEndpoint.type;
await manifestLoader.loadPagesManifest(page);
if (type === 'edge') {
await manifestLoader.loadMiddlewareManifest(page, 'pages');
} else {
manifestLoader.deleteMiddlewareManifest(key);
}
manifestLoader.writeManifests({
devRewrites,
productionRewrites,
entrypoints
});
(0, _utils.processIssues)(currentEntryIssues, key, writtenEndpoint, true, logErrors);
break;
}
case 'app-page':
{
const key = (0, _entrykey.getEntryKey)('app', 'server', page);
const writtenEndpoint = await route.htmlEndpoint.writeToDisk();
hooks == null ? void 0 : hooks.handleWrittenEndpoint(key, writtenEndpoint, false);
if (dev) {
// TODO subscriptions should only be caused by the WebSocket connections
// otherwise we don't known when to unsubscribe and this leaking
hooks == null ? void 0 : hooks.subscribeToChanges(key, true, route.rscEndpoint, (change, hash)=>{
if (change.issues.some((issue)=>issue.severity === 'error')) {
// Ignore any updates that has errors
// There will be another update without errors eventually
return;
}
// Report the next compilation again
readyIds == null ? void 0 : readyIds.delete(pathname);
return {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.SERVER_COMPONENT_CHANGES,
hash
};
}, (e)=>{
return {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.RELOAD_PAGE,
data: `error in ${page} app-page subscription: ${e}`
};
});
}
const type = writtenEndpoint.type;
if (type === 'edge') {
manifestLoader.loadMiddlewareManifest(page, 'app');
} else {
manifestLoader.deleteMiddlewareManifest(key);
}
manifestLoader.loadBuildManifest(page, 'app');
manifestLoader.loadAppPathsManifest(page);
manifestLoader.loadActionManifest(page);
manifestLoader.loadFontManifest(page, 'app');
if (shouldCreateWebpackStats) {
manifestLoader.loadWebpackStats(page, 'app');
}
manifestLoader.writeManifests({
devRewrites,
productionRewrites,
entrypoints
});
(0, _utils.processIssues)(currentEntryIssues, key, writtenEndpoint, dev, logErrors);
break;
}
case 'app-route':
{
const key = (0, _entrykey.getEntryKey)('app', 'server', page);
const writtenEndpoint = await route.endpoint.writeToDisk();
hooks == null ? void 0 : hooks.handleWrittenEndpoint(key, writtenEndpoint, false);
const type = writtenEndpoint.type;
manifestLoader.loadAppPathsManifest(page);
if (type === 'edge') {
manifestLoader.loadMiddlewareManifest(page, 'app');
} else {
manifestLoader.deleteMiddlewareManifest(key);
}
manifestLoader.writeManifests({
devRewrites,
productionRewrites,
entrypoints
});
(0, _utils.processIssues)(currentEntryIssues, key, writtenEndpoint, true, logErrors);
break;
}
default:
{
throw Object.defineProperty(new Error(`unknown route type ${route.type} for ${page}`), "__NEXT_ERROR_CODE", {
value: "E316",
enumerable: false,
configurable: true
});
}
}
}
class AssetMapper {
/**
* Overrides asset paths for a key and updates the mapping from path to key.
*
* @param key
* @param assetPaths asset paths relative to the .next directory
*/ setPathsForKey(key, assetPaths) {
this.delete(key);
const newAssetPaths = new Set(assetPaths);
this.entryMap.set(key, newAssetPaths);
for (const assetPath of newAssetPaths){
let assetPathKeys = this.assetMap.get(assetPath);
if (!assetPathKeys) {
assetPathKeys = new Set();
this.assetMap.set(assetPath, assetPathKeys);
}
assetPathKeys.add(key);
}
}
/**
* Deletes the key and any asset only referenced by this key.
*
* @param key
*/ delete(key) {
for (const assetPath of this.getAssetPathsByKey(key)){
const assetPathKeys = this.assetMap.get(assetPath);
assetPathKeys == null ? void 0 : assetPathKeys.delete(key);
if (!(assetPathKeys == null ? void 0 : assetPathKeys.size)) {
this.assetMap.delete(assetPath);
}
}
this.entryMap.delete(key);
}
getAssetPathsByKey(key) {
return Array.from(this.entryMap.get(key) ?? []);
}
getKeysByAsset(path) {
return Array.from(this.assetMap.get(path) ?? []);
}
keys() {
return this.entryMap.keys();
}
constructor(){
this.entryMap = new Map();
this.assetMap = new Map();
}
}
function hasEntrypointForKey(entrypoints, key, assetMapper) {
const { type, page } = (0, _entrykey.splitEntryKey)(key);
switch(type){
case 'app':
return entrypoints.app.has(page);
case 'pages':
switch(page){
case '_app':
return entrypoints.global.app != null;
case '_document':
return entrypoints.global.document != null;
case '_error':
return entrypoints.global.error != null;
default:
return entrypoints.page.has(page);
}
case 'root':
switch(page){
case 'middleware':
return entrypoints.global.middleware != null;
case 'instrumentation':
return entrypoints.global.instrumentation != null;
default:
return false;
}
case 'assets':
if (!assetMapper) {
return false;
}
return assetMapper.getKeysByAsset(page).some((pageKey)=>hasEntrypointForKey(entrypoints, pageKey, assetMapper));
default:
{
// validation that we covered all cases, this should never run.
const _ = type;
return false;
}
}
}
async function handleEntrypoints({ entrypoints, currentEntrypoints, currentEntryIssues, manifestLoader, devRewrites, logErrors, dev }) {
currentEntrypoints.global.app = entrypoints.pagesAppEndpoint;
currentEntrypoints.global.document = entrypoints.pagesDocumentEndpoint;
currentEntrypoints.global.error = entrypoints.pagesErrorEndpoint;
currentEntrypoints.global.instrumentation = entrypoints.instrumentation;
currentEntrypoints.page.clear();
currentEntrypoints.app.clear();
for (const [pathname, route] of entrypoints.routes){
switch(route.type){
case 'page':
case 'page-api':
currentEntrypoints.page.set(pathname, route);
break;
case 'app-page':
{
route.pages.forEach((page)=>{
currentEntrypoints.app.set(page.originalName, {
type: 'app-page',
...page
});
});
break;
}
case 'app-route':
{
currentEntrypoints.app.set(route.originalName, route);
break;
}
case 'conflict':
_log.info(`skipping ${pathname} (${route.type})`);
break;
default:
route;
}
}
if (dev) {
await handleEntrypointsDevCleanup({
currentEntryIssues,
currentEntrypoints,
...dev
});
}
const { middleware, instrumentation } = entrypoints;
// We check for explicit true/false, since it's initialized to
// undefined during the first loop (middlewareChanges event is
// unnecessary during the first serve)
if (currentEntrypoints.global.middleware && !middleware) {
const key = (0, _entrykey.getEntryKey)('root', 'server', 'middleware');
// Went from middleware to no middleware
await (dev == null ? void 0 : dev.hooks.unsubscribeFromChanges(key));
currentEntryIssues.delete(key);
dev.hooks.sendHmr('middleware', {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.MIDDLEWARE_CHANGES
});
} else if (!currentEntrypoints.global.middleware && middleware) {
// Went from no middleware to middleware
dev.hooks.sendHmr('middleware', {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.MIDDLEWARE_CHANGES
});
}
currentEntrypoints.global.middleware = middleware;
if (instrumentation) {
const processInstrumentation = async (name, prop)=>{
const prettyName = {
nodeJs: 'Node.js',
edge: 'Edge'
};
const finishBuilding = dev.hooks.startBuilding(`instrumentation ${prettyName[prop]}`, undefined, true);
const key = (0, _entrykey.getEntryKey)('root', 'server', name);
const writtenEndpoint = await instrumentation[prop].writeToDisk();
dev.hooks.handleWrittenEndpoint(key, writtenEndpoint, false);
(0, _utils.processIssues)(currentEntryIssues, key, writtenEndpoint, false, logErrors);
finishBuilding();
};
await processInstrumentation('instrumentation.nodeJs', 'nodeJs');
await processInstrumentation('instrumentation.edge', 'edge');
await manifestLoader.loadMiddlewareManifest('instrumentation', 'instrumentation');
manifestLoader.writeManifests({
devRewrites,
productionRewrites: undefined,
entrypoints: currentEntrypoints
});
dev.serverFields.actualInstrumentationHookFile = '/instrumentation';
await dev.hooks.propagateServerField('actualInstrumentationHookFile', dev.serverFields.actualInstrumentationHookFile);
} else {
dev.serverFields.actualInstrumentationHookFile = undefined;
await dev.hooks.propagateServerField('actualInstrumentationHookFile', dev.serverFields.actualInstrumentationHookFile);
}
if (middleware) {
const key = (0, _entrykey.getEntryKey)('root', 'server', 'middleware');
const endpoint = middleware.endpoint;
const triggerName = middleware.isProxy ? _constants.PROXY_FILENAME : _constants.MIDDLEWARE_FILENAME;
async function processMiddleware() {
var _manifestLoader_getMiddlewareManifest;
const finishBuilding = dev.hooks.startBuilding(triggerName, undefined, true);
const writtenEndpoint = await endpoint.writeToDisk();
dev.hooks.handleWrittenEndpoint(key, writtenEndpoint, false);
(0, _utils.processIssues)(currentEntryIssues, key, writtenEndpoint, false, logErrors);
await manifestLoader.loadMiddlewareManifest('middleware', 'middleware');
const middlewareConfig = (_manifestLoader_getMiddlewareManifest = manifestLoader.getMiddlewareManifest(key)) == null ? void 0 : _manifestLoader_getMiddlewareManifest.middleware['/'];
if (dev && middlewareConfig) {
dev.serverFields.middleware = {
match: null,
page: '/',
matchers: middlewareConfig.matchers
};
}
finishBuilding();
}
await processMiddleware();
if (dev) {
dev == null ? void 0 : dev.hooks.subscribeToChanges(key, false, endpoint, async ()=>{
const finishBuilding = dev.hooks.startBuilding(triggerName, undefined, true);
await processMiddleware();
await dev.hooks.propagateServerField('actualMiddlewareFile', dev.serverFields.actualMiddlewareFile);
await dev.hooks.propagateServerField('middleware', dev.serverFields.middleware);
manifestLoader.writeManifests({
devRewrites,
productionRewrites: undefined,
entrypoints: currentEntrypoints
});
finishBuilding == null ? void 0 : finishBuilding();
return {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.MIDDLEWARE_CHANGES
};
}, ()=>{
return {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.MIDDLEWARE_CHANGES
};
});
}
} else {
manifestLoader.deleteMiddlewareManifest((0, _entrykey.getEntryKey)('root', 'server', 'middleware'));
dev.serverFields.actualMiddlewareFile = undefined;
dev.serverFields.middleware = undefined;
}
await dev.hooks.propagateServerField('actualMiddlewareFile', dev.serverFields.actualMiddlewareFile);
await dev.hooks.propagateServerField('middleware', dev.serverFields.middleware);
}
async function handleEntrypointsDevCleanup({ currentEntryIssues, currentEntrypoints, assetMapper, changeSubscriptions, clients, clientStates, hooks }) {
// this needs to be first as `hasEntrypointForKey` uses the `assetMapper`
for (const key of assetMapper.keys()){
if (!hasEntrypointForKey(currentEntrypoints, key, assetMapper)) {
assetMapper.delete(key);
}
}
for (const key of changeSubscriptions.keys()){
// middleware is handled separately
if (!hasEntrypointForKey(currentEntrypoints, key, assetMapper)) {
await hooks.unsubscribeFromChanges(key);
}
}
for (const [key] of currentEntryIssues){
if (!hasEntrypointForKey(currentEntrypoints, key, assetMapper)) {
currentEntryIssues.delete(key);
}
}
for (const client of clients){
const state = clientStates.get(client);
if (!state) {
continue;
}
for (const key of state.clientIssues.keys()){
if (!hasEntrypointForKey(currentEntrypoints, key, assetMapper)) {
state.clientIssues.delete(key);
}
}
for (const id of state.subscriptions.keys()){
if (!hasEntrypointForKey(currentEntrypoints, (0, _entrykey.getEntryKey)('assets', 'client', id), assetMapper)) {
hooks.unsubscribeFromHmrEvents(client, id);
}
}
}
}
async function handlePagesErrorRoute({ currentEntryIssues, entrypoints, manifestLoader, devRewrites, productionRewrites, logErrors, hooks }) {
if (entrypoints.global.app) {
const key = (0, _entrykey.getEntryKey)('pages', 'server', '_app');
const writtenEndpoint = await entrypoints.global.app.writeToDisk();
hooks.handleWrittenEndpoint(key, writtenEndpoint, false);
hooks.subscribeToChanges(key, false, entrypoints.global.app, ()=>{
// There's a special case for this in `../client/page-bootstrap.ts`.
// https://github.com/vercel/next.js/blob/08d7a7e5189a835f5dcb82af026174e587575c0e/packages/next/src/client/page-bootstrap.ts#L69-L71
return {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.CLIENT_CHANGES
};
}, ()=>{
return {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.RELOAD_PAGE,
data: '_app has changed (error route)'
};
});
(0, _utils.processIssues)(currentEntryIssues, key, writtenEndpoint, false, logErrors);
}
await manifestLoader.loadBuildManifest('_app');
await manifestLoader.loadPagesManifest('_app');
await manifestLoader.loadFontManifest('_app');
if (entrypoints.global.document) {
const key = (0, _entrykey.getEntryKey)('pages', 'server', '_document');
const writtenEndpoint = await entrypoints.global.document.writeToDisk();
hooks.handleWrittenEndpoint(key, writtenEndpoint, false);
hooks.subscribeToChanges(key, false, entrypoints.global.document, ()=>{
return {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.RELOAD_PAGE,
data: '_document has changed (error route)'
};
}, (e)=>{
return {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.RELOAD_PAGE,
data: `error in _document subscription (error route): ${e}`
};
});
(0, _utils.processIssues)(currentEntryIssues, key, writtenEndpoint, false, logErrors);
}
await manifestLoader.loadPagesManifest('_document');
if (entrypoints.global.error) {
const key = (0, _entrykey.getEntryKey)('pages', 'server', '_error');
const writtenEndpoint = await entrypoints.global.error.writeToDisk();
hooks.handleWrittenEndpoint(key, writtenEndpoint, false);
hooks.subscribeToChanges(key, false, entrypoints.global.error, ()=>{
// There's a special case for this in `../client/page-bootstrap.ts`.
// https://github.com/vercel/next.js/blob/08d7a7e5189a835f5dcb82af026174e587575c0e/packages/next/src/client/page-bootstrap.ts#L69-L71
return {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.CLIENT_CHANGES
};
}, (e)=>{
return {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.RELOAD_PAGE,
data: `error in _error subscription: ${e}`
};
});
(0, _utils.processIssues)(currentEntryIssues, key, writtenEndpoint, false, logErrors);
}
await manifestLoader.loadClientBuildManifest('_error');
await manifestLoader.loadBuildManifest('_error');
await manifestLoader.loadPagesManifest('_error');
await manifestLoader.loadFontManifest('_error');
manifestLoader.writeManifests({
devRewrites,
productionRewrites,
entrypoints
});
}
function removeRouteSuffix(route) {
return route.replace(/\/route$/, '');
}
function addRouteSuffix(route) {
return route + '/route';
}
function addMetadataIdToRoute(route) {
return route + '/[__metadata_id__]';
}
function normalizedPageToTurbopackStructureRoute(route, ext) {
let entrypointKey = route;
if ((0, _ismetadataroute.isMetadataRoute)(entrypointKey)) {
entrypointKey = entrypointKey.endsWith('/route') ? entrypointKey.slice(0, -'/route'.length) : entrypointKey;
if (ext) {
if (entrypointKey.endsWith('/[__metadata_id__]')) {
entrypointKey = entrypointKey.slice(0, -'/[__metadata_id__]'.length);
}
if (entrypointKey.endsWith('/sitemap.xml') && ext !== '.xml') {
// For dynamic sitemap route, remove the extension
entrypointKey = entrypointKey.slice(0, -'.xml'.length);
}
}
entrypointKey = entrypointKey + '/route';
}
return entrypointKey;
}
//# sourceMappingURL=turbopack-utils.js.map

File diff suppressed because one or more lines are too long