🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@arcgis/node-toolkit

Package Overview
Dependencies
Maintainers
5
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@arcgis/node-toolkit - npm Package Compare versions

Comparing version
5.2.0-next.52
to
5.2.0-next.53
+76
dist/shell.d.ts
import { ExecSyncOptionsWithStringEncoding, SpawnSyncOptionsWithStringEncoding, SpawnOptions } from 'node:child_process';
type SyncProcessOptions = Omit<SpawnSyncOptionsWithStringEncoding, "stdio">;
type AsyncProcessOptions = Omit<SpawnOptions, "stdio"> & {
input?: NonNullable<SpawnSyncOptionsWithStringEncoding["input"]>;
};
/**
* Synchronously execute a shell command and return the output.
*
* Prefer {@link runCommandSync} for command-only execution, or {@link collectOutputSync}
* when you need to capture stdout. {@link sh} goes through a shell, which
* requires careful escaping and can mis-handle dynamic input with spaces or
* shell metacharacters.
*
* Use {@link sh} only when shell features are intentionally required, such as
* pipes, redirects, `&&`, or command substitution.
*
* Example (shell features required):
* `sh("pnpm list | grep @arcgis/core")`
*/
export declare function sh(command: string, options?: Partial<ExecSyncOptionsWithStringEncoding>): string;
/**
* Asynchronously execute a shell command and return the output.
*
* Prefer {@link runCommand} for command-only execution, or {@link collectOutput}
* when you need to capture stdout. {@link asyncSh} executes through a shell,
* so callers must handle shell escaping and quoting correctly.
*
* Use {@link asyncSh} only when shell syntax is intentionally needed.
*
* Example (shell features required):
* `await asyncSh("pnpm list | grep @arcgis/core")`
*/
export declare function asyncSh(command: string, options?: Partial<ExecSyncOptionsWithStringEncoding>): Promise<string>;
/**
* Synchronously execute a command without shell interpolation and return the output.
*
* This is usually safer than {@link sh} because arguments are passed as
* discrete tokens, which avoids most shell escaping issues and command
* injection pitfalls.
*
* Example:
* `sp("git", ["show", `${baseRef}:pnpm-workspace.yaml`])`
*
* Avoid {@link sp} only when you explicitly need shell features.
* @deprecated Use {@link collectOutputSync} or {@link runCommandSync} instead.
*/
export declare function sp(command: string, args: string[], options?: Partial<SpawnSyncOptionsWithStringEncoding>): string;
/**
* Synchronously execute a command and stream output to the current process.
* Note 1:
* `pnpm` command will be automatically invoked with `shell: process.platform === "win32"`
* if the `shell` option is not explicitly provided.
* Note 2:
* If the `input` option is provided, it will be piped to the child process's stdin.
*/
export declare function runCommandSync(command: string, args: string[], options?: Partial<SyncProcessOptions>): void;
/**
* Asynchronously execute a command and stream output to the current process.
* Note 1:
* `pnpm` command will be automatically invoked with `shell: process.platform === "win32"`
* if the `shell` option is not explicitly provided.
* Note 2:
* If the `input` option is provided, it will be piped to the child process's stdin.
*/
export declare function runCommand(command: string, args: string[], options?: Partial<AsyncProcessOptions>): Promise<void>;
/**
* Synchronously execute a command and collect stdout while streaming stderr.
* Note that `pnpm` command will be automatically invoked with `shell: process.platform === "win32"`.
*/
export declare function collectOutputSync(command: string, args: string[], options?: Partial<SyncProcessOptions>): string;
/**
* Asynchronously execute a command and collect stdout while streaming stderr.
* Note that `pnpm` command will be automatically invoked with `shell: process.platform === "win32"`.
*/
export declare function collectOutput(command: string, args: string[], options?: Partial<AsyncProcessOptions>): Promise<string>;
export {};
import { exec, spawn, spawnSync, execSync } from "node:child_process";
import { styleText } from "node:util";
function sh(command, options = {}) {
try {
const normalizedOptions = { encoding: "utf8", ...options };
return execSync(command.trim(), normalizedOptions).trim();
} catch (error) {
makeExecErrorReadable(error);
throw error;
}
}
async function asyncSh(command, options = {}) {
const normalizedOptions = { encoding: "utf8", ...options };
return await new Promise((resolve, reject) => {
exec(command.trim(), normalizedOptions, (error, stdout, stderr) => {
if (error) {
makeExecErrorReadable(error);
reject(error);
return;
}
resolve(stdout.trim() || stderr.trim());
});
});
}
function makeExecErrorReadable(error) {
if (error instanceof Error && error.stack && "output" in error && Array.isArray(error.output) && "status" in error) {
const stackIndex = error.stack.indexOf("\n at ");
if (stackIndex !== -1) {
const output = error.output.filter(Boolean).join("\n").trim();
const newHeader = `${styleText("red", error.message)} (exit code: ${String(error.status)})
${output}`;
const oldStackFrames = error.stack.substring(stackIndex);
error.stack = `Error: ${newHeader}${oldStackFrames}`;
}
Object.defineProperties(error, {
output: { enumerable: false },
stdout: { enumerable: false },
stderr: { enumerable: false },
signal: { enumerable: false },
status: { enumerable: false },
pid: { enumerable: false },
stdio: { enumerable: false }
});
}
}
function sp(command, args, options = {}) {
if (process.platform === "win32" && command === "pnpm" && // Allow explicit shell config including shell:false for environment-specific handling.
!("shell" in options)) {
throw Error(
'If invoking pnpm on Windows, provide { shell: true } or { shell: process.platform === "win32" } and handle shell escaping.'
);
}
const normalizedOptions = { encoding: "utf8", ...options };
const result = spawnSync(command, args, normalizedOptions);
if (result.error) {
throw result.error;
}
const sep = result.stdout && result.stderr ? "\n" : "";
const output = `${result.stdout ?? ""}${sep}${result.stderr ?? ""}`.trim();
const exitCode = result.status ?? 0;
if (exitCode !== 0) {
throw makeSpawnError(command, args, exitCode, result.signal, output);
}
return output;
}
function runCommandSync(command, args, options = {}) {
const fixedOptions = fixPnpmUsage(command, options);
const { input } = fixedOptions;
const stdio = input === void 0 ? "inherit" : ["pipe", "inherit", "inherit"];
const result = spawnSync(command, args, { ...fixedOptions, stdio });
assertSyncResultSuccess(command, args, result);
}
async function runCommand(command, args, options = {}) {
const fixedOptions = fixPnpmUsage(command, options);
const { input } = fixedOptions;
const stdio = input === void 0 ? "inherit" : ["pipe", "inherit", "inherit"];
const child = spawn(command, args, { ...fixedOptions, stdio });
if (input !== void 0) {
child.stdin?.end(input);
}
await new Promise((resolve, reject) => {
child.on("error", (error) => reject(error));
child.on("close", (code, signal) => {
if (code !== 0) {
reject(makeSpawnError(command, args, code, signal, ""));
return;
}
resolve();
});
});
}
function collectOutputSync(command, args, options = {}) {
const fixedOptions = fixPnpmUsage(command, options);
const result = spawnSync(command, args, {
encoding: "utf8",
...fixedOptions,
stdio: ["ignore", "pipe", "inherit"]
});
assertSyncResultSuccess(command, args, result);
return (result.stdout ?? "").trim();
}
async function collectOutput(command, args, options = {}) {
const fixedOptions = fixPnpmUsage(command, options);
const child = spawn(command, args, {
...fixedOptions,
stdio: ["ignore", "pipe", "inherit"]
});
const stdoutChunks = [];
child.stdout?.on(
"data",
(chunk) => stdoutChunks.push(Buffer.isBuffer(chunk) ? chunk.toString("utf8") : String(chunk))
);
await new Promise((resolve, reject) => {
child.on("error", (error) => reject(error));
child.on("close", (code, signal) => {
if (code !== 0) {
reject(makeSpawnError(command, args, code, signal, ""));
return;
}
resolve();
});
});
return stdoutChunks.join("").trim();
}
function fixPnpmUsage(command, options) {
if (process.platform === "win32" && command === "pnpm") {
const fixedOptions = { shell: process.platform === "win32", ...options };
return fixedOptions;
}
return options;
}
function assertSyncResultSuccess(command, args, result) {
if (result.error) {
throw result.error;
}
if (result.status !== 0) {
throw makeSpawnError(command, args, result.status, result.signal, String(result.stderr ?? "").trim());
}
}
function makeSpawnError(command, args, code, signal, output) {
const commandText = `${command} ${args.join(" ")}`.trim();
const statusText = code !== null ? `exit code ${String(code)}` : `signal ${signal ?? "unknown"}`;
return new Error(`Command failed with ${statusText}: ${commandText}
${output}`.trim());
}
export {
asyncSh,
collectOutput,
collectOutputSync,
runCommand,
runCommandSync,
sh,
sp
};
+0
-46

