You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@vltpkg/run

Package Overview
Dependencies
Maintainers
6
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vltpkg/run - npm Package Compare versions

Comparing version
1.0.0-rc.10
to
1.0.0-rc.11
+15
dist/aliasRunner.d.ts
/**
* 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"]}
+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"
}