UNPKG

next

Version:

The React Framework

256 lines (255 loc) • 9.54 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); 0 && (module.exports = { getTypeScriptApiMissingError: null, getTypeScriptConfigurationCli: null, getTypeScriptPackageInfo: null, hasNativeTypeScriptPreview: null, runTypeScriptCli: null }); function _export(target, all) { for(var name in all)Object.defineProperty(target, name, { enumerable: true, get: all[name] }); } _export(exports, { getTypeScriptApiMissingError: function() { return getTypeScriptApiMissingError; }, getTypeScriptConfigurationCli: function() { return getTypeScriptConfigurationCli; }, getTypeScriptPackageInfo: function() { return getTypeScriptPackageInfo; }, hasNativeTypeScriptPreview: function() { return hasNativeTypeScriptPreview; }, runTypeScriptCli: function() { return runTypeScriptCli; } }); const _nodefs = require("node:fs"); const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path")); const _nodechild_process = require("node:child_process"); const _crossspawn = /*#__PURE__*/ _interop_require_default(require("next/dist/compiled/cross-spawn")); const _picocolors = require("../picocolors"); const _resolvefrom = require("../resolve-from"); function _interop_require_default(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function getTypeScriptPackageInfo(baseDir) { var _packageJson_bin; let packageJsonPath; try { packageJsonPath = (0, _resolvefrom.resolveFrom)(baseDir, 'typescript/package.json'); } catch { return null; } const packageJson = JSON.parse((0, _nodefs.readFileSync)(packageJsonPath, 'utf8')); const packageDir = _nodepath.default.dirname(packageJsonPath); const apiPath = _nodepath.default.join(packageDir, 'lib', 'typescript.js'); const tscBin = typeof packageJson.bin === 'string' ? packageJson.bin : (_packageJson_bin = packageJson.bin) == null ? void 0 : _packageJson_bin.tsc; const tscBinPath = tscBin ? _nodepath.default.resolve(packageDir, tscBin) : undefined; let tscPath = tscBinPath; if (tscBinPath && (0, _nodefs.existsSync)(tscBinPath) && packageJson.type === 'module' && _nodepath.default.extname(tscBinPath) === '') { // TypeScript 7's extensionless ESM bin wrapper cannot be used as Node's // main entry point on Node.js 20.9. Its imported JS entry is the same CLI // wrapper and works across all supported Node.js versions. const tscJsPath = _nodepath.default.join(packageDir, 'lib', 'tsc.js'); if ((0, _nodefs.existsSync)(tscJsPath)) { tscPath = tscJsPath; } } return { packageJsonPath, packageDir, version: packageJson.version, apiPath: (0, _nodefs.existsSync)(apiPath) ? apiPath : undefined, tscPath: tscPath && (0, _nodefs.existsSync)(tscPath) ? tscPath : undefined }; } function hasNativeTypeScriptPreview(baseDir) { try { (0, _resolvefrom.resolveFrom)(baseDir, '@typescript/native-preview/package.json'); return true; } catch { return false; } } function getTypeScriptApiMissingError(version) { return Object.defineProperty(new Error(`TypeScript ${version} does not provide the compiler API required by Next.js. ` + `Enable ${(0, _picocolors.bold)('experimental.useTypeScriptCli')} in your Next.js config to use the TypeScript CLI, ` + `or install TypeScript 6 instead.`), "__NEXT_ERROR_CODE", { value: "E1150", enumerable: false, configurable: true }); } const terminationSignals = [ 'SIGINT', 'SIGTERM', 'SIGHUP' ]; function runTypeScriptCli({ cwd, tscPath, args, captureOutput = false, onFirstOutput }) { return new Promise((resolve, reject)=>{ var _child_stdout, _child_stderr; const child = (0, _crossspawn.default)(process.execPath, [ tscPath, ...args ], { cwd, // TypeScript 7's Node wrapper starts the native compiler synchronously // on older Node.js releases. A separate process group lets termination // reach both processes instead of orphaning the native compiler. detached: process.platform !== 'win32', shell: false, stdio: [ 'ignore', 'pipe', 'pipe' ], env: { ...process.env, // Piping stdio makes `tsc` disable colored/pretty diagnostics. Restore // them when we are forwarding output to a TTY (not capturing it for // parsing, e.g. `--showConfig`). ...!captureOutput && process.stdout.isTTY ? { FORCE_COLOR: '1' } : undefined } }); let stdout = ''; let stderr = ''; (_child_stdout = child.stdout) == null ? void 0 : _child_stdout.setEncoding('utf8'); (_child_stderr = child.stderr) == null ? void 0 : _child_stderr.setEncoding('utf8'); if (captureOutput) { var _child_stdout1, _child_stderr1; (_child_stdout1 = child.stdout) == null ? void 0 : _child_stdout1.on('data', (chunk)=>{ stdout += chunk; }); (_child_stderr1 = child.stderr) == null ? void 0 : _child_stderr1.on('data', (chunk)=>{ stderr += chunk; }); } else { var _child_stdout2, _child_stderr2; const forward = (dest, chunk)=>{ onFirstOutput == null ? void 0 : onFirstOutput(); onFirstOutput = undefined // ensure we don't call it again ; dest.write(chunk); }; (_child_stdout2 = child.stdout) == null ? void 0 : _child_stdout2.on('data', (chunk)=>{ forward(process.stdout, chunk); }); (_child_stderr2 = child.stderr) == null ? void 0 : _child_stderr2.on('data', (chunk)=>{ forward(process.stderr, chunk); }); } let terminationRequested = false; const terminateChild = ()=>{ if (terminationRequested || child.killed || child.pid === undefined) { return; } terminationRequested = true; // The native compiler ignores SIGTERM and SIGINT, so send a kill signal. // Target the whole process group so the signal reaches the native compiler whether // it is a grandchild or a direct child. // https://github.com/microsoft/typescript-go/pull/4592 should improve this in the long run if (process.platform === 'win32') { (0, _nodechild_process.spawnSync)('taskkill', [ '/pid', String(child.pid), '/T', '/F' ], { stdio: 'ignore', windowsHide: true }); } else { try { // https://www.youtube.com/watch?v=Fow7iUaKrq4 process.kill(-child.pid, 'SIGKILL'); } catch { // The process may have exited between the lifecycle event and kill. } } }; const terminateOnExit = ()=>terminateChild(); process.once('exit', terminateOnExit); const handler = ()=>{ terminateChild(); process.exit(1); }; for (const signal of terminationSignals){ process.once(signal, handler); } const cleanup = ()=>{ process.off('exit', terminateOnExit); for (const signal of terminationSignals){ process.off(signal, handler); } }; let settled = false; const finish = (settle)=>{ if (settled) { return; } settled = true; cleanup(); settle(); }; child.on('error', (error)=>{ finish(()=>reject(error)); }); child.on('close', (code, signal)=>{ finish(()=>{ resolve({ exitCode: code ?? 1, signal, stdout, stderr }); }); }); }); } async function getTypeScriptConfigurationCli({ baseDir, tsConfigPath, tscPath }) { const result = await runTypeScriptCli({ cwd: baseDir, tscPath, args: [ '--showConfig', '--project', tsConfigPath, '--pretty', 'false' ], captureOutput: true }); if (result.exitCode !== 0) { throw Object.defineProperty(new Error([ result.stdout, result.stderr ].filter(Boolean).join('\n').trim()), "__NEXT_ERROR_CODE", { value: "E394", enumerable: false, configurable: true }); } try { return JSON.parse(result.stdout); } catch (cause) { throw Object.defineProperty(new Error(`Could not parse output from TypeScript's --showConfig.`, { cause }), "__NEXT_ERROR_CODE", { value: "E1149", enumerable: false, configurable: true }); } } //# sourceMappingURL=runTypeScriptCli.js.map