@@ -1,2 +0,1 @@

import { ExecSyncOptionsWithStringEncoding, SpawnOptions, SpawnSyncOptionsWithStringEncoding } from 'node:child_process';
/**

@@ -9,47 +8,2 @@ * Asynchronously check if a file or directory exists.

/**
* Synchronously execute a shell command and return the output.
*
* Prefer {@link sp} for most use cases. {@link sh} goes through a shell,
* which requires careful escaping and can mis-handle dynamic input with spaces
* or shell metacharacters.
*
* Use {@link sh} only when shell features are intentionally required, such as
* pipes, redirects, `&&`, or command substitution.
*/
export declare function sh(command: string, options?: Partial<ExecSyncOptionsWithStringEncoding>): string;
/**
* Asynchronously execute a shell command and return the output.
*
* Prefer {@link asyncSp} for most use cases. {@link asyncSh} executes through
* a shell, so callers must handle shell escaping and quoting correctly.
*
* Use {@link asyncSh} only when shell syntax is intentionally needed.
*/
export declare function asyncSh(command: string, options?: Partial<ExecSyncOptionsWithStringEncoding>): Promise<string>;
/**
* Synchronously execute a command without shell interpolation and return the output.
*
* This is usually safer than {@link sh} because arguments are passed as
* discrete tokens, which avoids most shell escaping issues and command
* injection pitfalls.
*
* Example:
* `sp("git", ["show", `${baseRef}:pnpm-workspace.yaml`])`
*
* Avoid {@link sp} only when you explicitly need shell features.
*/
export declare function sp(command: string, args: string[], options?: Partial<SpawnSyncOptionsWithStringEncoding>): string;
/**
* Asynchronously execute a command without shell interpolation and return the output.
*
* This is usually safer than {@link asyncSh} because arguments are not parsed
* by a shell.
*
* Example:
* `await asyncSp("pnpm", ["--filter=@arcgis/map-components", "list", "@arcgis/core", "--json"])`
*
* Prefer {@link asyncSp} by default for external command execution.
*/
export declare function asyncSp(command: string, args: string[], options?: Partial<SpawnOptions>): Promise<string>;
/**
* Create a file with the specified content if it does not already exist.

@@ -56,0 +10,0 @@ */

