@vltpkg/run
Advanced tools
| /** | ||
| * Get or create the node-gyp shim file path | ||
| * The shim redirects node-gyp calls to vlx node-gyp@latest | ||
| */ | ||
| export declare function getNodeGypShim(): Promise<string>; | ||
| /** | ||
| * Get the directory containing the node-gyp shim | ||
| * This can be prepended to PATH to make the shim available | ||
| */ | ||
| export declare function getNodeGypShimDir(): Promise<string>; | ||
| /** | ||
| * Check if a command contains node-gyp references | ||
| */ | ||
| export declare function hasNodeGypReference(command: string): boolean; | ||
| //# sourceMappingURL=aliasRunner.d.ts.map |
| {"version":3,"file":"aliasRunner.d.ts","sourceRoot":"","sources":["../src/aliasRunner.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAsCtD;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAGzD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE5D"} |
| import { XDG } from '@vltpkg/xdg'; | ||
| import { chmod, mkdir, stat, writeFile } from 'node:fs/promises'; | ||
| import { dirname, join } from 'node:path'; | ||
| const xdg = new XDG('vlt'); | ||
| let shimPath; | ||
| /** | ||
| * Get or create the node-gyp shim file path | ||
| * The shim redirects node-gyp calls to vlx node-gyp@latest | ||
| */ | ||
| export async function getNodeGypShim() { | ||
| if (shimPath) | ||
| return shimPath; | ||
| const runtimeDir = xdg.runtime('run'); | ||
| const shimFile = join(runtimeDir, 'node-gyp'); | ||
| // Check if shim already exists | ||
| try { | ||
| await stat(shimFile); | ||
| /* c8 ignore next 2 - hard to test */ | ||
| shimPath = shimFile; | ||
| return shimPath; | ||
| } | ||
| catch { | ||
| // Shim doesn't exist, create it | ||
| } | ||
| // Create runtime directory if needed | ||
| await mkdir(runtimeDir, { recursive: true }); | ||
| // Create shim that calls vlx | ||
| /* c8 ignore start - ignore platform-dependent coverage */ | ||
| const shimContent = process.platform === 'win32' ? | ||
| `@echo off\nvlx node-gyp@latest %*\n` | ||
| : `#!/bin/sh\nexec vlx node-gyp@latest "$@"\n`; | ||
| /* c8 ignore stop */ | ||
| await writeFile(shimFile, shimContent, 'utf8'); | ||
| // Make executable on Unix systems | ||
| /* c8 ignore start - unix-only */ | ||
| if (process.platform !== 'win32') { | ||
| await chmod(shimFile, 0o755); | ||
| } | ||
| /* c8 ignore stop */ | ||
| shimPath = shimFile; | ||
| return shimPath; | ||
| } | ||
| /** | ||
| * Get the directory containing the node-gyp shim | ||
| * This can be prepended to PATH to make the shim available | ||
| */ | ||
| export async function getNodeGypShimDir() { | ||
| const shim = await getNodeGypShim(); | ||
| return dirname(shim); | ||
| } | ||
| /** | ||
| * Check if a command contains node-gyp references | ||
| */ | ||
| export function hasNodeGypReference(command) { | ||
| return command.includes('node-gyp'); | ||
| } | ||
| //# sourceMappingURL=aliasRunner.js.map |
| {"version":3,"file":"aliasRunner.js","sourceRoot":"","sources":["../src/aliasRunner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AACjC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEzC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;AAC1B,IAAI,QAA4B,CAAA;AAEhC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAA;IAE7B,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAA;IAE7C,+BAA+B;IAC/B,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAA;QACpB,qCAAqC;QACrC,QAAQ,GAAG,QAAQ,CAAA;QACnB,OAAO,QAAQ,CAAA;IACjB,CAAC;IAAC,MAAM,CAAC;QACP,gCAAgC;IAClC,CAAC;IAED,qCAAqC;IACrC,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAE5C,6BAA6B;IAC7B,0DAA0D;IAC1D,MAAM,WAAW,GACf,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;QAC5B,qCAAqC;QACvC,CAAC,CAAC,4CAA4C,CAAA;IAChD,oBAAoB;IAEpB,MAAM,SAAS,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC,CAAA;IAE9C,kCAAkC;IAClC,iCAAiC;IACjC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;IAC9B,CAAC;IACD,oBAAoB;IAEpB,QAAQ,GAAG,QAAQ,CAAA;IACnB,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,IAAI,GAAG,MAAM,cAAc,EAAE,CAAA;IACnC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAA;AACtB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,OAAO,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;AACrC,CAAC","sourcesContent":["import { XDG } from '@vltpkg/xdg'\nimport { chmod, mkdir, stat, writeFile } from 'node:fs/promises'\nimport { dirname, join } from 'node:path'\n\nconst xdg = new XDG('vlt')\nlet shimPath: string | undefined\n\n/**\n * Get or create the node-gyp shim file path\n * The shim redirects node-gyp calls to vlx node-gyp@latest\n */\nexport async function getNodeGypShim(): Promise<string> {\n if (shimPath) return shimPath\n\n const runtimeDir = xdg.runtime('run')\n const shimFile = join(runtimeDir, 'node-gyp')\n\n // Check if shim already exists\n try {\n await stat(shimFile)\n /* c8 ignore next 2 - hard to test */\n shimPath = shimFile\n return shimPath\n } catch {\n // Shim doesn't exist, create it\n }\n\n // Create runtime directory if needed\n await mkdir(runtimeDir, { recursive: true })\n\n // Create shim that calls vlx\n /* c8 ignore start - ignore platform-dependent coverage */\n const shimContent =\n process.platform === 'win32' ?\n `@echo off\\nvlx node-gyp@latest %*\\n`\n : `#!/bin/sh\\nexec vlx node-gyp@latest \"$@\"\\n`\n /* c8 ignore stop */\n\n await writeFile(shimFile, shimContent, 'utf8')\n\n // Make executable on Unix systems\n /* c8 ignore start - unix-only */\n if (process.platform !== 'win32') {\n await chmod(shimFile, 0o755)\n }\n /* c8 ignore stop */\n\n shimPath = shimFile\n return shimPath\n}\n\n/**\n * Get the directory containing the node-gyp shim\n * This can be prepended to PATH to make the shim available\n */\nexport async function getNodeGypShimDir(): Promise<string> {\n const shim = await getNodeGypShim()\n return dirname(shim)\n}\n\n/**\n * Check if a command contains node-gyp references\n */\nexport function hasNodeGypReference(command: string): boolean {\n return command.includes('node-gyp')\n}\n"]} |
+131
| import { PackageJson } from '@vltpkg/package-json'; | ||
| import type { PromiseSpawnOptions, SpawnResultNoStdio, SpawnResultStdioStrings } from '@vltpkg/promise-spawn'; | ||
| import type { Manifest } from '@vltpkg/types'; | ||
| /** options shared by run() and exec() */ | ||
| export type SharedOptions = PromiseSpawnOptions & { | ||
| /** additional arguments to pass to the command */ | ||
| args?: string[]; | ||
| /** the root of the project, which we don't walk up past */ | ||
| projectRoot: string; | ||
| /** the directory where the package.json lives and the script runs */ | ||
| cwd: string; | ||
| /** | ||
| * environment variables to set. `process.env` is always included, | ||
| * to omit fields, set them explicitly to undefined. | ||
| * | ||
| * vlt will add some of its own, as well: | ||
| * - npm_lifecycle_event: the event name | ||
| * - npm_lifecycle_script: the command in package.json#scripts | ||
| * - npm_package_json: path to the package.json file | ||
| * - VLT_* envs for all vlt configuration values that are set | ||
| */ | ||
| env?: NodeJS.ProcessEnv; | ||
| /** | ||
| * the shell to run the script in. If not set, then the default | ||
| * platform-specific shell will be used. | ||
| */ | ||
| 'script-shell'?: boolean | string; | ||
| /** | ||
| * If true, then `FORCE_COLOR=1` will be set in the environment so that | ||
| * scripts will typically have colored output enablled, even if the output | ||
| * is not a tty. | ||
| */ | ||
| color?: boolean; | ||
| }; | ||
| /** | ||
| * Options for run() and runFG() | ||
| */ | ||
| export type RunOptions = SharedOptions & { | ||
| /** the name of the thing in package.json#scripts */ | ||
| arg0: string; | ||
| /** | ||
| * pass in a @vltpkg/package-json.PackageJson instance, and | ||
| * it'll be used for reading the package.json file. Optional, | ||
| * may improve performance somewhat. | ||
| */ | ||
| packageJson?: PackageJson; | ||
| /** | ||
| * Pass in a manifest to avoid having to read it at all | ||
| */ | ||
| manifest?: Pick<Manifest, 'scripts' | 'gypfile'>; | ||
| /** | ||
| * if the script is not defined in package.json#scripts, just ignore it and | ||
| * treat as success. Otherwise, treat as an error. Default false. | ||
| */ | ||
| ignoreMissing?: boolean; | ||
| /** | ||
| * skip the pre/post commands, just run the one specified. | ||
| * This can be used to run JUST the specified script, without any | ||
| * pre/post commands. | ||
| */ | ||
| ignorePrePost?: boolean; | ||
| }; | ||
| /** | ||
| * Options for exec() and execFG() | ||
| */ | ||
| export type ExecOptions = SharedOptions & { | ||
| /** the command to execute */ | ||
| arg0: string; | ||
| }; | ||
| /** | ||
| * Options for runExec() and runExecFG() | ||
| */ | ||
| export type RunExecOptions = SharedOptions & { | ||
| /** | ||
| * Either the command to be executed, or the event to be run | ||
| */ | ||
| arg0: string; | ||
| /** | ||
| * pass in a @vltpkg/package-json.PackageJson instance, and | ||
| * it'll be used for reading the package.json file. Optional, | ||
| * may improve performance somewhat. | ||
| */ | ||
| packageJson?: PackageJson; | ||
| }; | ||
| /** | ||
| * Run a package.json#scripts event in the background | ||
| */ | ||
| export declare const run: (options: RunOptions) => Promise<RunResult>; | ||
| /** | ||
| * Run a package.json#scripts event in the foreground | ||
| */ | ||
| export declare const runFG: (options: RunOptions) => Promise<RunFGResult>; | ||
| /** Return type of {@link run} */ | ||
| export type RunResult = SpawnResultStdioStrings & { | ||
| pre?: SpawnResultStdioStrings; | ||
| post?: SpawnResultStdioStrings; | ||
| }; | ||
| /** Return type of {@link runFG} */ | ||
| export type RunFGResult = SpawnResultNoStdio & { | ||
| pre?: SpawnResultNoStdio; | ||
| post?: SpawnResultNoStdio; | ||
| }; | ||
| export declare const isRunResult: (v: unknown) => v is RunResult; | ||
| /** | ||
| * Return type of {@link run} or {@link runFG}, as determined by their base | ||
| * type | ||
| * @internal | ||
| */ | ||
| export type RunImplResult<R extends SpawnResultNoStdio | SpawnResultStdioStrings> = R & { | ||
| pre?: R; | ||
| post?: R; | ||
| }; | ||
| /** | ||
| * Execute an arbitrary command in the background | ||
| */ | ||
| export declare const exec: (options: ExecOptions) => Promise<SpawnResultStdioStrings>; | ||
| /** | ||
| * Execute an arbitrary command in the foreground | ||
| */ | ||
| export declare const execFG: (options: ExecOptions) => Promise<SpawnResultNoStdio>; | ||
| /** | ||
| * If the arg0 is a defined package.json script, then run(), otherwise exec() | ||
| */ | ||
| export declare const runExec: (options: RunExecOptions) => Promise<RunResult | SpawnResultStdioStrings>; | ||
| /** | ||
| * If the arg0 is a defined package.json script, then runFG(), otherwise | ||
| * execFG() | ||
| */ | ||
| export declare const runExecFG: (options: RunExecOptions) => Promise<RunFGResult | SpawnResultNoStdio>; | ||
| export { getNodeGypShim, getNodeGypShimDir, hasNodeGypReference, } from './aliasRunner.ts'; | ||
| //# sourceMappingURL=index.d.ts.map |
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} |
+258
| import { error } from '@vltpkg/error-cause'; | ||
| import { PackageJson } from '@vltpkg/package-json'; | ||
| import { promiseSpawn } from '@vltpkg/promise-spawn'; | ||
| import { foregroundChild } from 'foreground-child'; | ||
| import { proxySignals } from 'foreground-child/proxy-signals'; | ||
| import { statSync } from 'node:fs'; | ||
| import { delimiter, resolve, sep } from 'node:path'; | ||
| import { walkUp } from 'walk-up-path'; | ||
| import { getNodeGypShimDir, hasNodeGypReference, } from "./aliasRunner.js"; | ||
| /** map of which node_modules/.bin folders exist */ | ||
| const dotBins = new Map(); | ||
| /** Check if a directory exists, and cache result */ | ||
| const dirExists = (p) => { | ||
| const cached = dotBins.get(p); | ||
| if (cached !== undefined) | ||
| return cached; | ||
| try { | ||
| const isDir = statSync(p).isDirectory(); | ||
| dotBins.set(p, isDir); | ||
| return isDir; | ||
| } | ||
| catch { | ||
| dotBins.set(p, false); | ||
| return false; | ||
| } | ||
| }; | ||
| const nmBin = `${sep}node_modules${sep}.bin`; | ||
| /** | ||
| * Add all existing `node_modules/.bin` folders to the PATH that | ||
| * exist between the cwd and the projectRoot, so dependency bins | ||
| * are found, with closer paths higher priority. | ||
| * | ||
| * If command contains node-gyp reference, also inject the shim directory | ||
| * as a fallback (after all existing PATH entries). | ||
| */ | ||
| const addPaths = async (projectRoot, cwd, env, command) => { | ||
| const { PATH = '' } = env; | ||
| const PATHsplit = PATH.split(delimiter); | ||
| const paths = new Set(); | ||
| // anything in the PATH that already has node_modules/.bin is a thing | ||
| // we put there, perhaps for the vlx exec cache usage | ||
| for (const p of PATHsplit) { | ||
| if (p.endsWith(nmBin)) { | ||
| paths.add(p); | ||
| } | ||
| } | ||
| for (const p of walkUp(cwd)) { | ||
| const dotBin = resolve(p, 'node_modules/.bin'); | ||
| if (dirExists(dotBin)) | ||
| paths.add(dotBin); | ||
| if (p === projectRoot) | ||
| break; | ||
| } | ||
| for (const p of PATH.split(delimiter)) { | ||
| /* c8 ignore next - pretty rare to have an empty entry */ | ||
| if (p) | ||
| paths.add(p); | ||
| } | ||
| // If command has node-gyp, inject shim directory as fallback (last) | ||
| if (command && hasNodeGypReference(command)) { | ||
| try { | ||
| const shimDir = await getNodeGypShimDir(); | ||
| paths.add(shimDir); | ||
| /* c8 ignore start */ | ||
| } | ||
| catch { | ||
| // Ignore shim creation errors, command will fail naturally if node-gyp is needed | ||
| } | ||
| /* c8 ignore stop */ | ||
| } | ||
| env.PATH = [...paths].join(delimiter); | ||
| return env; | ||
| }; | ||
| /** | ||
| * Run a package.json#scripts event in the background | ||
| */ | ||
| export const run = async (options) => runImpl(options, exec, ''); | ||
| /** | ||
| * Run a package.json#scripts event in the foreground | ||
| */ | ||
| export const runFG = async (options) => runImpl(options, execFG, null); | ||
| export const isRunResult = (v) => !!v && | ||
| typeof v === 'object' && | ||
| !Array.isArray(v) && | ||
| 'stdout' in v && | ||
| 'stderr' in v && | ||
| 'status' in v && | ||
| 'signal' in v; | ||
| /** | ||
| * Internal implementation of run() and runFG(), since they're mostly identical | ||
| */ | ||
| const runImpl = async (options, execImpl, empty) => { | ||
| const { arg0, packageJson = new PackageJson(), ignoreMissing = false, manifest, 'script-shell': shell = true, ...execArgs } = options; | ||
| const pjPath = resolve(options.cwd, 'package.json'); | ||
| // npm adds a `"install": "node-gyp rebuild"` if a binding.gyp | ||
| // is present at the time of publish, EVEN IF it's not included | ||
| // in the package. So, we need to read the actual package.json | ||
| // in those cases. | ||
| const untrustworthy = !!(manifest?.gypfile && | ||
| arg0 === 'install' && | ||
| manifest.scripts?.install === 'node-gyp rebuild'); | ||
| const pj = (untrustworthy ? undefined : manifest) ?? | ||
| packageJson.read(options.cwd); | ||
| const { scripts } = pj; | ||
| const command = scripts?.[arg0]; | ||
| if (!command) { | ||
| if (ignoreMissing) { | ||
| return { | ||
| command: '', | ||
| /* c8 ignore next */ | ||
| args: execArgs.args ?? [], | ||
| cwd: options.cwd, | ||
| status: 0, | ||
| signal: null, | ||
| stdout: empty, | ||
| stderr: empty, | ||
| // `as` to workaround "could be instantiated with arbitrary type". | ||
| // it's private and used in 2 places, we know that it isn't. | ||
| }; | ||
| } | ||
| throw error('Script not defined in package.json', { | ||
| name: arg0, | ||
| cwd: options.cwd, | ||
| args: options.args, | ||
| path: pjPath, | ||
| manifest: pj, | ||
| }); | ||
| } | ||
| const precommand = !options.ignorePrePost && scripts[`pre${arg0}`]; | ||
| const pre = precommand ? | ||
| await execImpl({ | ||
| arg0: precommand, | ||
| ...execArgs, | ||
| 'script-shell': shell, | ||
| args: [], | ||
| env: { | ||
| ...execArgs.env, | ||
| npm_package_json: pjPath, | ||
| npm_lifecycle_event: `pre${arg0}`, | ||
| npm_lifecycle_script: precommand, | ||
| }, | ||
| }) | ||
| : undefined; | ||
| if (pre && (pre.status || pre.signal)) { | ||
| return pre; | ||
| } | ||
| const result = await execImpl({ | ||
| arg0: command, | ||
| ...execArgs, | ||
| 'script-shell': shell, | ||
| env: { | ||
| ...execArgs.env, | ||
| npm_package_json: pjPath, | ||
| npm_lifecycle_event: arg0, | ||
| npm_lifecycle_script: command, | ||
| }, | ||
| }); | ||
| result.pre = pre; | ||
| if (result.signal || result.status) { | ||
| return result; | ||
| } | ||
| const postcommand = !options.ignorePrePost && scripts[`post${arg0}`]; | ||
| if (!postcommand) | ||
| return result; | ||
| const post = await execImpl({ | ||
| arg0: postcommand, | ||
| ...execArgs, | ||
| 'script-shell': shell, | ||
| args: [], | ||
| env: { | ||
| ...execArgs.env, | ||
| npm_package_json: pjPath, | ||
| npm_lifecycle_event: `post${arg0}`, | ||
| npm_lifecycle_script: postcommand, | ||
| }, | ||
| }); | ||
| if (post.status || post.signal) { | ||
| const { status, signal } = post; | ||
| return Object.assign(result, { post, status, signal }); | ||
| } | ||
| result.post = post; | ||
| return result; | ||
| }; | ||
| /** | ||
| * Execute an arbitrary command in the background | ||
| */ | ||
| export const exec = async (options) => { | ||
| const { arg0, args = [], cwd, env = {}, projectRoot, 'script-shell': shell = false, color = false, signal, ...spawnOptions } = options; | ||
| const p = promiseSpawn(arg0, args, { | ||
| ...spawnOptions, | ||
| shell, | ||
| stdio: 'pipe', | ||
| stdioString: true, | ||
| cwd, | ||
| env: await addPaths(projectRoot, cwd, { | ||
| ...process.env, | ||
| ...env, | ||
| FORCE_COLOR: color ? '1' : '0', | ||
| }, arg0), | ||
| windowsHide: true, | ||
| }); | ||
| proxySignals(p.process); | ||
| return await p; | ||
| }; | ||
| /** | ||
| * Execute an arbitrary command in the foreground | ||
| */ | ||
| export const execFG = async (options) => { | ||
| const { arg0, args = [], cwd, projectRoot, env = {}, 'script-shell': shell = false, color = true, signal, ...spawnOptions } = options; | ||
| const processEnv = await addPaths(projectRoot, cwd, { | ||
| ...process.env, | ||
| ...env, | ||
| FORCE_COLOR: color ? '1' : '0', | ||
| }, arg0); | ||
| return new Promise(res => { | ||
| foregroundChild(arg0, args, { | ||
| ...spawnOptions, | ||
| shell, | ||
| cwd, | ||
| env: processEnv, | ||
| }, (status, signal) => { | ||
| res({ | ||
| command: arg0, | ||
| args, | ||
| cwd, | ||
| stdout: null, | ||
| stderr: null, | ||
| status, | ||
| signal, | ||
| }); | ||
| return false; | ||
| }); | ||
| }); | ||
| }; | ||
| const runExecImpl = async (options, runImpl, execImpl) => { | ||
| const { arg0, packageJson = new PackageJson(), ...args } = options; | ||
| const pj = packageJson.read(options.cwd); | ||
| const { scripts } = pj; | ||
| const command = scripts?.[arg0]; | ||
| if (command) { | ||
| return runImpl({ ...args, packageJson, arg0 }); | ||
| } | ||
| else { | ||
| return execImpl({ ...args, arg0 }); | ||
| } | ||
| }; | ||
| /** | ||
| * If the arg0 is a defined package.json script, then run(), otherwise exec() | ||
| */ | ||
| export const runExec = async (options) => runExecImpl(options, run, exec); | ||
| /** | ||
| * If the arg0 is a defined package.json script, then runFG(), otherwise | ||
| * execFG() | ||
| */ | ||
| export const runExecFG = async (options) => runExecImpl(options, runFG, execFG); | ||
| // Export shim utilities | ||
| export { getNodeGypShim, getNodeGypShimDir, hasNodeGypReference, } from "./aliasRunner.js"; | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { error } from '@vltpkg/error-cause'\nimport { PackageJson } from '@vltpkg/package-json'\nimport type {\n PromiseSpawnOptions,\n SpawnResultNoStdio,\n SpawnResultStdioStrings,\n} from '@vltpkg/promise-spawn'\nimport { promiseSpawn } from '@vltpkg/promise-spawn'\nimport type { Manifest } from '@vltpkg/types'\nimport { foregroundChild } from 'foreground-child'\nimport { proxySignals } from 'foreground-child/proxy-signals'\nimport { statSync } from 'node:fs'\nimport { delimiter, resolve, sep } from 'node:path'\nimport { walkUp } from 'walk-up-path'\nimport {\n getNodeGypShimDir,\n hasNodeGypReference,\n} from './aliasRunner.ts'\n\n/** map of which node_modules/.bin folders exist */\nconst dotBins = new Map<string, boolean>()\n\n/** Check if a directory exists, and cache result */\nconst dirExists = (p: string) => {\n const cached = dotBins.get(p)\n if (cached !== undefined) return cached\n try {\n const isDir = statSync(p).isDirectory()\n dotBins.set(p, isDir)\n return isDir\n } catch {\n dotBins.set(p, false)\n return false\n }\n}\n\nconst nmBin = `${sep}node_modules${sep}.bin`\n\n/**\n * Add all existing `node_modules/.bin` folders to the PATH that\n * exist between the cwd and the projectRoot, so dependency bins\n * are found, with closer paths higher priority.\n *\n * If command contains node-gyp reference, also inject the shim directory\n * as a fallback (after all existing PATH entries).\n */\nconst addPaths = async (\n projectRoot: string,\n cwd: string,\n env: NodeJS.ProcessEnv,\n command?: string,\n): Promise<NodeJS.ProcessEnv> => {\n const { PATH = '' } = env\n const PATHsplit = PATH.split(delimiter)\n const paths = new Set<string>()\n\n // anything in the PATH that already has node_modules/.bin is a thing\n // we put there, perhaps for the vlx exec cache usage\n for (const p of PATHsplit) {\n if (p.endsWith(nmBin)) {\n paths.add(p)\n }\n }\n for (const p of walkUp(cwd)) {\n const dotBin = resolve(p, 'node_modules/.bin')\n if (dirExists(dotBin)) paths.add(dotBin)\n if (p === projectRoot) break\n }\n for (const p of PATH.split(delimiter)) {\n /* c8 ignore next - pretty rare to have an empty entry */\n if (p) paths.add(p)\n }\n\n // If command has node-gyp, inject shim directory as fallback (last)\n if (command && hasNodeGypReference(command)) {\n try {\n const shimDir = await getNodeGypShimDir()\n paths.add(shimDir)\n /* c8 ignore start */\n } catch {\n // Ignore shim creation errors, command will fail naturally if node-gyp is needed\n }\n /* c8 ignore stop */\n }\n\n env.PATH = [...paths].join(delimiter)\n return env\n}\n\n/** options shared by run() and exec() */\nexport type SharedOptions = PromiseSpawnOptions & {\n /** additional arguments to pass to the command */\n args?: string[]\n /** the root of the project, which we don't walk up past */\n projectRoot: string\n\n /** the directory where the package.json lives and the script runs */\n cwd: string\n /**\n * environment variables to set. `process.env` is always included,\n * to omit fields, set them explicitly to undefined.\n *\n * vlt will add some of its own, as well:\n * - npm_lifecycle_event: the event name\n * - npm_lifecycle_script: the command in package.json#scripts\n * - npm_package_json: path to the package.json file\n * - VLT_* envs for all vlt configuration values that are set\n */\n env?: NodeJS.ProcessEnv\n /**\n * the shell to run the script in. If not set, then the default\n * platform-specific shell will be used.\n */\n 'script-shell'?: boolean | string\n\n /**\n * If true, then `FORCE_COLOR=1` will be set in the environment so that\n * scripts will typically have colored output enablled, even if the output\n * is not a tty.\n */\n color?: boolean\n}\n\n/**\n * Options for run() and runFG()\n */\nexport type RunOptions = SharedOptions & {\n /** the name of the thing in package.json#scripts */\n arg0: string\n /**\n * pass in a @vltpkg/package-json.PackageJson instance, and\n * it'll be used for reading the package.json file. Optional,\n * may improve performance somewhat.\n */\n packageJson?: PackageJson\n\n /**\n * Pass in a manifest to avoid having to read it at all\n */\n manifest?: Pick<Manifest, 'scripts' | 'gypfile'>\n\n /**\n * if the script is not defined in package.json#scripts, just ignore it and\n * treat as success. Otherwise, treat as an error. Default false.\n */\n ignoreMissing?: boolean\n\n /**\n * skip the pre/post commands, just run the one specified.\n * This can be used to run JUST the specified script, without any\n * pre/post commands.\n */\n ignorePrePost?: boolean\n}\n\n/**\n * Options for exec() and execFG()\n */\nexport type ExecOptions = SharedOptions & {\n /** the command to execute */\n arg0: string\n}\n\n/**\n * Options for runExec() and runExecFG()\n */\nexport type RunExecOptions = SharedOptions & {\n /**\n * Either the command to be executed, or the event to be run\n */\n arg0: string\n /**\n * pass in a @vltpkg/package-json.PackageJson instance, and\n * it'll be used for reading the package.json file. Optional,\n * may improve performance somewhat.\n */\n packageJson?: PackageJson\n}\n\n/**\n * Run a package.json#scripts event in the background\n */\nexport const run = async (options: RunOptions): Promise<RunResult> =>\n runImpl(options, exec, '')\n\n/**\n * Run a package.json#scripts event in the foreground\n */\nexport const runFG = async (\n options: RunOptions,\n): Promise<RunFGResult> => runImpl(options, execFG, null)\n\n/** Return type of {@link run} */\nexport type RunResult = SpawnResultStdioStrings & {\n pre?: SpawnResultStdioStrings\n post?: SpawnResultStdioStrings\n}\n\n/** Return type of {@link runFG} */\nexport type RunFGResult = SpawnResultNoStdio & {\n pre?: SpawnResultNoStdio\n post?: SpawnResultNoStdio\n}\n\nexport const isRunResult = (v: unknown): v is RunResult =>\n !!v &&\n typeof v === 'object' &&\n !Array.isArray(v) &&\n 'stdout' in v &&\n 'stderr' in v &&\n 'status' in v &&\n 'signal' in v\n\n/**\n * Return type of {@link run} or {@link runFG}, as determined by their base\n * type\n * @internal\n */\nexport type RunImplResult<\n R extends SpawnResultNoStdio | SpawnResultStdioStrings,\n> = R & { pre?: R; post?: R }\n\n/**\n * Internal implementation of run() and runFG(), since they're mostly identical\n */\nconst runImpl = async <\n R extends SpawnResultNoStdio | SpawnResultStdioStrings,\n>(\n options: RunOptions,\n execImpl: (options: ExecOptions) => Promise<R>,\n empty: R['stdout'],\n): Promise<RunImplResult<R>> => {\n const {\n arg0,\n packageJson = new PackageJson(),\n ignoreMissing = false,\n manifest,\n 'script-shell': shell = true,\n ...execArgs\n } = options\n const pjPath = resolve(options.cwd, 'package.json')\n // npm adds a `\"install\": \"node-gyp rebuild\"` if a binding.gyp\n // is present at the time of publish, EVEN IF it's not included\n // in the package. So, we need to read the actual package.json\n // in those cases.\n const untrustworthy = !!(\n manifest?.gypfile &&\n arg0 === 'install' &&\n manifest.scripts?.install === 'node-gyp rebuild'\n )\n const pj =\n (untrustworthy ? undefined : manifest) ??\n packageJson.read(options.cwd)\n const { scripts } = pj\n const command = scripts?.[arg0]\n if (!command) {\n if (ignoreMissing) {\n return {\n command: '',\n /* c8 ignore next */\n args: execArgs.args ?? [],\n cwd: options.cwd,\n status: 0,\n signal: null,\n stdout: empty,\n stderr: empty,\n // `as` to workaround \"could be instantiated with arbitrary type\".\n // it's private and used in 2 places, we know that it isn't.\n } as R\n }\n throw error('Script not defined in package.json', {\n name: arg0,\n cwd: options.cwd,\n args: options.args,\n path: pjPath,\n manifest: pj,\n })\n }\n\n const precommand = !options.ignorePrePost && scripts[`pre${arg0}`]\n const pre =\n precommand ?\n await execImpl({\n arg0: precommand,\n ...execArgs,\n 'script-shell': shell,\n args: [],\n env: {\n ...execArgs.env,\n npm_package_json: pjPath,\n npm_lifecycle_event: `pre${arg0}`,\n npm_lifecycle_script: precommand,\n },\n })\n : undefined\n if (pre && (pre.status || pre.signal)) {\n return pre as RunImplResult<R>\n }\n const result: RunImplResult<R> = await execImpl({\n arg0: command,\n ...execArgs,\n 'script-shell': shell,\n env: {\n ...execArgs.env,\n npm_package_json: pjPath,\n npm_lifecycle_event: arg0,\n npm_lifecycle_script: command,\n },\n })\n result.pre = pre\n if (result.signal || result.status) {\n return result\n }\n\n const postcommand = !options.ignorePrePost && scripts[`post${arg0}`]\n if (!postcommand) return result\n\n const post = await execImpl({\n arg0: postcommand,\n ...execArgs,\n 'script-shell': shell,\n args: [],\n env: {\n ...execArgs.env,\n npm_package_json: pjPath,\n npm_lifecycle_event: `post${arg0}`,\n npm_lifecycle_script: postcommand,\n },\n })\n\n if (post.status || post.signal) {\n const { status, signal } = post\n return Object.assign(result, { post, status, signal })\n }\n result.post = post\n return result\n}\n\n/**\n * Execute an arbitrary command in the background\n */\nexport const exec = async (\n options: ExecOptions,\n): Promise<SpawnResultStdioStrings> => {\n const {\n arg0,\n args = [],\n cwd,\n env = {},\n projectRoot,\n 'script-shell': shell = false,\n color = false,\n signal,\n ...spawnOptions\n } = options\n\n const p = promiseSpawn(arg0, args, {\n ...spawnOptions,\n shell,\n stdio: 'pipe',\n stdioString: true,\n cwd,\n env: await addPaths(\n projectRoot,\n cwd,\n {\n ...process.env,\n ...env,\n FORCE_COLOR: color ? '1' : '0',\n },\n arg0,\n ),\n windowsHide: true,\n })\n proxySignals(p.process)\n return await p\n}\n\n/**\n * Execute an arbitrary command in the foreground\n */\nexport const execFG = async (\n options: ExecOptions,\n): Promise<SpawnResultNoStdio> => {\n const {\n arg0,\n args = [],\n cwd,\n projectRoot,\n env = {},\n 'script-shell': shell = false,\n color = true,\n signal,\n ...spawnOptions\n } = options\n\n const processEnv = await addPaths(\n projectRoot,\n cwd,\n {\n ...process.env,\n ...env,\n FORCE_COLOR: color ? '1' : '0',\n },\n arg0,\n )\n\n return new Promise<SpawnResultNoStdio>(res => {\n foregroundChild(\n arg0,\n args,\n {\n ...spawnOptions,\n shell,\n cwd,\n env: processEnv,\n },\n (status, signal) => {\n res({\n command: arg0,\n args,\n cwd,\n stdout: null,\n stderr: null,\n status,\n signal,\n })\n return false\n },\n )\n })\n}\n\nconst runExecImpl = async <\n R extends SpawnResultNoStdio | SpawnResultStdioStrings,\n>(\n options: RunExecOptions,\n runImpl: (options: RunOptions) => Promise<RunImplResult<R>>,\n execImpl: (options: ExecOptions) => Promise<R>,\n): Promise<R | RunImplResult<R>> => {\n const { arg0, packageJson = new PackageJson(), ...args } = options\n const pj = packageJson.read(options.cwd)\n const { scripts } = pj\n const command = scripts?.[arg0]\n if (command) {\n return runImpl({ ...args, packageJson, arg0 })\n } else {\n return execImpl({ ...args, arg0 })\n }\n}\n\n/**\n * If the arg0 is a defined package.json script, then run(), otherwise exec()\n */\nexport const runExec = async (\n options: RunExecOptions,\n): Promise<RunResult | SpawnResultStdioStrings> =>\n runExecImpl<SpawnResultStdioStrings>(options, run, exec)\n\n/**\n * If the arg0 is a defined package.json script, then runFG(), otherwise\n * execFG()\n */\nexport const runExecFG = async (\n options: RunExecOptions,\n): Promise<RunFGResult | SpawnResultNoStdio> =>\n runExecImpl<SpawnResultNoStdio>(options, runFG, execFG)\n\n// Export shim utilities\nexport {\n getNodeGypShim,\n getNodeGypShimDir,\n hasNodeGypReference,\n} from './aliasRunner.ts'\n"]} |
+8
-22
| { | ||
| "name": "@vltpkg/run", | ||
| "description": "Run package.json scripts and execute commands", | ||
| "version": "1.0.0-rc.10", | ||
| "version": "1.0.0-rc.11", | ||
| "repository": { | ||
@@ -11,21 +11,10 @@ "type": "git", | ||
| "author": "vlt technology inc. <support@vlt.sh> (http://vlt.sh)", | ||
| "tshy": { | ||
| "selfLink": false, | ||
| "liveDev": true, | ||
| "dialects": [ | ||
| "esm" | ||
| ], | ||
| "exports": { | ||
| "./package.json": "./package.json", | ||
| ".": "./src/index.ts" | ||
| } | ||
| }, | ||
| "dependencies": { | ||
| "foreground-child": "^3.3.1", | ||
| "walk-up-path": "^4.0.0", | ||
| "@vltpkg/error-cause": "1.0.0-rc.10", | ||
| "@vltpkg/package-json": "1.0.0-rc.10", | ||
| "@vltpkg/promise-spawn": "1.0.0-rc.10", | ||
| "@vltpkg/xdg": "1.0.0-rc.10", | ||
| "@vltpkg/types": "1.0.0-rc.10" | ||
| "@vltpkg/package-json": "1.0.0-rc.11", | ||
| "@vltpkg/error-cause": "1.0.0-rc.11", | ||
| "@vltpkg/types": "1.0.0-rc.11", | ||
| "@vltpkg/promise-spawn": "1.0.0-rc.11", | ||
| "@vltpkg/xdg": "1.0.0-rc.11" | ||
| }, | ||
@@ -38,3 +27,2 @@ "devDependencies": { | ||
| "tap": "^21.5.0", | ||
| "tshy": "^3.1.0", | ||
| "typedoc": "~0.27.9", | ||
@@ -52,3 +40,3 @@ "typescript": "5.7.3", | ||
| "prettier": "../../.prettierrc.js", | ||
| "module": "./dist/esm/index.js", | ||
| "module": "./dist/index.js", | ||
| "type": "module", | ||
@@ -59,4 +47,3 @@ "exports": { | ||
| "import": { | ||
| "types": "./dist/esm/index.d.ts", | ||
| "default": "./dist/esm/index.js" | ||
| "default": "./dist/index.js" | ||
| } | ||
@@ -76,5 +63,4 @@ } | ||
| "posttest": "tsc --noEmit", | ||
| "tshy": "tshy", | ||
| "typecheck": "tsc --noEmit" | ||
| } | ||
| } |
| /** | ||
| * Get or create the node-gyp shim file path | ||
| * The shim redirects node-gyp calls to vlx node-gyp@latest | ||
| */ | ||
| export declare function getNodeGypShim(): Promise<string>; | ||
| /** | ||
| * Get the directory containing the node-gyp shim | ||
| * This can be prepended to PATH to make the shim available | ||
| */ | ||
| export declare function getNodeGypShimDir(): Promise<string>; | ||
| /** | ||
| * Check if a command contains node-gyp references | ||
| */ | ||
| export declare function hasNodeGypReference(command: string): boolean; | ||
| //# sourceMappingURL=aliasRunner.d.ts.map |
| {"version":3,"file":"aliasRunner.d.ts","sourceRoot":"","sources":["../../src/aliasRunner.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAsCtD;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAGzD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE5D"} |
| import { XDG } from '@vltpkg/xdg'; | ||
| import { chmod, mkdir, stat, writeFile } from 'node:fs/promises'; | ||
| import { dirname, join } from 'node:path'; | ||
| const xdg = new XDG('vlt'); | ||
| let shimPath; | ||
| /** | ||
| * Get or create the node-gyp shim file path | ||
| * The shim redirects node-gyp calls to vlx node-gyp@latest | ||
| */ | ||
| export async function getNodeGypShim() { | ||
| if (shimPath) | ||
| return shimPath; | ||
| const runtimeDir = xdg.runtime('run'); | ||
| const shimFile = join(runtimeDir, 'node-gyp'); | ||
| // Check if shim already exists | ||
| try { | ||
| await stat(shimFile); | ||
| /* c8 ignore next 2 - hard to test */ | ||
| shimPath = shimFile; | ||
| return shimPath; | ||
| } | ||
| catch { | ||
| // Shim doesn't exist, create it | ||
| } | ||
| // Create runtime directory if needed | ||
| await mkdir(runtimeDir, { recursive: true }); | ||
| // Create shim that calls vlx | ||
| /* c8 ignore start - ignore platform-dependent coverage */ | ||
| const shimContent = process.platform === 'win32' ? | ||
| `@echo off\nvlx node-gyp@latest %*\n` | ||
| : `#!/bin/sh\nexec vlx node-gyp@latest "$@"\n`; | ||
| /* c8 ignore stop */ | ||
| await writeFile(shimFile, shimContent, 'utf8'); | ||
| // Make executable on Unix systems | ||
| /* c8 ignore start - unix-only */ | ||
| if (process.platform !== 'win32') { | ||
| await chmod(shimFile, 0o755); | ||
| } | ||
| /* c8 ignore stop */ | ||
| shimPath = shimFile; | ||
| return shimPath; | ||
| } | ||
| /** | ||
| * Get the directory containing the node-gyp shim | ||
| * This can be prepended to PATH to make the shim available | ||
| */ | ||
| export async function getNodeGypShimDir() { | ||
| const shim = await getNodeGypShim(); | ||
| return dirname(shim); | ||
| } | ||
| /** | ||
| * Check if a command contains node-gyp references | ||
| */ | ||
| export function hasNodeGypReference(command) { | ||
| return command.includes('node-gyp'); | ||
| } | ||
| //# sourceMappingURL=aliasRunner.js.map |
| {"version":3,"file":"aliasRunner.js","sourceRoot":"","sources":["../../src/aliasRunner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AACjC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEzC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;AAC1B,IAAI,QAA4B,CAAA;AAEhC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAA;IAE7B,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAA;IAE7C,+BAA+B;IAC/B,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAA;QACpB,qCAAqC;QACrC,QAAQ,GAAG,QAAQ,CAAA;QACnB,OAAO,QAAQ,CAAA;IACjB,CAAC;IAAC,MAAM,CAAC;QACP,gCAAgC;IAClC,CAAC;IAED,qCAAqC;IACrC,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAE5C,6BAA6B;IAC7B,0DAA0D;IAC1D,MAAM,WAAW,GACf,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;QAC5B,qCAAqC;QACvC,CAAC,CAAC,4CAA4C,CAAA;IAChD,oBAAoB;IAEpB,MAAM,SAAS,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC,CAAA;IAE9C,kCAAkC;IAClC,iCAAiC;IACjC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;IAC9B,CAAC;IACD,oBAAoB;IAEpB,QAAQ,GAAG,QAAQ,CAAA;IACnB,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,IAAI,GAAG,MAAM,cAAc,EAAE,CAAA;IACnC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAA;AACtB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,OAAO,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;AACrC,CAAC","sourcesContent":["import { XDG } from '@vltpkg/xdg'\nimport { chmod, mkdir, stat, writeFile } from 'node:fs/promises'\nimport { dirname, join } from 'node:path'\n\nconst xdg = new XDG('vlt')\nlet shimPath: string | undefined\n\n/**\n * Get or create the node-gyp shim file path\n * The shim redirects node-gyp calls to vlx node-gyp@latest\n */\nexport async function getNodeGypShim(): Promise<string> {\n if (shimPath) return shimPath\n\n const runtimeDir = xdg.runtime('run')\n const shimFile = join(runtimeDir, 'node-gyp')\n\n // Check if shim already exists\n try {\n await stat(shimFile)\n /* c8 ignore next 2 - hard to test */\n shimPath = shimFile\n return shimPath\n } catch {\n // Shim doesn't exist, create it\n }\n\n // Create runtime directory if needed\n await mkdir(runtimeDir, { recursive: true })\n\n // Create shim that calls vlx\n /* c8 ignore start - ignore platform-dependent coverage */\n const shimContent =\n process.platform === 'win32' ?\n `@echo off\\nvlx node-gyp@latest %*\\n`\n : `#!/bin/sh\\nexec vlx node-gyp@latest \"$@\"\\n`\n /* c8 ignore stop */\n\n await writeFile(shimFile, shimContent, 'utf8')\n\n // Make executable on Unix systems\n /* c8 ignore start - unix-only */\n if (process.platform !== 'win32') {\n await chmod(shimFile, 0o755)\n }\n /* c8 ignore stop */\n\n shimPath = shimFile\n return shimPath\n}\n\n/**\n * Get the directory containing the node-gyp shim\n * This can be prepended to PATH to make the shim available\n */\nexport async function getNodeGypShimDir(): Promise<string> {\n const shim = await getNodeGypShim()\n return dirname(shim)\n}\n\n/**\n * Check if a command contains node-gyp references\n */\nexport function hasNodeGypReference(command: string): boolean {\n return command.includes('node-gyp')\n}\n"]} |
| import { PackageJson } from '@vltpkg/package-json'; | ||
| import type { PromiseSpawnOptions, SpawnResultNoStdio, SpawnResultStdioStrings } from '@vltpkg/promise-spawn'; | ||
| import type { Manifest } from '@vltpkg/types'; | ||
| /** options shared by run() and exec() */ | ||
| export type SharedOptions = PromiseSpawnOptions & { | ||
| /** additional arguments to pass to the command */ | ||
| args?: string[]; | ||
| /** the root of the project, which we don't walk up past */ | ||
| projectRoot: string; | ||
| /** the directory where the package.json lives and the script runs */ | ||
| cwd: string; | ||
| /** | ||
| * environment variables to set. `process.env` is always included, | ||
| * to omit fields, set them explicitly to undefined. | ||
| * | ||
| * vlt will add some of its own, as well: | ||
| * - npm_lifecycle_event: the event name | ||
| * - npm_lifecycle_script: the command in package.json#scripts | ||
| * - npm_package_json: path to the package.json file | ||
| * - VLT_* envs for all vlt configuration values that are set | ||
| */ | ||
| env?: NodeJS.ProcessEnv; | ||
| /** | ||
| * the shell to run the script in. If not set, then the default | ||
| * platform-specific shell will be used. | ||
| */ | ||
| 'script-shell'?: boolean | string; | ||
| /** | ||
| * If true, then `FORCE_COLOR=1` will be set in the environment so that | ||
| * scripts will typically have colored output enablled, even if the output | ||
| * is not a tty. | ||
| */ | ||
| color?: boolean; | ||
| }; | ||
| /** | ||
| * Options for run() and runFG() | ||
| */ | ||
| export type RunOptions = SharedOptions & { | ||
| /** the name of the thing in package.json#scripts */ | ||
| arg0: string; | ||
| /** | ||
| * pass in a @vltpkg/package-json.PackageJson instance, and | ||
| * it'll be used for reading the package.json file. Optional, | ||
| * may improve performance somewhat. | ||
| */ | ||
| packageJson?: PackageJson; | ||
| /** | ||
| * Pass in a manifest to avoid having to read it at all | ||
| */ | ||
| manifest?: Pick<Manifest, 'scripts' | 'gypfile'>; | ||
| /** | ||
| * if the script is not defined in package.json#scripts, just ignore it and | ||
| * treat as success. Otherwise, treat as an error. Default false. | ||
| */ | ||
| ignoreMissing?: boolean; | ||
| /** | ||
| * skip the pre/post commands, just run the one specified. | ||
| * This can be used to run JUST the specified script, without any | ||
| * pre/post commands. | ||
| */ | ||
| ignorePrePost?: boolean; | ||
| }; | ||
| /** | ||
| * Options for exec() and execFG() | ||
| */ | ||
| export type ExecOptions = SharedOptions & { | ||
| /** the command to execute */ | ||
| arg0: string; | ||
| }; | ||
| /** | ||
| * Options for runExec() and runExecFG() | ||
| */ | ||
| export type RunExecOptions = SharedOptions & { | ||
| /** | ||
| * Either the command to be executed, or the event to be run | ||
| */ | ||
| arg0: string; | ||
| /** | ||
| * pass in a @vltpkg/package-json.PackageJson instance, and | ||
| * it'll be used for reading the package.json file. Optional, | ||
| * may improve performance somewhat. | ||
| */ | ||
| packageJson?: PackageJson; | ||
| }; | ||
| /** | ||
| * Run a package.json#scripts event in the background | ||
| */ | ||
| export declare const run: (options: RunOptions) => Promise<RunResult>; | ||
| /** | ||
| * Run a package.json#scripts event in the foreground | ||
| */ | ||
| export declare const runFG: (options: RunOptions) => Promise<RunFGResult>; | ||
| /** Return type of {@link run} */ | ||
| export type RunResult = SpawnResultStdioStrings & { | ||
| pre?: SpawnResultStdioStrings; | ||
| post?: SpawnResultStdioStrings; | ||
| }; | ||
| /** Return type of {@link runFG} */ | ||
| export type RunFGResult = SpawnResultNoStdio & { | ||
| pre?: SpawnResultNoStdio; | ||
| post?: SpawnResultNoStdio; | ||
| }; | ||
| export declare const isRunResult: (v: unknown) => v is RunResult; | ||
| /** | ||
| * Return type of {@link run} or {@link runFG}, as determined by their base | ||
| * type | ||
| * @internal | ||
| */ | ||
| export type RunImplResult<R extends SpawnResultNoStdio | SpawnResultStdioStrings> = R & { | ||
| pre?: R; | ||
| post?: R; | ||
| }; | ||
| /** | ||
| * Execute an arbitrary command in the background | ||
| */ | ||
| export declare const exec: (options: ExecOptions) => Promise<SpawnResultStdioStrings>; | ||
| /** | ||
| * Execute an arbitrary command in the foreground | ||
| */ | ||
| export declare const execFG: (options: ExecOptions) => Promise<SpawnResultNoStdio>; | ||
| /** | ||
| * If the arg0 is a defined package.json script, then run(), otherwise exec() | ||
| */ | ||
| export declare const runExec: (options: RunExecOptions) => Promise<RunResult | SpawnResultStdioStrings>; | ||
| /** | ||
| * If the arg0 is a defined package.json script, then runFG(), otherwise | ||
| * execFG() | ||
| */ | ||
| export declare const runExecFG: (options: RunExecOptions) => Promise<RunFGResult | SpawnResultNoStdio>; | ||
| export { getNodeGypShim, getNodeGypShimDir, hasNodeGypReference, } from './aliasRunner.ts'; | ||
| //# sourceMappingURL=index.d.ts.map |
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"} |
| import { error } from '@vltpkg/error-cause'; | ||
| import { PackageJson } from '@vltpkg/package-json'; | ||
| import { promiseSpawn } from '@vltpkg/promise-spawn'; | ||
| import { foregroundChild } from 'foreground-child'; | ||
| import { proxySignals } from 'foreground-child/proxy-signals'; | ||
| import { statSync } from 'node:fs'; | ||
| import { delimiter, resolve, sep } from 'node:path'; | ||
| import { walkUp } from 'walk-up-path'; | ||
| import { getNodeGypShimDir, hasNodeGypReference, } from "./aliasRunner.js"; | ||
| /** map of which node_modules/.bin folders exist */ | ||
| const dotBins = new Map(); | ||
| /** Check if a directory exists, and cache result */ | ||
| const dirExists = (p) => { | ||
| const cached = dotBins.get(p); | ||
| if (cached !== undefined) | ||
| return cached; | ||
| try { | ||
| const isDir = statSync(p).isDirectory(); | ||
| dotBins.set(p, isDir); | ||
| return isDir; | ||
| } | ||
| catch { | ||
| dotBins.set(p, false); | ||
| return false; | ||
| } | ||
| }; | ||
| const nmBin = `${sep}node_modules${sep}.bin`; | ||
| /** | ||
| * Add all existing `node_modules/.bin` folders to the PATH that | ||
| * exist between the cwd and the projectRoot, so dependency bins | ||
| * are found, with closer paths higher priority. | ||
| * | ||
| * If command contains node-gyp reference, also inject the shim directory | ||
| * as a fallback (after all existing PATH entries). | ||
| */ | ||
| const addPaths = async (projectRoot, cwd, env, command) => { | ||
| const { PATH = '' } = env; | ||
| const PATHsplit = PATH.split(delimiter); | ||
| const paths = new Set(); | ||
| // anything in the PATH that already has node_modules/.bin is a thing | ||
| // we put there, perhaps for the vlx exec cache usage | ||
| for (const p of PATHsplit) { | ||
| if (p.endsWith(nmBin)) { | ||
| paths.add(p); | ||
| } | ||
| } | ||
| for (const p of walkUp(cwd)) { | ||
| const dotBin = resolve(p, 'node_modules/.bin'); | ||
| if (dirExists(dotBin)) | ||
| paths.add(dotBin); | ||
| if (p === projectRoot) | ||
| break; | ||
| } | ||
| for (const p of PATH.split(delimiter)) { | ||
| /* c8 ignore next - pretty rare to have an empty entry */ | ||
| if (p) | ||
| paths.add(p); | ||
| } | ||
| // If command has node-gyp, inject shim directory as fallback (last) | ||
| if (command && hasNodeGypReference(command)) { | ||
| try { | ||
| const shimDir = await getNodeGypShimDir(); | ||
| paths.add(shimDir); | ||
| /* c8 ignore start */ | ||
| } | ||
| catch { | ||
| // Ignore shim creation errors, command will fail naturally if node-gyp is needed | ||
| } | ||
| /* c8 ignore stop */ | ||
| } | ||
| env.PATH = [...paths].join(delimiter); | ||
| return env; | ||
| }; | ||
| /** | ||
| * Run a package.json#scripts event in the background | ||
| */ | ||
| export const run = async (options) => runImpl(options, exec, ''); | ||
| /** | ||
| * Run a package.json#scripts event in the foreground | ||
| */ | ||
| export const runFG = async (options) => runImpl(options, execFG, null); | ||
| export const isRunResult = (v) => !!v && | ||
| typeof v === 'object' && | ||
| !Array.isArray(v) && | ||
| 'stdout' in v && | ||
| 'stderr' in v && | ||
| 'status' in v && | ||
| 'signal' in v; | ||
| /** | ||
| * Internal implementation of run() and runFG(), since they're mostly identical | ||
| */ | ||
| const runImpl = async (options, execImpl, empty) => { | ||
| const { arg0, packageJson = new PackageJson(), ignoreMissing = false, manifest, 'script-shell': shell = true, ...execArgs } = options; | ||
| const pjPath = resolve(options.cwd, 'package.json'); | ||
| // npm adds a `"install": "node-gyp rebuild"` if a binding.gyp | ||
| // is present at the time of publish, EVEN IF it's not included | ||
| // in the package. So, we need to read the actual package.json | ||
| // in those cases. | ||
| const untrustworthy = !!(manifest?.gypfile && | ||
| arg0 === 'install' && | ||
| manifest.scripts?.install === 'node-gyp rebuild'); | ||
| const pj = (untrustworthy ? undefined : manifest) ?? | ||
| packageJson.read(options.cwd); | ||
| const { scripts } = pj; | ||
| const command = scripts?.[arg0]; | ||
| if (!command) { | ||
| if (ignoreMissing) { | ||
| return { | ||
| command: '', | ||
| /* c8 ignore next */ | ||
| args: execArgs.args ?? [], | ||
| cwd: options.cwd, | ||
| status: 0, | ||
| signal: null, | ||
| stdout: empty, | ||
| stderr: empty, | ||
| // `as` to workaround "could be instantiated with arbitrary type". | ||
| // it's private and used in 2 places, we know that it isn't. | ||
| }; | ||
| } | ||
| throw error('Script not defined in package.json', { | ||
| name: arg0, | ||
| cwd: options.cwd, | ||
| args: options.args, | ||
| path: pjPath, | ||
| manifest: pj, | ||
| }); | ||
| } | ||
| const precommand = !options.ignorePrePost && scripts[`pre${arg0}`]; | ||
| const pre = precommand ? | ||
| await execImpl({ | ||
| arg0: precommand, | ||
| ...execArgs, | ||
| 'script-shell': shell, | ||
| args: [], | ||
| env: { | ||
| ...execArgs.env, | ||
| npm_package_json: pjPath, | ||
| npm_lifecycle_event: `pre${arg0}`, | ||
| npm_lifecycle_script: precommand, | ||
| }, | ||
| }) | ||
| : undefined; | ||
| if (pre && (pre.status || pre.signal)) { | ||
| return pre; | ||
| } | ||
| const result = await execImpl({ | ||
| arg0: command, | ||
| ...execArgs, | ||
| 'script-shell': shell, | ||
| env: { | ||
| ...execArgs.env, | ||
| npm_package_json: pjPath, | ||
| npm_lifecycle_event: arg0, | ||
| npm_lifecycle_script: command, | ||
| }, | ||
| }); | ||
| result.pre = pre; | ||
| if (result.signal || result.status) { | ||
| return result; | ||
| } | ||
| const postcommand = !options.ignorePrePost && scripts[`post${arg0}`]; | ||
| if (!postcommand) | ||
| return result; | ||
| const post = await execImpl({ | ||
| arg0: postcommand, | ||
| ...execArgs, | ||
| 'script-shell': shell, | ||
| args: [], | ||
| env: { | ||
| ...execArgs.env, | ||
| npm_package_json: pjPath, | ||
| npm_lifecycle_event: `post${arg0}`, | ||
| npm_lifecycle_script: postcommand, | ||
| }, | ||
| }); | ||
| if (post.status || post.signal) { | ||
| const { status, signal } = post; | ||
| return Object.assign(result, { post, status, signal }); | ||
| } | ||
| result.post = post; | ||
| return result; | ||
| }; | ||
| /** | ||
| * Execute an arbitrary command in the background | ||
| */ | ||
| export const exec = async (options) => { | ||
| const { arg0, args = [], cwd, env = {}, projectRoot, 'script-shell': shell = false, color = false, signal, ...spawnOptions } = options; | ||
| const p = promiseSpawn(arg0, args, { | ||
| ...spawnOptions, | ||
| shell, | ||
| stdio: 'pipe', | ||
| stdioString: true, | ||
| cwd, | ||
| env: await addPaths(projectRoot, cwd, { | ||
| ...process.env, | ||
| ...env, | ||
| FORCE_COLOR: color ? '1' : '0', | ||
| }, arg0), | ||
| windowsHide: true, | ||
| }); | ||
| proxySignals(p.process); | ||
| return await p; | ||
| }; | ||
| /** | ||
| * Execute an arbitrary command in the foreground | ||
| */ | ||
| export const execFG = async (options) => { | ||
| const { arg0, args = [], cwd, projectRoot, env = {}, 'script-shell': shell = false, color = true, signal, ...spawnOptions } = options; | ||
| const processEnv = await addPaths(projectRoot, cwd, { | ||
| ...process.env, | ||
| ...env, | ||
| FORCE_COLOR: color ? '1' : '0', | ||
| }, arg0); | ||
| return new Promise(res => { | ||
| foregroundChild(arg0, args, { | ||
| ...spawnOptions, | ||
| shell, | ||
| cwd, | ||
| env: processEnv, | ||
| }, (status, signal) => { | ||
| res({ | ||
| command: arg0, | ||
| args, | ||
| cwd, | ||
| stdout: null, | ||
| stderr: null, | ||
| status, | ||
| signal, | ||
| }); | ||
| return false; | ||
| }); | ||
| }); | ||
| }; | ||
| const runExecImpl = async (options, runImpl, execImpl) => { | ||
| const { arg0, packageJson = new PackageJson(), ...args } = options; | ||
| const pj = packageJson.read(options.cwd); | ||
| const { scripts } = pj; | ||
| const command = scripts?.[arg0]; | ||
| if (command) { | ||
| return runImpl({ ...args, packageJson, arg0 }); | ||
| } | ||
| else { | ||
| return execImpl({ ...args, arg0 }); | ||
| } | ||
| }; | ||
| /** | ||
| * If the arg0 is a defined package.json script, then run(), otherwise exec() | ||
| */ | ||
| export const runExec = async (options) => runExecImpl(options, run, exec); | ||
| /** | ||
| * If the arg0 is a defined package.json script, then runFG(), otherwise | ||
| * execFG() | ||
| */ | ||
| export const runExecFG = async (options) => runExecImpl(options, runFG, execFG); | ||
| // Export shim utilities | ||
| export { getNodeGypShim, getNodeGypShimDir, hasNodeGypReference, } from "./aliasRunner.js"; | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { error } from '@vltpkg/error-cause'\nimport { PackageJson } from '@vltpkg/package-json'\nimport type {\n PromiseSpawnOptions,\n SpawnResultNoStdio,\n SpawnResultStdioStrings,\n} from '@vltpkg/promise-spawn'\nimport { promiseSpawn } from '@vltpkg/promise-spawn'\nimport type { Manifest } from '@vltpkg/types'\nimport { foregroundChild } from 'foreground-child'\nimport { proxySignals } from 'foreground-child/proxy-signals'\nimport { statSync } from 'node:fs'\nimport { delimiter, resolve, sep } from 'node:path'\nimport { walkUp } from 'walk-up-path'\nimport {\n getNodeGypShimDir,\n hasNodeGypReference,\n} from './aliasRunner.ts'\n\n/** map of which node_modules/.bin folders exist */\nconst dotBins = new Map<string, boolean>()\n\n/** Check if a directory exists, and cache result */\nconst dirExists = (p: string) => {\n const cached = dotBins.get(p)\n if (cached !== undefined) return cached\n try {\n const isDir = statSync(p).isDirectory()\n dotBins.set(p, isDir)\n return isDir\n } catch {\n dotBins.set(p, false)\n return false\n }\n}\n\nconst nmBin = `${sep}node_modules${sep}.bin`\n\n/**\n * Add all existing `node_modules/.bin` folders to the PATH that\n * exist between the cwd and the projectRoot, so dependency bins\n * are found, with closer paths higher priority.\n *\n * If command contains node-gyp reference, also inject the shim directory\n * as a fallback (after all existing PATH entries).\n */\nconst addPaths = async (\n projectRoot: string,\n cwd: string,\n env: NodeJS.ProcessEnv,\n command?: string,\n): Promise<NodeJS.ProcessEnv> => {\n const { PATH = '' } = env\n const PATHsplit = PATH.split(delimiter)\n const paths = new Set<string>()\n\n // anything in the PATH that already has node_modules/.bin is a thing\n // we put there, perhaps for the vlx exec cache usage\n for (const p of PATHsplit) {\n if (p.endsWith(nmBin)) {\n paths.add(p)\n }\n }\n for (const p of walkUp(cwd)) {\n const dotBin = resolve(p, 'node_modules/.bin')\n if (dirExists(dotBin)) paths.add(dotBin)\n if (p === projectRoot) break\n }\n for (const p of PATH.split(delimiter)) {\n /* c8 ignore next - pretty rare to have an empty entry */\n if (p) paths.add(p)\n }\n\n // If command has node-gyp, inject shim directory as fallback (last)\n if (command && hasNodeGypReference(command)) {\n try {\n const shimDir = await getNodeGypShimDir()\n paths.add(shimDir)\n /* c8 ignore start */\n } catch {\n // Ignore shim creation errors, command will fail naturally if node-gyp is needed\n }\n /* c8 ignore stop */\n }\n\n env.PATH = [...paths].join(delimiter)\n return env\n}\n\n/** options shared by run() and exec() */\nexport type SharedOptions = PromiseSpawnOptions & {\n /** additional arguments to pass to the command */\n args?: string[]\n /** the root of the project, which we don't walk up past */\n projectRoot: string\n\n /** the directory where the package.json lives and the script runs */\n cwd: string\n /**\n * environment variables to set. `process.env` is always included,\n * to omit fields, set them explicitly to undefined.\n *\n * vlt will add some of its own, as well:\n * - npm_lifecycle_event: the event name\n * - npm_lifecycle_script: the command in package.json#scripts\n * - npm_package_json: path to the package.json file\n * - VLT_* envs for all vlt configuration values that are set\n */\n env?: NodeJS.ProcessEnv\n /**\n * the shell to run the script in. If not set, then the default\n * platform-specific shell will be used.\n */\n 'script-shell'?: boolean | string\n\n /**\n * If true, then `FORCE_COLOR=1` will be set in the environment so that\n * scripts will typically have colored output enablled, even if the output\n * is not a tty.\n */\n color?: boolean\n}\n\n/**\n * Options for run() and runFG()\n */\nexport type RunOptions = SharedOptions & {\n /** the name of the thing in package.json#scripts */\n arg0: string\n /**\n * pass in a @vltpkg/package-json.PackageJson instance, and\n * it'll be used for reading the package.json file. Optional,\n * may improve performance somewhat.\n */\n packageJson?: PackageJson\n\n /**\n * Pass in a manifest to avoid having to read it at all\n */\n manifest?: Pick<Manifest, 'scripts' | 'gypfile'>\n\n /**\n * if the script is not defined in package.json#scripts, just ignore it and\n * treat as success. Otherwise, treat as an error. Default false.\n */\n ignoreMissing?: boolean\n\n /**\n * skip the pre/post commands, just run the one specified.\n * This can be used to run JUST the specified script, without any\n * pre/post commands.\n */\n ignorePrePost?: boolean\n}\n\n/**\n * Options for exec() and execFG()\n */\nexport type ExecOptions = SharedOptions & {\n /** the command to execute */\n arg0: string\n}\n\n/**\n * Options for runExec() and runExecFG()\n */\nexport type RunExecOptions = SharedOptions & {\n /**\n * Either the command to be executed, or the event to be run\n */\n arg0: string\n /**\n * pass in a @vltpkg/package-json.PackageJson instance, and\n * it'll be used for reading the package.json file. Optional,\n * may improve performance somewhat.\n */\n packageJson?: PackageJson\n}\n\n/**\n * Run a package.json#scripts event in the background\n */\nexport const run = async (options: RunOptions): Promise<RunResult> =>\n runImpl(options, exec, '')\n\n/**\n * Run a package.json#scripts event in the foreground\n */\nexport const runFG = async (\n options: RunOptions,\n): Promise<RunFGResult> => runImpl(options, execFG, null)\n\n/** Return type of {@link run} */\nexport type RunResult = SpawnResultStdioStrings & {\n pre?: SpawnResultStdioStrings\n post?: SpawnResultStdioStrings\n}\n\n/** Return type of {@link runFG} */\nexport type RunFGResult = SpawnResultNoStdio & {\n pre?: SpawnResultNoStdio\n post?: SpawnResultNoStdio\n}\n\nexport const isRunResult = (v: unknown): v is RunResult =>\n !!v &&\n typeof v === 'object' &&\n !Array.isArray(v) &&\n 'stdout' in v &&\n 'stderr' in v &&\n 'status' in v &&\n 'signal' in v\n\n/**\n * Return type of {@link run} or {@link runFG}, as determined by their base\n * type\n * @internal\n */\nexport type RunImplResult<\n R extends SpawnResultNoStdio | SpawnResultStdioStrings,\n> = R & { pre?: R; post?: R }\n\n/**\n * Internal implementation of run() and runFG(), since they're mostly identical\n */\nconst runImpl = async <\n R extends SpawnResultNoStdio | SpawnResultStdioStrings,\n>(\n options: RunOptions,\n execImpl: (options: ExecOptions) => Promise<R>,\n empty: R['stdout'],\n): Promise<RunImplResult<R>> => {\n const {\n arg0,\n packageJson = new PackageJson(),\n ignoreMissing = false,\n manifest,\n 'script-shell': shell = true,\n ...execArgs\n } = options\n const pjPath = resolve(options.cwd, 'package.json')\n // npm adds a `\"install\": \"node-gyp rebuild\"` if a binding.gyp\n // is present at the time of publish, EVEN IF it's not included\n // in the package. So, we need to read the actual package.json\n // in those cases.\n const untrustworthy = !!(\n manifest?.gypfile &&\n arg0 === 'install' &&\n manifest.scripts?.install === 'node-gyp rebuild'\n )\n const pj =\n (untrustworthy ? undefined : manifest) ??\n packageJson.read(options.cwd)\n const { scripts } = pj\n const command = scripts?.[arg0]\n if (!command) {\n if (ignoreMissing) {\n return {\n command: '',\n /* c8 ignore next */\n args: execArgs.args ?? [],\n cwd: options.cwd,\n status: 0,\n signal: null,\n stdout: empty,\n stderr: empty,\n // `as` to workaround \"could be instantiated with arbitrary type\".\n // it's private and used in 2 places, we know that it isn't.\n } as R\n }\n throw error('Script not defined in package.json', {\n name: arg0,\n cwd: options.cwd,\n args: options.args,\n path: pjPath,\n manifest: pj,\n })\n }\n\n const precommand = !options.ignorePrePost && scripts[`pre${arg0}`]\n const pre =\n precommand ?\n await execImpl({\n arg0: precommand,\n ...execArgs,\n 'script-shell': shell,\n args: [],\n env: {\n ...execArgs.env,\n npm_package_json: pjPath,\n npm_lifecycle_event: `pre${arg0}`,\n npm_lifecycle_script: precommand,\n },\n })\n : undefined\n if (pre && (pre.status || pre.signal)) {\n return pre as RunImplResult<R>\n }\n const result: RunImplResult<R> = await execImpl({\n arg0: command,\n ...execArgs,\n 'script-shell': shell,\n env: {\n ...execArgs.env,\n npm_package_json: pjPath,\n npm_lifecycle_event: arg0,\n npm_lifecycle_script: command,\n },\n })\n result.pre = pre\n if (result.signal || result.status) {\n return result\n }\n\n const postcommand = !options.ignorePrePost && scripts[`post${arg0}`]\n if (!postcommand) return result\n\n const post = await execImpl({\n arg0: postcommand,\n ...execArgs,\n 'script-shell': shell,\n args: [],\n env: {\n ...execArgs.env,\n npm_package_json: pjPath,\n npm_lifecycle_event: `post${arg0}`,\n npm_lifecycle_script: postcommand,\n },\n })\n\n if (post.status || post.signal) {\n const { status, signal } = post\n return Object.assign(result, { post, status, signal })\n }\n result.post = post\n return result\n}\n\n/**\n * Execute an arbitrary command in the background\n */\nexport const exec = async (\n options: ExecOptions,\n): Promise<SpawnResultStdioStrings> => {\n const {\n arg0,\n args = [],\n cwd,\n env = {},\n projectRoot,\n 'script-shell': shell = false,\n color = false,\n signal,\n ...spawnOptions\n } = options\n\n const p = promiseSpawn(arg0, args, {\n ...spawnOptions,\n shell,\n stdio: 'pipe',\n stdioString: true,\n cwd,\n env: await addPaths(\n projectRoot,\n cwd,\n {\n ...process.env,\n ...env,\n FORCE_COLOR: color ? '1' : '0',\n },\n arg0,\n ),\n windowsHide: true,\n })\n proxySignals(p.process)\n return await p\n}\n\n/**\n * Execute an arbitrary command in the foreground\n */\nexport const execFG = async (\n options: ExecOptions,\n): Promise<SpawnResultNoStdio> => {\n const {\n arg0,\n args = [],\n cwd,\n projectRoot,\n env = {},\n 'script-shell': shell = false,\n color = true,\n signal,\n ...spawnOptions\n } = options\n\n const processEnv = await addPaths(\n projectRoot,\n cwd,\n {\n ...process.env,\n ...env,\n FORCE_COLOR: color ? '1' : '0',\n },\n arg0,\n )\n\n return new Promise<SpawnResultNoStdio>(res => {\n foregroundChild(\n arg0,\n args,\n {\n ...spawnOptions,\n shell,\n cwd,\n env: processEnv,\n },\n (status, signal) => {\n res({\n command: arg0,\n args,\n cwd,\n stdout: null,\n stderr: null,\n status,\n signal,\n })\n return false\n },\n )\n })\n}\n\nconst runExecImpl = async <\n R extends SpawnResultNoStdio | SpawnResultStdioStrings,\n>(\n options: RunExecOptions,\n runImpl: (options: RunOptions) => Promise<RunImplResult<R>>,\n execImpl: (options: ExecOptions) => Promise<R>,\n): Promise<R | RunImplResult<R>> => {\n const { arg0, packageJson = new PackageJson(), ...args } = options\n const pj = packageJson.read(options.cwd)\n const { scripts } = pj\n const command = scripts?.[arg0]\n if (command) {\n return runImpl({ ...args, packageJson, arg0 })\n } else {\n return execImpl({ ...args, arg0 })\n }\n}\n\n/**\n * If the arg0 is a defined package.json script, then run(), otherwise exec()\n */\nexport const runExec = async (\n options: RunExecOptions,\n): Promise<RunResult | SpawnResultStdioStrings> =>\n runExecImpl<SpawnResultStdioStrings>(options, run, exec)\n\n/**\n * If the arg0 is a defined package.json script, then runFG(), otherwise\n * execFG()\n */\nexport const runExecFG = async (\n options: RunExecOptions,\n): Promise<RunFGResult | SpawnResultNoStdio> =>\n runExecImpl<SpawnResultNoStdio>(options, runFG, execFG)\n\n// Export shim utilities\nexport {\n getNodeGypShim,\n getNodeGypShimDir,\n hasNodeGypReference,\n} from './aliasRunner.ts'\n"]} |
| { | ||
| "type": "module" | ||
| } |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
8
-11.11%50089
-0.63%11
-8.33%1
Infinity%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated