deployphp/node_modules/zx/build/cli.js

248 lines
7.9 KiB
JavaScript
Raw Permalink Normal View History

2023-01-10 15:49:41 +00:00
#!/usr/bin/env node
// 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.
import fs from 'fs-extra';
import minimist from 'minimist';
import { createRequire } from 'node:module';
import { basename, dirname, extname, join, resolve } from 'node:path';
import url from 'node:url';
import { updateArgv } from './goods.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)
$.verbose = false;
if (argv.shell)
$.shell = argv.shell;
if (argv.prefix)
$.prefix = argv.prefix;
if (argv.experimental) {
Object.assign(global, await import('./experimental.js'));
}
if (argv.version) {
console.log(getVersion());
return;
}
if (argv.help) {
printUsage();
return;
}
if (argv.repl) {
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)
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 require = createRequire(origin);
Object.assign(global, { __filename, __dirname, require });
await import(url.pathToFileURL(filepath).toString());
}
function transformMarkdown(buf) {
const source = buf.toString();
const output = [];
let state = 'root';
2023-03-28 15:15:22 +00:00
let codeBlockEnd = '';
2023-01-10 15:49:41 +00:00
let prevLineIsEmpty = true;
2023-03-28 15:15:22 +00:00
const jsCodeBlock = /^(```+|~~~+)(js|javascript)$/;
const shCodeBlock = /^(```+|~~~+)(sh|bash)$/;
const otherCodeBlock = /^(```+|~~~+)(.*)$/;
2023-01-10 15:49:41 +00:00
for (let line of source.split('\n')) {
switch (state) {
case 'root':
if (/^( {4}|\t)/.test(line) && prevLineIsEmpty) {
output.push(line);
state = 'tab';
}
2023-03-28 15:15:22 +00:00
else if (jsCodeBlock.test(line)) {
2023-01-10 15:49:41 +00:00
output.push('');
state = 'js';
2023-03-28 15:15:22 +00:00
codeBlockEnd = line.match(jsCodeBlock)[1];
2023-01-10 15:49:41 +00:00
}
2023-03-28 15:15:22 +00:00
else if (shCodeBlock.test(line)) {
2023-01-10 15:49:41 +00:00
output.push('await $`');
state = 'bash';
2023-03-28 15:15:22 +00:00
codeBlockEnd = line.match(shCodeBlock)[1];
2023-01-10 15:49:41 +00:00
}
2023-03-28 15:15:22 +00:00
else if (otherCodeBlock.test(line)) {
2023-01-10 15:49:41 +00:00
output.push('');
state = 'other';
2023-03-28 15:15:22 +00:00
codeBlockEnd = line.match(otherCodeBlock)[1];
2023-01-10 15:49:41 +00:00
}
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':
2023-03-28 15:15:22 +00:00
if (line === codeBlockEnd) {
2023-01-10 15:49:41 +00:00
output.push('');
state = 'root';
}
else {
output.push(line);
}
break;
case 'bash':
2023-03-28 15:15:22 +00:00
if (line === codeBlockEnd) {
2023-01-10 15:49:41 +00:00
output.push('`');
state = 'root';
}
else {
output.push(line);
}
break;
case 'other':
2023-03-28 15:15:22 +00:00
if (line === codeBlockEnd) {
2023-01-10 15:49:41 +00:00
output.push('');
state = 'root';
}
else {
output.push('// ' + line);
}
break;
}
}
return output.join('\n');
}
function getVersion() {
return createRequire(import.meta.url)('../package.json').version;
}