New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

zx

Package Overview
Dependencies
Maintainers
2
Versions
166
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

zx - npm Package Compare versions

Comparing version 7.1.0-dev.65d76da to 7.1.0-dev.6f7b331

184

build/cli.js

@@ -16,71 +16,89 @@ #!/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
--interactive, -i start repl
--eval=<js>, -e evaluate script
--experimental enable new api proposals
--install parse and load script dependencies from the registry
--version, -v print current zx version
--help, -h print help
`);
}
const argv = minimist(process.argv.slice(2), {
string: ['shell', 'prefix', 'eval'],
boolean: [
'version',
'help',
'quiet',
'install',
'interactive',
'experimental',
],
alias: { e: 'eval', i: 'interactive', 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) {
if (argv.interactive) {
startRepl();
return;
}
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)
startRepl();
}
return;
}
else if (firstArg.startsWith('http://') ||
firstArg.startsWith('https://')) {
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) => {

@@ -96,5 +114,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);
}

@@ -116,3 +133,3 @@ async function scriptFromStdin() {

async function scriptFromHttp(remote) {
let res = await fetch(remote);
const res = await fetch(remote);
if (!res.ok) {

@@ -122,32 +139,37 @@ 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) {
const contents = script.toString();
await fs.writeFile(filepath, contents);
if (argv.install) {
await installDeps(parseDeps(contents), dirname(filepath));
await fs.writeFile(filepath, script.toString());
try {
await importPath(filepath, origin);
}
let wait = importPath(filepath, origin);
await fs.rm(filepath);
await wait;
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));
console.log('Installing dependencies...', deps);
await installDeps(deps, dirname(filepath));
}
const __filename = resolve(origin);
const __dirname = dirname(__filename);
const require = createRequire(origin);
Object.assign(global, { __filename, __dirname, require });

@@ -157,4 +179,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';

@@ -232,21 +254,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
--install parse and load script dependencies from the registry
--version, -v print current zx version
--help, -h print help
`);
}

@@ -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;

@@ -62,0 +62,0 @@ while (i < args.length) {

@@ -1,2 +0,3 @@

export declare function installDeps(dependencies?: Record<string, any>, prefix?: string): Promise<void>;
export declare function parseDeps(content: string): Record<string, any>;
/// <reference types="node" resolution-mode="require"/>
export declare function installDeps(dependencies: Record<string, string>, prefix?: string): Promise<void>;
export declare function parseDeps(content: Buffer): Record<string, string>;

@@ -15,22 +15,98 @@ // Copyright 2021 Google LLC

import { $ } from './core.js';
export async function installDeps(dependencies = {}, prefix) {
const pkgs = Object.entries(dependencies).map(([name, version]) => `${name}@${version}`);
export async function installDeps(dependencies, prefix) {
const packages = Object.entries(dependencies).map(([name, version]) => `${name}@${version}`);
const flags = prefix ? `--prefix=${prefix}` : '';
if (pkgs.length === 0) {
if (packages.length === 0) {
return;
}
await $ `npm install --no-save --no-audit --no-fund ${flags} ${pkgs}`;
await $ `npm install --no-save --no-audit --no-fund ${flags} ${packages}`;
}
const builtinsRe = /^(_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|diagnostics_channel|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)$/;
const builtins = 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',
]);
const importRe = [
/\bimport\s+['"](?<path>[^'"]+)['"]/,
/\bimport\(['"](?<path>[^'"]+)['"]\)/,
/\brequire\(['"](?<path>[^'"]+)['"]\)/,
/\bfrom\s+['"](?<path>[^'"]+)['"]/,
];
const nameRe = /^(?<name>(@[a-z0-9-]+\/)?[a-z0-9-]+)\/?.*$/i;
const versionRe = /(\/\/|\/\*)\s*@(?<version>[~^]?([\dvx*]+([-.][\dx*]+)*))/i;
export function parseDeps(content) {
const re = /(?:\sfrom\s+|[\s(:\[](?:import|require)\s*\()["']((?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*)[/a-z0-9-._~]*["'](?:\s*;?\s*(?:\/\*|\/\/)\s*([a-z0-9-._~^*]+))?/g;
const deps = {};
let m;
do {
m = re.exec(content);
if (m && !builtinsRe.test(m[1])) {
deps[m[1]] = m[2] || 'latest';
const lines = content.toString().split('\n');
for (let line of lines) {
for (let re of importRe) {
const m1 = re.exec(line);
if (m1 && m1.groups) {
const m2 = nameRe.exec(m1.groups.path);
if (m2 && m2.groups) {
const name = m2.groups.name;
if (!builtins.has(name)) {
let version = 'latest';
const m3 = versionRe.exec(line);
if (m3 && m3.groups) {
version = m3.groups.version;
}
deps[name] = version;
}
}
}
}
} while (m);
}
return deps;
}

@@ -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) &&

{
"name": "zx",
"version": "7.1.0-dev.65d76da",
"version": "7.1.0-dev.6f7b331",
"description": "A tool for writing better scripts.",

@@ -72,3 +72,3 @@ "type": "module",

"prettier": "^2.7.1",
"tsd": "^0.24.0",
"tsd": "^0.24.1",
"typescript": "^4.8.3",

@@ -75,0 +75,0 @@ "uvu": "^0.5.6"

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc