@thomas.f/prnext 0.1.18-alpha → 0.1.20-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 (162) hide show
  1. package/README.md +2 -0
  2. package/build/actions.mjs +26 -14
  3. package/build/app.mjs +90 -101
  4. package/build/build-lock.mjs +2 -71
  5. package/build/build-retention.mjs +119 -0
  6. package/build/bundle-runtime.mjs +9 -8
  7. package/build/cache-command.mjs +31 -0
  8. package/build/check.mjs +41 -3
  9. package/build/compilation-cache.mjs +32 -12
  10. package/build/compilation-storage.mjs +190 -0
  11. package/build/compiler.mjs +8 -7
  12. package/build/config.mjs +25 -2
  13. package/build/create.mjs +1 -1
  14. package/build/css-modules.mjs +4 -0
  15. package/build/dev-action-graph.mjs +21 -0
  16. package/build/dev-css-assets.mjs +173 -0
  17. package/build/dev-css-update.mjs +14 -12
  18. package/build/dev-lazy-build.mjs +77 -0
  19. package/build/dynamic.mjs +13 -6
  20. package/build/font-cache.mjs +9 -6
  21. package/build/font-files.mjs +1 -1
  22. package/build/incremental.mjs +112 -18
  23. package/build/index.mjs +61 -15
  24. package/build/lazy-dynamic-imports.mjs +137 -0
  25. package/build/migrate.mjs +4 -4
  26. package/build/migration-audit.mjs +19 -31
  27. package/build/migration-imports.mjs +245 -0
  28. package/build/migration-scenarios-runner.mjs +73 -0
  29. package/build/migration-scenarios.mjs +72 -0
  30. package/build/native-discovery.mjs +65 -5
  31. package/build/native-packages.mjs +2 -0
  32. package/build/native-ppr.mjs +32 -0
  33. package/build/npm-packages.mjs +1 -0
  34. package/build/og.mjs +121 -1
  35. package/build/parallel-plan.mjs +55 -0
  36. package/build/persistent-cache.mjs +29 -24
  37. package/build/production-builder.mjs +1 -1
  38. package/build/production-check.mjs +34 -0
  39. package/build/react-compiler-report.mjs +31 -8
  40. package/build/react-compiler.mjs +101 -10
  41. package/build/server-config.mjs +35 -0
  42. package/build/source-analysis.mjs +54 -4
  43. package/build/standalone.mjs +21 -3
  44. package/build/static-adapter.mjs +7 -3
  45. package/build/transform.mjs +38 -6
  46. package/build/typescript-dev.mjs +3 -1
  47. package/build/webpack-graph.mjs +13 -3
  48. package/cli.mjs +24 -6
  49. package/compat/app-dynamic.cjs +12 -1
  50. package/compat/app-layout-context.cjs +7 -3
  51. package/compat/cache-handlers.cjs +3 -1
  52. package/compat/flight-delta.cjs +50 -13
  53. package/compat/index.d.ts +24 -1
  54. package/compat/link.cjs +2 -2
  55. package/compat/navigation-authorization.cjs +8 -1
  56. package/docs/ai/compatibility.md +187 -7
  57. package/docs/ai/deployment.md +141 -0
  58. package/docs/ai/quickstart.md +5 -0
  59. package/docs/ai/routing.md +11 -0
  60. package/docs/ai/troubleshooting.md +79 -0
  61. package/package.json +26 -11
  62. package/release/fontkit.mjs +31 -0
  63. package/release/verify.mjs +3 -0
  64. package/runtime/api.mjs +5 -2
  65. package/runtime/app-client.mjs +254 -53
  66. package/runtime/app-partial.mjs +2 -10
  67. package/runtime/app-prefetch.mjs +2 -2
  68. package/runtime/app-render.mjs +11 -7
  69. package/runtime/app-stream-channel.mjs +3 -2
  70. package/runtime/app-styles.mjs +22 -4
  71. package/runtime/atomic-file.mjs +27 -0
  72. package/runtime/cache-components-rsc.mjs +3 -1
  73. package/runtime/compile-cache-retention.mjs +53 -0
  74. package/runtime/compile-cache.mjs +28 -1
  75. package/runtime/dev-client.mjs +13 -5
  76. package/runtime/dev-file-changes.mjs +123 -8
  77. package/runtime/dev-gateway.mjs +3 -2
  78. package/runtime/dev-lazy-imports.mjs +121 -0
  79. package/runtime/dev-lazy-staging.mjs +14 -0
  80. package/runtime/dev-route-selection.mjs +64 -0
  81. package/runtime/dev-runtime-pool.mjs +3 -2
  82. package/runtime/dev-runtime-spare.mjs +1 -1
  83. package/runtime/dev-session-retention.mjs +154 -0
  84. package/runtime/dev-style-retention.mjs +15 -0
  85. package/runtime/development.mjs +86 -26
  86. package/runtime/env.mjs +9 -0
  87. package/runtime/flight-delta.mjs +59 -9
  88. package/runtime/fs.mjs +15 -8
  89. package/runtime/lazy-import-client.mjs +38 -0
  90. package/runtime/native-ppr.mjs +35 -0
  91. package/runtime/og/NOTICE.txt +1 -1
  92. package/runtime/og/index.node.mjs +76 -31216
  93. package/runtime/og/upstream.json +115 -0
  94. package/runtime/persistent/client.mjs +4 -2
  95. package/runtime/persistent/daemon.mjs +3 -11
  96. package/runtime/persistent/health.mjs +58 -0
  97. package/runtime/project-lock.mjs +71 -0
  98. package/runtime/request-transport.mjs +112 -32
  99. package/runtime/storage-path.mjs +36 -0
  100. package/runtime/trace.mjs +44 -4
  101. package/runtime/worker.mjs +9 -4
  102. package/vendor/fontkit/NOTICE.txt +5 -0
  103. package/vendor/fontkit/SOURCE-NOTICES.txt +209 -0
  104. package/vendor/fontkit/index.mjs +3 -0
  105. package/vendor/fontkit/licenses/@swc__helpers/LICENSE +201 -0
  106. package/vendor/fontkit/licenses/base64-js/LICENSE +21 -0
  107. package/vendor/fontkit/licenses/brotli/readme.md +61 -0
  108. package/vendor/fontkit/licenses/clone/LICENSE +18 -0
  109. package/vendor/fontkit/licenses/dfa/README.md +83 -0
  110. package/vendor/fontkit/licenses/fast-deep-equal/LICENSE +21 -0
  111. package/vendor/fontkit/licenses/fontkit/README.md +266 -0
  112. package/vendor/fontkit/licenses/restructure/LICENSE +21 -0
  113. package/vendor/fontkit/licenses/tiny-inflate/LICENSE +21 -0
  114. package/vendor/fontkit/licenses/tslib/LICENSE.txt +12 -0
  115. package/vendor/fontkit/licenses/unicode-properties/LICENSE +8 -0
  116. package/vendor/fontkit/licenses/unicode-trie/LICENSE +8 -0
  117. package/vendor/fontkit/upstream.json +215 -0
  118. package/vendor/nft/LICENSE +7 -0
  119. package/vendor/nft/README.md +16 -0
  120. package/vendor/nft/out/analyze.d.ts +8 -0
  121. package/vendor/nft/out/analyze.js +1216 -0
  122. package/vendor/nft/out/analyze.js.map +1 -0
  123. package/vendor/nft/out/cli.d.ts +2 -0
  124. package/vendor/nft/out/cli.js +94 -0
  125. package/vendor/nft/out/cli.js.map +1 -0
  126. package/vendor/nft/out/fs.d.ts +22 -0
  127. package/vendor/nft/out/fs.js +106 -0
  128. package/vendor/nft/out/fs.js.map +1 -0
  129. package/vendor/nft/out/index.d.ts +4 -0
  130. package/vendor/nft/out/index.js +25 -0
  131. package/vendor/nft/out/index.js.map +1 -0
  132. package/vendor/nft/out/node-file-trace.d.ts +41 -0
  133. package/vendor/nft/out/node-file-trace.js +380 -0
  134. package/vendor/nft/out/node-file-trace.js.map +1 -0
  135. package/vendor/nft/out/resolve-dependency.d.ts +6 -0
  136. package/vendor/nft/out/resolve-dependency.js +427 -0
  137. package/vendor/nft/out/resolve-dependency.js.map +1 -0
  138. package/vendor/nft/out/types.d.ts +66 -0
  139. package/vendor/nft/out/types.js +2 -0
  140. package/vendor/nft/out/types.js.map +1 -0
  141. package/vendor/nft/out/utils/ast-helpers.js +49 -0
  142. package/vendor/nft/out/utils/ast-helpers.js.map +1 -0
  143. package/vendor/nft/out/utils/binary-locators.js +88 -0
  144. package/vendor/nft/out/utils/binary-locators.js.map +1 -0
  145. package/vendor/nft/out/utils/get-package-base.js +30 -0
  146. package/vendor/nft/out/utils/get-package-base.js.map +1 -0
  147. package/vendor/nft/out/utils/interop-require.js +24 -0
  148. package/vendor/nft/out/utils/interop-require.js.map +1 -0
  149. package/vendor/nft/out/utils/node-version.js +10 -0
  150. package/vendor/nft/out/utils/node-version.js.map +1 -0
  151. package/vendor/nft/out/utils/sharedlib-emit.js +33 -0
  152. package/vendor/nft/out/utils/sharedlib-emit.js.map +1 -0
  153. package/vendor/nft/out/utils/special-cases.js +347 -0
  154. package/vendor/nft/out/utils/special-cases.js.map +1 -0
  155. package/vendor/nft/out/utils/static-eval.js +579 -0
  156. package/vendor/nft/out/utils/static-eval.js.map +1 -0
  157. package/vendor/nft/out/utils/types.js +2 -0
  158. package/vendor/nft/out/utils/types.js.map +1 -0
  159. package/vendor/nft/out/utils/wrappers.js +659 -0
  160. package/vendor/nft/out/utils/wrappers.js.map +1 -0
  161. package/vendor/nft/package.json +4 -0
  162. package/vendor/nft/upstream.json +51 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thomas.f/prnext",
3
- "version": "0.1.18-alpha",
3
+ "version": "0.1.20-alpha",
4
4
  "license": "MIT",
5
5
  "description": "Experimental Rust-powered runtime for Next.js apps, React and npm",
6
6
  "homepage": "https://prnext.dev",
@@ -41,7 +41,8 @@
41
41
  "runtime/",
42
42
  "compat/",
43
43
  "native/",
44
- "release/"
44
+ "release/",
45
+ "vendor/"
45
46
  ],
46
47
  "scripts": {
47
48
  "prepublishOnly": "node release/verify.mjs"
@@ -133,18 +134,27 @@
133
134
  "@babel/types": "^7.29.0",
134
135
  "@edge-runtime/vm": "5.0.0",
135
136
  "@jridgewell/trace-mapping": "0.3.31",
136
- "@vercel/nft": "1.11.0",
137
+ "@mapbox/node-pre-gyp": "2.0.3",
138
+ "@rollup/pluginutils": "5.4.0",
139
+ "acorn": "8.18.0",
140
+ "acorn-import-attributes": "1.9.5",
141
+ "async-sema": "3.1.1",
137
142
  "babel-plugin-react-compiler": "1.0.0",
143
+ "bindings": "1.5.0",
138
144
  "browserslist": "4.29.0",
139
145
  "dotenv": "16.6.1",
140
146
  "dotenv-expand": "11.0.7",
141
147
  "esbuild": "^0.28.2",
142
- "fontkit": "2.0.4",
148
+ "estree-walker": "2.0.2",
143
149
  "get-tsconfig": "4.14.3",
150
+ "glob": "14.0.2",
151
+ "graceful-fs": "4.2.11",
144
152
  "html-to-image": "1.11.13",
145
153
  "jsonc-parser": "3.3.1",
146
154
  "lightningcss": "1.31.0",
147
155
  "loader-runner": "4.3.2",
156
+ "minimatch": "11.0.1",
157
+ "node-gyp-build": "4.8.4",
148
158
  "oxc-parser": "0.155.0",
149
159
  "path-to-regexp": "6.3.0",
150
160
  "picomatch": "4.0.7",
@@ -154,6 +164,7 @@
154
164
  "postcss-selector-parser": "7.1.6",
155
165
  "postcss-value-parser": "4.2.0",
156
166
  "react-refresh": "0.19.0",
167
+ "resolve-from": "5.0.0",
157
168
  "schema-utils": "4.3.3",
158
169
  "webpack": "5.111.1"
159
170
  },
