Commit c9d6511
Changed files (20)
build/goods.d.ts
@@ -4,6 +4,7 @@ import { type Mode } from 'node:fs';
import { type ProcessPromise } from './core.js';
import { type Duration } from './util.js';
import { type RequestInfo, type RequestInit, minimist } from './vendor.js';
+export { versions } from './versions.js';
export declare function tempdir(prefix?: string, mode?: Mode): string;
export declare function tempfile(name?: string, data?: string | Buffer, mode?: Mode): string;
export { tempdir as tmpdir, tempfile as tmpfile };
build/index.cjs
@@ -9,27 +9,21 @@ const {
__forAwait
} = require('./esblib.cjs');
-const import_meta_url =
- typeof document === 'undefined'
- ? new (require('url').URL)('file:' + __filename).href
- : (document.currentScript && document.currentScript.src) ||
- new URL('main.js', document.baseURI).href
-
// src/index.ts
var index_exports = {};
__export(index_exports, {
VERSION: () => VERSION,
- YAML: () => import_vendor3.YAML,
+ YAML: () => import_vendor2.YAML,
argv: () => argv,
- dotenv: () => import_vendor3.dotenv,
+ dotenv: () => import_vendor2.dotenv,
echo: () => echo,
expBackoff: () => expBackoff,
fetch: () => fetch,
- fs: () => import_vendor3.fs,
- glob: () => import_vendor3.glob,
- globby: () => import_vendor3.glob,
- minimist: () => import_vendor3.minimist,
+ fs: () => import_vendor2.fs,
+ glob: () => import_vendor2.glob,
+ globby: () => import_vendor2.glob,
+ minimist: () => import_vendor2.minimist,
nothrow: () => nothrow,
parseArgv: () => parseArgv,
question: () => question,
@@ -43,11 +37,10 @@ __export(index_exports, {
tmpdir: () => tempdir,
tmpfile: () => tempfile,
updateArgv: () => updateArgv,
- version: () => version
+ version: () => version,
+ versions: () => versions
});
module.exports = __toCommonJS(index_exports);
-var import_vendor2 = require("./vendor.cjs");
-__reExport(index_exports, require("./core.cjs"), module.exports);
// src/goods.ts
var import_node_buffer = require("buffer");
@@ -57,6 +50,23 @@ var import_node_stream = require("stream");
var import_core = require("./core.cjs");
var import_util = require("./util.cjs");
var import_vendor = require("./vendor.cjs");
+
+// src/versions.ts
+var versions = {
+ zx: "8.7.2",
+ chalk: "5.4.1",
+ depseek: "0.4.1",
+ dotenv: "0.2.3",
+ fetch: "1.6.6",
+ fs: "11.3.0",
+ glob: "14.1.0",
+ minimist: "1.2.8",
+ ps: "0.1.4",
+ which: "5.0.0",
+ yaml: "2.8.0"
+};
+
+// src/goods.ts
function tempdir(prefix = `zx-${(0, import_util.randomId)()}`, mode) {
const dirpath = import_core.path.join(import_core.os.tmpdir(), prefix);
import_vendor.fs.mkdirSync(dirpath, { recursive: true, mode });
@@ -89,8 +99,8 @@ function sleep(duration) {
});
}
var responseToReadable = (response, rs) => {
- var _a2;
- const reader = (_a2 = response.body) == null ? void 0 : _a2.getReader();
+ var _a;
+ const reader = (_a = response.body) == null ? void 0 : _a.getReader();
if (!reader) {
rs.push(null);
return rs;
@@ -113,12 +123,12 @@ function fetch(url, init) {
})(dest, ...args) : dest;
p.then(
(r) => {
- var _a2;
- return responseToReadable(r, rs).pipe((_a2 = _dest.run) == null ? void 0 : _a2.call(_dest));
+ var _a;
+ return responseToReadable(r, rs).pipe((_a = _dest.run) == null ? void 0 : _a.call(_dest));
},
(err) => {
- var _a2;
- return (_a2 = _dest.abort) == null ? void 0 : _a2.call(_dest, err);
+ var _a;
+ return (_a = _dest.abort) == null ? void 0 : _a.call(_dest, err);
}
);
return _dest;
@@ -239,12 +249,9 @@ function spinner(title, callback) {
}
// src/index.ts
-var import_vendor3 = require("./vendor.cjs");
-var import_meta = {};
-var _a;
-var VERSION = ((_a = import_vendor2.fs.readJsonSync(new URL("../package.json", import_meta_url), {
- throws: false
-})) == null ? void 0 : _a.version) || URL.parse(import_meta_url).pathname.split("/")[3];
+__reExport(index_exports, require("./core.cjs"), module.exports);
+var import_vendor2 = require("./vendor.cjs");
+var VERSION = versions.zx || "0.0.0";
var version = VERSION;
function nothrow(promise) {
return promise.nothrow();
@@ -280,5 +287,6 @@ function quiet(promise) {
tmpfile,
updateArgv,
version,
+ versions,
...require("./core.cjs")
});
\ No newline at end of file
build/index.d.ts
@@ -1,7 +1,7 @@
/// <reference types="node" />
/// <reference types="fs-extra" />
-import { ProcessPromise } from './core.js';
+import { type ProcessPromise } from './core.js';
export * from './core.js';
export * from './goods.js';
export { minimist, dotenv, fs, YAML, glob, glob as globby } from './vendor.js';
build/index.js
@@ -27,6 +27,7 @@ const {
tmpfile,
updateArgv,
version,
+ versions,
$,
Fail,
ProcessOutput,
@@ -75,6 +76,7 @@ export {
tmpfile,
updateArgv,
version,
+ versions,
$,
Fail,
ProcessOutput,
build/versions.d.ts
@@ -0,0 +1,1 @@
+export declare const versions: Record<string, string>;
docs/api.md
@@ -425,6 +425,16 @@ dotenv.config('.env')
process.env.FOO // BAR
```
+## `versions`
+Exports versions of the zx dependencies.
+
+```ts
+import { versions } from 'zx'
+
+versions.zx // 8.7.2
+versions.chalk // 5.4.1
+```
+
## `quote()`
Default bash quoting function.
scripts/build-js.mjs
@@ -59,10 +59,10 @@ const {
const formats = format.split(',')
const cwd = [_cwd].flat().pop()
const entries = entry.split(/:\s?/)
-const entryPoints = entry.includes('*')
- ? await glob(entries, { absolute: false, onlyFiles: true, cwd, root: cwd })
- : entries.map((p) => path.relative(cwd, path.resolve(cwd, p)))
-
+const entryPoints =
+ entry.includes('*') || entry.includes('{')
+ ? await glob(entries, { absolute: false, onlyFiles: true, cwd, root: cwd })
+ : entries.map((p) => path.relative(cwd, path.resolve(cwd, p)))
const _bundle = bundle && bundle !== 'none'
const _external = ['zx/globals', ...(_bundle ? external.split(',') : [])] // https://github.com/evanw/esbuild/issues/1466
scripts/build-versions.mjs
@@ -0,0 +1,78 @@
+#!/usr/bin/env node
+
+// Copyright 2025 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.
+
+import fs from 'fs-extra'
+import path from 'node:path'
+import minimist from 'minimist'
+
+const root = path.resolve(new URL(import.meta.url).pathname, '../..')
+const copyright = await fs.readFileSync(
+ path.resolve(root, 'test/fixtures/copyright.txt'),
+ 'utf8'
+)
+const deps = [
+ 'chalk',
+ 'depseek',
+ 'dotenv',
+ 'fetch',
+ 'fs',
+ 'glob',
+ 'minimist',
+ 'ps',
+ 'which',
+ 'yaml',
+]
+const namemap = {
+ dotenv: 'envapi',
+ fs: 'fs-extra',
+ fetch: 'node-fetch-native',
+ glob: 'globby',
+ ps: '@webpod/ps',
+}
+const versions = deps.reduce(
+ (m, name) => {
+ m[name] = fs.readJsonSync(
+ path.resolve(root, 'node_modules', namemap[name] || name, 'package.json')
+ ).version
+ return m
+ },
+ {
+ zx: fs.readJsonSync(path.join(root, 'package.json')).version,
+ }
+)
+
+const argv = minimist(process.argv.slice(2), {
+ default: versions,
+ string: ['zx', ...deps],
+})
+
+delete argv._
+
+const list = JSON.stringify(argv, null, 2)
+ .replaceAll(' "', ' ')
+ .replaceAll('": ', ': ')
+ .replaceAll('"', "'")
+ .replace(/\n}$/, ',\n}')
+
+const versionsTs = `${copyright.replace('YEAR', new Date().getFullYear())}
+export const versions: Record<string, string> = ${list}
+`
+const versionsCjs = `${copyright.replace('YEAR', new Date().getFullYear())}
+module.exports = { versions: ${list}
+`
+
+fs.writeFileSync(path.join(root, 'src/versions.ts'), versionsTs, 'utf8')
+// fs.writeFileSync(path.join(root, 'build/versions.cjs'), versionsCjs, 'utf8')
scripts/prepublish-lite.mjs
@@ -48,7 +48,9 @@ const pkgJson = {
'build/core.js',
'build/core.d.ts',
'build/deno.js',
+ 'build/error.d.ts',
'build/esblib.cjs',
+ 'build/log.d.ts',
'build/util.cjs',
'build/util.js',
'build/util.d.ts',
src/goods.ts
@@ -44,6 +44,8 @@ import {
fs,
} from './vendor.ts'
+export { versions } from './versions.ts'
+
export function tempdir(
prefix: string = `zx-${randomId()}`,
mode?: Mode
src/index.ts
@@ -12,18 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import { ProcessPromise } from './core.ts'
-import { fs } from './vendor.ts'
+import { type ProcessPromise } from './core.ts'
+import { versions } from './goods.ts'
export * from './core.ts'
export * from './goods.ts'
export { minimist, dotenv, fs, YAML, glob, glob as globby } from './vendor.ts'
-export const VERSION: string =
- fs.readJsonSync(new URL('../package.json', import.meta.url), {
- throws: false,
- })?.version || URL.parse(import.meta.url)!.pathname.split('/')[3] // extracts version from JSR url
-
+export const VERSION: string = versions.zx || '0.0.0'
export const version: string = VERSION
/**
src/versions.ts
@@ -0,0 +1,27 @@
+// Copyright 2025 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.
+
+export const versions: Record<string, string> = {
+ zx: '8.7.2',
+ chalk: '5.4.1',
+ depseek: '0.4.1',
+ dotenv: '0.2.3',
+ fetch: '1.6.6',
+ fs: '11.3.0',
+ glob: '14.1.0',
+ minimist: '1.2.8',
+ ps: '0.1.4',
+ which: '5.0.0',
+ yaml: '2.8.0',
+}
test/it/build-npm.test.js
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import { tempdir, $, path, fs } from '../../build/index.js'
+import { tempdir, $, path, fs, version } from '../../build/index.js'
import assert from 'node:assert'
import { describe, before, after, it } from 'node:test'
@@ -28,6 +28,7 @@ describe('npm artifact', () => {
name: 'zx-test',
dependencies: {
typescript: '^5',
+ esbuild: '^0.25.8',
'@types/node': '*',
'@types/fs-extra': '*',
},
@@ -50,17 +51,12 @@ describe('npm artifact', () => {
after(() => fs.remove(tmp))
- it('looks buildable with tsc', async () => {
- const indexTs = `import {$} from 'zx'
-(async () => {
- await $({verbose: true, stdio: 'pipe'})\`echo hello\`
-})()
-`
+ it('buildable with tsc', async () => {
const tsconfig = {
compilerOptions: {
module: 'commonjs',
target: 'esnext',
- outDir: 'build-tsc',
+ outDir: 'bundle',
rootDir: 'src',
declaration: true,
declarationMap: false,
@@ -68,12 +64,29 @@ describe('npm artifact', () => {
},
include: ['src'],
}
-
+ const indexTs = `import {$} from 'zx'
+(async () => {
+ await $({verbose: true})\`echo hello\`
+})()
+`
await fs.outputJSON(path.resolve(tmp, 'tsconfig.json'), tsconfig)
await fs.outputFile(path.resolve(tmp, 'src/index.ts'), indexTs)
+
await t$`tsc`
- const result = await t$`node build-tsc/index.js`.text()
+ const out = await t$`node bundle/index.js`.text()
+ assert.strictEqual(out, '$ echo hello\nhello\n')
+ })
+
+ it('compilable with esbuild (iife)', async () => {
+ const verJs = `import {version, $} from 'zx'
+(async () => {
+ await $({verbose: true})\`echo \${version}\`
+})()
+`
+ await fs.outputFile(path.resolve(tmp, 'src/ver.js'), verJs)
- assert.strictEqual(result, '$ echo hello\nhello\n')
+ await t$`npx esbuild src/ver.js --bundle --format=iife --platform=node > bundle/ver.js`
+ const out = await t$`node bundle/ver.js`.text()
+ assert.strictEqual(out, `$ echo ${version}\n${version}\n`)
})
})
test/export.test.js
@@ -472,6 +472,18 @@ describe('index', () => {
assert.equal(typeof index.usePowerShell, 'function', 'index.usePowerShell')
assert.equal(typeof index.usePwsh, 'function', 'index.usePwsh')
assert.equal(typeof index.version, 'string', 'index.version')
+ assert.equal(typeof index.versions, 'object', 'index.versions')
+ assert.equal(typeof index.versions.chalk, 'string', 'index.versions.chalk')
+ assert.equal(typeof index.versions.depseek, 'string', 'index.versions.depseek')
+ assert.equal(typeof index.versions.dotenv, 'string', 'index.versions.dotenv')
+ assert.equal(typeof index.versions.fetch, 'string', 'index.versions.fetch')
+ assert.equal(typeof index.versions.fs, 'string', 'index.versions.fs')
+ assert.equal(typeof index.versions.glob, 'string', 'index.versions.glob')
+ assert.equal(typeof index.versions.minimist, 'string', 'index.versions.minimist')
+ assert.equal(typeof index.versions.ps, 'string', 'index.versions.ps')
+ assert.equal(typeof index.versions.which, 'string', 'index.versions.which')
+ assert.equal(typeof index.versions.yaml, 'string', 'index.versions.yaml')
+ assert.equal(typeof index.versions.zx, 'string', 'index.versions.zx')
assert.equal(typeof index.which, 'function', 'index.which')
assert.equal(typeof index.which.sync, 'function', 'index.which.sync')
assert.equal(typeof index.within, 'function', 'index.within')
test/goods.test.ts
@@ -32,6 +32,7 @@ import {
tempdir,
tmpdir,
tmpfile,
+ versions,
} from '../src/goods.ts'
import { Writable } from 'node:stream'
import process from 'node:process'
@@ -464,4 +465,25 @@ ENV5=v5 # comment
assert.equal(fs.readFileSync(tf, 'utf-8'), 'bar')
})
})
+
+ describe('versions', () => {
+ test('exports deps versions', () => {
+ assert.deepEqual(
+ Object.keys(versions).sort(),
+ [
+ 'chalk',
+ 'depseek',
+ 'dotenv',
+ 'fetch',
+ 'fs',
+ 'glob',
+ 'minimist',
+ 'ps',
+ 'which',
+ 'yaml',
+ 'zx',
+ ].sort()
+ )
+ })
+ })
})
test/index.test.js
@@ -17,6 +17,7 @@ import { describe, test } from 'node:test'
import {
nothrow,
quiet,
+ versions,
version,
VERSION,
$,
@@ -67,6 +68,7 @@ describe('index', () => {
assert(nothrow)
assert(quiet)
assert(version)
+ assert(versions)
assert.equal(version, VERSION)
// core
test/package.test.js
@@ -66,6 +66,7 @@ describe('package', () => {
'build/md.d.ts',
'build/util.cjs',
'build/util.d.ts',
+ 'build/versions.d.ts',
'build/vendor-core.cjs',
'build/vendor-core.d.ts',
'build/vendor-extra.cjs',
.size-limit.json
@@ -29,14 +29,14 @@
"build/globals.js",
"build/deno.js"
],
- "limit": "813.75 kB",
+ "limit": "813.60 kB",
"brotli": false,
"gzip": false
},
{
"name": "libdefs",
"path": "build/*.d.ts",
- "limit": "40.25 kB",
+ "limit": "40.35 kB",
"brotli": false,
"gzip": false
},
@@ -62,7 +62,7 @@
"README.md",
"LICENSE"
],
- "limit": "870.85 kB",
+ "limit": "870.80 kB",
"brotli": false,
"gzip": false
}
package.json
@@ -70,9 +70,10 @@
"fmt": "prettier --write .",
"fmt:check": "prettier --check .",
"prebuild": "rm -rf build",
- "build": "npm run build:js && npm run build:dts && npm run build:tests",
- "build:js": "node scripts/build-js.mjs --format=cjs --hybrid --entry=src/*.ts:!src/error.ts:!src/repl.ts:!src/md.ts:!src/log.ts:!src/globals-jsr.ts:!src/goods.ts && npm run build:vendor",
+ "build": "npm run build:versions && npm run build:js && npm run build:dts && npm run build:tests",
+ "build:js": "node scripts/build-js.mjs --format=cjs --hybrid --entry='src/{cli,core,deps,globals,index,internals,util,vendor*}.ts' && npm run build:vendor",
"build:vendor": "node scripts/build-js.mjs --format=cjs --entry=src/vendor-*.ts --bundle=all --external='./internals.ts'",
+ "build:versions": "node scripts/build-versions.mjs",
"build:tests": "node scripts/build-tests.mjs",
"build:dts": "tsc --project tsconfig.json && rm build/repl.d.ts build/globals-jsr.d.ts && node scripts/build-dts.mjs",
"build:dcr": "docker build -f ./dcr/Dockerfile . -t zx",
tsconfig.json
@@ -10,6 +10,7 @@
"declaration": true,
"emitDeclarationOnly": true,
"allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
"types": ["node", "fs-extra"]
},
"include": ["./src/**/*"],