| #!/usr/bin/env node |
| "use strict"; |
| Object.defineProperty(exports, "__esModule", { |
| value: true |
| }); |
| Object.defineProperty(exports, "nextInfo", { |
| enumerable: true, |
| get: function() { |
| return nextInfo; |
| } |
| }); |
| const _os = _interop_require_default(require("os")); |
| const _child_process = _interop_require_default(require("child_process")); |
| const _picocolors = require("../lib/picocolors"); |
| const _constants = require("../shared/lib/constants"); |
| const _config = _interop_require_default(require("../server/config")); |
| const _getregistry = require("../lib/helpers/get-registry"); |
| const _parseversioninfo = require("../server/dev/parse-version-info"); |
| const _versionstaleness = require("../next-devtools/shared/version-staleness"); |
| const _log = require("../build/output/log"); |
| function _interop_require_default(obj) { |
| return obj && obj.__esModule ? obj : { |
| default: obj |
| }; |
| } |
| function getPackageVersion(packageName) { |
| try { |
| return require(`${packageName}/package.json`).version; |
| } catch { |
| return 'N/A'; |
| } |
| } |
| async function getNextConfig() { |
| var _config_experimental; |
| const config = await (0, _config.default)(_constants.PHASE_INFO, process.cwd()); |
| return { |
| output: config.output ?? 'N/A', |
| experimental: { |
| useWasmBinary: (_config_experimental = config.experimental) == null ? void 0 : _config_experimental.useWasmBinary |
| } |
| }; |
| } |
| |
| |
| |
| function getBinaryVersion(binaryName) { |
| try { |
| return _child_process.default.execFileSync(binaryName, [ |
| '--version' |
| ]).toString().trim(); |
| } catch { |
| try { |
| return _child_process.default.execSync(`${binaryName} --version`).toString().trim(); |
| } catch { |
| return 'N/A'; |
| } |
| } |
| } |
| |
| |
| async function printInfo() { |
| const installedRelease = getPackageVersion('next'); |
| const nextConfig = await getNextConfig(); |
| let stalenessWithTitle = ''; |
| let title = ''; |
| let versionInfo; |
| try { |
| const registry = (0, _getregistry.getRegistry)(); |
| const res = await fetch(`${registry}-/package/next/dist-tags`); |
| const tags = await res.json(); |
| versionInfo = (0, _parseversioninfo.parseVersionInfo)({ |
| installed: installedRelease, |
| latest: tags.latest, |
| canary: tags.canary |
| }); |
| title = (0, _versionstaleness.getStaleness)(versionInfo).title; |
| if (title) { |
| stalenessWithTitle = ` // ${title}`; |
| } |
| } catch (e) { |
| console.warn(`${(0, _picocolors.yellow)((0, _picocolors.bold)('warn'))} - Failed to fetch latest canary version. (Reason: ${e.message}.) |
| Detected "${installedRelease}". Visit https://github.com/vercel/next.js/releases. |
| Make sure to try the latest canary version (eg.: \`npm install next@canary\`) to confirm the issue still exists before creating a new issue. |
| \nLearn more: ${(0, _picocolors.cyan)('https://nextjs.org/docs/messages/opening-an-issue')}`); |
| } |
| const cpuCores = _os.default.cpus().length; |
| let relevantPackages = ` next: ${installedRelease}${stalenessWithTitle} |
| eslint-config-next: ${getPackageVersion('eslint-config-next')} |
| react: ${getPackageVersion('react')} |
| react-dom: ${getPackageVersion('react-dom')} |
| typescript: ${getPackageVersion('typescript')}`; |
| if (process.env.NEXT_RSPACK) { |
| relevantPackages += ` |
| next-rspack: ${getPackageVersion('next-rspack')}`; |
| } |
| console.log(` |
| Operating System: |
| Platform: ${_os.default.platform()} |
| Arch: ${_os.default.arch()} |
| Version: ${_os.default.version()} |
| Available memory (MB): ${Math.ceil(_os.default.totalmem() / 1024 / 1024)} |
| Available CPU cores: ${cpuCores > 0 ? cpuCores : 'N/A'} |
| Binaries: |
| Node: ${process.versions.node} |
| npm: ${getBinaryVersion('npm')} |
| Yarn: ${getBinaryVersion('yarn')} |
| pnpm: ${getBinaryVersion('pnpm')} |
| Relevant Packages: |
| ${relevantPackages} |
| Next.js Config: |
| output: ${nextConfig.output}`); |
| if (versionInfo == null ? void 0 : versionInfo.staleness.startsWith('stale')) { |
| (0, _log.warn)(`${title} |
| Please try the latest canary version (\`npm install next@canary\`) to confirm the issue still exists before creating a new issue. |
| Read more - https://nextjs.org/docs/messages/opening-an-issue`); |
| } |
| } |
| |
| |
| |
| |
| |
| async function runSharedDependencyCheck(tools, skipMessage) { |
| var _getSupportedArchTriples_currentPlatform; |
| const currentPlatform = _os.default.platform(); |
| const spawn = require('next/dist/compiled/cross-spawn'); |
| const { getSupportedArchTriples } = require('../build/swc'); |
| const triples = ((_getSupportedArchTriples_currentPlatform = getSupportedArchTriples()[currentPlatform]) == null ? void 0 : _getSupportedArchTriples_currentPlatform[_os.default.arch()]) ?? []; |
| |
| const availableTools = []; |
| for (const tool of tools){ |
| try { |
| const check = spawn.sync(tool.bin, tool.checkArgs); |
| if (check.status === 0) { |
| availableTools.push(tool); |
| } |
| } catch { |
| |
| } |
| } |
| if (availableTools.length === 0) { |
| return { |
| messages: skipMessage, |
| result: 'skipped' |
| }; |
| } |
| const outputs = []; |
| let result = 'fail'; |
| for (const triple of triples){ |
| const triplePkgName = `@next/swc-${triple.platformArchABI}`; |
| let resolved; |
| try { |
| resolved = require.resolve(triplePkgName); |
| } catch (e) { |
| return { |
| messages: 'Cannot find next-swc installation, skipping dependencies check', |
| result: 'skipped' |
| }; |
| } |
| for (const tool of availableTools){ |
| const proc = spawn(tool.bin, [ |
| ...tool.args, |
| resolved |
| ]); |
| outputs.push(`Running ${tool.bin} ------------- `); |
| |
| const procPromise = new Promise((resolve)=>{ |
| proc.stdout.on('data', function(data) { |
| outputs.push(data); |
| }); |
| proc.stderr.on('data', function(data) { |
| outputs.push(data); |
| }); |
| proc.on('close', (c)=>resolve(c)); |
| }); |
| let code = await procPromise; |
| if (code === 0) { |
| result = 'pass'; |
| } |
| } |
| } |
| return { |
| output: outputs.join('\n'), |
| result |
| }; |
| } |
| |
| |
| async function printVerboseInfo() { |
| const fs = require('fs'); |
| const currentPlatform = _os.default.platform(); |
| if (currentPlatform !== 'win32' && currentPlatform !== 'linux' && currentPlatform !== 'darwin') { |
| console.log('Unsupported platform, only win32, linux, darwin are supported.'); |
| return; |
| } |
| |
| const tasks = [ |
| { |
| title: 'Host system information', |
| scripts: { |
| default: async ()=>{ |
| |
| |
| const isWsl = require('next/dist/compiled/is-wsl'); |
| const ciInfo = require('next/dist/compiled/ci-info'); |
| const isDocker = require('next/dist/compiled/is-docker'); |
| const output = ` |
| WSL: ${isWsl} |
| Docker: ${isDocker()} |
| CI: ${ciInfo.isCI ? ciInfo.name || 'unknown' : 'false'} |
| `; |
| return { |
| output, |
| result: 'pass' |
| }; |
| } |
| } |
| }, |
| { |
| title: 'Next.js installation', |
| scripts: { |
| default: async ()=>{ |
| const installedRelease = getPackageVersion('next'); |
| const nextConfig = await getNextConfig(); |
| const output = ` |
| Binaries: |
| Node: ${process.versions.node} |
| npm: ${getBinaryVersion('npm')} |
| Yarn: ${getBinaryVersion('yarn')} |
| pnpm: ${getBinaryVersion('pnpm')} |
| Relevant Packages: |
| next: ${installedRelease} |
| eslint-config-next: ${getPackageVersion('eslint-config-next')} |
| react: ${getPackageVersion('react')} |
| react-dom: ${getPackageVersion('react-dom')} |
| typescript: ${getPackageVersion('typescript')} |
| Next.js Config: |
| output: ${nextConfig.output} |
| |
| `; |
| return { |
| output, |
| result: 'pass' |
| }; |
| } |
| } |
| }, |
| { |
| title: 'Node.js diagnostic report', |
| scripts: { |
| default: async ()=>{ |
| var _process_report; |
| const report = (_process_report = process.report) == null ? void 0 : _process_report.getReport(); |
| if (!report) { |
| return { |
| messages: 'Node.js diagnostic report is not available.', |
| result: 'fail' |
| }; |
| } |
| const { header, javascriptHeap, sharedObjects } = report; |
| |
| header == null ? true : delete header.cwd; |
| header == null ? true : delete header.commandLine; |
| header == null ? true : delete header.host; |
| header == null ? true : delete header.cpus; |
| header == null ? true : delete header.networkInterfaces; |
| const reportSummary = { |
| header, |
| javascriptHeap, |
| sharedObjects |
| }; |
| return { |
| output: JSON.stringify(reportSummary, null, 2), |
| result: 'pass' |
| }; |
| } |
| } |
| }, |
| { |
| title: 'next-swc installation', |
| scripts: { |
| default: async ()=>{ |
| var _platformArchTriples_currentPlatform; |
| const output = []; |
| |
| try { |
| var _nextConfig_experimental; |
| let nextConfig = await getNextConfig(); |
| const { loadBindings } = require('../build/swc'); |
| const bindings = await loadBindings((_nextConfig_experimental = nextConfig.experimental) == null ? void 0 : _nextConfig_experimental.useWasmBinary); |
| |
| const target = bindings.getTargetTriple(); |
| |
| return { |
| output: `next-swc is installed correctly for ${target}`, |
| result: 'pass' |
| }; |
| } catch (e) { |
| output.push(`loadBindings() failed: ${e.message}`); |
| } |
| const { platformArchTriples } = require('next/dist/compiled/@napi-rs/triples'); |
| const triples = (_platformArchTriples_currentPlatform = platformArchTriples[currentPlatform]) == null ? void 0 : _platformArchTriples_currentPlatform[_os.default.arch()]; |
| if (!triples || triples.length === 0) { |
| return { |
| messages: `No target triples found for ${currentPlatform} / ${_os.default.arch()}`, |
| result: 'fail' |
| }; |
| } |
| |
| const path = require('path'); |
| let fallbackBindingsDirectory; |
| try { |
| const nextPath = path.dirname(require.resolve('next/package.json')); |
| fallbackBindingsDirectory = path.join(nextPath, 'next-swc-fallback'); |
| } catch (e) { |
| |
| } |
| const tryResolve = (pkgName)=>{ |
| try { |
| const resolved = require.resolve(pkgName); |
| const fileExists = fs.existsSync(resolved); |
| let loadError; |
| let loadSuccess; |
| try { |
| loadSuccess = !!require(resolved).getTargetTriple(); |
| } catch (e) { |
| loadError = e.message; |
| } |
| output.push(`${pkgName} exists: ${fileExists} for the triple ${loadSuccess}`); |
| if (loadError) { |
| output.push(`${pkgName} load failed: ${loadError ?? 'unknown'}`); |
| } |
| if (loadSuccess) { |
| return true; |
| } |
| } catch (e) { |
| output.push(`${pkgName} resolve failed: ${e.message ?? 'unknown'}`); |
| } |
| return false; |
| }; |
| for (const triple of triples){ |
| const triplePkgName = `@next/swc-${triple.platformArchABI}`; |
| |
| |
| if (tryResolve(triplePkgName)) { |
| break; |
| } |
| |
| if (!fallbackBindingsDirectory) { |
| continue; |
| } |
| tryResolve(path.join(fallbackBindingsDirectory, triplePkgName)); |
| } |
| return { |
| output: output.join('\n'), |
| result: 'pass' |
| }; |
| } |
| } |
| }, |
| { |
| |
| |
| |
| title: 'next-swc shared object dependencies', |
| scripts: { |
| linux: async ()=>{ |
| const skipMessage = 'This diagnostics uses system-installed tools (ldd) to check next-swc dependencies, but it is not found. Skipping dependencies check.'; |
| return await runSharedDependencyCheck([ |
| { |
| bin: 'ldd', |
| checkArgs: [ |
| '--help' |
| ], |
| args: [ |
| '--verbose' |
| ] |
| } |
| ], skipMessage); |
| }, |
| win32: async ()=>{ |
| const skipMessage = `This diagnostics uses system-installed tools (dumpbin.exe) to check next-swc dependencies, but it was not found in the path. Skipping dependencies check. |
| dumpbin (https://learn.microsoft.com/en-us/cpp/build/reference/dumpbin-reference) is a part of Microsoft VC toolset, |
| can be installed with Windows SDK, Windows Build tools or Visual Studio. |
| |
| Please make sure you have one of them installed and dumpbin.exe is in the path. |
| `; |
| return await runSharedDependencyCheck([ |
| { |
| bin: 'dumpbin.exe', |
| checkArgs: [ |
| '/summary' |
| ], |
| args: [ |
| '/imports' |
| ] |
| } |
| ], skipMessage); |
| }, |
| darwin: async ()=>{ |
| const skipMessage = 'This diagnostics uses system-installed tools (otools, dyld_info) to check next-swc dependencies, but none of them are found. Skipping dependencies check.'; |
| return await runSharedDependencyCheck([ |
| { |
| bin: 'otool', |
| checkArgs: [ |
| '--version' |
| ], |
| args: [ |
| '-L' |
| ] |
| }, |
| { |
| bin: 'dyld_info', |
| checkArgs: [], |
| args: [] |
| } |
| ], skipMessage); |
| } |
| } |
| } |
| ]; |
| |
| const report = []; |
| console.log('\n'); |
| for (const task of tasks){ |
| if (task.targetPlatform && task.targetPlatform !== currentPlatform) { |
| report.push({ |
| title: task.title, |
| result: { |
| messages: undefined, |
| output: `[SKIPPED (${_os.default.platform()} / ${task.targetPlatform})] ${task.title}`, |
| result: 'skipped' |
| } |
| }); |
| continue; |
| } |
| const taskScript = task.scripts[currentPlatform] ?? task.scripts.default; |
| let taskResult; |
| try { |
| taskResult = await taskScript(); |
| } catch (e) { |
| taskResult = { |
| messages: `Unexpected failure while running diagnostics: ${e.message}`, |
| result: 'fail' |
| }; |
| } |
| console.log(`- ${task.title}: ${taskResult.result}`); |
| if (taskResult.messages) { |
| console.log(` ${taskResult.messages}`); |
| } |
| report.push({ |
| title: task.title, |
| result: taskResult |
| }); |
| } |
| console.log(`\n${(0, _picocolors.bold)('Generated diagnostics report')}`); |
| console.log(`\nPlease copy below report and paste it into your issue.`); |
| for (const { title, result } of report){ |
| console.log(`\n### ${title}`); |
| if (result.messages) { |
| console.log(result.messages); |
| } |
| if (result.output) { |
| console.log(result.output); |
| } |
| } |
| } |
| |
| |
| |
| |
| const nextInfo = async (options)=>{ |
| if (options.verbose) { |
| await printVerboseInfo(); |
| } else { |
| await printInfo(); |
| } |
| }; |
|
|
| |