@thomas.f/prnext 0.1.17-alpha → 0.1.19-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/README.md +27 -868
  2. package/build/actions.mjs +27 -15
  3. package/build/analyze.mjs +180 -24
  4. package/build/app-config.mjs +13 -0
  5. package/build/app-static.mjs +34 -12
  6. package/build/app-styles.mjs +79 -0
  7. package/build/app.mjs +122 -46
  8. package/build/bundle-runtime.mjs +22 -9
  9. package/build/cache-components.mjs +1 -1
  10. package/build/cache-handlers.mjs +1 -1
  11. package/build/compact-css.mjs +53 -0
  12. package/build/compilation-cache.mjs +269 -0
  13. package/build/compilation-store.mjs +142 -0
  14. package/build/compiler.mjs +34 -10
  15. package/build/config.mjs +34 -3
  16. package/build/create.mjs +239 -0
  17. package/build/css-modules.mjs +56 -12
  18. package/build/deployment-assets.mjs +89 -0
  19. package/build/deployment-config.mjs +18 -0
  20. package/build/dev-css-assets.mjs +173 -0
  21. package/build/dev-css-update.mjs +18 -14
  22. package/build/dev-dependencies.mjs +1 -1
  23. package/build/dev-discovery.mjs +3 -3
  24. package/build/dev-lazy-build.mjs +77 -0
  25. package/build/dev.mjs +15 -8
  26. package/build/dynamic.mjs +14 -7
  27. package/build/edge.mjs +3 -3
  28. package/build/fonts.mjs +1 -1
  29. package/build/framework-imports.mjs +15 -5
  30. package/build/html-only-config.mjs +53 -0
  31. package/build/html-only-graph.mjs +67 -0
  32. package/build/incremental.mjs +112 -18
  33. package/build/index.mjs +90 -28
  34. package/build/instrumentation.mjs +30 -0
  35. package/build/lazy-dynamic-imports.mjs +137 -0
  36. package/build/metadata-routes.mjs +1 -1
  37. package/build/migrate.mjs +4 -4
  38. package/build/migration-audit.mjs +19 -31
  39. package/build/migration-imports.mjs +245 -0
  40. package/build/migration-scenarios-runner.mjs +73 -0
  41. package/build/migration-scenarios.mjs +72 -0
  42. package/build/native-discovery.mjs +65 -5
  43. package/build/native-packages.mjs +2 -0
  44. package/build/native-type-config.mjs +37 -0
  45. package/build/npm-packages.mjs +1 -0
  46. package/build/persistent-cache.mjs +18 -3
  47. package/build/precompress.mjs +1 -1
  48. package/build/prerender-cache.mjs +70 -0
  49. package/build/prerender-config.mjs +29 -0
  50. package/build/prerender-pages.mjs +19 -9
  51. package/build/prerender-pool.mjs +165 -0
  52. package/build/prerender-process-worker.mjs +58 -0
  53. package/build/prerender-worker.mjs +5 -5
  54. package/build/production-builder.mjs +59 -10
  55. package/build/react-compiler-report.mjs +225 -0
  56. package/build/react-compiler.mjs +139 -0
  57. package/build/runtime-contract.mjs +2 -2
  58. package/build/standalone.mjs +21 -3
  59. package/build/static-export.mjs +4 -4
  60. package/build/styles.mjs +6 -4
  61. package/build/transform.mjs +1 -1
  62. package/build/typed-routes.mjs +4 -0
  63. package/build/typescript-dev.mjs +35 -8
  64. package/build/typescript-native-worker.mjs +55 -0
  65. package/build/typescript-native.mjs +18 -0
  66. package/build/typescript-toolchain.mjs +19 -0
  67. package/build/typescript.mjs +6 -4
  68. package/build/webpack-graph.mjs +19 -6
  69. package/build/worker-memory.mjs +9 -0
  70. package/cli.mjs +70 -5
  71. package/compat/activity-cache.cjs +26 -0
  72. package/compat/after.cjs +6 -4
  73. package/compat/app-dynamic.cjs +12 -1
  74. package/compat/app-layout-context.cjs +52 -2
  75. package/compat/base64.cjs +10 -0
  76. package/compat/cache-handlers.cjs +15 -3
  77. package/compat/cache-wire.cjs +28 -0
  78. package/compat/cache.cjs +2 -1
  79. package/compat/cache.d.cts +4 -0
  80. package/compat/cookies.cjs +21 -5
  81. package/compat/data-cache.cjs +12 -8
  82. package/compat/flight-delta.cjs +152 -0
  83. package/compat/headers.cjs +4 -2
  84. package/compat/incremental-cache.cjs +20 -7
  85. package/compat/index.d.ts +69 -4
  86. package/compat/link.cjs +13 -10
  87. package/compat/navigation-authorization.cjs +9 -0
  88. package/compat/navigation-stages.cjs +19 -0
  89. package/compat/offline-store.cjs +11 -0
  90. package/compat/offline.cjs +5 -0
  91. package/compat/offline.d.cts +2 -0
  92. package/compat/redis-cache.cjs +201 -0
  93. package/compat/redis-cache.d.cts +37 -0
  94. package/compat/server-primitives.cjs +31 -11
  95. package/compat/server.d.cts +15 -2
  96. package/compat/static-generation.cjs +7 -0
  97. package/compat/use-cache.cjs +3 -0
  98. package/docs/ai/compatibility.md +248 -2
  99. package/docs/ai/data.md +165 -5
  100. package/docs/ai/deployment.md +158 -0
  101. package/docs/ai/quickstart.md +29 -4
  102. package/docs/ai/routing.md +93 -0
  103. package/docs/ai/troubleshooting.md +116 -2
  104. package/package.json +40 -9
  105. package/runtime/action-client.mjs +10 -4
  106. package/runtime/action-server.mjs +2 -0
  107. package/runtime/app-client.mjs +316 -92
  108. package/runtime/app-content.mjs +4 -3
  109. package/runtime/app-partial-client.mjs +3 -0
  110. package/runtime/app-partial.mjs +1 -1
  111. package/runtime/app-prefetch-constants.mjs +4 -0
  112. package/runtime/app-prefetch.mjs +2 -3
  113. package/runtime/app-render-key.mjs +5 -0
  114. package/runtime/app-render.mjs +88 -28
  115. package/runtime/app-routing.mjs +22 -9
  116. package/runtime/app-static.mjs +18 -8
  117. package/runtime/app-stream-html.mjs +10 -53
  118. package/runtime/app-style-selection.mjs +34 -0
  119. package/runtime/app-styles.mjs +154 -0
  120. package/runtime/atomic-file.mjs +27 -0
  121. package/runtime/cache-components-rsc.mjs +7 -2
  122. package/runtime/cache-request.mjs +2 -1
  123. package/runtime/deployment-client.mjs +19 -0
  124. package/runtime/dev-client.mjs +13 -3
  125. package/runtime/dev-compiler-broker.mjs +42 -0
  126. package/runtime/dev-file-changes.mjs +123 -8
  127. package/runtime/dev-indicator.mjs +8 -3
  128. package/runtime/dev-lazy-imports.mjs +121 -0
  129. package/runtime/dev-lazy-staging.mjs +14 -0
  130. package/runtime/dev-lazy-tool.mjs +16 -0
  131. package/runtime/dev-style-retention.mjs +15 -0
  132. package/runtime/development.mjs +83 -25
  133. package/runtime/document.mjs +1 -1
  134. package/runtime/edge.mjs +6 -5
  135. package/runtime/fetch-cache.mjs +10 -8
  136. package/runtime/flight-delta.mjs +74 -0
  137. package/runtime/flight-tap.mjs +28 -0
  138. package/runtime/fs.mjs +15 -8
  139. package/runtime/html-only.mjs +27 -0
  140. package/runtime/http.mjs +2 -0
  141. package/runtime/incremental-cache.mjs +25 -4
  142. package/runtime/instrumentation.mjs +49 -0
  143. package/runtime/lazy-import-client.mjs +38 -0
  144. package/runtime/navigation-recovery.mjs +36 -0
  145. package/runtime/navigation.mjs +7 -0
  146. package/runtime/node-html-stream.mjs +47 -0
  147. package/runtime/pages-client.mjs +14 -7
  148. package/runtime/pages-navigation.mjs +48 -63
  149. package/runtime/prefetch-scheduler.mjs +110 -0
  150. package/runtime/profile.mjs +14 -0
  151. package/runtime/profiles.json +2 -2
  152. package/runtime/render.mjs +3 -0
  153. package/runtime/route-pattern.mjs +44 -0
  154. package/runtime/rsc-worker.mjs +34 -12
  155. package/runtime/trace.mjs +78 -0
  156. package/runtime/watch-project.mjs +19 -15
  157. package/runtime/worker.mjs +70 -26
  158. package/vendor/nft/LICENSE +7 -0
  159. package/vendor/nft/README.md +16 -0
  160. package/vendor/nft/out/analyze.d.ts +8 -0
  161. package/vendor/nft/out/analyze.js +1216 -0
  162. package/vendor/nft/out/analyze.js.map +1 -0
  163. package/vendor/nft/out/cli.d.ts +2 -0
  164. package/vendor/nft/out/cli.js +94 -0
  165. package/vendor/nft/out/cli.js.map +1 -0
  166. package/vendor/nft/out/fs.d.ts +22 -0
  167. package/vendor/nft/out/fs.js +106 -0
  168. package/vendor/nft/out/fs.js.map +1 -0
  169. package/vendor/nft/out/index.d.ts +4 -0
  170. package/vendor/nft/out/index.js +25 -0
  171. package/vendor/nft/out/index.js.map +1 -0
  172. package/vendor/nft/out/node-file-trace.d.ts +41 -0
  173. package/vendor/nft/out/node-file-trace.js +380 -0
  174. package/vendor/nft/out/node-file-trace.js.map +1 -0
  175. package/vendor/nft/out/resolve-dependency.d.ts +6 -0
  176. package/vendor/nft/out/resolve-dependency.js +427 -0
  177. package/vendor/nft/out/resolve-dependency.js.map +1 -0
  178. package/vendor/nft/out/types.d.ts +66 -0
  179. package/vendor/nft/out/types.js +2 -0
  180. package/vendor/nft/out/types.js.map +1 -0
  181. package/vendor/nft/out/utils/ast-helpers.js +49 -0
  182. package/vendor/nft/out/utils/ast-helpers.js.map +1 -0
  183. package/vendor/nft/out/utils/binary-locators.js +88 -0
  184. package/vendor/nft/out/utils/binary-locators.js.map +1 -0
  185. package/vendor/nft/out/utils/get-package-base.js +30 -0
  186. package/vendor/nft/out/utils/get-package-base.js.map +1 -0
  187. package/vendor/nft/out/utils/interop-require.js +24 -0
  188. package/vendor/nft/out/utils/interop-require.js.map +1 -0
  189. package/vendor/nft/out/utils/node-version.js +10 -0
  190. package/vendor/nft/out/utils/node-version.js.map +1 -0
  191. package/vendor/nft/out/utils/sharedlib-emit.js +33 -0
  192. package/vendor/nft/out/utils/sharedlib-emit.js.map +1 -0
  193. package/vendor/nft/out/utils/special-cases.js +347 -0
  194. package/vendor/nft/out/utils/special-cases.js.map +1 -0
  195. package/vendor/nft/out/utils/static-eval.js +579 -0
  196. package/vendor/nft/out/utils/static-eval.js.map +1 -0
  197. package/vendor/nft/out/utils/types.js +2 -0
  198. package/vendor/nft/out/utils/types.js.map +1 -0
  199. package/vendor/nft/out/utils/wrappers.js +659 -0
  200. package/vendor/nft/out/utils/wrappers.js.map +1 -0
  201. package/vendor/nft/package.json +4 -0
  202. package/vendor/nft/upstream.json +51 -0
