@hyperfrontend/project-scope/core/process

process

Starting commands that are .cmd shims on Windows, such as npm, npx, pnpm and yarn, the same way on every platform.

Node refuses to start a .cmd file without a shell, and with a shell it joins an argument array without escaping it and prints the DEP0190 deprecation. shimCommand returns the program, arguments and shell option to spread into execFileSync, execFile, spawn or spawnSync: on Windows one command line with every argument passed through quoteForCmd and no argument array, elsewhere the command and its arguments as given with no shell. An argument holding ", %, ! or a line break is refused on Windows, because the shim's batch file expands or splits those whatever the quoting.

import { execFileSync } from 'node:child_process'
import { shimCommand } from '@hyperfrontend/project-scope/core/process'

const npm = shimCommand('npm', ['install', 'C:\\My Packages\\lib.tgz'])
execFileSync(npm.file, npm.args, { cwd: consumerDir, shell: npm.shell })

API Reference§

ƒ Functions

§function

quoteForCmd(argument: string): string

Quotes one argument for a command line that cmd.exe reads before handing it to a .cmd shim: an argument holding anything but word characters and - . / : = @ + \ is wrapped in double quotes, a trailing run of backslashes is doubled so it does not escape the closing quote, and every character cmd.exe interprets, the quotes included, is escaped with ^. The program receives the argument as written.
Parameters
NameTypeDescription
§argument
stringOne argument of the command
Returns
string
The argument as it is written into the command line
Example

Quoting a path with a space and an ampersand

quoteForCmd('--save-dev') // => '--save-dev'
quoteForCmd('C:\\Tom & Jerry\\lib.tgz') // => '^"C:\\Tom^ ^&^ Jerry\\lib.tgz^"'
§function

shimCommand(command: string, args: unknown, platform: Platform): ShimCommand

How to start npm, npx, pnpm, yarn or any other command that is a .cmd shim on Windows. Node refuses to start a .cmd file without a shell, and with one it joins an argument array unescaped and prints DEP0190, so on Windows the arguments are quoted for cmd.exe and joined into one command line passed with no array. Everywhere else the command starts directly with its arguments as given.
Parameters
NameTypeDescription
§command
stringThe shim's name, such as npm
§args
unknownIts arguments
§platform
PlatformThe platform it starts on, this one by default(default: process.platform)
Returns
ShimCommand
The program, arguments and shell option to spawn it with
Example

Packing a package on every platform

import { execFileSync } from 'node:child_process'

const npm = shimCommand('npm', ['pack', '--json'])
execFileSync(npm.file, npm.args, { cwd: packageDir, shell: npm.shell })
// on Windows npm.file is 'npm pack --json', npm.args is [] and npm.shell is true

◈ Interfaces

§interface

ShimCommand

How to start a command that is a .cmd shim on Windows: the values to spread into execFileSync, execFile, spawn or spawnSync from node:child_process.
Properties
§readonly file:stringThe program, or on Windows the whole command line with its arguments quoted for cmd.exe.
§readonly args:unknownThe arguments, or none on Windows, where they are already part of the line.
§readonly shell:booleanWhether the command starts through the platform shell: only on Windows.