+1
-106

@@ -5,4 +5,2 @@ import { access, existsSync } from "node:fs";

import { fileURLToPath } from "node:url";
import { execSync, exec, spawnSync, spawn } from "node:child_process";
import { styleText } from "node:util";
const existsAsync = async (file) => (

@@ -12,101 +10,2 @@ //#endregion existsAsync

);
function sh(command, options = {}) {
try {
const normalizedOptions = { encoding: "utf8", ...options };
return execSync(command.trim(), normalizedOptions).trim();
} catch (error) {
makeExecErrorReadable(error);
throw error;
}
}
async function asyncSh(command, options = {}) {
const normalizedOptions = { encoding: "utf8", ...options };
return await new Promise((resolve2, reject) => {
exec(command.trim(), normalizedOptions, (error, stdout, stderr) => {
if (error) {
makeExecErrorReadable(error);
reject(error);
return;
}
resolve2(stdout.trim() || stderr.trim());
});
});
}
function sp(command, args, options = {}) {
validatePnpmUsage(command, options);
const normalizedOptions = { encoding: "utf8", ...options };
const result = spawnSync(command, args, normalizedOptions);
if (result.error) {
throw result.error;
}
const output = `${result.stdout ?? ""}${result.stderr ?? ""}`.trim();
const exitCode = result.status ?? 0;
if (exitCode !== 0) {
throw new Error(
`Command failed with exit code ${String(exitCode)}: ${command} ${args.join(" ")}
${output}`.trim()
);
}
return output;
}
async function asyncSp(command, args, options = {}) {
validatePnpmUsage(command, options);
const child = spawn(command, args, options);
const stdoutChunks = [];
const stderrChunks = [];
child.stdout?.on(
"data",
(chunk) => stdoutChunks.push(Buffer.isBuffer(chunk) ? chunk.toString("utf8") : String(chunk))
);
child.stderr?.on(
"data",
(chunk) => stderrChunks.push(Buffer.isBuffer(chunk) ? chunk.toString("utf8") : String(chunk))
);
return await new Promise((resolve2, reject) => {
child.on("error", (error) => reject(error));
child.on("close", (code) => {
const output = `${stdoutChunks.join("")}${stderrChunks.join("")}`.trim();
const exitCode = code ?? 0;
if (exitCode !== 0) {
reject(
new Error(
`Command failed with exit code ${String(exitCode)}: ${command} ${args.join(" ")}
${output}`.trim()
)
);
return;
}
resolve2(output);
});
});
}
function validatePnpmUsage(command, options) {
if (command === "pnpm" && // Don't error for explicit shell:false to permit system-dependent handling
!("shell" in options)) {
throw Error(
'If invoking pnpm using sp/asyncSp, must provide {shell:true} or {shell:process.platform==="win32"} option and manually handle shell escaping'
);
}
}
function makeExecErrorReadable(error) {
if (error instanceof Error && error.stack && "output" in error && Array.isArray(error.output) && "status" in error) {
const stackIndex = error.stack.indexOf("\n at ");
if (stackIndex !== -1) {
const output = error.output.filter(Boolean).join("\n").trim();
const newHeader = `${styleText("red", error.message)} (exit code: ${String(error.status)})
${output}`;
const oldStackFrames = error.stack.substring(stackIndex);
error.stack = `Error: ${newHeader}${oldStackFrames}`;
}
Object.defineProperties(error, {
output: { enumerable: false },
stdout: { enumerable: false },
stderr: { enumerable: false },
signal: { enumerable: false },
status: { enumerable: false },
pid: { enumerable: false },
stdio: { enumerable: false }
});
}
}
async function createFileIfNotExists(filePath, content) {

@@ -149,9 +48,5 @@ await mkdir(dirname(filePath), { recursive: true });

asyncFindPath,
asyncSh,
asyncSp,
createFileIfNotExists,
existsAsync,
findPath,
sh,
sp
findPath
};
{
"name": "@arcgis/node-toolkit",
"version": "5.2.0-next.52",
"version": "5.2.0-next.53",
"description": "Collection of common internal build-time patterns and utilities for ArcGIS Maps SDK for JavaScript components.",

@@ -9,2 +9,3 @@ "homepage": "https://developers.arcgis.com/javascript/latest/",

"./file": "./dist/file.js",
"./shell": "./dist/shell.js",
"./glob": "./dist/glob.js",

@@ -11,0 +12,0 @@ "./path": "./dist/path.js",