@@ -161,20 +172,24 @@
161
172
  "@redis/client": "^6.3.0",
162
173
  "react": "19.3.1",
163
174
  "react-dom": "19.3.1",
164
- "react-server-dom-webpack": "19.3.1"
175
+ "react-server-dom-webpack": "19.3.1",
176
+ "oxc-transform-react": "0.157.0"
165
177
  },
166
178
  "peerDependenciesMeta": {
167
179
  "@redis/client": {
168
180
  "optional": true
181
+ },
182
+ "oxc-transform-react": {
183
+ "optional": true
169
184
  }
170
185
  },
171
186
  "optionalDependencies": {
172
- "prnext-darwin-arm64": "0.1.18-alpha",
173
- "prnext-darwin-x64": "0.1.18-alpha",
174
- "prnext-linux-arm64-gnu": "0.1.18-alpha",
175
- "prnext-linux-x64-gnu": "0.1.18-alpha",
176
- "@thomas.f/prnext-win32-x64-msvc": "0.1.18-alpha",
177
- "@thomas.f/prnext-win32-arm64-msvc": "0.1.18-alpha"
187
+ "prnext-darwin-arm64": "0.1.20-alpha",
188
+ "prnext-darwin-x64": "0.1.20-alpha",
189
+ "prnext-linux-arm64-gnu": "0.1.20-alpha",
190
+ "prnext-linux-x64-gnu": "0.1.20-alpha",
191
+ "@thomas.f/prnext-win32-x64-msvc": "0.1.20-alpha",
192
+ "@thomas.f/prnext-win32-arm64-msvc": "0.1.20-alpha"
178
193
  },
