Something went wrong. Try again.
Monorepo for the nibling.run platform
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106// The guest `npm` command: a script the kernel seeds at// /usr/local/lib/node_modules/npm/bin/npm-cli.js (linked from /usr/local/bin/npm), and// again as bin/npx-cli.js (linked from /usr/local/bin/npx), where it runs as npx. The// runtime runs it like any other. It parses argv as npm 11.7.0 does, hands installs and// package lookups to the kernel through the runtime's npm hooks, runs scripts and bins// under node (run.ts, exec.ts), and prints what npm prints: reify-output.js's summary on// stdout, warnings and errors in npm's display format (lib/utils/display.js,// error-message.js) on stderr. Only node: builtins and the hooks: it is guest code.import { existsSync } from "node:fs";import { homedir } from "node:os";import { basename, dirname, join } from "node:path";import process from "node:process";import { npxArgv, parse, type Parsed } from "./command";import { exec, type RuntimeHooks } from "./exec";import { changedMessage, CI_USAGE, fail, logLines, NpmFailure, usage, VERSION } from "./output";import { run } from "./run";import { NPM_ROOT } from "./run-script";
/** npm's localPrefix: the nearest directory up from `cwd` with a package.json or a * node_modules, else `cwd` itself. */function localPrefix(cwd: string): string { for (let dir = cwd; ; dir = dirname(dir)) { if (existsSync(join(dir, "package.json")) || existsSync(join(dir, "node_modules"))) return dir; if (dir === dirname(dir)) return cwd; }}
/** @npmcli/config's set-envs.js, and the user-agent and npm_command npm sets: what every * script npm runs finds in its environment. */function setEnvs({ config, name }: Parsed, prefix: string): void { const env = process.env; const home = homedir(); Object.assign(env, { npm_config_user_agent: `npm/${VERSION} node/${process.version} ${process.platform} ${process.arch} workspaces/false`, npm_config_cache: join(home, ".npm"), npm_config_globalconfig: "/usr/local/etc/npmrc", npm_config_init_module: join(home, ".npm-init.js"), npm_config_userconfig: join(home, ".npmrc"), npm_config_prefix: "/usr/local", ...config, INIT_CWD: process.cwd(), HOME: home, npm_config_global_prefix: "/usr/local", npm_config_local_prefix: prefix, npm_config_node_gyp: `${NPM_ROOT}/node_modules/node-gyp/bin/node-gyp.js`, npm_config_npm_version: VERSION, npm_execpath: `${NPM_ROOT}/bin/npm-cli.js`, NODE: process.execPath, npm_node_execpath: process.execPath, COLOR: "0", }); if (name) env.npm_command = name;}
async function main(): Promise<void> { const prefix = localPrefix(process.cwd()); const npx = /^npx(?:-cli\.js)?$/.test(basename(process.argv[1] ?? "")); const argv = process.argv.slice(2); const parsed = parse(npx ? npxArgv(argv) : argv, prefix); const { command, warnings } = parsed; for (const w of warnings) process.stderr.write(logLines("warn", "", w)); const hooks = (globalThis as Record<symbol, Partial<RuntimeHooks> | undefined>)[Symbol.for("nib.runtime")]; const needHooks = (): RuntimeHooks => { if (!hooks?.npm || !hooks.npmLookup) throw new NpmFailure({ message: "npm needs the @nibling/kernel runtime's installer, which this process does not have" }); return hooks as RuntimeHooks; }; switch (command.kind) { case "version": process.stdout.write(`${VERSION}\n`); return; case "help": process.stdout.write(usage()); process.exitCode = 1; return; case "unknown": process.stdout.write(`Unknown command: "${command.command}"\n\nTo see a list of supported npm commands, run:\n npm help\n`); process.exitCode = 1; return; case "unsupported": return fail({ code: "ENOTSUP", message: `\`npm ${command.command}\` is not available in this runtime; install, ci, uninstall, run, exec and the lifecycle commands are.` }); case "error": return fail(command.error); case "run": setEnvs(parsed, prefix); return await run(command, prefix); case "exec": setEnvs(parsed, prefix); return await exec(command, prefix, needHooks()); case "install": { const outcome = await needHooks().npm(command.request); if (!outcome.ok) { const er = outcome.error; // A usage error carries the command's usage after it (BaseCommand#usageError). return fail(er.code === "EUSAGE" && command.request.command === "ci" ? { ...er, message: `\n${er.message}\n\n${CI_USAGE}` } : er); } for (const w of outcome.report.warnings) process.stderr.write(logLines("warn", "", w)); process.stdout.write(changedMessage(outcome.report.diff)); } }}
main().catch((e: unknown) => { if (e instanceof NpmFailure) return fail(e.error); throw e;});