next 16.2.11 → 16.2.12

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 (155) hide show
  1. package/dist/.build-commit +1 -1
  2. package/dist/bin/next +2 -2
  3. package/dist/build/index.js +3 -3
  4. package/dist/build/load-jsconfig.js +40 -20
  5. package/dist/build/load-jsconfig.js.map +1 -1
  6. package/dist/build/next-config-ts/transpile-config.js +3 -114
  7. package/dist/build/next-config-ts/transpile-config.js.map +1 -1
  8. package/dist/build/swc/index.js +1 -1
  9. package/dist/build/turbopack-analyze/index.js +1 -1
  10. package/dist/build/turbopack-build/impl.js +1 -1
  11. package/dist/build/type-check.js +20 -13
  12. package/dist/build/type-check.js.map +1 -1
  13. package/dist/build/webpack-config.js +3 -3
  14. package/dist/bundle-analyzer/404.html +2 -2
  15. package/dist/bundle-analyzer/__next.__PAGE__.txt +1 -1
  16. package/dist/bundle-analyzer/__next._full.txt +1 -1
  17. package/dist/bundle-analyzer/__next._head.txt +1 -1
  18. package/dist/bundle-analyzer/__next._index.txt +1 -1
  19. package/dist/bundle-analyzer/__next._tree.txt +1 -1
  20. package/dist/bundle-analyzer/_not-found/__next._full.txt +1 -1
  21. package/dist/bundle-analyzer/_not-found/__next._head.txt +1 -1
  22. package/dist/bundle-analyzer/_not-found/__next._index.txt +1 -1
  23. package/dist/bundle-analyzer/_not-found/__next._not-found.__PAGE__.txt +1 -1
  24. package/dist/bundle-analyzer/_not-found/__next._not-found.txt +1 -1
  25. package/dist/bundle-analyzer/_not-found/__next._tree.txt +1 -1
  26. package/dist/bundle-analyzer/_not-found.html +2 -2
  27. package/dist/bundle-analyzer/_not-found.txt +1 -1
  28. package/dist/bundle-analyzer/index.html +2 -2
  29. package/dist/bundle-analyzer/index.txt +1 -1
  30. package/dist/cli/next-test.js +2 -1
  31. package/dist/cli/next-test.js.map +1 -1
  32. package/dist/cli/next-typegen.js +2 -1
  33. package/dist/cli/next-typegen.js.map +1 -1
  34. package/dist/client/app-bootstrap.js +1 -1
  35. package/dist/client/index.js +1 -1
  36. package/dist/compiled/next-server/pages-api-turbo.runtime.dev.js +1 -1
  37. package/dist/compiled/next-server/pages-api-turbo.runtime.dev.js.map +1 -1
  38. package/dist/compiled/next-server/pages-turbo.runtime.dev.js +1 -1
  39. package/dist/compiled/next-server/pages-turbo.runtime.dev.js.map +1 -1
  40. package/dist/compiled/next-server/server.runtime.prod.js +1 -1
  41. package/dist/compiled/next-server/server.runtime.prod.js.map +1 -1
  42. package/dist/docs/01-app/01-getting-started/01-installation.md +33 -0
  43. package/dist/docs/01-app/01-getting-started/02-project-structure.md +1 -1
  44. package/dist/docs/01-app/01-getting-started/06-fetching-data.md +1 -1
  45. package/dist/docs/01-app/01-getting-started/09-revalidating.md +1 -1
  46. package/dist/docs/01-app/02-guides/authentication.md +18 -10
  47. package/dist/docs/01-app/02-guides/backend-for-frontend.md +1 -1
  48. package/dist/docs/01-app/02-guides/debugging.md +2 -2
  49. package/dist/docs/01-app/02-guides/migrating/app-router-migration.md +18 -14
  50. package/dist/docs/01-app/02-guides/single-page-applications.md +1 -1
  51. package/dist/docs/01-app/02-guides/static-exports.md +2 -0
  52. package/dist/docs/01-app/03-api-reference/02-components/form.md +1 -1
  53. package/dist/docs/01-app/03-api-reference/03-file-conventions/error.md +2 -0
  54. package/dist/docs/01-app/03-api-reference/03-file-conventions/not-found.md +3 -1
  55. package/dist/docs/01-app/03-api-reference/04-functions/redirect.md +1 -0
  56. package/dist/docs/01-app/03-api-reference/04-functions/refresh.md +4 -1
  57. package/dist/docs/01-app/03-api-reference/04-functions/revalidatePath.md +3 -0
  58. package/dist/docs/01-app/03-api-reference/04-functions/revalidateTag.md +3 -0
  59. package/dist/docs/01-app/03-api-reference/04-functions/unstable_cache.md +5 -5
  60. package/dist/docs/01-app/03-api-reference/04-functions/use-search-params.md +1 -1
  61. package/dist/docs/01-app/03-api-reference/05-config/01-next-config-js/headers.md +11 -11
  62. package/dist/docs/01-app/03-api-reference/05-config/01-next-config-js/redirects.md +10 -10
  63. package/dist/docs/01-app/03-api-reference/05-config/01-next-config-js/rewrites.md +16 -16
  64. package/dist/docs/01-app/03-api-reference/05-config/01-next-config-js/serverActions.md +4 -1
  65. package/dist/docs/01-app/03-api-reference/05-config/01-next-config-js/useTypeScriptCli.md +62 -0
  66. package/dist/docs/01-app/03-api-reference/05-config/02-typescript.md +55 -1
  67. package/dist/docs/01-app/03-api-reference/07-adapters/05-routing-with-next-routing.md +0 -3
  68. package/dist/docs/02-pages/02-guides/forms.md +6 -6
  69. package/dist/docs/02-pages/03-building-your-application/01-routing/08-custom-error.md +2 -0
  70. package/dist/docs/02-pages/04-api-reference/04-config/01-next-config-js/useTypeScriptCli.md +8 -0
  71. package/dist/esm/build/index.js +3 -3
  72. package/dist/esm/build/load-jsconfig.js +40 -20
  73. package/dist/esm/build/load-jsconfig.js.map +1 -1
  74. package/dist/esm/build/next-config-ts/transpile-config.js +3 -73
  75. package/dist/esm/build/next-config-ts/transpile-config.js.map +1 -1
  76. package/dist/esm/build/swc/index.js +1 -1
  77. package/dist/esm/build/turbopack-analyze/index.js +1 -1
  78. package/dist/esm/build/turbopack-build/impl.js +1 -1
  79. package/dist/esm/build/type-check.js +20 -13
  80. package/dist/esm/build/type-check.js.map +1 -1
  81. package/dist/esm/build/webpack-config.js +3 -3
  82. package/dist/esm/client/app-bootstrap.js +1 -1
  83. package/dist/esm/client/index.js +1 -1
  84. package/dist/esm/lib/has-necessary-dependencies.js.map +1 -1
  85. package/dist/esm/lib/install-dependencies.js +1 -1
  86. package/dist/esm/lib/install-dependencies.js.map +1 -1
  87. package/dist/esm/lib/patch-incorrect-lockfile.js +3 -3
  88. package/dist/esm/lib/typescript/loadTsConfig.js +129 -0
  89. package/dist/esm/lib/typescript/loadTsConfig.js.map +1 -0
  90. package/dist/esm/lib/typescript/missingDependencyError.js +1 -1
  91. package/dist/esm/lib/typescript/missingDependencyError.js.map +1 -1
  92. package/dist/esm/lib/typescript/runTypeCheck.js.map +1 -1
  93. package/dist/esm/lib/typescript/runTypeCheckCli.js +38 -0
  94. package/dist/esm/lib/typescript/runTypeCheckCli.js.map +1 -0
  95. package/dist/esm/lib/typescript/runTypeScriptCli.js +217 -0
  96. package/dist/esm/lib/typescript/runTypeScriptCli.js.map +1 -0
  97. package/dist/esm/lib/verify-typescript-setup.js +87 -52
  98. package/dist/esm/lib/verify-typescript-setup.js.map +1 -1
  99. package/dist/esm/server/config-schema.js +1 -0
  100. package/dist/esm/server/config-schema.js.map +1 -1
  101. package/dist/esm/server/config-shared.js +1 -0
  102. package/dist/esm/server/config-shared.js.map +1 -1
  103. package/dist/esm/server/config.js +1 -1
  104. package/dist/esm/server/dev/hot-reloader-turbopack.js +2 -2
  105. package/dist/esm/server/dev/hot-reloader-webpack.js +1 -1
  106. package/dist/esm/server/lib/app-info-log.js +1 -1
  107. package/dist/esm/server/lib/router-utils/setup-dev-bundler.js +2 -1
  108. package/dist/esm/server/lib/router-utils/setup-dev-bundler.js.map +1 -1
  109. package/dist/esm/server/lib/start-server.js +1 -1
  110. package/dist/esm/shared/lib/errors/canary-only-config-error.js +1 -1
  111. package/dist/lib/has-necessary-dependencies.d.ts +2 -0
  112. package/dist/lib/has-necessary-dependencies.js.map +1 -1
  113. package/dist/lib/install-dependencies.js +1 -1
  114. package/dist/lib/install-dependencies.js.map +1 -1
  115. package/dist/lib/patch-incorrect-lockfile.js +3 -3
  116. package/dist/lib/typescript/loadTsConfig.d.ts +13 -0
  117. package/dist/lib/typescript/loadTsConfig.js +181 -0
  118. package/dist/lib/typescript/loadTsConfig.js.map +1 -0
  119. package/dist/lib/typescript/missingDependencyError.js +1 -1
  120. package/dist/lib/typescript/missingDependencyError.js.map +1 -1
  121. package/dist/lib/typescript/runTypeCheck.d.ts +2 -2
  122. package/dist/lib/typescript/runTypeCheck.js.map +1 -1
  123. package/dist/lib/typescript/runTypeCheckCli.d.ts +12 -0
  124. package/dist/lib/typescript/runTypeCheckCli.js +53 -0
  125. package/dist/lib/typescript/runTypeCheckCli.js.map +1 -0
  126. package/dist/lib/typescript/runTypeScriptCli.d.ts +38 -0
  127. package/dist/lib/typescript/runTypeScriptCli.js +256 -0
  128. package/dist/lib/typescript/runTypeScriptCli.js.map +1 -0
  129. package/dist/lib/verify-typescript-setup.d.ts +16 -1
  130. package/dist/lib/verify-typescript-setup.js +97 -56
  131. package/dist/lib/verify-typescript-setup.js.map +1 -1
  132. package/dist/server/config-schema.d.ts +1 -0
  133. package/dist/server/config-schema.js +1 -0
  134. package/dist/server/config-schema.js.map +1 -1
  135. package/dist/server/config-shared.d.ts +6 -0
  136. package/dist/server/config-shared.js +1 -0
  137. package/dist/server/config-shared.js.map +1 -1
  138. package/dist/server/config.js +1 -1
  139. package/dist/server/dev/hot-reloader-turbopack.js +2 -2
  140. package/dist/server/dev/hot-reloader-webpack.js +1 -1
  141. package/dist/server/lib/app-info-log.js +1 -1
  142. package/dist/server/lib/router-utils/setup-dev-bundler.js +2 -1
  143. package/dist/server/lib/router-utils/setup-dev-bundler.js.map +1 -1
  144. package/dist/server/lib/start-server.js +1 -1
  145. package/dist/shared/lib/errors/canary-only-config-error.js +1 -1
  146. package/dist/telemetry/anonymous-meta.js +1 -1
  147. package/dist/telemetry/events/build.d.ts +1 -0
  148. package/dist/telemetry/events/build.js.map +1 -1
  149. package/dist/telemetry/events/session-stopped.js +2 -2
  150. package/dist/telemetry/events/swc-load-failure.js +1 -1
  151. package/dist/telemetry/events/version.js +2 -2
  152. package/package.json +10 -10
  153. /package/dist/bundle-analyzer/_next/static/{yuLxudwpXbv0jKSL-s0ZM → xR78HbVQBty3GRl-Ydf7i}/_buildManifest.js +0 -0
  154. /package/dist/bundle-analyzer/_next/static/{yuLxudwpXbv0jKSL-s0ZM → xR78HbVQBty3GRl-Ydf7i}/_clientMiddlewareManifest.json +0 -0
  155. /package/dist/bundle-analyzer/_next/static/{yuLxudwpXbv0jKSL-s0ZM → xR78HbVQBty3GRl-Ydf7i}/_ssgManifest.js +0 -0
@@ -0,0 +1,38 @@
1
+ import path from 'node:path';
2
+ import { CompileError } from '../compile-error';
3
+ import { getTypeScriptConfigurationCli, runTypeScriptCli } from './runTypeScriptCli';
4
+ export async function runTypeCheckCli({ baseDir, tsConfigPath, tscPath, cacheDir, onFirstOutput }) {
5
+ const configuration = await getTypeScriptConfigurationCli({
6
+ baseDir,
7
+ tsConfigPath,
8
+ tscPath
9
+ });
10
+ const incremental = Boolean(configuration.compilerOptions.incremental || configuration.compilerOptions.composite);
11
+ const args = [
12
+ '--project',
13
+ tsConfigPath,
14
+ '--noEmit',
15
+ '--declarationMap',
16
+ 'false',
17
+ '--emitDeclarationOnly',
18
+ 'false'
19
+ ];
20
+ if (incremental && cacheDir) {
21
+ args.push('--tsBuildInfoFile', path.join(cacheDir, '.tsbuildinfo'));
22
+ }
23
+ const result = await runTypeScriptCli({
24
+ cwd: baseDir,
25
+ tscPath,
26
+ args,
27
+ onFirstOutput
28
+ });
29
+ if (result.exitCode !== 0) {
30
+ throw new CompileError();
31
+ }
32
+ return {
33
+ hasWarnings: false,
34
+ incremental
35
+ };
36
+ }
37
+
38
+ //# sourceMappingURL=runTypeCheckCli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/lib/typescript/runTypeCheckCli.ts"],"sourcesContent":["import path from 'node:path'\n\nimport { CompileError } from '../compile-error'\nimport type { TypeCheckResult } from './runTypeCheck'\nimport {\n getTypeScriptConfigurationCli,\n runTypeScriptCli,\n} from './runTypeScriptCli'\n\nexport async function runTypeCheckCli({\n baseDir,\n tsConfigPath,\n tscPath,\n cacheDir,\n onFirstOutput,\n}: {\n baseDir: string\n tsConfigPath: string\n tscPath: string\n cacheDir?: string\n /**\n * Called once when `tsc` first produces output. Used to stop the build\n * spinner so it does not sit above the diagnostics.\n */\n onFirstOutput?: () => void\n}): Promise<TypeCheckResult> {\n const configuration = await getTypeScriptConfigurationCli({\n baseDir,\n tsConfigPath,\n tscPath,\n })\n const incremental = Boolean(\n configuration.compilerOptions.incremental ||\n configuration.compilerOptions.composite\n )\n const args = [\n '--project',\n tsConfigPath,\n '--noEmit',\n '--declarationMap',\n 'false',\n '--emitDeclarationOnly',\n 'false',\n ]\n\n if (incremental && cacheDir) {\n args.push('--tsBuildInfoFile', path.join(cacheDir, '.tsbuildinfo'))\n }\n\n const result = await runTypeScriptCli({\n cwd: baseDir,\n tscPath,\n args,\n onFirstOutput,\n })\n\n if (result.exitCode !== 0) {\n throw new CompileError()\n }\n\n return {\n hasWarnings: false,\n incremental,\n }\n}\n"],"names":["path","CompileError","getTypeScriptConfigurationCli","runTypeScriptCli","runTypeCheckCli","baseDir","tsConfigPath","tscPath","cacheDir","onFirstOutput","configuration","incremental","Boolean","compilerOptions","composite","args","push","join","result","cwd","exitCode","hasWarnings"],"mappings":"AAAA,OAAOA,UAAU,YAAW;AAE5B,SAASC,YAAY,QAAQ,mBAAkB;AAE/C,SACEC,6BAA6B,EAC7BC,gBAAgB,QACX,qBAAoB;AAE3B,OAAO,eAAeC,gBAAgB,EACpCC,OAAO,EACPC,YAAY,EACZC,OAAO,EACPC,QAAQ,EACRC,aAAa,EAWd;IACC,MAAMC,gBAAgB,MAAMR,8BAA8B;QACxDG;QACAC;QACAC;IACF;IACA,MAAMI,cAAcC,QAClBF,cAAcG,eAAe,CAACF,WAAW,IACvCD,cAAcG,eAAe,CAACC,SAAS;IAE3C,MAAMC,OAAO;QACX;QACAT;QACA;QACA;QACA;QACA;QACA;KACD;IAED,IAAIK,eAAeH,UAAU;QAC3BO,KAAKC,IAAI,CAAC,qBAAqBhB,KAAKiB,IAAI,CAACT,UAAU;IACrD;IAEA,MAAMU,SAAS,MAAMf,iBAAiB;QACpCgB,KAAKd;QACLE;QACAQ;QACAN;IACF;IAEA,IAAIS,OAAOE,QAAQ,KAAK,GAAG;QACzB,MAAM,IAAInB;IACZ;IAEA,OAAO;QACLoB,aAAa;QACbV;IACF;AACF","ignoreList":[0]}
@@ -0,0 +1,217 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { spawnSync } from 'node:child_process';
4
+ import spawn from 'next/dist/compiled/cross-spawn';
5
+ import { bold } from '../picocolors';
6
+ import { resolveFrom } from '../resolve-from';
7
+ export function getTypeScriptPackageInfo(baseDir) {
8
+ var _packageJson_bin;
9
+ let packageJsonPath;
10
+ try {
11
+ packageJsonPath = resolveFrom(baseDir, 'typescript/package.json');
12
+ } catch {
13
+ return null;
14
+ }
15
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
16
+ const packageDir = path.dirname(packageJsonPath);
17
+ const apiPath = path.join(packageDir, 'lib', 'typescript.js');
18
+ const tscBin = typeof packageJson.bin === 'string' ? packageJson.bin : (_packageJson_bin = packageJson.bin) == null ? void 0 : _packageJson_bin.tsc;
19
+ const tscBinPath = tscBin ? path.resolve(packageDir, tscBin) : undefined;
20
+ let tscPath = tscBinPath;
21
+ if (tscBinPath && existsSync(tscBinPath) && packageJson.type === 'module' && path.extname(tscBinPath) === '') {
22
+ // TypeScript 7's extensionless ESM bin wrapper cannot be used as Node's
23
+ // main entry point on Node.js 20.9. Its imported JS entry is the same CLI
24
+ // wrapper and works across all supported Node.js versions.
25
+ const tscJsPath = path.join(packageDir, 'lib', 'tsc.js');
26
+ if (existsSync(tscJsPath)) {
27
+ tscPath = tscJsPath;
28
+ }
29
+ }
30
+ return {
31
+ packageJsonPath,
32
+ packageDir,
33
+ version: packageJson.version,
34
+ apiPath: existsSync(apiPath) ? apiPath : undefined,
35
+ tscPath: tscPath && existsSync(tscPath) ? tscPath : undefined
36
+ };
37
+ }
38
+ export function hasNativeTypeScriptPreview(baseDir) {
39
+ try {
40
+ resolveFrom(baseDir, '@typescript/native-preview/package.json');
41
+ return true;
42
+ } catch {
43
+ return false;
44
+ }
45
+ }
46
+ export function getTypeScriptApiMissingError(version) {
47
+ return Object.defineProperty(new Error(`TypeScript ${version} does not provide the compiler API required by Next.js. ` + `Enable ${bold('experimental.useTypeScriptCli')} in your Next.js config to use the TypeScript CLI, ` + `or install TypeScript 6 instead.`), "__NEXT_ERROR_CODE", {
48
+ value: "E1150",
49
+ enumerable: false,
50
+ configurable: true
51
+ });
52
+ }
53
+ const terminationSignals = [
54
+ 'SIGINT',
55
+ 'SIGTERM',
56
+ 'SIGHUP'
57
+ ];
58
+ export function runTypeScriptCli({ cwd, tscPath, args, captureOutput = false, onFirstOutput }) {
59
+ return new Promise((resolve, reject)=>{
60
+ var _child_stdout, _child_stderr;
61
+ const child = spawn(process.execPath, [
62
+ tscPath,
63
+ ...args
64
+ ], {
65
+ cwd,
66
+ // TypeScript 7's Node wrapper starts the native compiler synchronously
67
+ // on older Node.js releases. A separate process group lets termination
68
+ // reach both processes instead of orphaning the native compiler.
69
+ detached: process.platform !== 'win32',
70
+ shell: false,
71
+ stdio: [
72
+ 'ignore',
73
+ 'pipe',
74
+ 'pipe'
75
+ ],
76
+ env: {
77
+ ...process.env,
78
+ // Piping stdio makes `tsc` disable colored/pretty diagnostics. Restore
79
+ // them when we are forwarding output to a TTY (not capturing it for
80
+ // parsing, e.g. `--showConfig`).
81
+ ...!captureOutput && process.stdout.isTTY ? {
82
+ FORCE_COLOR: '1'
83
+ } : undefined
84
+ }
85
+ });
86
+ let stdout = '';
87
+ let stderr = '';
88
+ (_child_stdout = child.stdout) == null ? void 0 : _child_stdout.setEncoding('utf8');
89
+ (_child_stderr = child.stderr) == null ? void 0 : _child_stderr.setEncoding('utf8');
90
+ if (captureOutput) {
91
+ var _child_stdout1, _child_stderr1;
92
+ (_child_stdout1 = child.stdout) == null ? void 0 : _child_stdout1.on('data', (chunk)=>{
93
+ stdout += chunk;
94
+ });
95
+ (_child_stderr1 = child.stderr) == null ? void 0 : _child_stderr1.on('data', (chunk)=>{
96
+ stderr += chunk;
97
+ });
98
+ } else {
99
+ var _child_stdout2, _child_stderr2;
100
+ const forward = (dest, chunk)=>{
101
+ onFirstOutput == null ? void 0 : onFirstOutput();
102
+ onFirstOutput = undefined // ensure we don't call it again
103
+ ;
104
+ dest.write(chunk);
105
+ };
106
+ (_child_stdout2 = child.stdout) == null ? void 0 : _child_stdout2.on('data', (chunk)=>{
107
+ forward(process.stdout, chunk);
108
+ });
109
+ (_child_stderr2 = child.stderr) == null ? void 0 : _child_stderr2.on('data', (chunk)=>{
110
+ forward(process.stderr, chunk);
111
+ });
112
+ }
113
+ let terminationRequested = false;
114
+ const terminateChild = ()=>{
115
+ if (terminationRequested || child.killed || child.pid === undefined) {
116
+ return;
117
+ }
118
+ terminationRequested = true;
119
+ // The native compiler ignores SIGTERM and SIGINT, so send a kill signal.
120
+ // Target the whole process group so the signal reaches the native compiler whether
121
+ // it is a grandchild or a direct child.
122
+ // https://github.com/microsoft/typescript-go/pull/4592 should improve this in the long run
123
+ if (process.platform === 'win32') {
124
+ spawnSync('taskkill', [
125
+ '/pid',
126
+ String(child.pid),
127
+ '/T',
128
+ '/F'
129
+ ], {
130
+ stdio: 'ignore',
131
+ windowsHide: true
132
+ });
133
+ } else {
134
+ try {
135
+ // https://www.youtube.com/watch?v=Fow7iUaKrq4
136
+ process.kill(-child.pid, 'SIGKILL');
137
+ } catch {
138
+ // The process may have exited between the lifecycle event and kill.
139
+ }
140
+ }
141
+ };
142
+ const terminateOnExit = ()=>terminateChild();
143
+ process.once('exit', terminateOnExit);
144
+ const handler = ()=>{
145
+ terminateChild();
146
+ process.exit(1);
147
+ };
148
+ for (const signal of terminationSignals){
149
+ process.once(signal, handler);
150
+ }
151
+ const cleanup = ()=>{
152
+ process.off('exit', terminateOnExit);
153
+ for (const signal of terminationSignals){
154
+ process.off(signal, handler);
155
+ }
156
+ };
157
+ let settled = false;
158
+ const finish = (settle)=>{
159
+ if (settled) {
160
+ return;
161
+ }
162
+ settled = true;
163
+ cleanup();
164
+ settle();
165
+ };
166
+ child.on('error', (error)=>{
167
+ finish(()=>reject(error));
168
+ });
169
+ child.on('close', (code, signal)=>{
170
+ finish(()=>{
171
+ resolve({
172
+ exitCode: code ?? 1,
173
+ signal,
174
+ stdout,
175
+ stderr
176
+ });
177
+ });
178
+ });
179
+ });
180
+ }
181
+ export async function getTypeScriptConfigurationCli({ baseDir, tsConfigPath, tscPath }) {
182
+ const result = await runTypeScriptCli({
183
+ cwd: baseDir,
184
+ tscPath,
185
+ args: [
186
+ '--showConfig',
187
+ '--project',
188
+ tsConfigPath,
189
+ '--pretty',
190
+ 'false'
191
+ ],
192
+ captureOutput: true
193
+ });
194
+ if (result.exitCode !== 0) {
195
+ throw Object.defineProperty(new Error([
196
+ result.stdout,
197
+ result.stderr
198
+ ].filter(Boolean).join('\n').trim()), "__NEXT_ERROR_CODE", {
199
+ value: "E394",
200
+ enumerable: false,
201
+ configurable: true
202
+ });
203
+ }
204
+ try {
205
+ return JSON.parse(result.stdout);
206
+ } catch (cause) {
207
+ throw Object.defineProperty(new Error(`Could not parse output from TypeScript's --showConfig.`, {
208
+ cause
209
+ }), "__NEXT_ERROR_CODE", {
210
+ value: "E1149",
211
+ enumerable: false,
212
+ configurable: true
213
+ });
214
+ }
215
+ }
216
+
217
+ //# sourceMappingURL=runTypeScriptCli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/lib/typescript/runTypeScriptCli.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\nimport path from 'node:path'\nimport { spawnSync } from 'node:child_process'\n\nimport spawn from 'next/dist/compiled/cross-spawn'\n\nimport { bold } from '../picocolors'\nimport { resolveFrom } from '../resolve-from'\n\nexport interface TypeScriptPackageInfo {\n packageJsonPath: string\n packageDir: string\n version: string\n apiPath?: string\n tscPath?: string\n}\n\nexport function getTypeScriptPackageInfo(\n baseDir: string\n): TypeScriptPackageInfo | null {\n let packageJsonPath: string\n try {\n packageJsonPath = resolveFrom(baseDir, 'typescript/package.json')\n } catch {\n return null\n }\n\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as {\n version: string\n type?: string\n bin?: string | Record<string, string>\n }\n const packageDir = path.dirname(packageJsonPath)\n const apiPath = path.join(packageDir, 'lib', 'typescript.js')\n const tscBin =\n typeof packageJson.bin === 'string' ? packageJson.bin : packageJson.bin?.tsc\n const tscBinPath = tscBin ? path.resolve(packageDir, tscBin) : undefined\n let tscPath = tscBinPath\n\n if (\n tscBinPath &&\n existsSync(tscBinPath) &&\n packageJson.type === 'module' &&\n path.extname(tscBinPath) === ''\n ) {\n // TypeScript 7's extensionless ESM bin wrapper cannot be used as Node's\n // main entry point on Node.js 20.9. Its imported JS entry is the same CLI\n // wrapper and works across all supported Node.js versions.\n const tscJsPath = path.join(packageDir, 'lib', 'tsc.js')\n if (existsSync(tscJsPath)) {\n tscPath = tscJsPath\n }\n }\n\n return {\n packageJsonPath,\n packageDir,\n version: packageJson.version,\n apiPath: existsSync(apiPath) ? apiPath : undefined,\n tscPath: tscPath && existsSync(tscPath) ? tscPath : undefined,\n }\n}\n\nexport function hasNativeTypeScriptPreview(baseDir: string): boolean {\n try {\n resolveFrom(baseDir, '@typescript/native-preview/package.json')\n return true\n } catch {\n return false\n }\n}\n\nexport function getTypeScriptApiMissingError(version: string): Error {\n return new Error(\n `TypeScript ${version} does not provide the compiler API required by Next.js. ` +\n `Enable ${bold('experimental.useTypeScriptCli')} in your Next.js config to use the TypeScript CLI, ` +\n `or install TypeScript 6 instead.`\n )\n}\n\nexport interface TypeScriptCliResult {\n exitCode: number\n signal: NodeJS.Signals | null\n stdout: string\n stderr: string\n}\n\nconst terminationSignals: NodeJS.Signals[] = ['SIGINT', 'SIGTERM', 'SIGHUP']\n\nexport function runTypeScriptCli({\n cwd,\n tscPath,\n args,\n captureOutput = false,\n onFirstOutput,\n}: {\n cwd: string\n tscPath: string\n args: string[]\n /**\n * Accumulate stdout/stderr into the resolved result instead of forwarding it\n * to this process's stdout/stderr (for e.g. parsing `--showConfig` output).\n */\n captureOutput?: boolean\n /**\n * Called once, on the first chunk of forwarded output. Used to stop the build\n * spinner before `tsc`'s diagnostics appear. Not called when capturing.\n */\n onFirstOutput?: () => void\n}): Promise<TypeScriptCliResult> {\n return new Promise((resolve, reject) => {\n const child = spawn(process.execPath, [tscPath, ...args], {\n cwd,\n // TypeScript 7's Node wrapper starts the native compiler synchronously\n // on older Node.js releases. A separate process group lets termination\n // reach both processes instead of orphaning the native compiler.\n detached: process.platform !== 'win32',\n shell: false,\n stdio: ['ignore', 'pipe', 'pipe'],\n env: {\n ...process.env,\n // Piping stdio makes `tsc` disable colored/pretty diagnostics. Restore\n // them when we are forwarding output to a TTY (not capturing it for\n // parsing, e.g. `--showConfig`).\n ...(!captureOutput && process.stdout.isTTY\n ? { FORCE_COLOR: '1' }\n : undefined),\n },\n })\n\n let stdout = ''\n let stderr = ''\n\n child.stdout?.setEncoding('utf8')\n child.stderr?.setEncoding('utf8')\n\n if (captureOutput) {\n child.stdout?.on('data', (chunk: string) => {\n stdout += chunk\n })\n child.stderr?.on('data', (chunk: string) => {\n stderr += chunk\n })\n } else {\n const forward = (dest: NodeJS.WriteStream, chunk: string) => {\n onFirstOutput?.()\n onFirstOutput = undefined // ensure we don't call it again\n dest.write(chunk)\n }\n\n child.stdout?.on('data', (chunk: string) => {\n forward(process.stdout, chunk)\n })\n child.stderr?.on('data', (chunk: string) => {\n forward(process.stderr, chunk)\n })\n }\n\n let terminationRequested = false\n const terminateChild = () => {\n if (terminationRequested || child.killed || child.pid === undefined) {\n return\n }\n terminationRequested = true\n\n // The native compiler ignores SIGTERM and SIGINT, so send a kill signal.\n // Target the whole process group so the signal reaches the native compiler whether\n // it is a grandchild or a direct child.\n // https://github.com/microsoft/typescript-go/pull/4592 should improve this in the long run\n if (process.platform === 'win32') {\n spawnSync('taskkill', ['/pid', String(child.pid), '/T', '/F'], {\n stdio: 'ignore',\n windowsHide: true,\n })\n } else {\n try {\n // https://www.youtube.com/watch?v=Fow7iUaKrq4\n process.kill(-child.pid, 'SIGKILL')\n } catch {\n // The process may have exited between the lifecycle event and kill.\n }\n }\n }\n const terminateOnExit = () => terminateChild()\n process.once('exit', terminateOnExit)\n\n const handler = () => {\n terminateChild()\n process.exit(1)\n }\n for (const signal of terminationSignals) {\n process.once(signal, handler)\n }\n\n const cleanup = () => {\n process.off('exit', terminateOnExit)\n for (const signal of terminationSignals) {\n process.off(signal, handler)\n }\n }\n\n let settled = false\n const finish = (settle: () => void) => {\n if (settled) {\n return\n }\n settled = true\n cleanup()\n settle()\n }\n\n child.on('error', (error) => {\n finish(() => reject(error))\n })\n child.on('close', (code, signal) => {\n finish(() => {\n resolve({\n exitCode: code ?? 1,\n signal,\n stdout,\n stderr,\n })\n })\n })\n })\n}\n\nexport async function getTypeScriptConfigurationCli({\n baseDir,\n tsConfigPath,\n tscPath,\n}: {\n baseDir: string\n tsConfigPath: string\n tscPath: string\n}): Promise<{ compilerOptions: Record<string, any> }> {\n const result = await runTypeScriptCli({\n cwd: baseDir,\n tscPath,\n args: ['--showConfig', '--project', tsConfigPath, '--pretty', 'false'],\n captureOutput: true,\n })\n\n if (result.exitCode !== 0) {\n throw new Error(\n [result.stdout, result.stderr].filter(Boolean).join('\\n').trim()\n )\n }\n\n try {\n return JSON.parse(result.stdout)\n } catch (cause) {\n throw new Error(`Could not parse output from TypeScript's --showConfig.`, {\n cause,\n })\n }\n}\n"],"names":["existsSync","readFileSync","path","spawnSync","spawn","bold","resolveFrom","getTypeScriptPackageInfo","baseDir","packageJson","packageJsonPath","JSON","parse","packageDir","dirname","apiPath","join","tscBin","bin","tsc","tscBinPath","resolve","undefined","tscPath","type","extname","tscJsPath","version","hasNativeTypeScriptPreview","getTypeScriptApiMissingError","Error","terminationSignals","runTypeScriptCli","cwd","args","captureOutput","onFirstOutput","Promise","reject","child","process","execPath","detached","platform","shell","stdio","env","stdout","isTTY","FORCE_COLOR","stderr","setEncoding","on","chunk","forward","dest","write","terminationRequested","terminateChild","killed","pid","String","windowsHide","kill","terminateOnExit","once","handler","exit","signal","cleanup","off","settled","finish","settle","error","code","exitCode","getTypeScriptConfigurationCli","tsConfigPath","result","filter","Boolean","trim","cause"],"mappings":"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","ignoreList":[0]}
@@ -1,5 +1,5 @@
1
1
  import { bold, cyan, red, yellow } from './picocolors';
