Commit 8c2aea8
Changed files (23)
src/context.mjs → src/context.ts
@@ -14,20 +14,20 @@
import { AsyncLocalStorage } from 'node:async_hooks'
-let root
+let root: any
-const storage = new AsyncLocalStorage()
+const storage = new AsyncLocalStorage<any>()
export function getCtx() {
return storage.getStore()
}
-export function setRootCtx(ctx) {
+export function setRootCtx(ctx: any) {
storage.enterWith(ctx)
root = ctx
}
export function getRootCtx() {
return root
}
-export function runInCtx(ctx, cb) {
+export function runInCtx(ctx: any, cb: any) {
return storage.run(ctx, cb)
}
src/core.mjs → src/core.ts
@@ -12,24 +12,44 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import { ChalkInstance } from 'chalk'
+import {
+ ChildProcessByStdio,
+ SpawnOptionsWithStdioTuple,
+ StdioPipe,
+} from 'child_process'
+import { Readable, Writable } from 'node:stream'
import { inspect, promisify } from 'node:util'
import { spawn } from 'node:child_process'
-import { chalk, which } from './goods.mjs'
-import { getCtx, runInCtx, setRootCtx } from './context.mjs'
-import { printStd, printCmd } from './print.mjs'
-import { formatCmd, quote } from './guards.mjs'
+import { chalk, which } from './goods.js'
+import { getCtx, runInCtx, setRootCtx } from './context.js'
+import { printStd, printCmd } from './print.js'
+import { quote, substitute } from './guards.js'
import psTreeModule from 'ps-tree'
const psTree = promisify(psTreeModule)
-export function $(...args) {
+export function $(pieces: TemplateStringsArray, ...args: any[]) {
let resolve, reject
let promise = new ProcessPromise((...args) => ([resolve, reject] = args))
+ let cmd = pieces[0],
+ i = 0
+ let quote = getCtx().quote
+ while (i < args.length) {
+ let s
+ if (Array.isArray(args[i])) {
+ s = args[i].map((x: any) => quote(substitute(x))).join(' ')
+ } else {
+ s = quote(substitute(args[i]))
+ }
+ cmd += s + pieces[++i]
+ }
+
promise.ctx = {
...getCtx(),
- cmd: formatCmd(...args),
- __from: new Error().stack.split(/^\s*at\s/m)[2].trim(),
+ cmd,
+ __from: new Error().stack!.split(/^\s*at\s/m)[2].trim(),
resolve,
reject,
}
@@ -53,29 +73,50 @@ try {
$.prefix = 'set -euo pipefail;'
} catch (e) {}
-export class ProcessPromise extends Promise {
- child = undefined
+type Options = {
+ nothrow: boolean
+ verbose: boolean
+ cmd: string
+ cwd: string
+ env: NodeJS.ProcessEnv
+ prefix: string
+ shell: string
+ maxBuffer: number
+ __from: string
+ resolve: any
+ reject: any
+}
+
+export class ProcessPromise extends Promise<ProcessOutput> {
+ child?: ChildProcessByStdio<Writable, Readable, Readable>
_resolved = false
_inheritStdin = true
_piped = false
- _prerun = undefined
- _postrun = undefined
+ _prerun: any = undefined
+ _postrun: any = undefined
+ ctx?: Options
get stdin() {
this._inheritStdin = false
this._run()
+ if (!this.child)
+ throw new Error('Access to stdin without creation a subprocess.')
return this.child.stdin
}
get stdout() {
this._inheritStdin = false
this._run()
+ if (!this.child)
+ throw new Error('Access to stdout without creation a subprocess.')
return this.child.stdout
}
get stderr() {
this._inheritStdin = false
this._run()
+ if (!this.child)
+ throw new Error('Access to stderr without creation a subprocess.')
return this.child.stderr
}
@@ -86,11 +127,11 @@ export class ProcessPromise extends Promise {
)
}
- pipe(dest) {
+ pipe(dest: Writable | ProcessPromise | string) {
if (typeof dest === 'string') {
throw new Error('The pipe() method does not take strings. Forgot $?')
}
- if (this._resolved === true) {
+ if (this._resolved) {
throw new Error(
"The pipe() method shouldn't be called after promise is already resolved!"
)
@@ -99,7 +140,13 @@ export class ProcessPromise extends Promise {
if (dest instanceof ProcessPromise) {
dest._inheritStdin = false
dest._prerun = this._run.bind(this)
- dest._postrun = () => this.stdout.pipe(dest.child.stdin)
+ dest._postrun = () => {
+ if (!dest.child)
+ throw new Error(
+ 'Access to stdin of pipe destination without creation a subprocess.'
+ )
+ this.stdout.pipe(dest.child.stdin)
+ }
return dest
} else {
this._postrun = () => this.stdout.pipe(dest)
@@ -109,10 +156,13 @@ export class ProcessPromise extends Promise {
async kill(signal = 'SIGTERM') {
this.catch((_) => _)
+ if (!this.child)
+ throw new Error('Trying to kill child process without creating one.')
+ if (!this.child.pid) throw new Error('Child process pid is undefined.')
let children = await psTree(this.child.pid)
for (const p of children) {
try {
- process.kill(p.PID, signal)
+ process.kill(+p.PID, signal)
} catch (e) {}
}
try {
@@ -136,18 +186,23 @@ export class ProcessPromise extends Promise {
__from,
resolve,
reject,
- } = this.ctx
+ } = this.ctx!
printCmd(cmd)
- let child = spawn(prefix + cmd, {
+ let options: SpawnOptionsWithStdioTuple<any, StdioPipe, StdioPipe> = {
cwd,
shell: typeof shell === 'string' ? shell : true,
stdio: [this._inheritStdin ? 'inherit' : 'pipe', 'pipe', 'pipe'],
windowsHide: true,
- maxBuffer,
+ // TODO: Surprise: maxBuffer have no effect for spawn.
+ // maxBuffer,
env,
- })
+ }
+ let child: ChildProcessByStdio<Writable, Readable, Readable> = spawn(
+ prefix + cmd,
+ options
+ )
child.on('close', (code, signal) => {
let message = `${stderr || '\n'} at ${__from}`
@@ -172,12 +227,12 @@ export class ProcessPromise extends Promise {
let stdout = '',
stderr = '',
combined = ''
- let onStdout = (data) => {
+ let onStdout = (data: any) => {
printStd(data)
stdout += data
combined += data
}
- let onStderr = (data) => {
+ let onStderr = (data: any) => {
printStd(null, data)
stderr += data
combined += data
@@ -191,13 +246,27 @@ export class ProcessPromise extends Promise {
}
export class ProcessOutput extends Error {
- #code = null
- #signal = null
+ #code: number | null = null
+ #signal: NodeJS.Signals | null = null
#stdout = ''
#stderr = ''
#combined = ''
- constructor({ code, signal, stdout, stderr, combined, message }) {
+ constructor({
+ code,
+ signal,
+ stdout,
+ stderr,
+ combined,
+ message,
+ }: {
+ code: number | null
+ signal: NodeJS.Signals | null
+ stdout: string
+ stderr: string
+ combined: string
+ message: string
+ }) {
super(message)
this.#code = code
this.#signal = signal
@@ -227,7 +296,8 @@ export class ProcessOutput extends Error {
}
[inspect.custom]() {
- let stringify = (s, c) => (s.length === 0 ? "''" : c(inspect(s)))
+ let stringify = (s: string, c: ChalkInstance) =>
+ s.length === 0 ? "''" : c(inspect(s))
return `ProcessOutput {
stdout: ${stringify(this.stdout, chalk.green)},
stderr: ${stringify(this.stderr, chalk.red)},
@@ -241,7 +311,7 @@ export class ProcessOutput extends Error {
}
}
-function exitCodeInfo(exitCode) {
+function exitCodeInfo(exitCode: number | null): string | undefined {
return {
2: 'Misuse of shell builtins',
126: 'Invoked command cannot execute',
@@ -275,5 +345,5 @@ function exitCodeInfo(exitCode) {
155: 'Profiling timer expired',
157: 'Pollable event',
159: 'Bad syscall',
- }[exitCode]
+ }[exitCode || -1]
}
src/experimental.mjs → src/experimental.ts
@@ -12,17 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import { ProcessOutput, $ } from './core.mjs'
-import { sleep } from './goods.mjs'
-import { isString } from './util.mjs'
-import { getCtx, runInCtx } from './context.mjs'
+import { ProcessOutput, $ } from './core.js'
+import { sleep } from './goods.js'
+import { isString } from './util.js'
+import { getCtx, runInCtx } from './context.js'
export { getCtx, runInCtx }
// Retries a command a few times. Will return after the first
// successful attempt, or will throw after specifies attempts count.
export function retry(count = 5, delay = 0) {
- return async function (cmd, ...args) {
+ return async function (cmd: TemplateStringsArray, ...args: any[]) {
while (count-- > 0)
try {
return await $(cmd, ...args)
@@ -30,12 +30,13 @@ export function retry(count = 5, delay = 0) {
if (count === 0) throw p
if (delay) await sleep(delay)
}
+ return
}
}
// Runs and sets a timeout for a cmd
-export function withTimeout(timeout, signal) {
- return async function (cmd, ...args) {
+export function withTimeout(timeout: number, signal: string) {
+ return async function (cmd: TemplateStringsArray, ...args: any[]) {
let p = $(cmd, ...args)
if (!timeout) return p
@@ -46,7 +47,7 @@ export function withTimeout(timeout, signal) {
}
// A console.log() alternative which can take ProcessOutput.
-export function echo(pieces, ...args) {
+export function echo(pieces: TemplateStringsArray, ...args: any[]) {
let msg
let lastIdx = pieces.length - 1
if (
@@ -62,7 +63,7 @@ export function echo(pieces, ...args) {
console.log(msg)
}
-function stringify(arg) {
+function stringify(arg: ProcessOutput | any) {
if (arg instanceof ProcessOutput) {
return arg.toString().replace(/\n$/, '')
}
src/globals.mjs
@@ -1,3 +0,0 @@
-import { registerGlobals } from './index.mjs'
-
-registerGlobals()
src/globals.ts
@@ -0,0 +1,3 @@
+import { registerGlobals } from './index.js'
+
+registerGlobals()
src/goods.mjs → src/goods.ts
@@ -15,9 +15,9 @@
import * as globbyModule from 'globby'
import minimist from 'minimist'
import { setTimeout as sleep } from 'node:timers/promises'
-import nodeFetch from 'node-fetch'
-import { getCtx, getRootCtx } from './context.mjs'
-import { colorize } from './print.mjs'
+import nodeFetch, { RequestInfo, RequestInit } from 'node-fetch'
+import { getCtx, getRootCtx } from './context.js'
+import { colorize } from './print.js'
export { default as chalk } from 'chalk'
export { default as fs } from 'fs-extra'
@@ -29,13 +29,17 @@ export { sleep }
export const argv = minimist(process.argv.slice(2))
-export const globby = Object.assign(function globby(...args) {
- return globbyModule.globby(...args)
-}, globbyModule)
+export const globby = Object.assign(function globby(
+ patterns: string | readonly string[],
+ options?: globbyModule.Options
+) {
+ return globbyModule.globby(patterns, options)
+},
+globbyModule)
export const glob = globby
-export async function fetch(url, init) {
+export async function fetch(url: RequestInfo, init?: RequestInit) {
if (getCtx().verbose) {
if (typeof init !== 'undefined') {
console.log('$', colorize(`fetch ${url}`), init)
@@ -46,7 +50,7 @@ export async function fetch(url, init) {
return nodeFetch(url, init)
}
-export function cd(path) {
+export function cd(path: string) {
if (getCtx().verbose) console.log('$', colorize(`cd ${path}`))
process.chdir(path)
getRootCtx().cwd = getCtx().cwd = process.cwd()
src/guards.mjs → src/guards.ts
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import { getCtx } from './context.mjs'
+import { getCtx } from './context.js'
+import { ProcessPromise } from './core.js'
-export function quote(arg) {
+export function quote(arg: string) {
if (/^[a-z0-9/_.-]+$/i.test(arg) || arg === '') {
return arg
}
@@ -33,24 +34,7 @@ export function quote(arg) {
)
}
-export function formatCmd(pieces, ...args) {
- let cmd = pieces[0],
- i = 0
- let quote = getCtx().quote
- while (i < args.length) {
- let s
- if (Array.isArray(args[i])) {
- s = args[i].map((x) => quote(substitute(x))).join(' ')
- } else {
- s = quote(substitute(args[i]))
- }
- cmd += s + pieces[++i]
- }
-
- return cmd
-}
-
-function substitute(arg) {
+export function substitute(arg: ProcessPromise | any) {
if (arg?.stdout) {
return arg.stdout.replace(/\n$/, '')
}
src/hooks.mjs → src/hooks.ts
@@ -12,12 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-export function nothrow(promise) {
- promise.ctx.nothrow = true
+import { ProcessPromise } from './core.js'
+
+export function nothrow(promise: ProcessPromise) {
+ promise.ctx!.nothrow = true
return promise
}
-export function quiet(promise) {
- promise.ctx.verbose = false
+export function quiet(promise: ProcessPromise) {
+ promise.ctx!.verbose = false
return promise
}
src/index.d.ts
@@ -1,151 +0,0 @@
-// Copyright 2021 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-declare module 'zx' {
- import { ChildProcess, spawn } from 'node:child_process'
- import { Readable, Writable } from 'node:stream'
- import * as _fs from 'fs-extra'
- import * as _globby from 'globby'
- import * as _os from 'node:os'
- import * as _path from 'node:path'
- import { ChalkInstance } from 'chalk'
- import * as _yaml from 'yaml'
- import _fetch from 'node-fetch'
- import { ParsedArgs } from 'minimist'
- import _which from 'which'
-
- export interface ZxTemplate {
- (
- pieces: TemplateStringsArray,
- ...args: any[]
- ): ProcessPromise<ProcessOutput>
- }
-
- interface $ extends ZxTemplate {
- verbose: boolean
- shell: string
- prefix: string
- quote: (input: string) => string
- spawn: typeof spawn
- maxBuffer?: number | undefined
- }
-
- export interface ProcessPromise<T> extends Promise<T> {
- child: ChildProcess
- readonly stdin: Writable
- readonly stdout: Readable
- readonly stderr: Readable
- readonly exitCode: Promise<number>
-
- pipe(
- dest: ProcessPromise<ProcessOutput> | Writable
- ): ProcessPromise<ProcessOutput>
-
- kill(signal?: string | number): Promise<void>
- }
-
- export class ProcessOutput {
- readonly exitCode: number | null
- readonly signal: NodeJS.Signals | null
- readonly stdout: string
- readonly stderr: string
-
- toString(): string
- }
-
- export type QuestionOptions = { choices: string[] }
-
- type cd = (path: string) => void
- type nothrow = (
- p: ProcessPromise<ProcessOutput>
- ) => ProcessPromise<ProcessOutput>
- type question = (query?: string, options?: QuestionOptions) => Promise<string>
- type sleep = (ms: number) => Promise<void>
- type quiet = (
- p: ProcessPromise<ProcessOutput>
- ) => ProcessPromise<ProcessOutput>
-
- export const $: $
- export const argv: ParsedArgs
- export const cd: cd
- export const chalk: ChalkInstance
- export const fetch: typeof _fetch
- export const YAML: typeof _yaml
- export const fs: typeof _fs
- export const glob: typeof _globby.globby & typeof _globby
- export const globby: typeof _globby.globby & typeof _globby
- export const nothrow: nothrow
- export const os: typeof _os
- export const path: typeof _path
- export const question: question
- export const sleep: sleep
- export const quiet: quiet
- export const which: typeof _which
-}
-
-declare module 'zx/globals' {
- import {
- $,
- argv as _argv,
- cd,
- chalk as _chalk,
- fetch as _fetch,
- fs as _fs,
- globby as _globby,
- nothrow,
- os as _os,
- path as _path,
- question,
- sleep,
- which as _which,
- } from 'zx'
-
- global {
- var $: $
- var argv: typeof _argv
- var cd: cd
- var chalk: typeof _chalk
- // @ts-ignore
- var fetch: typeof _fetch
- var fs: typeof _fs
- var globby: typeof _globby.globby & typeof _globby
- var glob: typeof _globby.globby & typeof _globby
- var nothrow: nothrow
- var os: typeof _os
- var path: typeof _path
- var question: question
- var sleep: sleep
- var which: typeof _which
- }
-}
-
-declare module 'zx/experimental' {
- import { ZxTemplate } from 'zx'
-
- interface Echo {
- (pieces: TemplateStringsArray, ...args: any[]): void
- (...args: any[]): void
- }
- export const echo: Echo
-
- export const retry: (count?: number, delay?: number) => ZxTemplate
-
- export const withTimeout: (
- delay?: number,
- signal?: string | number
- ) => ZxTemplate
-
- type StopSpinner = () => void
- export function startSpinner(title: string): StopSpinner
-}
src/index.mjs → src/index.ts
@@ -25,10 +25,10 @@ import {
which,
YAML,
os,
-} from './goods.mjs'
-import { nothrow, quiet } from './hooks.mjs'
-import { question } from './question.mjs'
-import { $, ProcessPromise, ProcessOutput } from './core.mjs'
+} from './goods.js'
+import { nothrow, quiet } from './hooks.js'
+import { question } from './question.js'
+import { $, ProcessPromise, ProcessOutput } from './core.js'
export {
$,
src/print.mjs → src/print.ts
@@ -12,10 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import { getCtx } from './context.mjs'
-import { chalk } from './goods.mjs'
+import { getCtx } from './context.js'
+import { chalk } from './goods.js'
-export function printCmd(cmd) {
+export function printCmd(cmd: string) {
if (!getCtx()?.verbose) return
if (/\n/.test(cmd)) {
console.log(
@@ -29,13 +29,13 @@ export function printCmd(cmd) {
}
}
-export function printStd(data, err) {
+export function printStd(data: any, err?: any) {
if (!getCtx()?.verbose) return
if (data) process.stdout.write(data)
if (err) process.stderr.write(err)
}
-export function colorize(cmd) {
+export function colorize(cmd: string) {
return cmd.replace(/^[\w_.-]+(\s|$)/, (substr) => {
return chalk.greenBright(substr)
})
src/question.mjs → src/question.ts
@@ -14,10 +14,10 @@
import { createInterface } from 'node:readline'
-export async function question(query, options) {
+export async function question(query: string, options: { choices: string[] }) {
let completer = undefined
if (Array.isArray(options?.choices)) {
- completer = function completer(line) {
+ completer = function completer(line: string) {
const completions = options.choices
const hits = completions.filter((c) => c.startsWith(line))
return [hits.length ? hits : completions, line]
src/util.mjs → src/util.ts
@@ -12,10 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-export const randomId = function () {
+export function randomId() {
return Math.random().toString(36).slice(2)
}
-export function isString(obj) {
+export function isString(obj: any) {
return typeof obj === 'string'
}
test/experimental.test.mjs → test/experimental.test.js
@@ -12,8 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import { echo, retry, startSpinner, withTimeout } from '../src/experimental.mjs'
-import { assert, testFactory } from './test-utils.mjs'
+import {
+ echo,
+ retry,
+ startSpinner,
+ withTimeout,
+} from '../build/experimental.js'
+import { assert, testFactory } from './test-utils.js'
import chalk from 'chalk'
const test = testFactory('experimental', import.meta)
test/full.test.mjs → test/full.test.js
@@ -12,6 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import './zx.test.mjs'
-import './index.test.mjs'
-import './experimental.test.mjs'
+import './zx.test.js'
+import './index.test.js'
+import './experimental.test.js'
test/index.test.mjs → test/index.test.js
@@ -17,9 +17,9 @@ import chalk from 'chalk'
import { Writable } from 'node:stream'
import { Socket } from 'node:net'
-import { assert, testFactory } from './test-utils.mjs'
-import { ProcessPromise } from '../src/index.mjs'
-import { getCtx, runInCtx } from '../src/context.mjs'
+import { assert, testFactory } from './test-utils.js'
+import { ProcessPromise } from '../build/index.js'
+import { getCtx, runInCtx } from '../build/context.js'
const test = testFactory('index', import.meta)
@@ -82,7 +82,7 @@ test('The toString() is called on arguments', async () => {
test('Can use array as an argument', async () => {
try {
- let files = ['./zx.mjs', './test/index.test.mjs']
+ let files = ['./zx.js', './test/index.test.js']
await $`tar czf archive ${files}`
} finally {
await $`rm archive`
@@ -248,7 +248,7 @@ test('Executes a script from $PATH', async () => {
const toPOSIXPath = (_path) => _path.split(path.sep).join(path.posix.sep)
- const zxPath = path.resolve('./zx.mjs')
+ const zxPath = path.resolve('./zx.js')
const zxLocation = isWindows ? toPOSIXPath(zxPath) : zxPath
const scriptCode = `#!/usr/bin/env ${zxLocation}\nconsole.log('The script from path runs.')`
test/test-utils.mjs → test/test-utils.js
File renamed without changes
test/zx.test.mjs → test/zx.test.js
@@ -12,19 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import { assert, testFactory } from './test-utils.mjs'
+import { assert, testFactory } from './test-utils.js'
const test = testFactory('zx', import.meta)
test('supports `-v` flag / prints version', async () => {
- let v = (await $`node zx.mjs -v`).toString().trim()
+ let v = (await $`node zx.js -v`).toString().trim()
assert.equal(v, require('../package.json').version)
})
test('prints help', async () => {
let help
try {
- await $`node zx.mjs`
+ await $`node zx.js`
} catch (err) {
help = err.toString().trim()
}
@@ -32,37 +32,37 @@ test('prints help', async () => {
})
test('supports `--experimental` flag', async () => {
- await $`echo 'echo("test")' | node zx.mjs --experimental`
+ await $`echo 'echo("test")' | node zx.js --experimental`
})
test('supports `--quiet` flag / Quiet mode is working', async () => {
- let p = await $`node zx.mjs --quiet docs/markdown.md`
+ let p = await $`node zx.js --quiet docs/markdown.md`
assert(!p.stdout.includes('whoami'))
})
test('supports `--shell` flag ', async () => {
let shell = $.shell
- let p = await $`node zx.mjs --shell=${shell} <<< '$\`echo \${$.shell}\`'`
+ let p = await $`node zx.js --shell=${shell} <<< '$\`echo \${$.shell}\`'`
assert(p.stdout.includes(shell))
})
test('supports `--prefix` flag ', async () => {
let prefix = 'set -e;'
- let p = await $`node zx.mjs --prefix=${prefix} <<< '$\`echo \${$.prefix}\`'`
+ let p = await $`node zx.js --prefix=${prefix} <<< '$\`echo \${$.prefix}\`'`
assert(p.stdout.includes(prefix))
})
test('Eval script from https ref', async () => {
let script = path.resolve('test/fixtures/echo.http')
let server = quiet($`while true; do cat ${script} | nc -l 8080; done`)
- let p = await quiet($`node zx.mjs http://127.0.0.1:8080/echo.mjs`)
+ let p = await quiet($`node zx.js http://127.0.0.1:8080/echo.mjs`)
assert(p.stdout.includes('test'))
server.kill()
let err
try {
- await quiet($`node zx.mjs http://127.0.0.1:8081/echo.mjs`)
+ await quiet($`node zx.js http://127.0.0.1:8081/echo.mjs`)
} catch (e) {
err = e
}
@@ -70,7 +70,7 @@ test('Eval script from https ref', async () => {
})
test('Scripts with no extension', async () => {
- await $`node zx.mjs test/fixtures/no-extension`
+ await $`node zx.js test/fixtures/no-extension`
assert.match(
(await fs.readFile('test/fixtures/no-extension.mjs')).toString(),
/Test file to verify no-extension didn't overwrite similarly name .mjs file./
@@ -78,9 +78,9 @@ test('Scripts with no extension', async () => {
})
test('The require() is working from stdin', async () => {
- await $`node zx.mjs <<< 'require("./package.json").name'`
+ await $`node zx.js <<< 'require("./package.json").name'`
})
test('Markdown scripts are working', async () => {
- await $`node zx.mjs docs/markdown.md`
+ await $`node zx.js docs/markdown.md`
})
.gitignore
@@ -1,4 +1,5 @@
/node_modules/
+/build/
+/coverage/
package-lock.json
yarn.lock
-coverage
.prettierignore
@@ -1,5 +1,6 @@
/node_modules/
+/build/
+/coverage/
package-lock.json
yarn.lock
-coverage
*.md
package.json
@@ -2,26 +2,28 @@
"name": "zx",
"version": "6.1.0",
"description": "A tool for writing better scripts.",
- "main": "src/index.mjs",
+ "type": "module",
+ "main": "build/index.js",
"types": "src/index.d.ts",
"exports": {
- ".": "./src/index.mjs",
- "./globals": "./src/globals.mjs",
- "./experimental": "./src/experimental.mjs",
- "./cli": "./zx.mjs",
- "./core": "./src/core.mjs",
+ ".": "./build/index.js",
+ "./globals": "./build/globals.js",
+ "./experimental": "./build/experimental.js",
+ "./cli": "./zx.js",
+ "./core": "./build/core.js",
"./package.json": "./package.json"
},
"bin": {
- "zx": "zx.mjs"
+ "zx": "zx.js"
},
"engines": {
"node": ">= 16.0.0"
},
"scripts": {
"fmt": "prettier --write .",
- "test": "npm run test:unit",
- "test:unit": "node zx.mjs test/full.test.mjs",
+ "build": "tsc",
+ "test": "tsc && npm run test:unit",
+ "test:unit": "node zx.js test/full.test.js",
"test:cov": "c8 --reporter=html npm run test:unit",
"test:zx": "npm run test zx",
"test:index": "npm run test index"
@@ -30,6 +32,7 @@
"@types/fs-extra": "^9.0.13",
"@types/minimist": "^1.2.2",
"@types/node": "^17.0",
+ "@types/ps-tree": "^1.1.2",
"@types/which": "^2.0.1",
"chalk": "^5.0.1",
"fs-extra": "^10.1.0",
@@ -42,7 +45,8 @@
},
"devDependencies": {
"c8": "^7.11.2",
- "prettier": "^2.6.2"
+ "prettier": "^2.6.2",
+ "typescript": "^4.8.0-dev.20220529"
},
"publishConfig": {
"registry": "https://wombat-dressing-room.appspot.com"
tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "target": "ES2021",
+ "lib": ["ES2021"],
+ "module": "nodenext",
+ "strict": true,
+ "noImplicitReturns": true,
+ "noFallthroughCasesInSwitch": true,
+ "outDir": "./build",
+ "declaration": true
+ },
+ "include": ["./src/**/*"]
+}
zx.mjs → zx.js
@@ -20,8 +20,14 @@ import { tmpdir } from 'node:os'
import { basename, dirname, extname, join, resolve } from 'node:path'
import url from 'node:url'
-import { $, argv, fetch, ProcessOutput, registerGlobals } from './src/index.mjs'
-import { randomId } from './src/util.mjs'
+import {
+ $,
+ argv,
+ fetch,
+ ProcessOutput,
+ registerGlobals,
+} from './build/index.js'
+import { randomId } from './build/util.js'
await (async function main() {
registerGlobals()
@@ -33,7 +39,7 @@ await (async function main() {
$.prefix = argv.prefix
}
if (argv.experimental) {
- Object.assign(global, await import('./src/experimental.mjs'))
+ Object.assign(global, await import('./build/experimental.js'))
}
try {
if (['--version', '-v', '-V'].includes(process.argv[2])) {