main
  1#!/usr/bin/env node
  2"use strict";
  3const {
  4  __export,
  5  __toESM,
  6  __toCommonJS,
  7  __async
  8} = require('./esblib.cjs');
  9
 10const import_meta_url =
 11  typeof document === 'undefined'
 12    ? new (require('url').URL)('file:' + __filename).href
 13    : (document.currentScript && document.currentScript.src) ||
 14      new URL('main.js', document.baseURI).href
 15
 16
 17// src/cli.ts
 18var cli_exports = {};
 19__export(cli_exports, {
 20  argv: () => argv,
 21  injectGlobalRequire: () => injectGlobalRequire,
 22  isMain: () => isMain,
 23  main: () => main,
 24  normalizeExt: () => normalizeExt,
 25  printUsage: () => printUsage,
 26  transformMarkdown: () => transformMarkdown
 27});
 28module.exports = __toCommonJS(cli_exports);
 29var import_node_url = __toESM(require("url"), 1);
 30var import_node_process2 = __toESM(require("process"), 1);
 31var import_index = require("./index.cjs");
 32var import_deps = require("./deps.cjs");
 33
 34// src/repl.ts
 35var import_node_process = __toESM(require("process"), 1);
 36var import_node_repl = __toESM(require("repl"), 1);
 37var import_node_util = require("util");
 38var import_core = require("./core.cjs");
 39var _a;
 40var HISTORY = (_a = import_node_process.default.env.ZX_REPL_HISTORY) != null ? _a : import_core.path.join(import_core.os.homedir(), ".zx_repl_history");
 41function startRepl() {
 42  return __async(this, arguments, function* (history = HISTORY) {
 43    import_core.defaults.verbose = false;
 44    const r = import_node_repl.default.start({
 45      prompt: import_core.chalk.greenBright.bold("\u276F "),
 46      useGlobal: true,
 47      preview: false,
 48      writer(output) {
 49        return output instanceof import_core.ProcessOutput ? output.toString().trimEnd() : (0, import_node_util.inspect)(output, { colors: true });
 50      }
 51    });
 52    r.setupHistory(history, () => {
 53    });
 54  });
 55}
 56
 57// src/cli.ts
 58var import_util2 = require("./util.cjs");
 59
 60// src/md.ts
 61var import_util = require("./util.cjs");
 62function transformMarkdown(buf) {
 63  var _a2;
 64  const output = [];
 65  const tabRe = /^(  +|\t)/;
 66  const codeBlockRe = new RegExp("^(?<fence>(`{3,20}|~{3,20}))(?:(?<js>(js|javascript|ts|typescript))|(?<bash>(sh|shell|bash))|.*)$");
 67  let state = "root";
 68  let codeBlockEnd = "";
 69  let prevLineIsEmpty = true;
 70  for (const line of (0, import_util.bufToString)(buf).split(/\r?\n/)) {
 71    switch (state) {
 72      case "root":
 73        if (tabRe.test(line) && prevLineIsEmpty) {
 74          output.push(line);
 75          state = "tab";
 76          continue;
 77        }
 78        const { fence, js, bash } = ((_a2 = line.match(codeBlockRe)) == null ? void 0 : _a2.groups) || {};
 79        if (!fence) {
 80          prevLineIsEmpty = line === "";
 81          output.push("// " + line);
 82          continue;
 83        }
 84        codeBlockEnd = fence;
 85        if (js) {
 86          state = "js";
 87          output.push("");
 88        } else if (bash) {
 89          state = "bash";
 90          output.push("await $`");
 91        } else {
 92          state = "other";
 93          output.push("");
 94        }
 95        break;
 96      case "tab":
 97        if (line === "") {
 98          output.push("");
 99        } else if (tabRe.test(line)) {
100          output.push(line);
101        } else {
102          output.push("// " + line);
103          state = "root";
104        }
105        break;
106      case "js":
107        if (line === codeBlockEnd) {
108          output.push("");
109          state = "root";
110        } else {
111          output.push(line);
112        }
113        break;
114      case "bash":
115        if (line === codeBlockEnd) {
116          output.push("`");
117          state = "root";
118        } else {
119          output.push(line);
120        }
121        break;
122      case "other":
123        if (line === codeBlockEnd) {
124          output.push("");
125          state = "root";
126        } else {
127          output.push("// " + line);
128        }
129        break;
130    }
131  }
132  return output.join("\n");
133}
134
135// src/cli.ts
136var import_vendor = require("./vendor.cjs");
137var import_meta = {};
138var EXT = ".mjs";
139var EXT_RE = /^\.[mc]?[jt]sx?$/;
140var argv = (0, import_index.parseArgv)(import_node_process2.default.argv.slice(2), {
141  default: (0, import_index.resolveDefaults)({ ["prefer-local"]: false }, "ZX_", import_node_process2.default.env, /* @__PURE__ */ new Set(["env", "install", "registry"])),
142  // exclude 'prefer-local' to let minimist infer the type
143  string: ["shell", "prefix", "postfix", "eval", "cwd", "ext", "registry", "env"],
144  boolean: ["version", "help", "quiet", "verbose", "install", "repl", "experimental"],
145  alias: { e: "eval", i: "install", v: "version", h: "help", l: "prefer-local", "env-file": "env" },
146  stopEarly: true,
147  parseBoolean: true,
148  camelCase: true
149});
150isMain() && main().catch((err) => {
151  if (err instanceof import_index.ProcessOutput) {
152    console.error("Error:", err.message);
153  } else {
154    console.error(err);
155  }
156  import_node_process2.default.exitCode = 1;
157});
158function printUsage() {
159  console.log(`
160 ${import_index.chalk.bold("zx " + import_index.VERSION)}
161   A tool for writing better scripts
162
163 ${import_index.chalk.bold("Usage")}
164   zx [options] <script>
165
166 ${import_index.chalk.bold("Options")}
167   --quiet              suppress any outputs
168   --verbose            enable verbose mode
169   --shell=<path>       custom shell binary
170   --prefix=<command>   prefix all commands
171   --postfix=<command>  postfix all commands
172   --prefer-local, -l   prefer locally installed packages and binaries
173   --cwd=<path>         set current directory
174   --eval=<js>, -e      evaluate script
175   --ext=<.mjs>         script extension
176   --install, -i        install dependencies
177   --registry=<URL>     npm registry, defaults to https://registry.npmjs.org/
178   --version, -v        print current zx version
179   --help, -h           print help
180   --repl               start repl
181   --env=<path>         path to env file
182   --experimental       enables experimental features (deprecated)
183
184 ${import_index.chalk.italic("Full documentation:")} ${import_index.chalk.underline(import_index.Fail.DOCS_URL)}
185`);
186}
187function main() {
188  return __async(this, null, function* () {
189    var _a2;
190    if (argv.version) {
191      console.log(import_index.VERSION);
192      return;
193    }
194    if (argv.help) {
195      printUsage();
196      return;
197    }
198    if (argv.cwd) import_index.$.cwd = argv.cwd;
199    if (argv.env) {
200      const envfile = import_index.path.resolve((_a2 = import_index.$.cwd) != null ? _a2 : import_node_process2.default.cwd(), argv.env);
201      import_index.dotenv.config(envfile);
202      (0, import_index.resolveDefaults)();
203    }
204    if (argv.verbose) import_index.$.verbose = true;
205    if (argv.quiet) import_index.$.quiet = true;
206    if (argv.shell) import_index.$.shell = argv.shell;
207    if (argv.prefix) import_index.$.prefix = argv.prefix;
208    if (argv.postfix) import_index.$.postfix = argv.postfix;
209    if (argv.preferLocal) import_index.$.preferLocal = argv.preferLocal;
210    yield require("./globals.cjs");
211    if (argv.repl) {
212      yield startRepl();
213      return;
214    }
215    argv.ext = normalizeExt(argv.ext);
216    const { script, scriptPath, tempPath } = yield readScript();
217    yield runScript(script, scriptPath, tempPath);
218  });
219}
220var rmrf = (p) => {
221  var _a2;
222  if (!p) return;
223  ((_a2 = lstat(p)) == null ? void 0 : _a2.isSymbolicLink()) ? import_index.fs.unlinkSync(p) : import_index.fs.rmSync(p, { force: true, recursive: true });
224};
225function runScript(script, scriptPath, tempPath) {
226  return __async(this, null, function* () {
227    let nmLink = "";
228    const rmTemp = () => {
229      rmrf(tempPath);
230      rmrf(nmLink);
231    };
232    try {
233      if (tempPath) {
234        scriptPath = tempPath;
235        yield import_index.fs.writeFile(tempPath, script);
236      }
237      const cwd = import_index.path.dirname(scriptPath);
238      if (typeof argv.preferLocal === "string") {
239        nmLink = linkNodeModules(cwd, argv.preferLocal);
240      }
241      if (argv.install) {
242        yield (0, import_deps.installDeps)((0, import_deps.parseDeps)(script), cwd, argv.registry);
243      }
244      injectGlobalRequire(scriptPath);
245      import_node_process2.default.once("exit", rmTemp);
246      yield import(import_node_url.default.pathToFileURL(scriptPath).toString());
247    } finally {
248      rmTemp();
249    }
250  });
251}
252function linkNodeModules(cwd, external) {
253  const nm = "node_modules";
254  const alias = import_index.path.resolve(cwd, nm);
255  const target = import_index.path.basename(external) === nm ? import_index.path.resolve(external) : import_index.path.resolve(external, nm);
256  const aliasStat = lstat(alias);
257  const targetStat = lstat(target);
258  if (!(targetStat == null ? void 0 : targetStat.isDirectory()))
259    throw new import_index.Fail(
260      `Can't link node_modules: ${target} doesn't exist or is not a directory`
261    );
262  if ((aliasStat == null ? void 0 : aliasStat.isDirectory()) && alias !== target)
263    throw new import_index.Fail(`Can't link node_modules: ${alias} already exists`);
264  if (aliasStat) return "";
265  import_index.fs.symlinkSync(target, alias, "junction");
266  return alias;
267}
268function lstat(p) {
269  try {
270    return import_index.fs.lstatSync(p);
271  } catch (e) {
272  }
273}
274function readScript() {
275  return __async(this, null, function* () {
276    const [firstArg] = argv._;
277    let script = "";
278    let scriptPath = "";
279    let tempPath = "";
280    let argSlice = 1;
281    if (argv.eval) {
282      argSlice = 0;
283      script = argv.eval;
284      tempPath = getFilepath(import_index.$.cwd, "zx", argv.ext);
285    } else if (!firstArg || firstArg === "-") {
286      script = yield readScriptFromStdin();
287      tempPath = getFilepath(import_index.$.cwd, "zx", argv.ext);
288      if (script.length === 0) {
289        printUsage();
290        import_node_process2.default.exitCode = 1;
291        throw new import_index.Fail("No script provided");
292      }
293    } else if (/^https?:/.test(firstArg)) {
294      const { name, ext: ext2 = argv.ext } = import_index.path.parse(new URL(firstArg).pathname);
295      script = yield readScriptFromHttp(firstArg);
296      tempPath = getFilepath(import_index.$.cwd, name, ext2);
297    } else {
298      script = yield import_index.fs.readFile(firstArg, "utf8");
299      scriptPath = firstArg.startsWith("file:") ? import_node_url.default.fileURLToPath(firstArg) : import_index.path.resolve(firstArg);
300    }
301    const { ext, base, dir } = import_index.path.parse(tempPath || scriptPath);
302    if (ext === "" || argv.ext && !EXT_RE.test(ext)) {
303      tempPath = getFilepath(dir, base);
304    }
305    if (ext === ".md") {
306      script = transformMarkdown(script);
307      tempPath = getFilepath(dir, base);
308    }
309    if (argSlice) (0, import_index.updateArgv)(argv._.slice(argSlice));
310    return { script, scriptPath, tempPath };
311  });
312}
313function readScriptFromStdin() {
314  return __async(this, null, function* () {
315    return import_node_process2.default.stdin.isTTY ? "" : (0, import_index.stdin)();
316  });
317}
318function readScriptFromHttp(remote) {
319  return __async(this, null, function* () {
320    const res = yield (0, import_index.fetch)(remote);
321    if (!res.ok) {
322      console.error(`Error: Can't get ${remote}`);
323      import_node_process2.default.exit(1);
324    }
325    return res.text();
326  });
327}
328function injectGlobalRequire(origin) {
329  const __filename = import_index.path.resolve(origin);
330  const __dirname = import_index.path.dirname(__filename);
331  const require2 = (0, import_vendor.createRequire)(origin);
332  Object.assign(globalThis, { __filename, __dirname, require: require2 });
333}
334function isMain(metaurl = import_meta_url, scriptpath = import_node_process2.default.argv[1]) {
335  if (metaurl.startsWith("file:")) {
336    const modulePath = import_node_url.default.fileURLToPath(metaurl).replace(/\.\w+$/, "");
337    const mainPath = import_index.fs.realpathSync(scriptpath).replace(/\.\w+$/, "");
338    return mainPath === modulePath;
339  }
340  return false;
341}
342function normalizeExt(ext) {
343  return ext ? import_index.path.parse(`foo.${ext}`).ext : ext;
344}
345function getFilepath(cwd = ".", name = "zx", _ext) {
346  const ext = _ext || argv.ext || EXT;
347  return [
348    name + ext,
349    name + "-" + (0, import_util2.randomId)() + ext
350  ].map((f) => import_index.path.resolve(import_node_process2.default.cwd(), cwd, f)).find((f) => !import_index.fs.existsSync(f));
351}
352/* c8 ignore next 100 */
353// Annotate the CommonJS export names for ESM import in node:
3540 && (module.exports = {
355  argv,
356  injectGlobalRequire,
357  isMain,
358  main,
359  normalizeExt,
360  printUsage,
361  transformMarkdown
362});