@@ -23,14 +23,14 @@ export async function watchProject(root, { onChange, onError, ignore = () => fal
23
23
  // Rebuilding on those reads restarts the server (and its SSE stream).
24
24
  try { if (statSync(path.join(root, relative)).isDirectory()) return; } catch {}
25
25
  }
26
- onChange(relative);
26
+ onChange(relative,event);
27
27
  });
28
28
  watcher.on('error', error => { watcher.close(); onError(error); });
29
29
  return { close: () => watcher.close(), async refresh() {} };
30
30
  }
31
31
  const directories = new Map();
32
- const pending = new Set();
33
- let closed = false, ready = false, timer, running, refreshAll = false;
32
+ const pending = new Map();
33
+ let closed = false, ready = false, timer, running;
34
34
  const allowedDirectory = relative => !relative || (!ignore(relative) && (relative === '.contentlayer' || shouldWatchProjectFile(relative)));
35
35
  const allowedFile = relative => relative && !ignore(relative) && shouldWatchProjectFile(relative);
36
36
  function remove(relative) {
@@ -51,9 +51,9 @@ export async function watchProject(root, { onChange, onError, ignore = () => fal
51
51
  close();
52
52
  onError(error);
53
53
  }
54
- function queue(relative) {
54
+ function queue(relative, recursive = false) {
55
55
  if (closed) return;
56
- pending.add(relative);
56
+ pending.set(relative, recursive || pending.get(relative) === true);
57
57
  clearTimeout(timer);
58
58
  timer = setTimeout(() => { void drain().catch(fail); }, 20);
59
59
  }
@@ -84,18 +84,24 @@ export async function watchProject(root, { onChange, onError, ignore = () => fal
84
84
  if (process.platform === 'win32' && event === 'change') {
85
85
  try { metadataOnly = statSync(path.join(root, changed)).isDirectory(); } catch {}
86
86
  }
87
- if (allowedFile(changed) && !metadataOnly) onChange(changed);
87
+ if (allowedFile(changed) && !metadataOnly) onChange(changed,event);
88
88
  // The .contentlayer container itself is ignored as a source, but
89
89
  // its generated directory may be created after the watcher starts.
90
- // Platforms can coalesce a directory rename into a change event.
91
- // Rescan only this directory, rather than relying on the event name.
92
- if (allowedDirectory(changed) || allowedFile(changed)) queue(relative);
90
+ // Coalesced notifications can name an already subscribed ancestor,
91
+ // without a separate event from the changed descendant. Reconcile
92
+ // that subtree even when its existing directory watches are intact.
93
+ // Ordinary file edits still scan only their immediate parent.
94
+ if (!filename) queue(relative, true);
95
+ else if (allowedDirectory(changed) || allowedFile(changed)) {
96
+ queue(relative);
97
+ if (!metadataOnly && directories.has(changed)) queue(changed, true);
98
+ }
93
99
  });
94
100
  } catch (error) { if (relative && missing(error)) { disappeared(relative); return; } throw error; }
95
101
  directories.set(relative, watcher);
96
102
  // Files may already exist by the time a newly created directory is
97
103
  // subscribed. Its discovery must also invalidate the source snapshot.
98
- if (ready && allowedFile(relative)) onChange(relative);
104
+ if (ready && allowedFile(relative)) onChange(relative,'rename');
99
105
  watcher.on('error', error => {
100
106
  if (closed) return;
101
107
  if (relative && missing(error)) disappeared(relative);
@@ -109,7 +115,7 @@ export async function watchProject(root, { onChange, onError, ignore = () => fal
109
115
  const children = new Set();
110
116
  for (const entry of entries) {
111
117
  const child = path.posix.join(relative, entry.name);
112
- if (fresh && ready && entry.isFile() && allowedFile(child)) onChange(child);
118
+ if (fresh && ready && entry.isFile() && allowedFile(child)) onChange(child,'rename');
113
119
  if (!entry.isDirectory() || !allowedDirectory(child)) continue;
114
120
  children.add(child);
115
121
  if (recursive || !directories.has(child)) await scan(child, recursive);
@@ -123,8 +129,7 @@ export async function watchProject(root, { onChange, onError, ignore = () => fal
123
129
  running = (async () => {
124
130
  while (!closed && pending.size) {
125
131
  const batch = [...pending]; pending.clear();
126
- const recursive = refreshAll; refreshAll = false;
127
- for (const relative of batch) await scan(relative, recursive);
132
+ for (const [relative, recursive] of batch) await scan(relative, recursive);
128
133
  }
129
134
  })().finally(() => { running = undefined; });
130
135
  return running;
@@ -136,8 +141,7 @@ export async function watchProject(root, { onChange, onError, ignore = () => fal
136
141
  close,
137
142
  async refresh() {
138
143
  if (closed) return;
139
- refreshAll = true;
140
- pending.add('');
144
+ pending.set('', true);
141
145
  await drain();
142
146
  },
143
147
  };
@@ -1,3 +1,7 @@
1
+ import {drainTraces} from './trace.mjs';
2
+ import {advancedRoutingSources} from './app-routing-state.mjs';
3
+ import {initializeInstrumentation,withInstrumentation} from './instrumentation.mjs';
4
+ import {deferredCompiler} from './dev-compiler-broker.mjs';
1
5
  // prnext-transport:socket-v2
2
6
  // prnext-concurrency:512
3
7
  import { requestFrames } from './request-transport.mjs';
@@ -38,6 +42,10 @@ loadEnvConfig(projectRoot, { dev: !!manifest.dev });
38
42
  // browser graph and the RSC worker's mode, including dev launched from CI.
39
43
  process.env.NODE_ENV = manifest.dev ? 'development' : 'production';
40
44
  const production = !manifest.dev;
45
+ const compilerDescriptor=process.env.PRNEXT_DEV_COMPILER;
46
+ delete process.env.PRNEXT_DEV_COMPILER;
47
+ process.env.NEXT_RUNTIME='nodejs';
48
+ await initializeInstrumentation(distDir,manifest);
41
49
  let dispatchRequest=handleRequest;
42
50
  if(!production){
43
51
  const {createDevWorkerConsole}=await import('./dev-worker-logs.mjs'),logs=createDevWorkerConsole();globalThis.console=logs.console;
@@ -48,9 +56,9 @@ if(!production){
48
56
  if (production) freezeClientModules(manifest.app?.clientModules);
49
57
  // Load each renderer beside the application only when that request needs it.
50
58
  // Middleware and API workers do not pay for React or the Pages/App renderers.
51
- const runtimeModule = async name => {
59
+ const runtimeModule = async (name,directory=distDir) => {
52
60
  const started = diagnostics.enabled ? performance.now() : 0;
53
- const module = await import(pathToFileURL(path.join(distDir, `runtime/${name}.mjs`)).href);
61
+ const module = await import(pathToFileURL(path.join(directory, `runtime/${name}.mjs`)).href);
54
62
  scheduleCompileCacheFlush();
55
63
  if (diagnostics.enabled) diagnostics.record('wake', { phase: 'module', module: name, durationMs: performance.now() - started });
56
64
  return module;
@@ -60,31 +68,61 @@ try { ({ errorResponse } = await runtimeModule('http')); }
60
68
  catch (error) { console.error('PRNext worker could not load the project runtime:', error.message); process.exit(1); }
61
69
  const routes = new Map(manifest.routes.map(route => [route.id, route]));
62
70
  const prerendered = new Set((manifest.prerendered || []).map(item => item.path));
63
- let appRuntime;
64
- let appStaticRuntime;
65
- let routeStaticRuntime;
66
- let middlewareRuntime;
67
- let pagesRuntime;
68
- let apiRuntime;
69
- let incrementalRuntime;
71
+ const deployment={distDir,manifest,routes,prerendered,modules:new Map()};
72
+ const deployments=new Map([[distDir,deployment]]);
73
+ const compileDeferred=!production&&compilerDescriptor?deferredCompiler(compilerDescriptor,{root:projectRoot,home:path.dirname(distDir)}):undefined;
74
+ async function deferredDeployment(route,signal,sources=[]){
75
+ if(!compileDeferred)throw Error('Deferred development compiler is unavailable');
76
+ const next=await compileDeferred(route.pattern,signal,sources);
77
+ let value=deployments.get(next.distDir);
78
+ if(!value){value={...next,routes:new Map(next.manifest.routes.map(route=>[route.id,route])),prerendered:new Set(),modules:new Map()};deployments.set(next.distDir,value);while(deployments.size>4)deployments.delete(deployments.keys().next().value);}
79
+ const resolved=value.routes.get(route.id);
80
+ if(!resolved||resolved.devDeferred)throw Error('Compiler did not materialize the selected route');
81
+ return value;
82
+ }
83
+
84
+ async function drainRuntime(){
85
+ for(const value of deployments.values())if(value.modules.has('app-render')||value.modules.has('app-static')){
86
+ const runtime=await(value.modules.get('app-render')||import(pathToFileURL(path.join(value.distDir,'runtime/app-render.mjs')).href));
87
+ await runtime.drainAppRuntime();
88
+ }
89
+ await drainTraces();
90
+ }
70
91
 
71
- async function handleRequest(input, output, signalController, responseComplete) {
92
+ async function handleRequest(input, output, signalController, responseComplete, selected=deployment) {
93
+ const {manifest,distDir,routes,prerendered}=selected;
94
+ const renderer=async name=>{
95
+ if(selected.modules.has(name))return selected.modules.get(name);
96
+ // Imports share one pending job, then retain only the namespace. Starting
97
+ // outside the visitor's ALS scope prevents the module cache retaining it.
98
+ const pending=workScope.runInAsyncScope(()=>runtimeModule(name,distDir));
99
+ selected.modules.set(name,pending);
100
+ try{const module=await pending;selected.modules.set(name,module);return module;}
101
+ catch(error){if(selected.modules.get(name)===pending)selected.modules.delete(name);throw error;}
102
+ };
72
103
  let responseStarted = false;
73
104
  const finalizers = new Set();
74
105
  try {
75
- if(input.routeId==='__prnext_preload'&&input.renderMode==='preload'){
76
- const options=manifest.config?.workerPreload;
106
+ if(input.routeId==='__prnext_preload'&&['preload','prewarm'].includes(input.renderMode)){
107
+ const frameworkOnly=input.renderMode==='prewarm';
108
+ const options=manifest.config?.workerPreload||(frameworkOnly?{routes:[],maxRssMb:256,timeoutMs:15000}:undefined);
77
109
  if(!production||!options){await output(input.id,{status:204,body:''},input);return;}
110
+ if(frameworkOnly){
111
+ if(manifest.routes.some(route=>route.router==='app'&&route.kind==='page'))await(await renderer('app-render')).prewarmAppRenderer(options);
112
+ if(manifest.routes.some(route=>route.kind==='page'&&route.router!=='app'))await renderer('render');
113
+ if(manifest.routes.some(route=>route.kind==='api'))await renderer('api');
114
+ scheduleCompileCacheFlush();await output(input.id,{status:204,body:''},input);return;
115
+ }
78
116
  const selected=options.routes.map(pattern=>manifest.routes.find(route=>route.pattern===pattern&&!route.internal)).filter(Boolean);
79
117
  const deadline=performance.now()+options.timeoutMs;
80
118
  for(const route of selected){
81
119
  if(performance.now()>=deadline||process.memoryUsage().rss>=options.maxRssMb*1024*1024)break;
82
120
  const remaining={...options,timeoutMs:Math.max(1,deadline-performance.now())};
83
121
  if(route.router==='app'&&route.kind==='page'){
84
- appRuntime??=await runtimeModule('app-render');
122
+ const appRuntime=await renderer('app-render');
85
123
  await appRuntime.preloadAppRoutes([path.resolve(distDir,route.module)],remaining);
86
124
  }else{
87
- if(route.kind==='page')pagesRuntime??=await runtimeModule('render');else apiRuntime??=await runtimeModule('api');
125
+ if(route.kind==='page')await renderer('render');else await renderer('api');
88
126
  await preloadModules([path.resolve(distDir,route.module)],remaining);
89
127
  }
90
128
  if(process.memoryUsage().rss>=options.maxRssMb*1024*1024)break;
@@ -92,7 +130,7 @@ async function handleRequest(input, output, signalController, responseComplete)
92
130
  scheduleCompileCacheFlush();await output(input.id,{status:204,body:''},input);return;
93
131
  }
94
132
  if (input.renderMode === 'incremental-cache' && input.routeId === '__prnext_incremental_cache') {
95
- incrementalRuntime ??= await runtimeModule('incremental-cache');
133
+ const incrementalRuntime = await renderer('incremental-cache');
96
134
  const result = await incrementalRuntime.runIncrementalCache({ ...input, manifest, distDir, production, signal: signalController.signal });
97
135
  input.body = undefined;
98
136
  responseStarted = true;
@@ -104,31 +142,38 @@ async function handleRequest(input, output, signalController, responseComplete)
104
142
  ? { ...manifest.middleware, id: '__prnext_middleware', kind: 'middleware' }
105
143
  : routes.get(input.routeId);
106
144
  if (!route) { await output(input.id, { status: 404, body: 'Not Found' }, input); return; }
145
+ const sourceModules=!production&&route.router==='app'&&route.kind==='page'?advancedRoutingSources({...input,basePath:manifest.config?.basePath||''},manifest.routes):[];
146
+ const deferredSources=sourceModules.length?manifest.routes.filter(candidate=>candidate.devDeferred&&sourceModules.includes(candidate.module)).map(candidate=>candidate.pattern):[];
147
+ if(route.devDeferred||deferredSources.length){
148
+ const next=await deferredDeployment(route,signalController.signal,deferredSources);
149
+ return await handleRequest(input,output,signalController,responseComplete,next);
150
+ }
107
151
  const requestedPath = new URL(input.url).pathname;
108
152
  if (route.router !== 'app' && !['isr', 'error404', 'error500'].includes(input.renderMode) && route.fallback === false && !prerendered.has(requestedPath) && !prerendered.has(requestedPath.replace(/\/$/, '') || '/')) {
109
153
  await output(input.id, { status: 404, body: 'Not Found' }, input); return;
110
154
  }
111
155
  const options = { ...input, modulePath: path.resolve(distDir, route.module), route, production, manifest, distDir, signal: signalController.signal, deferFinalizer: finalize => finalizers.add(finalize) };
156
+ return await withInstrumentation(options,async()=>{
112
157
  let result;
113
158
  if (isMiddleware) {
114
- middlewareRuntime ??= await import(pathToFileURL(path.join(distDir, 'runtime/middleware.mjs')).href);
159
+ const middlewareRuntime = await renderer('middleware');
115
160
  result = await middlewareRuntime.runMiddleware(options);
116
161
  } else if (route.router === 'app' && route.kind === 'page') {
117
162
  if (input.renderMode === 'isr') {
118
- appStaticRuntime ??= await import(pathToFileURL(path.join(distDir, 'runtime/app-static.mjs')).href);
163
+ const appStaticRuntime = await renderer('app-static');
119
164
  result = await appStaticRuntime.renderAppIsrPage(options);
120
165
  } else {
121
- appRuntime ??= await runtimeModule('app-render');
166
+ const appRuntime = await renderer('app-render');
122
167
  result = await appRuntime.renderAppPage(options);
123
168
  }
124
169
  } else if (route.router === 'app' && route.kind === 'api' && input.renderMode === 'isr') {
125
- routeStaticRuntime ??= await import(pathToFileURL(path.join(distDir, 'runtime/route-static.mjs')).href);
170
+ const routeStaticRuntime = await renderer('route-static');
126
171
  result = await routeStaticRuntime.renderRouteHandlerIsr(options);
127
172
  } else if (route.kind === 'api') {
128
- apiRuntime ??= await runtimeModule('api');
173
+ const apiRuntime = await renderer('api');
129
174
  result = await apiRuntime.runApi(options);
130
175
  } else {
131
- pagesRuntime ??= await runtimeModule('render');
176
+ const pagesRuntime = await renderer('render');
132
177
  result = input.renderMode === 'isr' ? await pagesRuntime.renderIsrPage({ ...options, capturePageFailure: true })
133
178
  : await pagesRuntime.renderPageRequest({ ...options, nativeErrors: true });
134
179
  }
@@ -140,6 +185,7 @@ async function handleRequest(input, output, signalController, responseComplete)
140
185
  if (result.finalizeCache) finalizers.add(result.finalizeCache);
141
186
  await output(input.id, result, { ...input, production, signalController });
142
187
  responseComplete?.();
188
+ });
143
189
  } catch (error) {
144
190
  const cancelled = signalController.signal.aborted || error instanceof ProtocolWriteError;
145
191
  signalController.abort(error);
@@ -189,7 +235,8 @@ if (token && laneLimit > 1) {
189
235
  reportedBusy = true;
190
236
  writeProtocol('busy\n');
191
237
  };
192
- const exitWhenDrained = () => { if (shuttingDown && !invocations.size) process.exit(0); };
238
+ let exiting=false;
239
+ const exitWhenDrained = () => { if (shuttingDown && !invocations.size&&!exiting){exiting=true;void drainRuntime().catch(error=>console.error('[prnext] Runtime drain failed:',error?.message)).finally(()=>process.exit(0));} };
193
240
  const server = net.createServer(socket => {
194
241
  if (sockets.size >= laneLimit) { socket.destroy(); return; }
195
242
  sockets.add(socket); socket.setNoDelay(true);
@@ -316,8 +363,5 @@ if (token && laneLimit > 1) {
316
363
  // The maintenance/ISR transport is serial and awaits its own finalizers.
317
364
  // RSC settlement can still outlive its terminal frame; drain it explicitly
318
365
  // before closing the isolate's MessagePorts after parent EOF.
319
- if (appRuntime || appStaticRuntime) {
320
- const runtime = appRuntime || await runtimeModule('app-render');
321
- await runtime.drainAppRuntime();
322
- }
366
+ await drainRuntime();
323
367
  }
@@ -0,0 +1,7 @@
1
+ Copyright 2019 Vercel, Inc.
2
+
3
+ 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:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ 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.
@@ -0,0 +1,16 @@
1
+ # Node File Trace
2
+
3
+ The `out/` files and MIT license are unchanged files from `@vercel/nft` 1.11.0.
4
+ `upstream.json` records the exact npm archive integrity and every file's SHA-256.
5
+ `node scripts/vendor-nft.mjs verify` checks those bytes and the complete inventory.
6
+
7
+ This copy uses PRNext's explicit dependencies, including glob 14.0.2 and
8
+ minimatch 11.0.1. Upstream 1.11.0 still declares glob 13; overriding a workspace
9
+ lockfile would not repair that dependency for independently installed consumers.
10
+ The tracing implementation itself has no local patches. Its runtime, resolver,
11
+ filesystem, native tracing and relocated standalone contracts are tested with
12
+ the patched dependency versions.
13
+
14
+ When upstream supports the patched dependencies, prefer returning to its normal
15
+ package after validating the same contracts. Updates to this copy must retain
16
+ the upstream license, reviewed archive integrity and complete byte inventory.
@@ -0,0 +1,8 @@
1
+ import { Job } from './node-file-trace';
2
+ export interface AnalyzeResult {
3
+ assets: Set<string>;
4
+ deps: Set<string>;
5
+ imports: Set<string>;
6
+ isESM: boolean;
7
+ }
8
+ export default function analyze(id: string, code: string, job: Job): Promise<AnalyzeResult>;