Comparing version 7.0.8 to 7.1.0-dev.862401
174
build/cli.js
@@ -16,70 +16,82 @@ #!/usr/bin/env node | ||
import fs from 'fs-extra'; | ||
import minimist from 'minimist'; | ||
import { createRequire } from 'node:module'; | ||
import { tmpdir } from 'node:os'; | ||
import { basename, dirname, extname, join, resolve } from 'node:path'; | ||
import url from 'node:url'; | ||
import { updateArgv } from './goods.js'; | ||
import { $, argv, chalk, fetch, ProcessOutput } from './index.js'; | ||
import { $, chalk, fetch, ProcessOutput } from './index.js'; | ||
import { startRepl } from './repl.js'; | ||
import { randomId } from './util.js'; | ||
import { installDeps, parseDeps } from './deps.js'; | ||
function printUsage() { | ||
// language=txt | ||
console.log(` | ||
${chalk.bold('zx ' + getVersion())} | ||
A tool for writing better scripts | ||
${chalk.bold('Usage')} | ||
zx [options] <script> | ||
${chalk.bold('Options')} | ||
--quiet don't echo commands | ||
--shell=<path> custom shell binary | ||
--prefix=<command> prefix all commands | ||
--eval=<js>, -e evaluate script | ||
--install, -i install dependencies | ||
--experimental enable experimental features | ||
--version, -v print current zx version | ||
--help, -h print help | ||
--repl start repl | ||
`); | ||
} | ||
const argv = minimist(process.argv.slice(2), { | ||
string: ['shell', 'prefix', 'eval'], | ||
boolean: ['version', 'help', 'quiet', 'install', 'repl', 'experimental'], | ||
alias: { e: 'eval', i: 'install', v: 'version', h: 'help' }, | ||
stopEarly: true, | ||
}); | ||
await (async function main() { | ||
const globals = './globals.js'; | ||
await import(globals); | ||
if (argv.quiet) { | ||
if (argv.quiet) | ||
$.verbose = false; | ||
} | ||
if (typeof argv.shell === 'string') { | ||
if (argv.shell) | ||
$.shell = argv.shell; | ||
} | ||
if (typeof argv.prefix === 'string') { | ||
if (argv.prefix) | ||
$.prefix = argv.prefix; | ||
} | ||
if (argv.experimental) { | ||
Object.assign(global, await import('./experimental.js')); | ||
} | ||
if (process.argv.length == 3) { | ||
if (['--version', '-v', '-V'].includes(process.argv[2])) { | ||
console.log(getVersion()); | ||
return; | ||
} | ||
if (['--help', '-h'].includes(process.argv[2])) { | ||
printUsage(); | ||
return; | ||
} | ||
if (['--interactive', '-i'].includes(process.argv[2])) { | ||
startRepl(); | ||
return; | ||
} | ||
if (argv.version) { | ||
console.log(getVersion()); | ||
return; | ||
} | ||
if (argv.eval || argv.e) { | ||
const script = (argv.eval || argv.e).toString(); | ||
await runScript(script); | ||
if (argv.help) { | ||
printUsage(); | ||
return; | ||
} | ||
let firstArg = process.argv.slice(2).find((a) => !a.startsWith('--')); | ||
if (typeof firstArg === 'undefined' || firstArg === '-') { | ||
let ok = await scriptFromStdin(); | ||
if (!ok) { | ||
startRepl(); | ||
} | ||
if (argv.repl) { | ||
startRepl(); | ||
return; | ||
} | ||
else if (firstArg.startsWith('http://') || | ||
firstArg.startsWith('https://')) { | ||
if (argv.eval) { | ||
await runScript(argv.eval); | ||
return; | ||
} | ||
const firstArg = argv._[0]; | ||
updateArgv(argv._.slice(firstArg === undefined ? 0 : 1)); | ||
if (!firstArg || firstArg === '-') { | ||
const success = await scriptFromStdin(); | ||
if (!success) | ||
printUsage(); | ||
return; | ||
} | ||
if (/^https?:/.test(firstArg)) { | ||
await scriptFromHttp(firstArg); | ||
return; | ||
} | ||
else { | ||
let filepath; | ||
if (firstArg.startsWith('/')) { | ||
filepath = firstArg; | ||
} | ||
else if (firstArg.startsWith('file:///')) { | ||
filepath = url.fileURLToPath(firstArg); | ||
} | ||
else { | ||
filepath = resolve(firstArg); | ||
} | ||
updateArgv({ sliceAt: 3 }); | ||
await importPath(filepath); | ||
} | ||
return; | ||
const filepath = firstArg.startsWith('file:///') | ||
? url.fileURLToPath(firstArg) | ||
: resolve(firstArg); | ||
await importPath(filepath); | ||
})().catch((err) => { | ||
@@ -95,5 +107,4 @@ if (err instanceof ProcessOutput) { | ||
async function runScript(script) { | ||
let filepath = join(tmpdir(), randomId() + '.mjs'); | ||
await fs.mkdtemp(filepath); | ||
await writeAndImport(script, filepath, join(process.cwd(), 'stdin.mjs')); | ||
const filepath = join(process.cwd(), `zx-${randomId()}.mjs`); | ||
await writeAndImport(script, filepath); | ||
} | ||
@@ -115,3 +126,3 @@ async function scriptFromStdin() { | ||
async function scriptFromHttp(remote) { | ||
let res = await fetch(remote); | ||
const res = await fetch(remote); | ||
if (!res.ok) { | ||
@@ -121,28 +132,36 @@ console.error(`Error: Can't get ${remote}`); | ||
} | ||
let script = await res.text(); | ||
let filename = new URL(remote).pathname; | ||
let filepath = join(tmpdir(), basename(filename)); | ||
await fs.mkdtemp(filepath); | ||
await writeAndImport(script, filepath, join(process.cwd(), basename(filename))); | ||
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()); | ||
let wait = importPath(filepath, origin); | ||
await fs.rm(filepath); | ||
await wait; | ||
try { | ||
await importPath(filepath, origin); | ||
} | ||
finally { | ||
await fs.rm(filepath); | ||
} | ||
} | ||
async function importPath(filepath, origin = filepath) { | ||
let ext = extname(filepath); | ||
const ext = extname(filepath); | ||
if (ext === '') { | ||
let tmpFilename = fs.existsSync(`${filepath}.mjs`) | ||
const tmpFilename = fs.existsSync(`${filepath}.mjs`) | ||
? `${basename(filepath)}-${randomId()}.mjs` | ||
: `${basename(filepath)}.mjs`; | ||
return await writeAndImport(await fs.readFile(filepath), join(dirname(filepath), tmpFilename), origin); | ||
return writeAndImport(await fs.readFile(filepath), join(dirname(filepath), tmpFilename), origin); | ||
} | ||
if (ext === '.md') { | ||
return await writeAndImport(transformMarkdown(await fs.readFile(filepath)), join(dirname(filepath), basename(filepath) + '.mjs'), origin); | ||
return writeAndImport(transformMarkdown(await fs.readFile(filepath)), join(dirname(filepath), basename(filepath) + '.mjs'), origin); | ||
} | ||
let __filename = resolve(origin); | ||
let __dirname = dirname(__filename); | ||
let require = createRequire(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 require = createRequire(origin); | ||
Object.assign(global, { __filename, __dirname, require }); | ||
@@ -152,4 +171,4 @@ await import(url.pathToFileURL(filepath).toString()); | ||
function transformMarkdown(buf) { | ||
let source = buf.toString(); | ||
let output = []; | ||
const source = buf.toString(); | ||
const output = []; | ||
let state = 'root'; | ||
@@ -227,20 +246,1 @@ let prevLineIsEmpty = true; | ||
} | ||
function printUsage() { | ||
console.log(` | ||
${chalk.bold('zx ' + getVersion())} | ||
A tool for writing better scripts | ||
${chalk.bold('Usage')} | ||
zx [options] <script> | ||
${chalk.bold('Options')} | ||
--quiet don't echo commands | ||
--shell=<path> custom shell binary | ||
--prefix=<command> prefix all commands | ||
--interactive, -i start repl | ||
--eval=<js>, -e evaluate script | ||
--experimental enable new api proposals | ||
--version, -v print current zx version | ||
--help, -h print help | ||
`); | ||
} |
@@ -41,2 +41,3 @@ /// <reference types="node" resolution-mode="require"/> | ||
private _resolved; | ||
private _halted; | ||
private _piped; | ||
@@ -46,13 +47,17 @@ _prerun: typeof noop; | ||
_bind(cmd: string, from: string, resolve: Resolve, reject: Resolve, options: Options): void; | ||
_run(): void; | ||
run(): ProcessPromise; | ||
get stdin(): Writable; | ||
get stdout(): Readable; | ||
get stderr(): Readable; | ||
get exitCode(): Promise<any>; | ||
get exitCode(): Promise<number | null>; | ||
then<R = ProcessOutput, E = ProcessOutput>(onfulfilled?: ((value: ProcessOutput) => PromiseLike<R> | R) | undefined | null, onrejected?: ((reason: ProcessOutput) => PromiseLike<E> | E) | undefined | null): Promise<R | E>; | ||
catch<T = ProcessOutput>(onrejected?: ((reason: ProcessOutput) => PromiseLike<T> | T) | undefined | null): Promise<ProcessOutput | T>; | ||
pipe(dest: Writable | ProcessPromise): ProcessPromise; | ||
kill(signal?: string): Promise<void>; | ||
stdio(stdin: IO, stdout?: IO, stderr?: IO): this; | ||
nothrow(): this; | ||
quiet(): this; | ||
timeout(d: Duration, signal?: string): this; | ||
stdio(stdin: IO, stdout?: IO, stderr?: IO): ProcessPromise; | ||
nothrow(): ProcessPromise; | ||
quiet(): ProcessPromise; | ||
timeout(d: Duration, signal?: string): ProcessPromise; | ||
halt(): ProcessPromise; | ||
get isHalted(): boolean; | ||
} | ||
@@ -59,0 +64,0 @@ export declare class ProcessOutput extends Error { |
@@ -59,3 +59,3 @@ // Copyright 2021 Google LLC | ||
let resolve, reject; | ||
let promise = new ProcessPromise((...args) => ([resolve, reject] = args)); | ||
const promise = new ProcessPromise((...args) => ([resolve, reject] = args)); | ||
let cmd = pieces[0], i = 0; | ||
@@ -73,3 +73,4 @@ while (i < args.length) { | ||
promise._bind(cmd, from, resolve, reject, getStore()); | ||
setImmediate(() => promise._run()); // Postpone run to allow promise configuration. | ||
// Postpone run to allow promise configuration. | ||
setImmediate(() => promise.isHalted || promise.run()); | ||
return promise; | ||
@@ -105,2 +106,3 @@ }, { | ||
this._resolved = false; | ||
this._halted = false; | ||
this._piped = false; | ||
@@ -117,6 +119,6 @@ this._prerun = noop; | ||
} | ||
_run() { | ||
run() { | ||
const $ = this._snapshot; | ||
if (this.child) | ||
return; // The _run() can be called from a few places. | ||
return this; // The _run() can be called from a few places. | ||
this._prerun(); // In case $1.pipe($2), the $2 returned, and on $2._run() invoke $1._run(). | ||
@@ -180,6 +182,7 @@ $.log({ | ||
} | ||
return this; | ||
} | ||
get stdin() { | ||
this.stdio('pipe'); | ||
this._run(); | ||
this.run(); | ||
assert(this.child); | ||
@@ -191,3 +194,3 @@ if (this.child.stdin == null) | ||
get stdout() { | ||
this._run(); | ||
this.run(); | ||
assert(this.child); | ||
@@ -199,3 +202,3 @@ if (this.child.stdout == null) | ||
get stderr() { | ||
this._run(); | ||
this.run(); | ||
assert(this.child); | ||
@@ -209,2 +212,11 @@ if (this.child.stderr == null) | ||
} | ||
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) { | ||
@@ -221,3 +233,3 @@ if (typeof dest == 'string') | ||
dest.stdio('pipe'); | ||
dest._prerun = this._run.bind(this); | ||
dest._prerun = this.run.bind(this); | ||
dest._postrun = () => { | ||
@@ -269,2 +281,9 @@ if (!dest.child) | ||
} | ||
halt() { | ||
this._halted = true; | ||
return this; | ||
} | ||
get isHalted() { | ||
return this._halted; | ||
} | ||
} | ||
@@ -271,0 +290,0 @@ export class ProcessOutput extends Error { |
@@ -12,5 +12,3 @@ import * as globbyModule from 'globby'; | ||
export declare let argv: minimist.ParsedArgs; | ||
export declare function updateArgv(params: { | ||
sliceAt: number; | ||
}): void; | ||
export declare function updateArgv(args: string[]): void; | ||
export declare const globby: ((patterns: string | readonly string[], options?: globbyModule.Options) => Promise<string[]>) & typeof globbyModule; | ||
@@ -17,0 +15,0 @@ export declare const glob: ((patterns: string | readonly string[], options?: globbyModule.Options) => Promise<string[]>) & typeof globbyModule; |
@@ -27,4 +27,4 @@ // Copyright 2022 Google LLC | ||
export let argv = minimist(process.argv.slice(2)); | ||
export function updateArgv(params) { | ||
argv = minimist(process.argv.slice(params.sliceAt)); | ||
export function updateArgv(args) { | ||
argv = minimist(args); | ||
global.argv = argv; | ||
@@ -47,3 +47,3 @@ } | ||
let msg; | ||
let lastIdx = pieces.length - 1; | ||
const lastIdx = pieces.length - 1; | ||
if (Array.isArray(pieces) && | ||
@@ -50,0 +50,0 @@ pieces.every(isString) && |
@@ -26,3 +26,3 @@ // Copyright 2022 Google LLC | ||
export function quote(arg) { | ||
if (/^[a-z0-9/_.-]+$/i.test(arg) || arg === '') { | ||
if (/^[a-z0-9/_.\-@:=]+$/i.test(arg) || arg === '') { | ||
return arg; | ||
@@ -29,0 +29,0 @@ } |
{ | ||
"name": "zx", | ||
"version": "7.0.8", | ||
"version": "7.1.0-dev.862401", | ||
"description": "A tool for writing better scripts.", | ||
@@ -55,3 +55,3 @@ "type": "module", | ||
"@types/minimist": "^1.2.2", | ||
"@types/node": "^18.6.3", | ||
"@types/node": "^18.7.20", | ||
"@types/ps-tree": "^1.1.2", | ||
@@ -63,3 +63,3 @@ "@types/which": "^2.0.1", | ||
"minimist": "^1.2.6", | ||
"node-fetch": "3.2.8", | ||
"node-fetch": "3.2.10", | ||
"ps-tree": "^1.2.0", | ||
@@ -70,8 +70,8 @@ "which": "^2.0.2", | ||
"devDependencies": { | ||
"@stryker-mutator/core": "^6.1.2", | ||
"@stryker-mutator/core": "^6.2.2", | ||
"c8": "^7.12.0", | ||
"madge": "^5.0.1", | ||
"prettier": "^2.7.1", | ||
"tsd": "^0.22.0", | ||
"typescript": "^4.8.0-dev.20220729", | ||
"tsd": "^0.24.1", | ||
"typescript": "^4.8.3", | ||
"uvu": "^0.5.6" | ||
@@ -78,0 +78,0 @@ }, |
@@ -353,4 +353,19 @@ # 🐚 zx | ||
Specifies a [logging function](src/log.ts). | ||
Specifies a [logging function](src/core.ts). | ||
```ts | ||
import { LogEntry, log } from 'zx/core' | ||
$.log = (entry: LogEntry) => { | ||
switch (entry.kind) { | ||
case 'cmd': | ||
// for example, apply custom data masker for cmd printing | ||
process.stderr.write(masker(entry.cmd)) | ||
break | ||
default: | ||
log(entry) | ||
} | ||
} | ||
``` | ||
## Polyfills | ||
@@ -498,6 +513,29 @@ | ||
### Installing dependencies via --install | ||
```js | ||
// script.mjs: | ||
import sh from 'tinysh' | ||
sh.say('Hello, world!') | ||
``` | ||
Add `--install` flag to the `zx` command to install missing dependencies | ||
automatically. | ||
```bash | ||
zx --install script.mjs | ||
``` | ||
You can also specify needed version by adding comment with `@` after | ||
the import. | ||
```js | ||
import sh from 'tinysh' // @^1 | ||
``` | ||
### Attaching a profile | ||
By default `child_process` does not include aliases and bash functions. | ||
But you are still able to do it by hand. Just attach necessary directives to `$.prefix`. | ||
But you are still able to do it by hand. Just attach necessary directives | ||
to the `$.prefix`. | ||
@@ -529,2 +567,9 @@ ```js | ||
### Canary / Beta / RC builds | ||
Impatient early adopters can try the experimental zx versions. But keep in mind: these builds are ⚠️️ __unstable__ in every sense. | ||
```bash | ||
npm i zx@dev | ||
npx zx@dev --install --quiet <<< 'import _ from "lodash" /* 4.17.15 */; console.log(_.VERSION)' | ||
``` | ||
## License | ||
@@ -531,0 +576,0 @@ |
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
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
75011
21
1502
577
2
+ Addednode-fetch@3.2.10(transitive)
- Removednode-fetch@3.2.8(transitive)
Updated@types/node@^18.7.20
Updatednode-fetch@3.2.10