Comparing version 8.0.2 to 8.1.0-dev.23fe548
235
build/cli.js
#!/usr/bin/env node | ||
"use strict"; | ||
import './deno.js' | ||
const { | ||
// src/cli.ts | ||
import { createRequire } from "node:module"; | ||
import { basename, dirname, extname, join, resolve } from "node:path"; | ||
import url from "node:url"; | ||
import { | ||
$, | ||
ProcessOutput, | ||
updateArgv, | ||
fetch, | ||
chalk, | ||
minimist, | ||
fs | ||
} from "./index.js"; | ||
import { randomId } from "./util.js"; | ||
import { installDeps, parseDeps } from "./deps.js"; | ||
function printUsage() { | ||
console.log(` | ||
${chalk.bold("zx " + getVersion())} | ||
A tool for writing better scripts | ||
} = await import('./cli.cjs') | ||
export { | ||
${chalk.bold("Usage")} | ||
zx [options] <script> | ||
} | ||
${chalk.bold("Options")} | ||
--quiet don't echo commands | ||
--shell=<path> custom shell binary | ||
--prefix=<command> prefix all commands | ||
--postfix=<command> postfix all commands | ||
--eval=<js>, -e evaluate script | ||
--install, -i install dependencies | ||
--version, -v print current zx version | ||
--help, -h print help | ||
--repl start repl | ||
`); | ||
} | ||
var argv = minimist(process.argv.slice(2), { | ||
string: ["shell", "prefix", "postfix", "eval"], | ||
boolean: ["version", "help", "quiet", "verbose", "install", "repl"], | ||
alias: { e: "eval", i: "install", v: "version", h: "help" }, | ||
stopEarly: true | ||
}); | ||
await async function main() { | ||
const globals = "./globals.js"; | ||
await import(globals); | ||
if (argv.verbose) | ||
$.verbose = true; | ||
if (argv.quiet) | ||
$.verbose = false; | ||
if (argv.shell) | ||
$.shell = argv.shell; | ||
if (argv.prefix) | ||
$.prefix = argv.prefix; | ||
if (argv.postfix) | ||
$.postfix = argv.postfix; | ||
if (argv.version) { | ||
console.log(getVersion()); | ||
return; | ||
} | ||
if (argv.help) { | ||
printUsage(); | ||
return; | ||
} | ||
if (argv.repl) { | ||
await (await import("./repl.js")).startRepl(); | ||
return; | ||
} | ||
if (argv.eval) { | ||
await runScript(argv.eval); | ||
return; | ||
} | ||
const firstArg = argv._[0]; | ||
updateArgv(argv._.slice(firstArg === void 0 ? 0 : 1)); | ||
if (!firstArg || firstArg === "-") { | ||
const success = await scriptFromStdin(); | ||
if (!success) | ||
printUsage(); | ||
return; | ||
} | ||
if (/^https?:/.test(firstArg)) { | ||
await scriptFromHttp(firstArg); | ||
return; | ||
} | ||
const filepath = firstArg.startsWith("file:///") ? url.fileURLToPath(firstArg) : resolve(firstArg); | ||
await importPath(filepath); | ||
}().catch((err) => { | ||
if (err instanceof ProcessOutput) { | ||
console.error("Error:", err.message); | ||
} else { | ||
console.error(err); | ||
} | ||
process.exitCode = 1; | ||
}); | ||
async function runScript(script) { | ||
const filepath = join(process.cwd(), `zx-${randomId()}.mjs`); | ||
await writeAndImport(script, filepath); | ||
} | ||
async function scriptFromStdin() { | ||
let script = ""; | ||
if (!process.stdin.isTTY) { | ||
process.stdin.setEncoding("utf8"); | ||
for await (const chunk of process.stdin) { | ||
script += chunk; | ||
} | ||
if (script.length > 0) { | ||
await runScript(script); | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
async function scriptFromHttp(remote) { | ||
const res = await fetch(remote); | ||
if (!res.ok) { | ||
console.error(`Error: Can't get ${remote}`); | ||
process.exit(1); | ||
} | ||
const script = await res.text(); | ||
const pathname = new URL(remote).pathname; | ||
const name = basename(pathname); | ||
const ext = extname(pathname) || ".mjs"; | ||
const filepath = join(process.cwd(), `${name}-${randomId()}${ext}`); | ||
await writeAndImport(script, filepath); | ||
} | ||
async function writeAndImport(script, filepath, origin = filepath) { | ||
await fs.writeFile(filepath, script.toString()); | ||
try { | ||
await importPath(filepath, origin); | ||
} finally { | ||
await fs.rm(filepath); | ||
} | ||
} | ||
async function importPath(filepath, origin = filepath) { | ||
const ext = extname(filepath); | ||
if (ext === "") { | ||
const tmpFilename = fs.existsSync(`${filepath}.mjs`) ? `${basename(filepath)}-${randomId()}.mjs` : `${basename(filepath)}.mjs`; | ||
return writeAndImport( | ||
await fs.readFile(filepath), | ||
join(dirname(filepath), tmpFilename), | ||
origin | ||
); | ||
} | ||
if (ext === ".md") { | ||
return writeAndImport( | ||
transformMarkdown(await fs.readFile(filepath)), | ||
join(dirname(filepath), basename(filepath) + ".mjs"), | ||
origin | ||
); | ||
} | ||
if (argv.install) { | ||
const deps = parseDeps(await fs.readFile(filepath)); | ||
await installDeps(deps, dirname(filepath)); | ||
} | ||
const __filename = resolve(origin); | ||
const __dirname = dirname(__filename); | ||
const require2 = createRequire(origin); | ||
Object.assign(global, { __filename, __dirname, require: require2 }); | ||
await import(url.pathToFileURL(filepath).toString()); | ||
} | ||
function transformMarkdown(buf) { | ||
const source = buf.toString(); | ||
const output = []; | ||
let state = "root"; | ||
let codeBlockEnd = ""; | ||
let prevLineIsEmpty = true; | ||
const jsCodeBlock = /^(```+|~~~+)(js|javascript)$/; | ||
const shCodeBlock = /^(```+|~~~+)(sh|bash)$/; | ||
const otherCodeBlock = /^(```+|~~~+)(.*)$/; | ||
for (let line of source.split("\n")) { | ||
switch (state) { | ||
case "root": | ||
if (/^( {4}|\t)/.test(line) && prevLineIsEmpty) { | ||
output.push(line); | ||
state = "tab"; | ||
} else if (jsCodeBlock.test(line)) { | ||
output.push(""); | ||
state = "js"; | ||
codeBlockEnd = line.match(jsCodeBlock)[1]; | ||
} else if (shCodeBlock.test(line)) { | ||
output.push("await $`"); | ||
state = "bash"; | ||
codeBlockEnd = line.match(shCodeBlock)[1]; | ||
} else if (otherCodeBlock.test(line)) { | ||
output.push(""); | ||
state = "other"; | ||
codeBlockEnd = line.match(otherCodeBlock)[1]; | ||
} else { | ||
prevLineIsEmpty = line === ""; | ||
output.push("// " + line); | ||
} | ||
break; | ||
case "tab": | ||
if (/^( +|\t)/.test(line)) { | ||
output.push(line); | ||
} else if (line === "") { | ||
output.push(""); | ||
} else { | ||
output.push("// " + line); | ||
state = "root"; | ||
} | ||
break; | ||
case "js": | ||
if (line === codeBlockEnd) { | ||
output.push(""); | ||
state = "root"; | ||
} else { | ||
output.push(line); | ||
} | ||
break; | ||
case "bash": | ||
if (line === codeBlockEnd) { | ||
output.push("`"); | ||
state = "root"; | ||
} else { | ||
output.push(line); | ||
} | ||
break; | ||
case "other": | ||
if (line === codeBlockEnd) { | ||
output.push(""); | ||
state = "root"; | ||
} else { | ||
output.push("// " + line); | ||
} | ||
break; | ||
} | ||
} | ||
return output.join("\n"); | ||
} | ||
function getVersion() { | ||
return createRequire(import.meta.url)("../package.json").version; | ||
} |
@@ -23,2 +23,4 @@ import { spawn, spawnSync, StdioOptions, IOType } from 'node:child_process'; | ||
input?: string | Buffer | Readable | ProcessOutput | ProcessPromise; | ||
timeout?: Duration; | ||
timeoutSignal?: string; | ||
stdio: StdioOptions; | ||
@@ -43,2 +45,3 @@ verbose: boolean; | ||
export declare function usePowerShell(): void; | ||
export declare function usePwsh(): void; | ||
export declare function useBash(): void; | ||
@@ -45,0 +48,0 @@ export declare const $: Shell & Options; |
@@ -1,482 +0,17 @@ | ||
// src/core.ts | ||
import assert from "node:assert"; | ||
import { spawn, spawnSync } from "node:child_process"; | ||
import { AsyncLocalStorage, createHook } from "node:async_hooks"; | ||
import { inspect } from "node:util"; | ||
import { | ||
exec, | ||
buildCmd, | ||
chalk, | ||
which, | ||
ps | ||
} from "./vendor.js"; | ||
import { | ||
errnoMessage, | ||
exitCodeInfo, | ||
formatCmd, | ||
getCallerLocation, | ||
noop, | ||
parseDuration, | ||
quote, | ||
quotePowerShell, | ||
noquote | ||
} from "./util.js"; | ||
var processCwd = Symbol("processCwd"); | ||
var syncExec = Symbol("syncExec"); | ||
var storage = new AsyncLocalStorage(); | ||
var cwdSyncHook = createHook({ | ||
init: syncCwd, | ||
before: syncCwd, | ||
promiseResolve: syncCwd, | ||
after: syncCwd, | ||
destroy: syncCwd | ||
}); | ||
function syncProcessCwd(flag = true) { | ||
if (flag) | ||
cwdSyncHook.enable(); | ||
else | ||
cwdSyncHook.disable(); | ||
} | ||
var defaults = { | ||
[processCwd]: process.cwd(), | ||
[syncExec]: false, | ||
verbose: false, | ||
env: process.env, | ||
sync: false, | ||
shell: true, | ||
stdio: ["inherit", "pipe", "pipe"], | ||
nothrow: false, | ||
quiet: false, | ||
prefix: "", | ||
postfix: "", | ||
quote: noquote, | ||
detached: false, | ||
spawn, | ||
spawnSync, | ||
"use strict"; | ||
import './deno.js' | ||
const { | ||
$, | ||
ProcessOutput, | ||
ProcessPromise, | ||
cd, | ||
defaults, | ||
kill, | ||
log, | ||
kill | ||
}; | ||
function usePowerShell() { | ||
$.shell = which.sync("powershell.exe"); | ||
$.prefix = ""; | ||
$.postfix = "; exit $LastExitCode"; | ||
$.quote = quotePowerShell; | ||
} | ||
function useBash() { | ||
$.shell = which.sync("bash"); | ||
$.prefix = "set -euo pipefail;"; | ||
$.quote = quote; | ||
} | ||
function checkShell() { | ||
if (!$.shell) { | ||
throw new Error(`shell is not available: setup guide goes here`); | ||
} | ||
} | ||
function getStore() { | ||
return storage.getStore() || defaults; | ||
} | ||
var $ = new Proxy( | ||
function(pieces, ...args) { | ||
checkShell(); | ||
if (!Array.isArray(pieces)) { | ||
return function(...args2) { | ||
const self = this; | ||
return within(() => { | ||
return Object.assign($, pieces).apply(self, args2); | ||
}); | ||
}; | ||
} | ||
const from = getCallerLocation(); | ||
if (pieces.some((p) => p == void 0)) { | ||
throw new Error(`Malformed command at ${from}`); | ||
} | ||
let resolve, reject; | ||
const promise = new ProcessPromise((...args2) => [resolve, reject] = args2); | ||
const cmd = buildCmd( | ||
$.quote, | ||
pieces, | ||
args | ||
); | ||
const snapshot = getStore(); | ||
const sync = snapshot[syncExec]; | ||
const callback = () => promise.isHalted || promise.run(); | ||
promise._bind( | ||
cmd, | ||
from, | ||
resolve, | ||
(v) => { | ||
reject(v); | ||
if (sync) | ||
throw v; | ||
}, | ||
snapshot | ||
); | ||
sync ? callback() : setImmediate(callback); | ||
return sync ? promise.output : promise; | ||
}, | ||
{ | ||
set(_, key, value) { | ||
const target = key in Function.prototype ? _ : getStore(); | ||
Reflect.set(target, key === "sync" ? syncExec : key, value); | ||
return true; | ||
}, | ||
get(_, key) { | ||
if (key === "sync") | ||
return $({ sync: true }); | ||
const target = key in Function.prototype ? _ : getStore(); | ||
return Reflect.get(target, key); | ||
} | ||
} | ||
); | ||
try { | ||
useBash(); | ||
} catch (err) { | ||
} | ||
var ProcessPromise = class _ProcessPromise extends Promise { | ||
constructor() { | ||
super(...arguments); | ||
this._command = ""; | ||
this._from = ""; | ||
this._resolve = noop; | ||
this._reject = noop; | ||
this._snapshot = getStore(); | ||
this._timeoutSignal = "SIGTERM"; | ||
this._resolved = false; | ||
this._halted = false; | ||
this._piped = false; | ||
this._zurk = null; | ||
this._output = null; | ||
this._prerun = noop; | ||
this._postrun = noop; | ||
} | ||
_bind(cmd, from, resolve, reject, options) { | ||
this._command = cmd; | ||
this._from = from; | ||
this._resolve = resolve; | ||
this._reject = reject; | ||
this._snapshot = { ...options }; | ||
} | ||
run() { | ||
if (this.child) | ||
return this; | ||
this._prerun(); | ||
const $2 = this._snapshot; | ||
const self = this; | ||
const input = $2.input?.stdout ?? $2.input; | ||
if (input) | ||
this.stdio("pipe"); | ||
$2.log({ | ||
kind: "cmd", | ||
cmd: this._command, | ||
verbose: self.isVerbose() | ||
}); | ||
this._zurk = exec({ | ||
input, | ||
cmd: $2.prefix + self._command + $2.postfix, | ||
cwd: $2.cwd ?? $2[processCwd], | ||
ac: $2.ac, | ||
signal: $2.signal, | ||
shell: typeof $2.shell === "string" ? $2.shell : true, | ||
env: $2.env, | ||
spawn: $2.spawn, | ||
spawnSync: $2.spawnSync, | ||
stdio: self._stdio ?? $2.stdio, | ||
sync: $2[syncExec], | ||
detached: $2.detached, | ||
run: (cb) => cb(), | ||
on: { | ||
start: () => { | ||
if (self._timeout) { | ||
const t = setTimeout( | ||
() => self.kill(self._timeoutSignal), | ||
self._timeout | ||
); | ||
self.finally(() => clearTimeout(t)).catch(noop); | ||
} | ||
}, | ||
stdout: (data) => { | ||
if (self._piped) | ||
return; | ||
$2.log({ kind: "stdout", data, verbose: self.isVerbose() }); | ||
}, | ||
stderr: (data) => { | ||
$2.log({ kind: "stderr", data, verbose: !self.isQuiet() }); | ||
}, | ||
end: ({ error, stdout, stderr, stdall, status, signal }) => { | ||
self._resolved = true; | ||
if (error) { | ||
const message = ProcessOutput.getErrorMessage(error, self._from); | ||
const output = new ProcessOutput( | ||
null, | ||
null, | ||
stdout, | ||
stderr, | ||
stdall, | ||
message | ||
); | ||
self._output = output; | ||
self._reject(output); | ||
} else { | ||
const message = ProcessOutput.getExitMessage( | ||
status, | ||
signal, | ||
stderr, | ||
self._from | ||
); | ||
const output = new ProcessOutput( | ||
status, | ||
signal, | ||
stdout, | ||
stderr, | ||
stdall, | ||
message | ||
); | ||
self._output = output; | ||
if (status === 0 || (self._nothrow ?? $2.nothrow)) { | ||
self._resolve(output); | ||
} else { | ||
self._reject(output); | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
this._postrun(); | ||
return this; | ||
} | ||
get child() { | ||
return this._zurk?.child; | ||
} | ||
get stdin() { | ||
this.stdio("pipe"); | ||
this.run(); | ||
assert(this.child); | ||
if (this.child.stdin == null) | ||
throw new Error("The stdin of subprocess is null."); | ||
return this.child.stdin; | ||
} | ||
get stdout() { | ||
this.run(); | ||
assert(this.child); | ||
if (this.child.stdout == null) | ||
throw new Error("The stdout of subprocess is null."); | ||
return this.child.stdout; | ||
} | ||
get stderr() { | ||
this.run(); | ||
assert(this.child); | ||
if (this.child.stderr == null) | ||
throw new Error("The stderr of subprocess is null."); | ||
return this.child.stderr; | ||
} | ||
get exitCode() { | ||
return this.then( | ||
(p) => p.exitCode, | ||
(p) => p.exitCode | ||
); | ||
} | ||
then(onfulfilled, onrejected) { | ||
if (this.isHalted && !this.child) { | ||
throw new Error("The process is halted!"); | ||
} | ||
return super.then(onfulfilled, onrejected); | ||
} | ||
catch(onrejected) { | ||
return super.catch(onrejected); | ||
} | ||
pipe(dest) { | ||
if (typeof dest == "string") | ||
throw new Error("The pipe() method does not take strings. Forgot $?"); | ||
if (this._resolved) { | ||
if (dest instanceof _ProcessPromise) | ||
dest.stdin.end(); | ||
throw new Error( | ||
"The pipe() method shouldn't be called after promise is already resolved!" | ||
); | ||
} | ||
this._piped = true; | ||
if (dest instanceof _ProcessPromise) { | ||
dest.stdio("pipe"); | ||
dest._prerun = this.run.bind(this); | ||
dest._postrun = () => { | ||
if (!dest.child) | ||
throw new Error( | ||
"Access to stdin of pipe destination without creation a subprocess." | ||
); | ||
this.stdout.pipe(dest.stdin); | ||
}; | ||
return dest; | ||
} else { | ||
this._postrun = () => this.stdout.pipe(dest); | ||
return this; | ||
} | ||
} | ||
abort(reason) { | ||
if (!this.child) | ||
throw new Error("Trying to abort a process without creating one."); | ||
this._zurk?.ac.abort(reason); | ||
} | ||
async kill(signal = "SIGTERM") { | ||
if (!this.child) | ||
throw new Error("Trying to kill a process without creating one."); | ||
if (!this.child.pid) | ||
throw new Error("The process pid is undefined."); | ||
return $.kill(this.child.pid, signal); | ||
} | ||
stdio(stdin, stdout = "pipe", stderr = "pipe") { | ||
this._stdio = [stdin, stdout, stderr]; | ||
return this; | ||
} | ||
nothrow() { | ||
this._nothrow = true; | ||
return this; | ||
} | ||
quiet() { | ||
this._quiet = true; | ||
return this; | ||
} | ||
isQuiet() { | ||
return this._quiet ?? this._snapshot.quiet; | ||
} | ||
isVerbose() { | ||
return this._snapshot.verbose && !this.isQuiet(); | ||
} | ||
timeout(d, signal = "SIGTERM") { | ||
this._timeout = parseDuration(d); | ||
this._timeoutSignal = signal; | ||
return this; | ||
} | ||
halt() { | ||
this._halted = true; | ||
return this; | ||
} | ||
get isHalted() { | ||
return this._halted; | ||
} | ||
get output() { | ||
return this._output; | ||
} | ||
}; | ||
var ProcessOutput = class extends Error { | ||
constructor(code, signal, stdout, stderr, combined, message) { | ||
super(message); | ||
this._code = code; | ||
this._signal = signal; | ||
this._stdout = stdout; | ||
this._stderr = stderr; | ||
this._combined = combined; | ||
} | ||
toString() { | ||
return this._combined; | ||
} | ||
valueOf() { | ||
return this._combined.trim(); | ||
} | ||
get stdout() { | ||
return this._stdout; | ||
} | ||
get stderr() { | ||
return this._stderr; | ||
} | ||
get exitCode() { | ||
return this._code; | ||
} | ||
get signal() { | ||
return this._signal; | ||
} | ||
static getExitMessage(code, signal, stderr, from) { | ||
let message = `exit code: ${code}`; | ||
if (code != 0 || signal != null) { | ||
message = `${stderr || "\n"} at ${from}`; | ||
message += ` | ||
exit code: ${code}${exitCodeInfo(code) ? " (" + exitCodeInfo(code) + ")" : ""}`; | ||
if (signal != null) { | ||
message += ` | ||
signal: ${signal}`; | ||
} | ||
} | ||
return message; | ||
} | ||
static getErrorMessage(err, from) { | ||
return `${err.message} | ||
errno: ${err.errno} (${errnoMessage(err.errno)}) | ||
code: ${err.code} | ||
at ${from}`; | ||
} | ||
[inspect.custom]() { | ||
let stringify = (s, c) => s.length === 0 ? "''" : c(inspect(s)); | ||
return `ProcessOutput { | ||
stdout: ${stringify(this.stdout, chalk.green)}, | ||
stderr: ${stringify(this.stderr, chalk.red)}, | ||
signal: ${inspect(this.signal)}, | ||
exitCode: ${(this.exitCode === 0 ? chalk.green : chalk.red)(this.exitCode)}${exitCodeInfo(this.exitCode) ? chalk.grey(" (" + exitCodeInfo(this.exitCode) + ")") : ""} | ||
}`; | ||
} | ||
}; | ||
function within(callback) { | ||
return storage.run({ ...getStore() }, callback); | ||
} | ||
function syncCwd() { | ||
if ($[processCwd] != process.cwd()) | ||
process.chdir($[processCwd]); | ||
} | ||
function cd(dir) { | ||
if (dir instanceof ProcessOutput) { | ||
dir = dir.toString().trim(); | ||
} | ||
$.log({ kind: "cd", dir }); | ||
process.chdir(dir); | ||
$[processCwd] = process.cwd(); | ||
} | ||
async function kill(pid, signal) { | ||
let children = await ps.tree({ pid, recursive: true }); | ||
for (const p of children) { | ||
try { | ||
process.kill(+p.pid, signal); | ||
} catch (e) { | ||
} | ||
} | ||
try { | ||
process.kill(-pid, signal); | ||
} catch (e) { | ||
try { | ||
process.kill(+pid, signal); | ||
} catch (e2) { | ||
} | ||
} | ||
} | ||
function log(entry) { | ||
switch (entry.kind) { | ||
case "cmd": | ||
if (!entry.verbose) | ||
return; | ||
process.stderr.write(formatCmd(entry.cmd)); | ||
break; | ||
case "stdout": | ||
case "stderr": | ||
if (!entry.verbose) | ||
return; | ||
process.stderr.write(entry.data); | ||
break; | ||
case "cd": | ||
if (!$.verbose) | ||
return; | ||
process.stderr.write("$ " + chalk.greenBright("cd") + ` ${entry.dir} | ||
`); | ||
break; | ||
case "fetch": | ||
if (!$.verbose) | ||
return; | ||
const init = entry.init ? " " + inspect(entry.init) : ""; | ||
process.stderr.write( | ||
"$ " + chalk.greenBright("fetch") + ` ${entry.url}${init} | ||
` | ||
); | ||
break; | ||
case "retry": | ||
if (!$.verbose) | ||
return; | ||
process.stderr.write(entry.error + "\n"); | ||
} | ||
} | ||
syncProcessCwd, | ||
useBash, | ||
usePowerShell, | ||
usePwsh, | ||
within | ||
} = await import('./core.cjs') | ||
export { | ||
@@ -493,3 +28,5 @@ $, | ||
usePowerShell, | ||
usePwsh, | ||
within | ||
}; | ||
} | ||
@@ -1,103 +0,11 @@ | ||
// src/deps.ts | ||
import { $ } from "./core.js"; | ||
import { spinner } from "./goods.js"; | ||
import { depseek } from "./vendor.js"; | ||
async function installDeps(dependencies, prefix) { | ||
const packages = Object.entries(dependencies).map( | ||
([name, version]) => `${name}@${version}` | ||
); | ||
const flags = prefix ? `--prefix=${prefix}` : ""; | ||
if (packages.length === 0) { | ||
return; | ||
} | ||
await spinner( | ||
`npm i ${packages.join(" ")}`, | ||
() => $`npm install --no-save --no-audit --no-fund ${flags} ${packages}`.nothrow() | ||
); | ||
} | ||
var builtins = /* @__PURE__ */ new Set([ | ||
"_http_agent", | ||
"_http_client", | ||
"_http_common", | ||
"_http_incoming", | ||
"_http_outgoing", | ||
"_http_server", | ||
"_stream_duplex", | ||
"_stream_passthrough", | ||
"_stream_readable", | ||
"_stream_transform", | ||
"_stream_wrap", | ||
"_stream_writable", | ||
"_tls_common", | ||
"_tls_wrap", | ||
"assert", | ||
"async_hooks", | ||
"buffer", | ||
"child_process", | ||
"cluster", | ||
"console", | ||
"constants", | ||
"crypto", | ||
"dgram", | ||
"dns", | ||
"domain", | ||
"events", | ||
"fs", | ||
"http", | ||
"http2", | ||
"https", | ||
"inspector", | ||
"module", | ||
"net", | ||
"os", | ||
"path", | ||
"perf_hooks", | ||
"process", | ||
"punycode", | ||
"querystring", | ||
"readline", | ||
"repl", | ||
"stream", | ||
"string_decoder", | ||
"sys", | ||
"timers", | ||
"tls", | ||
"trace_events", | ||
"tty", | ||
"url", | ||
"util", | ||
"v8", | ||
"vm", | ||
"wasi", | ||
"worker_threads", | ||
"zlib" | ||
]); | ||
var nameRe = /^(?<name>(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*)\/?.*$/i; | ||
var versionRe = /^@(?<version>[~^]?(v?[\dx*]+([-.][\d*a-z-]+)*))/i; | ||
function parseDeps(content) { | ||
return depseek(content.toString() + "\n", { comments: true }).reduce((m, { type, value }, i, list) => { | ||
if (type === "dep") { | ||
const meta = list[i + 1]; | ||
const name = parsePackageName(value); | ||
const version = meta?.type === "comment" && parseVersion(meta?.value.trim()) || "latest"; | ||
if (name) | ||
m[name] = version; | ||
} | ||
return m; | ||
}, {}); | ||
} | ||
function parsePackageName(path) { | ||
if (!path) | ||
return; | ||
const name = nameRe.exec(path)?.groups?.name; | ||
if (name && !builtins.has(name)) { | ||
return name; | ||
} | ||
} | ||
function parseVersion(line) { | ||
return versionRe.exec(line)?.groups?.version || "latest"; | ||
} | ||
"use strict"; | ||
import './deno.js' | ||
const { | ||
installDeps, | ||
parseDeps | ||
} = await import('./deps.cjs') | ||
export { | ||
installDeps, | ||
parseDeps | ||
}; | ||
} | ||
@@ -27,7 +27,12 @@ import * as _ from './index.js'; | ||
var retry: typeof _.retry; | ||
var usePowerShell: typeof _.usePowerShell; | ||
var useBash: typeof _.useBash; | ||
var sleep: typeof _.sleep; | ||
var spinner: typeof _.spinner; | ||
var stdin: typeof _.stdin; | ||
var tempdir: typeof _.tempdir; | ||
var tempfile: typeof _.tempfile; | ||
var tmpdir: typeof _.tempdir; | ||
var tmpfile: typeof _.tempfile; | ||
var usePowerShell: typeof _.usePowerShell; | ||
var usePwsh: typeof _.usePwsh; | ||
var useBash: typeof _.useBash; | ||
var which: typeof _.which; | ||
@@ -34,0 +39,0 @@ var within: typeof _.within; |
@@ -1,3 +0,9 @@ | ||
// src/globals.ts | ||
import * as _ from "./index.js"; | ||
Object.assign(global, _); | ||
"use strict"; | ||
import './deno.js' | ||
const { | ||
} = await import('./globals.cjs') | ||
export { | ||
} | ||
@@ -1,143 +0,17 @@ | ||
// src/goods.ts | ||
import assert from "node:assert"; | ||
import { createInterface } from "node:readline"; | ||
import { $, within, ProcessOutput } from "./core.js"; | ||
import { isString, parseDuration } from "./util.js"; | ||
import { | ||
chalk, | ||
minimist, | ||
nodeFetch | ||
} from "./vendor.js"; | ||
import { default as default2 } from "node:path"; | ||
import * as os from "node:os"; | ||
var argv = minimist(process.argv.slice(2)); | ||
function updateArgv(args) { | ||
argv = minimist(args); | ||
global.argv = argv; | ||
} | ||
function sleep(duration) { | ||
return new Promise((resolve) => { | ||
setTimeout(resolve, parseDuration(duration)); | ||
}); | ||
} | ||
async function fetch(url, init) { | ||
$.log({ kind: "fetch", url, init }); | ||
return nodeFetch(url, init); | ||
} | ||
function echo(pieces, ...args) { | ||
let msg; | ||
const lastIdx = pieces.length - 1; | ||
if (Array.isArray(pieces) && pieces.every(isString) && lastIdx === args.length) { | ||
msg = args.map((a, i) => pieces[i] + stringify(a)).join("") + pieces[lastIdx]; | ||
} else { | ||
msg = [pieces, ...args].map(stringify).join(" "); | ||
} | ||
console.log(msg); | ||
} | ||
function stringify(arg) { | ||
if (arg instanceof ProcessOutput) { | ||
return arg.toString().replace(/\n$/, ""); | ||
} | ||
return `${arg}`; | ||
} | ||
async function question(query, options) { | ||
let completer = void 0; | ||
if (options && Array.isArray(options.choices)) { | ||
completer = function completer2(line) { | ||
const completions = options.choices; | ||
const hits = completions.filter((c) => c.startsWith(line)); | ||
return [hits.length ? hits : completions, line]; | ||
}; | ||
} | ||
const rl = createInterface({ | ||
input: process.stdin, | ||
output: process.stdout, | ||
terminal: true, | ||
completer | ||
}); | ||
return new Promise( | ||
(resolve) => rl.question(query ?? "", (answer) => { | ||
rl.close(); | ||
resolve(answer); | ||
}) | ||
); | ||
} | ||
async function stdin() { | ||
let buf = ""; | ||
process.stdin.setEncoding("utf8"); | ||
for await (const chunk of process.stdin) { | ||
buf += chunk; | ||
} | ||
return buf; | ||
} | ||
async function retry(count, a, b) { | ||
const total = count; | ||
let callback; | ||
let delayStatic = 0; | ||
let delayGen; | ||
if (typeof a == "function") { | ||
callback = a; | ||
} else { | ||
if (typeof a == "object") { | ||
delayGen = a; | ||
} else { | ||
delayStatic = parseDuration(a); | ||
} | ||
assert(b); | ||
callback = b; | ||
} | ||
let lastErr; | ||
let attempt = 0; | ||
while (count-- > 0) { | ||
attempt++; | ||
try { | ||
return await callback(); | ||
} catch (err) { | ||
let delay = 0; | ||
if (delayStatic > 0) | ||
delay = delayStatic; | ||
if (delayGen) | ||
delay = delayGen.next().value; | ||
$.log({ | ||
kind: "retry", | ||
error: chalk.bgRed.white(" FAIL ") + ` Attempt: ${attempt}${total == Infinity ? "" : `/${total}`}` + (delay > 0 ? `; next in ${delay}ms` : "") | ||
}); | ||
lastErr = err; | ||
if (count == 0) | ||
break; | ||
if (delay) | ||
await sleep(delay); | ||
} | ||
} | ||
throw lastErr; | ||
} | ||
function* expBackoff(max = "60s", rand = "100ms") { | ||
const maxMs = parseDuration(max); | ||
const randMs = parseDuration(rand); | ||
let n = 1; | ||
while (true) { | ||
const ms = Math.floor(Math.random() * randMs); | ||
yield Math.min(2 ** n++, maxMs) + ms; | ||
} | ||
} | ||
async function spinner(title, callback) { | ||
if (typeof title == "function") { | ||
callback = title; | ||
title = ""; | ||
} | ||
let i = 0; | ||
const spin = () => process.stderr.write(` ${"\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F"[i++ % 10]} ${title}\r`); | ||
return within(async () => { | ||
$.verbose = false; | ||
const id = setInterval(spin, 100); | ||
let result; | ||
try { | ||
result = await callback(); | ||
} finally { | ||
clearInterval(id); | ||
process.stderr.write(" ".repeat((process.stdout.columns || 1) - 1) + "\r"); | ||
} | ||
return result; | ||
}); | ||
} | ||
"use strict"; | ||
import './deno.js' | ||
const { | ||
argv, | ||
echo, | ||
expBackoff, | ||
fetch, | ||
os, | ||
path, | ||
question, | ||
retry, | ||
sleep, | ||
spinner, | ||
stdin, | ||
updateArgv | ||
} = await import('./goods.cjs') | ||
export { | ||
@@ -149,3 +23,3 @@ argv, | ||
os, | ||
default2 as path, | ||
path, | ||
question, | ||
@@ -157,2 +31,3 @@ retry, | ||
updateArgv | ||
}; | ||
} | ||
@@ -5,3 +5,3 @@ import { ProcessPromise } from './core.js'; | ||
export { minimist, chalk, fs, which, YAML, ps, glob, glob as globby, } from './vendor.js'; | ||
export { type Duration, quote, quotePowerShell } from './util.js'; | ||
export { type Duration, quote, quotePowerShell, tempdir, tempdir as tmpdir, tempfile, tempfile as tmpfile, } from './util.js'; | ||
/** | ||
@@ -8,0 +8,0 @@ * @deprecated Use $`cmd`.nothrow() instead. |
@@ -1,21 +0,45 @@ | ||
// src/index.ts | ||
export * from "./core.js"; | ||
export * from "./goods.js"; | ||
import { | ||
minimist, | ||
"use strict"; | ||
import './deno.js' | ||
const { | ||
YAML, | ||
chalk, | ||
fs, | ||
glob, | ||
globby, | ||
minimist, | ||
nothrow, | ||
ps, | ||
quiet, | ||
quote, | ||
quotePowerShell, | ||
tempdir, | ||
tempfile, | ||
tmpdir, | ||
tmpfile, | ||
which, | ||
YAML, | ||
ps, | ||
glob, | ||
glob as glob2 | ||
} from "./vendor.js"; | ||
import { quote, quotePowerShell } from "./util.js"; | ||
function nothrow(promise) { | ||
return promise.nothrow(); | ||
} | ||
function quiet(promise) { | ||
return promise.quiet(); | ||
} | ||
$, | ||
ProcessOutput, | ||
ProcessPromise, | ||
cd, | ||
defaults, | ||
kill, | ||
log, | ||
syncProcessCwd, | ||
useBash, | ||
usePowerShell, | ||
usePwsh, | ||
within, | ||
argv, | ||
echo, | ||
expBackoff, | ||
fetch, | ||
os, | ||
path, | ||
question, | ||
retry, | ||
sleep, | ||
spinner, | ||
stdin, | ||
updateArgv | ||
} = await import('./index.cjs') | ||
export { | ||
@@ -26,3 +50,3 @@ YAML, | ||
glob, | ||
glob2 as globby, | ||
globby, | ||
minimist, | ||
@@ -34,3 +58,32 @@ nothrow, | ||
quotePowerShell, | ||
which | ||
}; | ||
tempdir, | ||
tempfile, | ||
tmpdir, | ||
tmpfile, | ||
which, | ||
$, | ||
ProcessOutput, | ||
ProcessPromise, | ||
cd, | ||
defaults, | ||
kill, | ||
log, | ||
syncProcessCwd, | ||
useBash, | ||
usePowerShell, | ||
usePwsh, | ||
within, | ||
argv, | ||
echo, | ||
expBackoff, | ||
fetch, | ||
os, | ||
path, | ||
question, | ||
retry, | ||
sleep, | ||
spinner, | ||
stdin, | ||
updateArgv | ||
} | ||
@@ -1,25 +0,9 @@ | ||
// src/repl.ts | ||
import os from "node:os"; | ||
import path from "node:path"; | ||
import { inspect } from "node:util"; | ||
import { ProcessOutput, defaults } from "./core.js"; | ||
import { chalk } from "./vendor.js"; | ||
async function startRepl() { | ||
defaults.verbose = false; | ||
const r = (await import("node:repl")).start({ | ||
prompt: chalk.greenBright.bold("\u276F "), | ||
useGlobal: true, | ||
preview: false, | ||
writer(output) { | ||
if (output instanceof ProcessOutput) { | ||
return output.toString().replace(/\n$/, ""); | ||
} | ||
return inspect(output, { colors: true }); | ||
} | ||
}); | ||
r.setupHistory(path.join(os.homedir(), ".zx_repl_history"), () => { | ||
}); | ||
} | ||
"use strict"; | ||
import './deno.js' | ||
const { | ||
startRepl | ||
} = await import('./repl.cjs') | ||
export { | ||
startRepl | ||
}; | ||
} | ||
@@ -0,1 +1,3 @@ | ||
export declare function tempdir(prefix?: string): string; | ||
export declare function tempfile(name?: string, data?: string | Buffer): string; | ||
export declare function noop(): void; | ||
@@ -15,1 +17,2 @@ export declare function randomId(): string; | ||
export declare function getCallerLocationFromString(stackString?: string): string; | ||
export declare function ensureEol(buffer: Buffer): Buffer; |
@@ -1,342 +0,23 @@ | ||
// src/util.ts | ||
import { chalk, parseLine } from "./vendor.js"; | ||
function noop() { | ||
} | ||
function randomId() { | ||
return Math.random().toString(36).slice(2); | ||
} | ||
function isString(obj) { | ||
return typeof obj === "string"; | ||
} | ||
var pad = (v) => v === " " ? " " : ""; | ||
function normalizeMultilinePieces(pieces) { | ||
return Object.assign( | ||
pieces.map( | ||
(p, i) => p.trim() ? pad(p[0]) + parseLine(p).words.map(({ w }) => w === "\\" ? "" : w.trim()).join(" ") + pad(p[p.length - 1]) : pieces[i] | ||
), | ||
{ raw: pieces.raw } | ||
); | ||
} | ||
function noquote() { | ||
throw new Error("No quote function is defined: https://\xEF.at/no-quote-func"); | ||
} | ||
function quote(arg) { | ||
if (/^[a-z0-9/_.\-@:=]+$/i.test(arg) || arg === "") { | ||
return arg; | ||
} | ||
return `$'` + arg.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\f/g, "\\f").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t").replace(/\v/g, "\\v").replace(/\0/g, "\\0") + `'`; | ||
} | ||
function quotePowerShell(arg) { | ||
if (/^[a-z0-9/_.\-]+$/i.test(arg) || arg === "") { | ||
return arg; | ||
} | ||
return `'` + arg.replace(/'/g, "''") + `'`; | ||
} | ||
function exitCodeInfo(exitCode) { | ||
return { | ||
2: "Misuse of shell builtins", | ||
126: "Invoked command cannot execute", | ||
127: "Command not found", | ||
128: "Invalid exit argument", | ||
129: "Hangup", | ||
130: "Interrupt", | ||
131: "Quit and dump core", | ||
132: "Illegal instruction", | ||
133: "Trace/breakpoint trap", | ||
134: "Process aborted", | ||
135: 'Bus error: "access to undefined portion of memory object"', | ||
136: 'Floating point exception: "erroneous arithmetic operation"', | ||
137: "Kill (terminate immediately)", | ||
138: "User-defined 1", | ||
139: "Segmentation violation", | ||
140: "User-defined 2", | ||
141: "Write to pipe with no one reading", | ||
142: "Signal raised by alarm", | ||
143: "Termination (request to terminate)", | ||
145: "Child process terminated, stopped (or continued*)", | ||
146: "Continue if stopped", | ||
147: "Stop executing temporarily", | ||
148: "Terminal stop signal", | ||
149: 'Background process attempting to read from tty ("in")', | ||
150: 'Background process attempting to write to tty ("out")', | ||
151: "Urgent data available on socket", | ||
152: "CPU time limit exceeded", | ||
153: "File size limit exceeded", | ||
154: 'Signal raised by timer counting virtual time: "virtual timer expired"', | ||
155: "Profiling timer expired", | ||
157: "Pollable event", | ||
159: "Bad syscall" | ||
}[exitCode || -1]; | ||
} | ||
function errnoMessage(errno) { | ||
if (errno === void 0) { | ||
return "Unknown error"; | ||
} | ||
return { | ||
0: "Success", | ||
1: "Not super-user", | ||
2: "No such file or directory", | ||
3: "No such process", | ||
4: "Interrupted system call", | ||
5: "I/O error", | ||
6: "No such device or address", | ||
7: "Arg list too long", | ||
8: "Exec format error", | ||
9: "Bad file number", | ||
10: "No children", | ||
11: "No more processes", | ||
12: "Not enough core", | ||
13: "Permission denied", | ||
14: "Bad address", | ||
15: "Block device required", | ||
16: "Mount device busy", | ||
17: "File exists", | ||
18: "Cross-device link", | ||
19: "No such device", | ||
20: "Not a directory", | ||
21: "Is a directory", | ||
22: "Invalid argument", | ||
23: "Too many open files in system", | ||
24: "Too many open files", | ||
25: "Not a typewriter", | ||
26: "Text file busy", | ||
27: "File too large", | ||
28: "No space left on device", | ||
29: "Illegal seek", | ||
30: "Read only file system", | ||
31: "Too many links", | ||
32: "Broken pipe", | ||
33: "Math arg out of domain of func", | ||
34: "Math result not representable", | ||
35: "File locking deadlock error", | ||
36: "File or path name too long", | ||
37: "No record locks available", | ||
38: "Function not implemented", | ||
39: "Directory not empty", | ||
40: "Too many symbolic links", | ||
42: "No message of desired type", | ||
43: "Identifier removed", | ||
44: "Channel number out of range", | ||
45: "Level 2 not synchronized", | ||
46: "Level 3 halted", | ||
47: "Level 3 reset", | ||
48: "Link number out of range", | ||
49: "Protocol driver not attached", | ||
50: "No CSI structure available", | ||
51: "Level 2 halted", | ||
52: "Invalid exchange", | ||
53: "Invalid request descriptor", | ||
54: "Exchange full", | ||
55: "No anode", | ||
56: "Invalid request code", | ||
57: "Invalid slot", | ||
59: "Bad font file fmt", | ||
60: "Device not a stream", | ||
61: "No data (for no delay io)", | ||
62: "Timer expired", | ||
63: "Out of streams resources", | ||
64: "Machine is not on the network", | ||
65: "Package not installed", | ||
66: "The object is remote", | ||
67: "The link has been severed", | ||
68: "Advertise error", | ||
69: "Srmount error", | ||
70: "Communication error on send", | ||
71: "Protocol error", | ||
72: "Multihop attempted", | ||
73: "Cross mount point (not really error)", | ||
74: "Trying to read unreadable message", | ||
75: "Value too large for defined data type", | ||
76: "Given log. name not unique", | ||
77: "f.d. invalid for this operation", | ||
78: "Remote address changed", | ||
79: "Can access a needed shared lib", | ||
80: "Accessing a corrupted shared lib", | ||
81: ".lib section in a.out corrupted", | ||
82: "Attempting to link in too many libs", | ||
83: "Attempting to exec a shared library", | ||
84: "Illegal byte sequence", | ||
86: "Streams pipe error", | ||
87: "Too many users", | ||
88: "Socket operation on non-socket", | ||
89: "Destination address required", | ||
90: "Message too long", | ||
91: "Protocol wrong type for socket", | ||
92: "Protocol not available", | ||
93: "Unknown protocol", | ||
94: "Socket type not supported", | ||
95: "Not supported", | ||
96: "Protocol family not supported", | ||
97: "Address family not supported by protocol family", | ||
98: "Address already in use", | ||
99: "Address not available", | ||
100: "Network interface is not configured", | ||
101: "Network is unreachable", | ||
102: "Connection reset by network", | ||
103: "Connection aborted", | ||
104: "Connection reset by peer", | ||
105: "No buffer space available", | ||
106: "Socket is already connected", | ||
107: "Socket is not connected", | ||
108: "Can't send after socket shutdown", | ||
109: "Too many references", | ||
110: "Connection timed out", | ||
111: "Connection refused", | ||
112: "Host is down", | ||
113: "Host is unreachable", | ||
114: "Socket already connected", | ||
115: "Connection already in progress", | ||
116: "Stale file handle", | ||
122: "Quota exceeded", | ||
123: "No medium (in tape drive)", | ||
125: "Operation canceled", | ||
130: "Previous owner died", | ||
131: "State not recoverable" | ||
}[-errno] || "Unknown error"; | ||
} | ||
function parseDuration(d) { | ||
if (typeof d == "number") { | ||
if (isNaN(d) || d < 0) | ||
throw new Error(`Invalid duration: "${d}".`); | ||
return d; | ||
} else if (/\d+s/.test(d)) { | ||
return +d.slice(0, -1) * 1e3; | ||
} else if (/\d+ms/.test(d)) { | ||
return +d.slice(0, -2); | ||
} else if (/\d+m/.test(d)) { | ||
return +d.slice(0, -1) * 1e3 * 60; | ||
} | ||
throw new Error(`Unknown duration: "${d}".`); | ||
} | ||
function formatCmd(cmd) { | ||
if (cmd == void 0) | ||
return chalk.grey("undefined"); | ||
const chars = [...cmd]; | ||
let out = "$ "; | ||
let buf = ""; | ||
let ch; | ||
let state = root; | ||
let wordCount = 0; | ||
while (state) { | ||
ch = chars.shift() || "EOF"; | ||
if (ch == "\n") { | ||
out += style(state, buf) + "\n> "; | ||
buf = ""; | ||
continue; | ||
} | ||
const next = ch == "EOF" ? void 0 : state(); | ||
if (next != state) { | ||
out += style(state, buf); | ||
buf = ""; | ||
} | ||
state = next == root ? next() : next; | ||
buf += ch; | ||
} | ||
function style(state2, s) { | ||
if (s == "") | ||
return ""; | ||
if (reservedWords.includes(s)) { | ||
return chalk.cyanBright(s); | ||
} | ||
if (state2 == word && wordCount == 0) { | ||
wordCount++; | ||
return chalk.greenBright(s); | ||
} | ||
if (state2 == syntax) { | ||
wordCount = 0; | ||
return chalk.cyanBright(s); | ||
} | ||
if (state2 == dollar) | ||
return chalk.yellowBright(s); | ||
if (state2?.name.startsWith("str")) | ||
return chalk.yellowBright(s); | ||
return s; | ||
} | ||
function isSyntax(ch2) { | ||
return "()[]{}<>;:+|&=".includes(ch2); | ||
} | ||
function root() { | ||
if (/\s/.test(ch)) | ||
return space; | ||
if (isSyntax(ch)) | ||
return syntax; | ||
if (/[$]/.test(ch)) | ||
return dollar; | ||
if (/["]/.test(ch)) | ||
return strDouble; | ||
if (/[']/.test(ch)) | ||
return strSingle; | ||
return word; | ||
} | ||
function space() { | ||
if (/\s/.test(ch)) | ||
return space; | ||
return root; | ||
} | ||
function word() { | ||
if (/[0-9a-z/_.]/i.test(ch)) | ||
return word; | ||
return root; | ||
} | ||
function syntax() { | ||
if (isSyntax(ch)) | ||
return syntax; | ||
return root; | ||
} | ||
function dollar() { | ||
if (/[']/.test(ch)) | ||
return str; | ||
return root; | ||
} | ||
function str() { | ||
if (/[']/.test(ch)) | ||
return strEnd; | ||
if (/[\\]/.test(ch)) | ||
return strBackslash; | ||
return str; | ||
} | ||
function strBackslash() { | ||
return strEscape; | ||
} | ||
function strEscape() { | ||
return str; | ||
} | ||
function strDouble() { | ||
if (/["]/.test(ch)) | ||
return strEnd; | ||
return strDouble; | ||
} | ||
function strSingle() { | ||
if (/[']/.test(ch)) | ||
return strEnd; | ||
return strSingle; | ||
} | ||
function strEnd() { | ||
return root; | ||
} | ||
return out + "\n"; | ||
} | ||
var reservedWords = [ | ||
"if", | ||
"then", | ||
"else", | ||
"elif", | ||
"fi", | ||
"case", | ||
"esac", | ||
"for", | ||
"select", | ||
"while", | ||
"until", | ||
"do", | ||
"done", | ||
"in" | ||
]; | ||
function getCallerLocation(err = new Error()) { | ||
return getCallerLocationFromString(err.stack); | ||
} | ||
function getCallerLocationFromString(stackString = "unknown") { | ||
return stackString.split(/^\s*(at\s)?/m).filter((s) => s?.includes(":"))[2]?.trim() || stackString; | ||
} | ||
"use strict"; | ||
import './deno.js' | ||
const { | ||
ensureEol, | ||
errnoMessage, | ||
exitCodeInfo, | ||
formatCmd, | ||
getCallerLocation, | ||
getCallerLocationFromString, | ||
isString, | ||
noop, | ||
noquote, | ||
normalizeMultilinePieces, | ||
parseDuration, | ||
quote, | ||
quotePowerShell, | ||
randomId, | ||
tempdir, | ||
tempfile | ||
} = await import('./util.cjs') | ||
export { | ||
ensureEol, | ||
errnoMessage, | ||
@@ -354,3 +35,6 @@ exitCodeInfo, | ||
quotePowerShell, | ||
randomId | ||
}; | ||
randomId, | ||
tempdir, | ||
tempfile | ||
} | ||
@@ -1,6 +0,5 @@ | ||
// Generated by dts-bundle-generator v9.3.1 | ||
// Generated by dts-bundle-generator v9.5.1 | ||
/// <reference types="node" /> | ||
import { parseLine } from '@webpod/ingrid'; | ||
import * as fs from 'fs'; | ||
@@ -10,2 +9,3 @@ import * as cp from 'node:child_process'; | ||
import { Readable, Stream, Writable } from 'node:stream'; | ||
import { URL as URL$1 } from 'node:url'; | ||
@@ -694,2 +694,11 @@ declare type ErrnoException = NodeJS.ErrnoException; | ||
} | ||
type TLineDigest = { | ||
spaces: number[]; | ||
words: { | ||
s: number; | ||
e: number; | ||
w: string; | ||
}[]; | ||
}; | ||
export declare const parseLine: (line: string, sep?: string) => TLineDigest; | ||
type TPsLookupCallback = (err: any, processList?: TPsLookupEntry[]) => void; | ||
@@ -723,2 +732,3 @@ type TPsLookupEntry = { | ||
}; | ||
export declare const createRequire: (filename: string | URL$1) => NodeRequire; | ||
export type RequestInfo = Parameters<typeof fetch$1>[0]; | ||
@@ -760,5 +770,4 @@ type RequestInit$1 = Parameters<typeof fetch$1>[1]; | ||
fs$1 as fs, | ||
parseLine, | ||
}; | ||
export {}; |
{ | ||
"name": "zx", | ||
"version": "8.0.2", | ||
"version": "8.1.0-dev.23fe548", | ||
"description": "A tool for writing better scripts", | ||
@@ -25,6 +25,26 @@ "type": "module", | ||
"exports": { | ||
".": "./build/index.js", | ||
"./globals": "./build/globals.js", | ||
"./cli": "./build/cli.js", | ||
"./core": "./build/core.js", | ||
".": { | ||
"types": "./build/index.d.ts", | ||
"import": "./build/index.js", | ||
"require": "./build/index.cjs", | ||
"default": "./build/index.js" | ||
}, | ||
"./globals": { | ||
"types": "./build/globals.d.ts", | ||
"import": "./build/globals.js", | ||
"require": "./build/globals.cjs", | ||
"default": "./build/globals.js" | ||
}, | ||
"./cli": { | ||
"types": "./build/cli.d.ts", | ||
"import": "./build/cli.js", | ||
"require": "./build/cli.cjs", | ||
"default": "./build/cli.js" | ||
}, | ||
"./core": { | ||
"types": "./build/core.d.ts", | ||
"import": "./build/core.js", | ||
"require": "./build/core.cjs", | ||
"default": "./build/core.js" | ||
}, | ||
"./package.json": "./package.json" | ||
@@ -35,4 +55,9 @@ }, | ||
}, | ||
"man": "./man/zx.1", | ||
"files": [ | ||
"build", | ||
"man" | ||
], | ||
"engines": { | ||
"node": ">= 16.0.0" | ||
"node": ">= 12.17.0" | ||
}, | ||
@@ -44,12 +69,20 @@ "scripts": { | ||
"build:check": "tsc", | ||
"build:js": "node scripts/build-js.mjs --format=esm --entry=src/*.ts && npm run build:vendor", | ||
"build:vendor": "node scripts/build-js.mjs --format=esm --entry=src/vendor.ts --bundle=all --banner", | ||
"build:js": "node scripts/build-js.mjs --format=cjs --hybrid --entry=src/*.ts && npm run build:vendor", | ||
"build:vendor": "node scripts/build-js.mjs --format=cjs --entry=src/vendor.ts --bundle=all", | ||
"build:dts": "tsc --project tsconfig.prod.json && node scripts/build-dts.mjs", | ||
"test": "npm run build && npm run test:unit && npm run test:types", | ||
"pretest": "npm run build", | ||
"test": "npm run test:unit && npm run test:types && npm run test:license", | ||
"test:unit": "node ./test/all.test.js", | ||
"test:circular": "madge --circular src/*", | ||
"test:types": "tsd", | ||
"test:license": "node ./test/extra.test.js", | ||
"test:smoke:tsx": "tsx test/smoke/ts.test.ts", | ||
"test:smoke:tsc": "cd test/smoke && mkdir -p node_modules && ln -s ../../../ ./node_modules/zx; tsc --esModuleInterop --module node16 --rootDir . --outdir ./temp ts.test.ts && node ./temp/ts.test.js", | ||
"test:smoke:ts-node": "node --loader ts-node/esm test/smoke/ts.test.ts", | ||
"test:smoke:bun": "bun test ./test/smoke/bun.test.js", | ||
"test:smoke:win32": "node ./test/smoke/win32.test.js", | ||
"coverage": "c8 -x build/vendor.js -x 'test/**' -x scripts --check-coverage npm test", | ||
"circular": "madge --circular src/*", | ||
"test:smoke:cjs": "node ./test/smoke/node.test.cjs", | ||
"test:smoke:mjs": "node ./test/smoke/node.test.mjs", | ||
"test:smoke:deno": "deno test ./test/smoke/deno.test.js --allow-read --allow-sys --allow-env --allow-run", | ||
"coverage": "c8 -x build/deno.js -x build/vendor.cjs -x build/esblib.cjs -x 'test/**' -x scripts --check-coverage npm test", | ||
"version": "cat package.json | fx .version" | ||
@@ -59,3 +92,3 @@ }, | ||
"@types/fs-extra": "^11.0.4", | ||
"@types/node": ">=20.12.5" | ||
"@types/node": ">=20.12.11" | ||
}, | ||
@@ -67,23 +100,31 @@ "devDependencies": { | ||
"@types/which": "^3.0.3", | ||
"@webpod/ingrid": "^0.0.0-beta.3", | ||
"@webpod/ps": "^0.0.0-beta.3", | ||
"@webpod/ingrid": "^0.0.0-beta.3", | ||
"c8": "^9.1.0", | ||
"chalk": "^5.3.0", | ||
"create-require": "^1.1.1", | ||
"depseek": "^0.4.1", | ||
"dts-bundle-generator": "^9.3.1", | ||
"esbuild": "^0.20.2", | ||
"esbuild-node-externals": "^1.13.0", | ||
"esbuild-plugin-entry-chunks": "^0.1.12", | ||
"dts-bundle-generator": "^9.5.1", | ||
"esbuild": "^0.21.1", | ||
"esbuild-node-externals": "^1.13.1", | ||
"esbuild-plugin-entry-chunks": "^0.1.14", | ||
"esbuild-plugin-extract-helpers": "^0.0.5", | ||
"esbuild-plugin-hybrid-export": "^0.2.3", | ||
"esbuild-plugin-transform-hook": "^0.0.3", | ||
"esbuild-plugin-utils": "^0.0.1", | ||
"fs-extra": "^11.2.0", | ||
"fx": "*", | ||
"globby": "^14.0.1", | ||
"madge": "^6.1.0", | ||
"madge": "^7.0.0", | ||
"minimist": "^1.2.8", | ||
"node-abort-controller": "^3.1.1", | ||
"node-fetch-native": "^1.6.4", | ||
"prettier": "^3.2.5", | ||
"ts-node": "^10.9.2", | ||
"tsd": "^0.31.0", | ||
"typescript": "^5.4.4", | ||
"tsx": "^4.9.4", | ||
"typescript": "^5.4.5", | ||
"which": "^4.0.0", | ||
"yaml": "^2.4.1", | ||
"zurk": "^0.1.2" | ||
"yaml": "^2.4.2", | ||
"zurk": "^0.1.4" | ||
}, | ||
@@ -93,5 +134,15 @@ "publishConfig": { | ||
}, | ||
"files": [ | ||
"build", | ||
"zx.js" | ||
"keywords": [ | ||
"shell", | ||
"script", | ||
"bash", | ||
"bin", | ||
"binary", | ||
"child", | ||
"process", | ||
"exec", | ||
"execute", | ||
"invoke", | ||
"call", | ||
"spawn" | ||
], | ||
@@ -98,0 +149,0 @@ "prettier": { |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
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
Network access
Supply chain riskThis module accesses the network.
Found 3 instances in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 2 instances in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
889811
33
24246
33
2
35
15