179
194
  "engines": {
180
195
  "node": "^22.23.4 || ^24.22.1 || >=26.12.1"
@@ -0,0 +1,31 @@
1
+ import {createHash} from 'node:crypto';
2
+ import {readFile, readdir} from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import {fileURLToPath} from 'node:url';
5
+
6
+ const destination = fileURLToPath(new URL('../vendor/fontkit/', import.meta.url));
7
+ const digest = bytes => createHash('sha256').update(bytes).digest('hex');
8
+
9
+ /** Validate the shipped inventory without loading fontkit or its build dependencies. */
10
+ export async function verifyVendoredFontkit(directory = destination) {
11
+ const provenance = JSON.parse(await readFile(path.join(directory, 'upstream.json'), 'utf8'));
12
+ if (provenance.schemaVersion !== 1 || provenance.name !== 'fontkit' || provenance.version !== '2.0.4'
13
+ || provenance.tool?.name !== 'esbuild' || !provenance.files?.['index.mjs']
14
+ || !provenance.files?.['NOTICE.txt'] || !provenance.files?.['SOURCE-NOTICES.txt']
15
+ || !provenance.packages?.fontkit || !provenance.packages?.brotli) throw new Error('Incomplete fontkit provenance.');
16
+ const actual = [];
17
+ async function visit(directory, prefix = '') {
18
+ for (const entry of await readdir(directory, {withFileTypes: true})) {
19
+ const name = prefix + entry.name;
20
+ if (entry.isDirectory()) await visit(path.join(directory, entry.name), name + '/');
21
+ else if (!entry.isFile()) throw new Error('Vendored fontkit files must be regular files.');
22
+ else if (name !== 'upstream.json') actual.push(name);
23
+ }
24
+ }
25
+ await visit(directory);
26
+ if (JSON.stringify(actual.sort()) !== JSON.stringify(Object.keys(provenance.files).sort())) throw new Error('Vendored fontkit inventory changed.');
27
+ for (const name of actual) {
28
+ if (digest(await readFile(path.join(directory, name))) !== provenance.files[name]) throw new Error(`Vendored fontkit differs from its reviewed build: ${name}`);
29
+ }
30
+ return {version: provenance.version, files: actual.length, bytes: (await readFile(path.join(directory, 'index.mjs'))).length};
31
+ }
@@ -3,6 +3,7 @@ import { fileURLToPath } from 'node:url';
3
3
  import path from 'node:path';
4
4
  import { packageRoot, packageManifest, platforms, sourceCheckout } from '../native/resolve.mjs';
5
5
  import { verifyAiDocumentation } from './ai-docs.mjs';
6
+ import { verifyVendoredFontkit } from './fontkit.mjs';
6
7
 
7
8
  export async function verifyPackage() {
8
9
  const pkg = packageManifest;
@@ -27,6 +28,8 @@ export async function verifyPackage() {
27
28
  }
28
29
  await exported(pkg.exports);
29
30
  await verifyAiDocumentation(packageRoot, pkg);
31
+ await verifyVendoredFontkit();
32
+ if (pkg.dependencies.fontkit || pkg.dependencies['oxc-transform-react'] || pkg.peerDependenciesMeta?.['oxc-transform-react']?.optional !== true) throw new Error('Fontkit must be bundled and the Oxc React compiler must remain an optional peer.');
30
33
  await access(path.join(packageRoot, 'runtime/profiles.json'));
31
34
  for (const name of ['index.node.mjs', 'resvg.wasm', 'hb.wasm', 'Geist-Regular.ttf', 'LICENSE', 'LICENSE.fflate', 'LICENSE.Geist', 'LICENSE.harfbuzzjs', 'LICENSE.satori', 'NOTICE.txt']) await access(path.join(packageRoot, 'runtime/og', name));
32
35
  if (pkg.dependencies['@vercel/og'] || (await readFile(path.join(packageRoot, 'runtime/og/index.node.mjs'), 'utf8')).includes('fflate@0.7.3')) throw new Error('OG renderer still depends on vulnerable upstream fflate. Run scripts/prepare-og.mjs.');
package/runtime/api.mjs CHANGED
@@ -195,7 +195,7 @@ async function runApiInner({ modulePath, route = {}, manifest = {}, production =
195
195
  // IncomingMessage here duplicates URL, header and cookie work and allocates
196
196
  // an unused Duplex. Keep the existing Pages request path unchanged.
197
197
  const { request, bytes } = appHandler
198
- ? { bytes: Buffer.isBuffer(body) ? body : Buffer.from(body || '', 'base64') }
198
+ ? { bytes: body instanceof ReadableStream ? body : Buffer.isBuffer(body) ? body : Buffer.from(body || '', 'base64') }
199
199
  : createRequest({ url, originalUrl: requestOriginal?.href, params, method, headers, body });
200
200
  if (!appHandler) {
201
201
  request.draftMode = cacheContext.draftMode;
@@ -226,7 +226,10 @@ async function runApiInner({ modulePath, route = {}, manifest = {}, production =
226
226
  throw abortError(lifecycle.controller.signal.reason);
227
227
  }
228
228
  const init = { method, headers, ...(lifecycle ? { signal: lifecycle.controller.signal } : {}) };
229
- if (!['GET', 'HEAD'].includes(method) && bytes.length) init.body = bytes;
229
+ if (!['GET', 'HEAD'].includes(method) && (bytes instanceof ReadableStream || bytes.length)) {
230
+ init.body = bytes;
231
+ if (bytes instanceof ReadableStream) init.duplex = 'half';
232
+ }
230
233
  const timeout = lifecycle && setTimeout(() => lifecycle.controller.abort(apiTimeoutError('response headers', timeoutMs)), timeoutMs);
231
234
  timeout?.unref();
232
235
  const pendingResponse = runRequestContext({ url, method, headers, params, production, cacheComponents: manifest.config?.cacheComponents, cacheLife: manifest.config?.cacheLife, cacheHandlers: manifest.config?.cacheHandlers, cacheHandler: manifest.config?.cacheHandler, cacheMaxMemorySize: manifest.config?.cacheMaxMemorySize, distDir: path.dirname(path.dirname(modulePath)), signal: lifecycle?.controller.signal || signal, previewModeId: manifest.previewModeId, basePath: manifest.config?.basePath || '', routePattern: route.pattern, cacheConfig: route.cacheConfig, phase: 'route', cacheState: cacheContext.cacheState, staticState: cacheContext.staticState, mutableCookies: true }, async () => {