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});