2
- import path, { join } from 'path';
2
+ import path from 'path';
3
3
  import { hasNecessaryDependencies } from './has-necessary-dependencies';
4
4
  import semver from 'next/dist/compiled/semver';
5
5
  import { CompileError } from './compile-error';
@@ -10,14 +10,19 @@ import { writeConfigurationDefaults } from './typescript/writeConfigurationDefau
10
10
  import { installDependencies } from './install-dependencies';
11
11
  import { isCI } from '../server/ci-info';
12
12
  import { missingDepsError } from './typescript/missingDependencyError';
13
- import { resolveFrom } from './resolve-from';
14
- const typescriptPackage = {
13
+ import { getTypeScriptApiMissingError, getTypeScriptPackageInfo, hasNativeTypeScriptPreview } from './typescript/runTypeScriptCli';
14
+ const typescriptApiPackage = {
15
15
  file: 'typescript/lib/typescript.js',
16
16
  pkg: 'typescript',
17
+ install: 'typescript@^6.0.0',
17
18
  exportsRestrict: true
18
19
  };
19
- const requiredPackages = [
20
- typescriptPackage,
20
+ const typescriptCliPackage = {
21
+ file: 'typescript/bin/tsc',
22
+ pkg: 'typescript',
23
+ exportsRestrict: true
24
+ };
25
+ const requiredTypePackages = [
21
26
  {
22
27
  file: '@types/react/index.d.ts',
23
28
  pkg: '@types/react',
@@ -29,21 +34,10 @@ const requiredPackages = [
29
34
  exportsRestrict: true
30
35
  }
31
36
  ];
32
- /**
33
- * Check if @typescript/native-preview is installed as an alternative TypeScript compiler.
34
- * This is a Go-based native TypeScript compiler that can be used instead of the standard
35
- * TypeScript package for faster compilation.
36
- */ function hasNativeTypeScriptPreview(dir) {
37
- try {
38
- resolveFrom(dir, '@typescript/native-preview/package.json');
39
- return true;
40
- } catch {
41
- return false;
42
- }
43
- }
44
- export async function verifyAndRunTypeScript({ dir, distDir, cacheDir, strictRouteTypes, tsconfigPath, shouldRunTypeCheck, typedRoutes, disableStaticImages, hasAppDir, hasPagesDir, appDir, pagesDir, debugBuildPaths }) {
37
+ export async function verifyAndRunTypeScript({ dir, distDir, cacheDir, strictRouteTypes, tsconfigPath, shouldRunTypeCheck, typedRoutes, disableStaticImages, hasAppDir, hasPagesDir, appDir, pagesDir, debugBuildPaths, useTypeScriptCli = false, onFirstCliOutput }) {
45
38
  const tsConfigFileName = tsconfigPath || 'tsconfig.json';
46
39
  const resolvedTsConfigPath = path.join(dir, tsConfigFileName);
40
+ const typeCheckMode = useTypeScriptCli ? 'typescript-cli' : 'typescript-api';
47
41
  // Construct intentDirs from appDir and pagesDir for getTypeScriptIntent
48
42
  const intentDirs = [
49
43
  pagesDir,
@@ -55,17 +49,26 @@ export async function verifyAndRunTypeScript({ dir, distDir, cacheDir, strictRou
55
49
  const intent = await getTypeScriptIntent(dir, intentDirs, tsConfigFileName);
56
50
  if (!intent) {
57
51
  return {
58
- version: null
52
+ version: null,
53
+ typeCheckMode
59
54
  };
60
55
  }
61
56
  // Check if @typescript/native-preview is installed as an alternative
62
57
  const hasNativePreview = hasNativeTypeScriptPreview(dir);
58
+ const installedTypeScript = getTypeScriptPackageInfo(dir);
59
+ if (!useTypeScriptCli && !hasNativePreview && installedTypeScript && !installedTypeScript.apiPath) {
60
+ throw getTypeScriptApiMissingError(installedTypeScript.version);
61
+ }
62
+ const requiredPackages = [
63
+ useTypeScriptCli ? typescriptCliPackage : typescriptApiPackage,
64
+ ...requiredTypePackages
65
+ ];
63
66
  // Ensure TypeScript and necessary `@types/*` are installed:
64
67
  let deps = hasNecessaryDependencies(dir, requiredPackages);
65
68
  // If @typescript/native-preview is installed and only the typescript package is missing,
66
69
  // we can skip auto-installing typescript since the native preview provides TS compilation.
67
70
  // However, we still need @types/react and @types/node for type checking.
68
- if (hasNativePreview && ((_deps_missing = deps.missing) == null ? void 0 : _deps_missing.length) > 0) {
71
+ if (!useTypeScriptCli && hasNativePreview && ((_deps_missing = deps.missing) == null ? void 0 : _deps_missing.length) > 0) {
69
72
  const missingWithoutTypescript = deps.missing.filter((dep)=>dep.pkg !== 'typescript');
70
73
  const onlyTypescriptMissing = deps.missing.length === 1 && deps.missing[0].pkg === 'typescript';
71
74
  if (onlyTypescriptMissing) {
@@ -83,7 +86,8 @@ export async function verifyAndRunTypeScript({ dir, distDir, cacheDir, strictRou
83
86
  typedRoutes
84
87
  });
85
88
  return {
86
- version: null
89
+ version: null,
90
+ typeCheckMode
87
91
  };
88
92
  }
89
93
  // If there are other missing deps besides typescript, only install those
@@ -106,10 +110,14 @@ export async function verifyAndRunTypeScript({ dir, distDir, cacheDir, strictRou
106
110
  });
107
111
  deps = hasNecessaryDependencies(dir, requiredPackages);
108
112
  }
109
- // Load TypeScript after we're sure it exists:
110
- const tsPackageJsonPath = deps.resolved.get(join('typescript', 'package.json'));
111
- const typescriptPackageJson = require(tsPackageJsonPath);
112
- const typescriptVersion = typescriptPackageJson.version;
113
+ const typeScriptPackage = getTypeScriptPackageInfo(dir);
114
+ const typeScriptPath = useTypeScriptCli ? typeScriptPackage == null ? void 0 : typeScriptPackage.tscPath : typeScriptPackage == null ? void 0 : typeScriptPackage.apiPath;
115
+ if (!typeScriptPackage || !typeScriptPath) {
116
+ missingDepsError(dir, deps.missing.length > 0 ? deps.missing : [
117
+ useTypeScriptCli ? typescriptCliPackage : typescriptApiPackage
118
+ ]);
119
+ }
120
+ const typescriptVersion = typeScriptPackage.version;
113
121
  if (semver.lt(typescriptVersion, '5.1.0')) {
114
122
  log.warn(`Minimum recommended TypeScript version is v5.1.0, older versions can potentially be incompatible with Next.js. Detected: ${typescriptVersion}`);
115
123
  }
@@ -128,45 +136,72 @@ export async function verifyAndRunTypeScript({ dir, distDir, cacheDir, strictRou
128
136
  });
129
137
  let result;
130
138
  if (shouldRunTypeCheck) {
131
- const { runTypeCheck } = require('./typescript/runTypeCheck');
132
- // Install native bindings so that code frame rendering works in the worker
133
- const { installBindings } = require('../build/swc/install-bindings');
134
- await installBindings();
135
- const tsPath = deps.resolved.get('typescript');
136
- const typescript = await Promise.resolve(require(tsPath));
137
- // Verify the project passes type-checking before we go to webpack phase:
138
- result = await runTypeCheck(typescript, dir, distDir, resolvedTsConfigPath, cacheDir, hasAppDir, {
139
- app: appDir,
140
- pages: pagesDir
141
- }, debugBuildPaths);
139
+ if (useTypeScriptCli) {
140
+ if (debugBuildPaths) {
141
+ log.warn('`experimental.useTypeScriptCli` checks the complete TypeScript project; `--debug-build-paths` does not limit type checking.');
142
+ }
143
+ const { runTypeCheckCli } = require('./typescript/runTypeCheckCli');
144
+ result = await runTypeCheckCli({
145
+ baseDir: dir,
146
+ tsConfigPath: resolvedTsConfigPath,
147
+ tscPath: typeScriptPath,
148
+ cacheDir,
149
+ onFirstOutput: onFirstCliOutput
150
+ });
151
+ } else {
152
+ const { runTypeCheck } = require('./typescript/runTypeCheck');
153
+ // Install native bindings so that code frame rendering works in the worker
154
+ const { installBindings } = require('../build/swc/install-bindings');
155
+ await installBindings();
156
+ const typescript = await Promise.resolve(require(typeScriptPath));
157
+ // Verify the project passes type-checking before we go to webpack phase:
158
+ result = await runTypeCheck(typescript, dir, distDir, resolvedTsConfigPath, cacheDir, hasAppDir, {
159
+ app: appDir,
160
+ pages: pagesDir
161
+ }, debugBuildPaths);
162
+ }
142
163
  }
143
164
  return {
144
165
  result,
145
- version: typescriptVersion
166
+ version: typescriptVersion,
167
+ typeCheckMode
146
168
  };
147
169
  } catch (err) {
148
- // These are special errors that should not show a stack trace:
170
+ // Print the user-facing message here and rethrow. This function runs both
171
+ // in-process (next dev / next test / next typegen, and the CLI type-check
172
+ // during build) and inside a jest worker (the TypeScript-API type-check
173
+ // during build). A thrown error does not survive the worker boundary — the
174
+ // parent only sees `Call retries were exceeded` — so the message must be
175
+ // printed on this side. The caller decides what to do with the throw (exit,
176
+ // or tolerate it as `next dev` does on re-verification).
149
177
  if (err instanceof CompileError) {
178
+ // The checker already printed its diagnostics.
150
179
  console.error(red('Failed to type check.\n'));
151
- console.error(err.message);
152
- process.exit(1);
153
- }
154
- /**
155
- * verifyAndRunTypeScript can be either invoked directly in the main thread (during next dev / next lint)
156
- * or run in a worker (during next build). In the latter case, we need to print the error message, as the
157
- * parent process will only receive an `Jest worker encountered 1 child process exceptions, exceeding retry limit`.
158
- */ // we are in a worker, print the error message and exit the process
159
- if (process.env.IS_NEXT_WORKER) {
160
- if (err instanceof Error) {
180
+ if (err.message) {
161
181
  console.error(err.message);
162
- } else {
163
- console.error(err);
164
182
  }
165
- process.exit(1);
183
+ } else if (err instanceof Error) {
184
+ console.error(err.message);
185
+ } else {
186
+ console.error(err);
166
187
  }
167
- // we are in the main thread, throw the error and it will be handled by the caller
168
188
  throw err;
169
189
  }
170
190
  }
191
+ /**
192
+ * Worker entrypoint used by `next build` for the TypeScript-API type-check.
193
+ * `verifyAndRunTypeScript` has already printed any error, so on failure we exit
194
+ * the worker directly rather than rethrowing: a thrown error would be retried by
195
+ * jest-worker and surface in the parent as the unhelpful
196
+ * `Jest worker encountered 1 child process exceptions, exceeding retry limit`.
197
+ */ export async function verifyAndRunTypeScriptInWorker(options) {
198
+ try {
199
+ return await verifyAndRunTypeScript(options);
200
+ } catch {
201
+ // The error was already printed by `verifyAndRunTypeScript`.
202
+ // Kill the worker with a non-zero exit code.
203
+ process.exit(1);
204
+ }
205
+ }
171
206
 
172
207
  //# sourceMappingURL=verify-typescript-setup.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/verify-typescript-setup.ts"],"sourcesContent":["import { bold, cyan, red, yellow } from './picocolors'\nimport path, { join } from 'path'\n\nimport { hasNecessaryDependencies } from './has-necessary-dependencies'\nimport type {\n MissingDependency,\n NecessaryDependencies,\n} from './has-necessary-dependencies'\nimport semver from 'next/dist/compiled/semver'\nimport { CompileError } from './compile-error'\nimport * as log from '../build/output/log'\n\nimport { getTypeScriptIntent } from './typescript/getTypeScriptIntent'\nimport type { TypeCheckResult } from './typescript/runTypeCheck'\nimport { writeAppTypeDeclarations } from './typescript/writeAppTypeDeclarations'\nimport { writeConfigurationDefaults } from './typescript/writeConfigurationDefaults'\nimport { installDependencies } from './install-dependencies'\nimport { isCI } from '../server/ci-info'\nimport { missingDepsError } from './typescript/missingDependencyError'\nimport { resolveFrom } from './resolve-from'\n\nconst typescriptPackage: MissingDependency = {\n file: 'typescript/lib/typescript.js',\n pkg: 'typescript',\n exportsRestrict: true,\n}\n\nconst requiredPackages: MissingDependency[] = [\n typescriptPackage,\n {\n file: '@types/react/index.d.ts',\n pkg: '@types/react',\n exportsRestrict: true,\n },\n {\n file: '@types/node/index.d.ts',\n pkg: '@types/node',\n exportsRestrict: true,\n },\n]\n\n/**\n * Check if @typescript/native-preview is installed as an alternative TypeScript compiler.\n * This is a Go-based native TypeScript compiler that can be used instead of the standard\n * TypeScript package for faster compilation.\n */\nfunction hasNativeTypeScriptPreview(dir: string): boolean {\n try {\n resolveFrom(dir, '@typescript/native-preview/package.json')\n return true\n } catch {\n return false\n }\n}\n\nexport async function verifyAndRunTypeScript({\n dir,\n distDir,\n cacheDir,\n strictRouteTypes,\n tsconfigPath,\n shouldRunTypeCheck,\n typedRoutes,\n disableStaticImages,\n hasAppDir,\n hasPagesDir,\n appDir,\n pagesDir,\n debugBuildPaths,\n}: {\n dir: string\n distDir: string\n cacheDir?: string\n strictRouteTypes: boolean\n tsconfigPath: string | undefined\n shouldRunTypeCheck: boolean\n typedRoutes: boolean\n disableStaticImages: boolean\n hasAppDir: boolean\n hasPagesDir: boolean\n appDir?: string\n pagesDir?: string\n debugBuildPaths?: { app?: string[]; pages?: string[] }\n}): Promise<{ result?: TypeCheckResult; version: string | null }> {\n const tsConfigFileName = tsconfigPath || 'tsconfig.json'\n const resolvedTsConfigPath = path.join(dir, tsConfigFileName)\n\n // Construct intentDirs from appDir and pagesDir for getTypeScriptIntent\n const intentDirs = [pagesDir, appDir].filter(Boolean) as string[]\n\n try {\n // Check if the project uses TypeScript:\n const intent = await getTypeScriptIntent(dir, intentDirs, tsConfigFileName)\n if (!intent) {\n return { version: null }\n }\n\n // Check if @typescript/native-preview is installed as an alternative\n const hasNativePreview = hasNativeTypeScriptPreview(dir)\n\n // Ensure TypeScript and necessary `@types/*` are installed:\n let deps: NecessaryDependencies = hasNecessaryDependencies(\n dir,\n requiredPackages\n )\n\n // If @typescript/native-preview is installed and only the typescript package is missing,\n // we can skip auto-installing typescript since the native preview provides TS compilation.\n // However, we still need @types/react and @types/node for type checking.\n if (hasNativePreview && deps.missing?.length > 0) {\n const missingWithoutTypescript = deps.missing.filter(\n (dep) => dep.pkg !== 'typescript'\n )\n const onlyTypescriptMissing =\n deps.missing.length === 1 && deps.missing[0].pkg === 'typescript'\n\n if (onlyTypescriptMissing) {\n // @typescript/native-preview is installed and only typescript is missing\n // Skip installation and return early - the project can use the native preview\n log.info(\n `Detected ${bold('@typescript/native-preview')} as TypeScript compiler. ` +\n `Some Next.js TypeScript features (like type checking during build) require the standard ${bold('typescript')} package.`\n )\n\n // Still write type declarations since they don't require the typescript package\n await writeAppTypeDeclarations({\n baseDir: dir,\n distDir,\n imageImportsEnabled: !disableStaticImages,\n hasPagesDir,\n hasAppDir,\n strictRouteTypes,\n typedRoutes,\n })\n\n return { version: null }\n }\n\n // If there are other missing deps besides typescript, only install those\n if (\n missingWithoutTypescript.length > 0 &&\n missingWithoutTypescript.length < deps.missing.length\n ) {\n deps.missing = missingWithoutTypescript\n }\n }\n\n if (deps.missing?.length > 0) {\n if (isCI) {\n // we don't attempt auto install in CI to avoid side-effects\n // and instead log the error for installing needed packages\n missingDepsError(dir, deps.missing)\n }\n console.log(\n bold(\n yellow(\n `It looks like you're trying to use TypeScript but do not have the required package(s) installed.`\n )\n ) +\n '\\n' +\n 'Installing dependencies' +\n '\\n\\n' +\n bold(\n 'If you are not trying to use TypeScript, please remove the ' +\n cyan('tsconfig.json') +\n ' file from your package root (and any TypeScript files in your app and pages directories).'\n ) +\n '\\n'\n )\n await installDependencies(dir, deps.missing, true).catch((err) => {\n if (err && typeof err === 'object' && 'command' in err) {\n console.error(\n `Failed to install required TypeScript dependencies, please install them manually to continue:\\n` +\n (err as any).command +\n '\\n'\n )\n }\n throw err\n })\n deps = hasNecessaryDependencies(dir, requiredPackages)\n }\n\n // Load TypeScript after we're sure it exists:\n const tsPackageJsonPath = deps.resolved.get(\n join('typescript', 'package.json')\n )!\n const typescriptPackageJson = require(tsPackageJsonPath)\n\n const typescriptVersion = typescriptPackageJson.version\n\n if (semver.lt(typescriptVersion, '5.1.0')) {\n log.warn(\n `Minimum recommended TypeScript version is v5.1.0, older versions can potentially be incompatible with Next.js. Detected: ${typescriptVersion}`\n )\n }\n\n // Reconfigure (or create) the user's `tsconfig.json` for them:\n await writeConfigurationDefaults(\n typescriptVersion,\n resolvedTsConfigPath,\n intent.firstTimeSetup,\n hasAppDir,\n distDir,\n hasPagesDir,\n strictRouteTypes\n )\n // Write out the necessary `next-env.d.ts` file to correctly register\n // Next.js' types:\n await writeAppTypeDeclarations({\n baseDir: dir,\n distDir,\n imageImportsEnabled: !disableStaticImages,\n hasPagesDir,\n hasAppDir,\n strictRouteTypes,\n typedRoutes,\n })\n\n let result\n if (shouldRunTypeCheck) {\n const { runTypeCheck } =\n require('./typescript/runTypeCheck') as typeof import('./typescript/runTypeCheck')\n // Install native bindings so that code frame rendering works in the worker\n const { installBindings } =\n require('../build/swc/install-bindings') as typeof import('../build/swc/install-bindings')\n await installBindings()\n\n const tsPath = deps.resolved.get('typescript')!\n const typescript = (await Promise.resolve(\n require(tsPath)\n )) as typeof import('typescript')\n\n // Verify the project passes type-checking before we go to webpack phase:\n result = await runTypeCheck(\n typescript,\n dir,\n distDir,\n resolvedTsConfigPath,\n cacheDir,\n hasAppDir,\n { app: appDir, pages: pagesDir },\n debugBuildPaths\n )\n }\n return { result, version: typescriptVersion }\n } catch (err) {\n // These are special errors that should not show a stack trace:\n if (err instanceof CompileError) {\n console.error(red('Failed to type check.\\n'))\n console.error(err.message)\n process.exit(1)\n }\n\n /**\n * verifyAndRunTypeScript can be either invoked directly in the main thread (during next dev / next lint)\n * or run in a worker (during next build). In the latter case, we need to print the error message, as the\n * parent process will only receive an `Jest worker encountered 1 child process exceptions, exceeding retry limit`.\n */\n\n // we are in a worker, print the error message and exit the process\n if (process.env.IS_NEXT_WORKER) {\n if (err instanceof Error) {\n console.error(err.message)\n } else {\n console.error(err)\n }\n process.exit(1)\n }\n // we are in the main thread, throw the error and it will be handled by the caller\n throw err\n }\n}\n"],"names":["bold","cyan","red","yellow","path","join","hasNecessaryDependencies","semver","CompileError","log","getTypeScriptIntent","writeAppTypeDeclarations","writeConfigurationDefaults","installDependencies","isCI","missingDepsError","resolveFrom","typescriptPackage","file","pkg","exportsRestrict","requiredPackages","hasNativeTypeScriptPreview","dir","verifyAndRunTypeScript","distDir","cacheDir","strictRouteTypes","tsconfigPath","shouldRunTypeCheck","typedRoutes","disableStaticImages","hasAppDir","hasPagesDir","appDir","pagesDir","debugBuildPaths","tsConfigFileName","resolvedTsConfigPath","intentDirs","filter","Boolean","deps","intent","version","hasNativePreview","missing","length","missingWithoutTypescript","dep","onlyTypescriptMissing","info","baseDir","imageImportsEnabled","console","catch","err","error","command","tsPackageJsonPath","resolved","get","typescriptPackageJson","require","typescriptVersion","lt","warn","firstTimeSetup","result","runTypeCheck","installBindings","tsPath","typescript","Promise","resolve","app","pages","message","process","exit","env","IS_NEXT_WORKER","Error"],"mappings":"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","ignoreList":[0]}
1
+ {"version":3,"sources":["../../../src/lib/verify-typescript-setup.ts"],"sourcesContent":["import { bold, cyan, red, yellow } from './picocolors'\nimport path from 'path'\n\nimport { hasNecessaryDependencies } from './has-necessary-dependencies'\nimport type {\n MissingDependency,\n NecessaryDependencies,\n} from './has-necessary-dependencies'\nimport semver from 'next/dist/compiled/semver'\nimport { CompileError } from './compile-error'\nimport * as log from '../build/output/log'\n\nimport { getTypeScriptIntent } from './typescript/getTypeScriptIntent'\nimport type { TypeCheckResult } from './typescript/runTypeCheck'\nimport { writeAppTypeDeclarations } from './typescript/writeAppTypeDeclarations'\nimport { writeConfigurationDefaults } from './typescript/writeConfigurationDefaults'\nimport { installDependencies } from './install-dependencies'\nimport { isCI } from '../server/ci-info'\nimport { missingDepsError } from './typescript/missingDependencyError'\nimport {\n getTypeScriptApiMissingError,\n getTypeScriptPackageInfo,\n hasNativeTypeScriptPreview,\n} from './typescript/runTypeScriptCli'\n\nconst typescriptApiPackage: MissingDependency = {\n file: 'typescript/lib/typescript.js',\n pkg: 'typescript',\n install: 'typescript@^6.0.0',\n exportsRestrict: true,\n}\n\nconst typescriptCliPackage: MissingDependency = {\n file: 'typescript/bin/tsc',\n pkg: 'typescript',\n exportsRestrict: true,\n}\n\nconst requiredTypePackages: MissingDependency[] = [\n {\n file: '@types/react/index.d.ts',\n pkg: '@types/react',\n exportsRestrict: true,\n },\n {\n file: '@types/node/index.d.ts',\n pkg: '@types/node',\n exportsRestrict: true,\n },\n]\n\nexport async function verifyAndRunTypeScript({\n dir,\n distDir,\n cacheDir,\n strictRouteTypes,\n tsconfigPath,\n shouldRunTypeCheck,\n typedRoutes,\n disableStaticImages,\n hasAppDir,\n hasPagesDir,\n appDir,\n pagesDir,\n debugBuildPaths,\n useTypeScriptCli = false,\n onFirstCliOutput,\n}: {\n dir: string\n distDir: string\n cacheDir?: string\n strictRouteTypes: boolean\n tsconfigPath: string | undefined\n shouldRunTypeCheck: boolean\n typedRoutes: boolean\n disableStaticImages: boolean\n hasAppDir: boolean\n hasPagesDir: boolean\n appDir?: string\n pagesDir?: string\n debugBuildPaths?: { app?: string[]; pages?: string[] }\n useTypeScriptCli?: boolean\n /**\n * Called once when the CLI checker first produces output, so the caller can\n * stop the build spinner. Only used on the in-process CLI path.\n */\n onFirstCliOutput?: () => void\n}): Promise<{\n result?: TypeCheckResult\n version: string | null\n typeCheckMode: 'typescript-api' | 'typescript-cli'\n}> {\n const tsConfigFileName = tsconfigPath || 'tsconfig.json'\n const resolvedTsConfigPath = path.join(dir, tsConfigFileName)\n const typeCheckMode = useTypeScriptCli ? 'typescript-cli' : 'typescript-api'\n\n // Construct intentDirs from appDir and pagesDir for getTypeScriptIntent\n const intentDirs = [pagesDir, appDir].filter(Boolean) as string[]\n\n try {\n // Check if the project uses TypeScript:\n const intent = await getTypeScriptIntent(dir, intentDirs, tsConfigFileName)\n if (!intent) {\n return { version: null, typeCheckMode }\n }\n\n // Check if @typescript/native-preview is installed as an alternative\n const hasNativePreview = hasNativeTypeScriptPreview(dir)\n const installedTypeScript = getTypeScriptPackageInfo(dir)\n\n if (\n !useTypeScriptCli &&\n !hasNativePreview &&\n installedTypeScript &&\n !installedTypeScript.apiPath\n ) {\n throw getTypeScriptApiMissingError(installedTypeScript.version)\n }\n\n const requiredPackages: MissingDependency[] = [\n useTypeScriptCli ? typescriptCliPackage : typescriptApiPackage,\n ...requiredTypePackages,\n ]\n\n // Ensure TypeScript and necessary `@types/*` are installed:\n let deps: NecessaryDependencies = hasNecessaryDependencies(\n dir,\n requiredPackages\n )\n\n // If @typescript/native-preview is installed and only the typescript package is missing,\n // we can skip auto-installing typescript since the native preview provides TS compilation.\n // However, we still need @types/react and @types/node for type checking.\n if (!useTypeScriptCli && hasNativePreview && deps.missing?.length > 0) {\n const missingWithoutTypescript = deps.missing.filter(\n (dep) => dep.pkg !== 'typescript'\n )\n const onlyTypescriptMissing =\n deps.missing.length === 1 && deps.missing[0].pkg === 'typescript'\n\n if (onlyTypescriptMissing) {\n // @typescript/native-preview is installed and only typescript is missing\n // Skip installation and return early - the project can use the native preview\n log.info(\n `Detected ${bold('@typescript/native-preview')} as TypeScript compiler. ` +\n `Some Next.js TypeScript features (like type checking during build) require the standard ${bold('typescript')} package.`\n )\n\n // Still write type declarations since they don't require the typescript package\n await writeAppTypeDeclarations({\n baseDir: dir,\n distDir,\n imageImportsEnabled: !disableStaticImages,\n hasPagesDir,\n hasAppDir,\n strictRouteTypes,\n typedRoutes,\n })\n\n return { version: null, typeCheckMode }\n }\n\n // If there are other missing deps besides typescript, only install those\n if (\n missingWithoutTypescript.length > 0 &&\n missingWithoutTypescript.length < deps.missing.length\n ) {\n deps.missing = missingWithoutTypescript\n }\n }\n\n if (deps.missing?.length > 0) {\n if (isCI) {\n // we don't attempt auto install in CI to avoid side-effects\n // and instead log the error for installing needed packages\n missingDepsError(dir, deps.missing)\n }\n console.log(\n bold(\n yellow(\n `It looks like you're trying to use TypeScript but do not have the required package(s) installed.`\n )\n ) +\n '\\n' +\n 'Installing dependencies' +\n '\\n\\n' +\n bold(\n 'If you are not trying to use TypeScript, please remove the ' +\n cyan('tsconfig.json') +\n ' file from your package root (and any TypeScript files in your app and pages directories).'\n ) +\n '\\n'\n )\n await installDependencies(dir, deps.missing, true).catch((err) => {\n if (err && typeof err === 'object' && 'command' in err) {\n console.error(\n `Failed to install required TypeScript dependencies, please install them manually to continue:\\n` +\n (err as any).command +\n '\\n'\n )\n }\n throw err\n })\n deps = hasNecessaryDependencies(dir, requiredPackages)\n }\n\n const typeScriptPackage = getTypeScriptPackageInfo(dir)\n const typeScriptPath = useTypeScriptCli\n ? typeScriptPackage?.tscPath\n : typeScriptPackage?.apiPath\n\n if (!typeScriptPackage || !typeScriptPath) {\n missingDepsError(\n dir,\n deps.missing.length > 0\n ? deps.missing\n : [useTypeScriptCli ? typescriptCliPackage : typescriptApiPackage]\n )\n }\n\n const typescriptVersion = typeScriptPackage.version\n\n if (semver.lt(typescriptVersion, '5.1.0')) {\n log.warn(\n `Minimum recommended TypeScript version is v5.1.0, older versions can potentially be incompatible with Next.js. Detected: ${typescriptVersion}`\n )\n }\n\n // Reconfigure (or create) the user's `tsconfig.json` for them:\n await writeConfigurationDefaults(\n typescriptVersion,\n resolvedTsConfigPath,\n intent.firstTimeSetup,\n hasAppDir,\n distDir,\n hasPagesDir,\n strictRouteTypes\n )\n // Write out the necessary `next-env.d.ts` file to correctly register\n // Next.js' types:\n await writeAppTypeDeclarations({\n baseDir: dir,\n distDir,\n imageImportsEnabled: !disableStaticImages,\n hasPagesDir,\n hasAppDir,\n strictRouteTypes,\n typedRoutes,\n })\n\n let result\n if (shouldRunTypeCheck) {\n if (useTypeScriptCli) {\n if (debugBuildPaths) {\n log.warn(\n '`experimental.useTypeScriptCli` checks the complete TypeScript project; `--debug-build-paths` does not limit type checking.'\n )\n }\n\n const { runTypeCheckCli } =\n require('./typescript/runTypeCheckCli') as typeof import('./typescript/runTypeCheckCli')\n result = await runTypeCheckCli({\n baseDir: dir,\n tsConfigPath: resolvedTsConfigPath,\n tscPath: typeScriptPath,\n cacheDir,\n onFirstOutput: onFirstCliOutput,\n })\n } else {\n const { runTypeCheck } =\n require('./typescript/runTypeCheck') as typeof import('./typescript/runTypeCheck')\n // Install native bindings so that code frame rendering works in the worker\n const { installBindings } =\n require('../build/swc/install-bindings') as typeof import('../build/swc/install-bindings')\n await installBindings()\n\n const typescript = (await Promise.resolve(\n require(typeScriptPath)\n )) as typeof import('typescript')\n\n // Verify the project passes type-checking before we go to webpack phase:\n result = await runTypeCheck(\n typescript,\n dir,\n distDir,\n resolvedTsConfigPath,\n cacheDir,\n hasAppDir,\n { app: appDir, pages: pagesDir },\n debugBuildPaths\n )\n }\n }\n return { result, version: typescriptVersion, typeCheckMode }\n } catch (err) {\n // Print the user-facing message here and rethrow. This function runs both\n // in-process (next dev / next test / next typegen, and the CLI type-check\n // during build) and inside a jest worker (the TypeScript-API type-check\n // during build). A thrown error does not survive the worker boundary — the\n // parent only sees `Call retries were exceeded` — so the message must be\n // printed on this side. The caller decides what to do with the throw (exit,\n // or tolerate it as `next dev` does on re-verification).\n if (err instanceof CompileError) {\n // The checker already printed its diagnostics.\n console.error(red('Failed to type check.\\n'))\n if (err.message) {\n console.error(err.message)\n }\n } else if (err instanceof Error) {\n console.error(err.message)\n } else {\n console.error(err)\n }\n throw err\n }\n}\n\n/**\n * Worker entrypoint used by `next build` for the TypeScript-API type-check.\n * `verifyAndRunTypeScript` has already printed any error, so on failure we exit\n * the worker directly rather than rethrowing: a thrown error would be retried by\n * jest-worker and surface in the parent as the unhelpful\n * `Jest worker encountered 1 child process exceptions, exceeding retry limit`.\n */\nexport async function verifyAndRunTypeScriptInWorker(\n options: Parameters<typeof verifyAndRunTypeScript>[0]\n): ReturnType<typeof verifyAndRunTypeScript> {\n try {\n return await verifyAndRunTypeScript(options)\n } catch {\n // The error was already printed by `verifyAndRunTypeScript`.\n // Kill the worker with a non-zero exit code.\n process.exit(1)\n }\n}\n"],"names":["bold","cyan","red","yellow","path","hasNecessaryDependencies","semver","CompileError","log","getTypeScriptIntent","writeAppTypeDeclarations","writeConfigurationDefaults","installDependencies","isCI","missingDepsError","getTypeScriptApiMissingError","getTypeScriptPackageInfo","hasNativeTypeScriptPreview","typescriptApiPackage","file","pkg","install","exportsRestrict","typescriptCliPackage","requiredTypePackages","verifyAndRunTypeScript","dir","distDir","cacheDir","strictRouteTypes","tsconfigPath","shouldRunTypeCheck","typedRoutes","disableStaticImages","hasAppDir","hasPagesDir","appDir","pagesDir","debugBuildPaths","useTypeScriptCli","onFirstCliOutput","tsConfigFileName","resolvedTsConfigPath","join","typeCheckMode","intentDirs","filter","Boolean","deps","intent","version","hasNativePreview","installedTypeScript","apiPath","requiredPackages","missing","length","missingWithoutTypescript","dep","onlyTypescriptMissing","info","baseDir","imageImportsEnabled","console","catch","err","error","command","typeScriptPackage","typeScriptPath","tscPath","typescriptVersion","lt","warn","firstTimeSetup","result","runTypeCheckCli","require","tsConfigPath","onFirstOutput","runTypeCheck","installBindings","typescript","Promise","resolve","app","pages","message","Error","verifyAndRunTypeScriptInWorker","options","process","exit"],"mappings":"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","ignoreList":[0]}
@@ -350,6 +350,7 @@ export const experimentalSchema = {
350
350
  optimizePackageImports: z.array(z.string()).optional(),
351
351
  optimizeServerReact: z.boolean().optional(),
352
352
  strictRouteTypes: z.boolean().optional(),
353
+ useTypeScriptCli: z.boolean().optional(),
353
354
  clientTraceMetadata: z.array(z.string()).optional(),
354
355
  serverMinification: z.boolean().optional(),
355
356
  serverSourceMaps: z.boolean().optional(),