zapdev 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +17 -29
  2. package/dist/cli.js +1725 -1996
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -84,1697 +84,1700 @@ var require_src = __commonJS({
84
84
  }
85
85
  });
86
86
 
87
- // node_modules/@clack/core/dist/index.mjs
88
- import { styleText } from "node:util";
89
- import { stdout, stdin } from "node:process";
90
- import * as l from "node:readline";
91
- import l__default from "node:readline";
92
-
93
- // node_modules/fast-string-truncated-width/dist/utils.js
94
- var getCodePointsLength = /* @__PURE__ */ (() => {
95
- const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
96
- return (input) => {
97
- let surrogatePairsNr = 0;
98
- SURROGATE_PAIR_RE.lastIndex = 0;
99
- while (SURROGATE_PAIR_RE.test(input)) {
100
- surrogatePairsNr += 1;
101
- }
102
- return input.length - surrogatePairsNr;
103
- };
104
- })();
105
- var isFullWidth = (x2) => {
106
- return x2 === 12288 || x2 >= 65281 && x2 <= 65376 || x2 >= 65504 && x2 <= 65510;
107
- };
108
- var isWideNotCJKTNotEmoji = (x2) => {
109
- return x2 === 8987 || x2 === 9001 || x2 >= 12272 && x2 <= 12287 || x2 >= 12289 && x2 <= 12350 || x2 >= 12441 && x2 <= 12543 || x2 >= 12549 && x2 <= 12591 || x2 >= 12593 && x2 <= 12686 || x2 >= 12688 && x2 <= 12771 || x2 >= 12783 && x2 <= 12830 || x2 >= 12832 && x2 <= 12871 || x2 >= 12880 && x2 <= 19903 || x2 >= 65040 && x2 <= 65049 || x2 >= 65072 && x2 <= 65106 || x2 >= 65108 && x2 <= 65126 || x2 >= 65128 && x2 <= 65131 || x2 >= 127488 && x2 <= 127490 || x2 >= 127504 && x2 <= 127547 || x2 >= 127552 && x2 <= 127560 || x2 >= 131072 && x2 <= 196605 || x2 >= 196608 && x2 <= 262141;
110
- };
111
-
112
- // node_modules/fast-string-truncated-width/dist/index.js
113
- var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
114
- var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
115
- var CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu;
116
- var TAB_RE = /\t{1,1000}/y;
117
- var EMOJI_RE = new RegExp("[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F\\u20E3?))*", "yu");
118
- var LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
119
- var MODIFIER_RE = new RegExp("\\p{M}+", "gu");
120
- var NO_TRUNCATION = { limit: Infinity, ellipsis: "" };
121
- var getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
122
- const LIMIT = truncationOptions.limit ?? Infinity;
123
- const ELLIPSIS = truncationOptions.ellipsis ?? "";
124
- const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION, widthOptions).width : 0);
125
- const ANSI_WIDTH = 0;
126
- const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
127
- const TAB_WIDTH = widthOptions.tabWidth ?? 8;
128
- const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
129
- const FULL_WIDTH_WIDTH = 2;
130
- const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
131
- const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
132
- const PARSE_BLOCKS = [
133
- [LATIN_RE, REGULAR_WIDTH],
134
- [ANSI_RE, ANSI_WIDTH],
135
- [CONTROL_RE, CONTROL_WIDTH],
136
- [TAB_RE, TAB_WIDTH],
137
- [EMOJI_RE, EMOJI_WIDTH],
138
- [CJKT_WIDE_RE, WIDE_WIDTH]
139
- ];
140
- let indexPrev = 0;
141
- let index = 0;
142
- let length = input.length;
143
- let lengthExtra = 0;
144
- let truncationEnabled = false;
145
- let truncationIndex = length;
146
- let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
147
- let unmatchedStart = 0;
148
- let unmatchedEnd = 0;
149
- let width = 0;
150
- let widthExtra = 0;
151
- outer: while (true) {
152
- if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
153
- const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
154
- lengthExtra = 0;
155
- for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
156
- const codePoint = char.codePointAt(0) || 0;
157
- if (isFullWidth(codePoint)) {
158
- widthExtra = FULL_WIDTH_WIDTH;
159
- } else if (isWideNotCJKTNotEmoji(codePoint)) {
160
- widthExtra = WIDE_WIDTH;
161
- } else {
162
- widthExtra = REGULAR_WIDTH;
163
- }
164
- if (width + widthExtra > truncationLimit) {
165
- truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
166
- }
167
- if (width + widthExtra > LIMIT) {
168
- truncationEnabled = true;
169
- break outer;
170
- }
171
- lengthExtra += char.length;
172
- width += widthExtra;
173
- }
174
- unmatchedStart = unmatchedEnd = 0;
175
- }
176
- if (index >= length) {
177
- break outer;
178
- }
179
- for (let i3 = 0, l3 = PARSE_BLOCKS.length; i3 < l3; i3++) {
180
- const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i3];
181
- BLOCK_RE.lastIndex = index;
182
- if (BLOCK_RE.test(input)) {
183
- lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
184
- widthExtra = lengthExtra * BLOCK_WIDTH;
185
- if (width + widthExtra > truncationLimit) {
186
- truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
187
- }
188
- if (width + widthExtra > LIMIT) {
189
- truncationEnabled = true;
190
- break outer;
191
- }
192
- width += widthExtra;
193
- unmatchedStart = indexPrev;
194
- unmatchedEnd = index;
195
- index = indexPrev = BLOCK_RE.lastIndex;
196
- continue outer;
197
- }
198
- }
199
- index += 1;
200
- }
201
- return {
202
- width: truncationEnabled ? truncationLimit : width,
203
- index: truncationEnabled ? truncationIndex : length,
204
- truncated: truncationEnabled,
205
- ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
206
- };
207
- };
208
- var dist_default = getStringTruncatedWidth;
209
-
210
- // node_modules/fast-string-width/dist/index.js
211
- var NO_TRUNCATION2 = {
212
- limit: Infinity,
213
- ellipsis: "",
214
- ellipsisWidth: 0
215
- };
216
- var fastStringWidth = (input, options = {}) => {
217
- return dist_default(input, NO_TRUNCATION2, options).width;
218
- };
219
- var dist_default2 = fastStringWidth;
220
-
221
- // node_modules/fast-wrap-ansi/lib/main.js
222
- var ESC = "\x1B";
223
- var CSI = "\x9B";
224
- var END_CODE = 39;
225
- var ANSI_ESCAPE_BELL = "\x07";
226
- var ANSI_CSI = "[";
227
- var ANSI_OSC = "]";
228
- var ANSI_SGR_TERMINATOR = "m";
229
- var ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
230
- var GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
231
- var getClosingCode = (openingCode) => {
232
- if (openingCode >= 30 && openingCode <= 37)
233
- return 39;
234
- if (openingCode >= 90 && openingCode <= 97)
235
- return 39;
236
- if (openingCode >= 40 && openingCode <= 47)
237
- return 49;
238
- if (openingCode >= 100 && openingCode <= 107)
239
- return 49;
240
- if (openingCode === 1 || openingCode === 2)
241
- return 22;
242
- if (openingCode === 3)
243
- return 23;
244
- if (openingCode === 4)
245
- return 24;
246
- if (openingCode === 7)
247
- return 27;
248
- if (openingCode === 8)
249
- return 28;
250
- if (openingCode === 9)
251
- return 29;
252
- if (openingCode === 0)
253
- return 0;
254
- return void 0;
255
- };
256
- var wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
257
- var wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
258
- var wrapWord = (rows, word, columns) => {
259
- const characters = word[Symbol.iterator]();
260
- let isInsideEscape = false;
261
- let isInsideLinkEscape = false;
262
- let lastRow = rows.at(-1);
263
- let visible = lastRow === void 0 ? 0 : dist_default2(lastRow);
264
- let currentCharacter = characters.next();
265
- let nextCharacter = characters.next();
266
- let rawCharacterIndex = 0;
267
- while (!currentCharacter.done) {
268
- const character = currentCharacter.value;
269
- const characterLength = dist_default2(character);
270
- if (visible + characterLength <= columns) {
271
- rows[rows.length - 1] += character;
272
- } else {
273
- rows.push(character);
274
- visible = 0;
275
- }
276
- if (character === ESC || character === CSI) {
277
- isInsideEscape = true;
278
- isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
279
- }
280
- if (isInsideEscape) {
281
- if (isInsideLinkEscape) {
282
- if (character === ANSI_ESCAPE_BELL) {
283
- isInsideEscape = false;
284
- isInsideLinkEscape = false;
285
- }
286
- } else if (character === ANSI_SGR_TERMINATOR) {
287
- isInsideEscape = false;
288
- }
289
- } else {
290
- visible += characterLength;
291
- if (visible === columns && !nextCharacter.done) {
292
- rows.push("");
293
- visible = 0;
294
- }
295
- }
296
- currentCharacter = nextCharacter;
297
- nextCharacter = characters.next();
298
- rawCharacterIndex += character.length;
299
- }
300
- lastRow = rows.at(-1);
301
- if (!visible && lastRow !== void 0 && lastRow.length && rows.length > 1) {
302
- rows[rows.length - 2] += rows.pop();
303
- }
304
- };
305
- var stringVisibleTrimSpacesRight = (string) => {
306
- const words = string.split(" ");
307
- let last = words.length;
308
- while (last) {
309
- if (dist_default2(words[last - 1])) {
310
- break;
311
- }
312
- last--;
313
- }
314
- if (last === words.length) {
315
- return string;
316
- }
317
- return words.slice(0, last).join(" ") + words.slice(last).join("");
318
- };
319
- var exec = (string, columns, options = {}) => {
320
- if (options.trim !== false && string.trim() === "") {
321
- return "";
322
- }
323
- let returnValue = "";
324
- let escapeCode;
325
- let escapeUrl;
326
- const words = string.split(" ");
327
- let rows = [""];
328
- let rowLength = 0;
329
- for (let index = 0; index < words.length; index++) {
330
- const word = words[index];
331
- if (options.trim !== false) {
332
- const row = rows.at(-1) ?? "";
333
- const trimmed = row.trimStart();
334
- if (row.length !== trimmed.length) {
335
- rows[rows.length - 1] = trimmed;
336
- rowLength = dist_default2(trimmed);
337
- }
338
- }
339
- if (index !== 0) {
340
- if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
341
- rows.push("");
342
- rowLength = 0;
343
- }
344
- if (rowLength || options.trim === false) {
345
- rows[rows.length - 1] += " ";
346
- rowLength++;
347
- }
348
- }
349
- const wordLength = dist_default2(word);
350
- if (options.hard && wordLength > columns) {
351
- const remainingColumns = columns - rowLength;
352
- const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
353
- const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);
354
- if (breaksStartingNextLine < breaksStartingThisLine) {
355
- rows.push("");
356
- }
357
- wrapWord(rows, word, columns);
358
- rowLength = dist_default2(rows.at(-1) ?? "");
87
+ // node_modules/citty/dist/_chunks/libs/scule.mjs
88
+ var NUMBER_CHAR_RE = /\d/;
89
+ var STR_SPLITTERS = [
90
+ "-",
91
+ "_",
92
+ "/",
93
+ "."
94
+ ];
95
+ function isUppercase(char = "") {
96
+ if (NUMBER_CHAR_RE.test(char)) return;
97
+ return char !== char.toLowerCase();
98
+ }
99
+ function splitByCase(str, separators) {
100
+ const splitters = separators ?? STR_SPLITTERS;
101
+ const parts = [];
102
+ if (!str || typeof str !== "string") return parts;
103
+ let buff = "";
104
+ let previousUpper;
105
+ let previousSplitter;
106
+ for (const char of str) {
107
+ const isSplitter = splitters.includes(char);
108
+ if (isSplitter === true) {
109
+ parts.push(buff);
110
+ buff = "";
111
+ previousUpper = void 0;
359
112
  continue;
360
113
  }
361
- if (rowLength + wordLength > columns && rowLength && wordLength) {
362
- if (options.wordWrap === false && rowLength < columns) {
363
- wrapWord(rows, word, columns);
364
- rowLength = dist_default2(rows.at(-1) ?? "");
114
+ const isUpper = isUppercase(char);
115
+ if (previousSplitter === false) {
116
+ if (previousUpper === false && isUpper === true) {
117
+ parts.push(buff);
118
+ buff = char;
119
+ previousUpper = isUpper;
365
120
  continue;
366
121
  }
367
- rows.push("");
368
- rowLength = 0;
369
- }
370
- if (rowLength + wordLength > columns && options.wordWrap === false) {
371
- wrapWord(rows, word, columns);
372
- rowLength = dist_default2(rows.at(-1) ?? "");
373
- continue;
374
- }
375
- rows[rows.length - 1] += word;
376
- rowLength += wordLength;
377
- }
378
- if (options.trim !== false) {
379
- rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
380
- }
381
- const preString = rows.join("\n");
382
- let inSurrogate = false;
383
- for (let i3 = 0; i3 < preString.length; i3++) {
384
- const character = preString[i3];
385
- returnValue += character;
386
- if (!inSurrogate) {
387
- inSurrogate = character >= "\uD800" && character <= "\uDBFF";
388
- if (inSurrogate) {
122
+ if (previousUpper === true && isUpper === false && buff.length > 1) {
123
+ const lastChar = buff.at(-1);
124
+ parts.push(buff.slice(0, Math.max(0, buff.length - 1)));
125
+ buff = lastChar + char;
126
+ previousUpper = isUpper;
389
127
  continue;
390
128
  }
391
- } else {
392
- inSurrogate = false;
393
- }
394
- if (character === ESC || character === CSI) {
395
- GROUP_REGEX.lastIndex = i3 + 1;
396
- const groupsResult = GROUP_REGEX.exec(preString);
397
- const groups = groupsResult?.groups;
398
- if (groups?.code !== void 0) {
399
- const code = Number.parseFloat(groups.code);
400
- escapeCode = code === END_CODE ? void 0 : code;
401
- } else if (groups?.uri !== void 0) {
402
- escapeUrl = groups.uri.length === 0 ? void 0 : groups.uri;
403
- }
404
- }
405
- if (preString[i3 + 1] === "\n") {
406
- if (escapeUrl) {
407
- returnValue += wrapAnsiHyperlink("");
408
- }
409
- const closingCode = escapeCode ? getClosingCode(escapeCode) : void 0;
410
- if (escapeCode && closingCode) {
411
- returnValue += wrapAnsiCode(closingCode);
412
- }
413
- } else if (character === "\n") {
414
- if (escapeCode && getClosingCode(escapeCode)) {
415
- returnValue += wrapAnsiCode(escapeCode);
416
- }
417
- if (escapeUrl) {
418
- returnValue += wrapAnsiHyperlink(escapeUrl);
419
- }
420
129
  }
130
+ buff += char;
131
+ previousUpper = isUpper;
132
+ previousSplitter = isSplitter;
421
133
  }
422
- return returnValue;
423
- };
424
- var CRLF_OR_LF = /\r?\n/;
425
- function wrapAnsi(string, columns, options) {
426
- return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join("\n");
134
+ parts.push(buff);
135
+ return parts;
427
136
  }
428
-
429
- // node_modules/@clack/core/dist/index.mjs
430
- var import_sisteransi = __toESM(require_src(), 1);
431
- import { ReadStream } from "node:tty";
432
- function findCursor(s2, o2, l3) {
433
- if (!l3.some((r3) => !r3.disabled))
434
- return s2;
435
- const t3 = s2 + o2, n4 = Math.max(l3.length - 1, 0), e2 = t3 < 0 ? n4 : t3 > n4 ? 0 : t3;
436
- return l3[e2]?.disabled ? findCursor(e2, o2 < 0 ? -1 : 1, l3) : e2;
137
+ function upperFirst(str) {
138
+ return str ? str[0].toUpperCase() + str.slice(1) : "";
437
139
  }
438
- var a$1 = ["up", "down", "left", "right", "space", "enter", "cancel"];
439
- var t = [
440
- "January",
441
- "February",
442
- "March",
443
- "April",
444
- "May",
445
- "June",
446
- "July",
447
- "August",
448
- "September",
449
- "October",
450
- "November",
451
- "December"
452
- ];
453
- var settings = {
454
- actions: new Set(a$1),
455
- aliases: /* @__PURE__ */ new Map([
456
- // vim support
457
- ["k", "up"],
458
- ["j", "down"],
459
- ["h", "left"],
460
- ["l", "right"],
461
- ["", "cancel"],
462
- // opinionated defaults!
463
- ["escape", "cancel"]
464
- ]),
465
- messages: {
466
- cancel: "Canceled",
467
- error: "Something went wrong"
468
- },
469
- withGuide: true,
470
- date: {
471
- monthNames: [...t],
472
- messages: {
473
- required: "Please enter a valid date",
474
- invalidMonth: "There are only 12 months in a year",
475
- invalidDay: (n4, e2) => `There are only ${n4} days in ${e2}`,
476
- afterMin: (n4) => `Date must be on or after ${n4.toISOString().slice(0, 10)}`,
477
- beforeMax: (n4) => `Date must be on or before ${n4.toISOString().slice(0, 10)}`
478
- }
479
- }
480
- };
481
- function isActionKey(n4, e2) {
482
- if (typeof n4 == "string")
483
- return settings.aliases.get(n4) === e2;
484
- for (const s2 of n4)
485
- if (s2 !== void 0 && isActionKey(s2, e2))
486
- return true;
487
- return false;
140
+ function lowerFirst(str) {
141
+ return str ? str[0].toLowerCase() + str.slice(1) : "";
488
142
  }
489
- function diffLines(i3, s2) {
490
- if (i3 === s2) return;
491
- const e2 = i3.split(`
492
- `), t3 = s2.split(`
493
- `), r3 = Math.max(e2.length, t3.length), f2 = [];
494
- for (let n4 = 0; n4 < r3; n4++)
495
- e2[n4] !== t3[n4] && f2.push(n4);
496
- return {
497
- lines: f2,
498
- numLinesBefore: e2.length,
499
- numLinesAfter: t3.length,
500
- numLines: r3
501
- };
143
+ function pascalCase(str, opts) {
144
+ return str ? (Array.isArray(str) ? str : splitByCase(str)).map((p2) => upperFirst(opts?.normalize ? p2.toLowerCase() : p2)).join("") : "";
502
145
  }
503
- var R = globalThis.process.platform.startsWith("win");
504
- var CANCEL_SYMBOL = /* @__PURE__ */ Symbol("clack:cancel");
505
- function isCancel(e2) {
506
- return e2 === CANCEL_SYMBOL;
146
+ function camelCase(str, opts) {
147
+ return lowerFirst(pascalCase(str || "", opts));
507
148
  }
508
- function setRawMode(e2, r3) {
509
- const o2 = e2;
510
- o2.isTTY && o2.setRawMode(r3);
149
+ function kebabCase(str, joiner) {
150
+ return str ? (Array.isArray(str) ? str : splitByCase(str)).map((p2) => p2.toLowerCase()).join(joiner ?? "-") : "";
511
151
  }
512
- function block({
513
- input: e2 = stdin,
514
- output: r3 = stdout,
515
- overwrite: o2 = true,
516
- hideCursor: t3 = true
517
- } = {}) {
518
- const s2 = l.createInterface({
519
- input: e2,
520
- output: r3,
521
- prompt: "",
522
- tabSize: 1
523
- });
524
- l.emitKeypressEvents(e2, s2), e2 instanceof ReadStream && e2.isTTY && e2.setRawMode(true);
525
- const n4 = (f2, { name: a3, sequence: p2 }) => {
526
- const c3 = String(f2);
527
- if (isActionKey([c3, a3, p2], "cancel")) {
528
- t3 && r3.write(import_sisteransi.cursor.show), process.exit(0);
529
- return;
530
- }
531
- if (!o2) return;
532
- const i3 = a3 === "return" ? 0 : -1, m2 = a3 === "return" ? -1 : 0;
533
- l.moveCursor(r3, i3, m2, () => {
534
- l.clearLine(r3, 1, () => {
535
- e2.once("keypress", n4);
536
- });
537
- });
538
- };
539
- return t3 && r3.write(import_sisteransi.cursor.hide), e2.once("keypress", n4), () => {
540
- e2.off("keypress", n4), t3 && r3.write(import_sisteransi.cursor.show), e2 instanceof ReadStream && e2.isTTY && !R && e2.setRawMode(false), s2.terminal = false, s2.close();
541
- };
152
+ function snakeCase(str) {
153
+ return kebabCase(str || "", "_");
542
154
  }
543
- var getColumns = (e2) => "columns" in e2 && typeof e2.columns == "number" ? e2.columns : 80;
544
- var getRows = (e2) => "rows" in e2 && typeof e2.rows == "number" ? e2.rows : 20;
545
- function wrapTextWithPrefix(e2, r3, o2, t3 = o2, s2 = o2, n4) {
546
- const f2 = getColumns(e2 ?? stdout);
547
- return wrapAnsi(r3, f2 - o2.length, {
548
- hard: true,
549
- trim: false
550
- }).split(`
551
- `).map((c3, i3, m2) => {
552
- const d2 = n4 ? n4(c3, i3) : c3;
553
- return i3 === 0 ? `${t3}${d2}` : i3 === m2.length - 1 ? `${s2}${d2}` : `${o2}${d2}`;
554
- }).join(`
555
- `);
155
+
156
+ // node_modules/citty/dist/index.mjs
157
+ import { parseArgs as parseArgs$1 } from "node:util";
158
+ function toArray(val) {
159
+ if (Array.isArray(val)) return val;
160
+ return val === void 0 ? [] : [val];
556
161
  }
557
- function runValidation(e2, n4) {
558
- if ("~standard" in e2) {
559
- const a3 = e2["~standard"].validate(n4);
560
- if (a3 instanceof Promise)
561
- throw new TypeError(
562
- "Schema validation must be synchronous. Update `validate()` and remove any asynchronous logic."
563
- );
564
- return a3.issues?.at(0)?.message;
565
- }
566
- return e2(n4);
162
+ function formatLineColumns(lines, linePrefix = "") {
163
+ const maxLength = [];
164
+ for (const line of lines) for (const [i3, element] of line.entries()) maxLength[i3] = Math.max(maxLength[i3] || 0, element.length);
165
+ return lines.map((l3) => l3.map((c3, i3) => linePrefix + c3[i3 === 0 ? "padStart" : "padEnd"](maxLength[i3])).join(" ")).join("\n");
567
166
  }
568
- var V = class {
569
- input;
570
- output;
571
- _abortSignal;
572
- rl;
573
- opts;
574
- _render;
575
- _track = false;
576
- _prevFrame = "";
577
- _subscribers = /* @__PURE__ */ new Map();
578
- _cursor = 0;
579
- state = "initial";
580
- error = "";
581
- value;
582
- userInput = "";
583
- constructor(t3, e2 = true) {
584
- const { input: i3 = stdin, output: n4 = stdout, render: s2, signal: r3, ...o2 } = t3;
585
- this.opts = o2, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = s2.bind(this), this._track = e2, this._abortSignal = r3, this.input = i3, this.output = n4;
586
- }
587
- /**
588
- * Unsubscribe all listeners
589
- */
590
- unsubscribe() {
591
- this._subscribers.clear();
167
+ function resolveValue(input) {
168
+ return typeof input === "function" ? input() : input;
169
+ }
170
+ var CLIError = class extends Error {
171
+ code;
172
+ constructor(message, code) {
173
+ super(message);
174
+ this.name = "CLIError";
175
+ this.code = code;
592
176
  }
593
- /**
594
- * Set a subscriber with opts
595
- * @param event - The event name
596
- */
597
- setSubscriber(t3, e2) {
598
- const i3 = this._subscribers.get(t3) ?? [];
599
- i3.push(e2), this._subscribers.set(t3, i3);
177
+ };
178
+ function parseRawArgs(args = [], opts = {}) {
179
+ const booleans = new Set(opts.boolean || []);
180
+ const strings = new Set(opts.string || []);
181
+ const aliasMap = opts.alias || {};
182
+ const defaults = opts.default || {};
183
+ const aliasToMain = /* @__PURE__ */ new Map();
184
+ const mainToAliases = /* @__PURE__ */ new Map();
185
+ for (const [key, value] of Object.entries(aliasMap)) {
186
+ const targets = value;
187
+ for (const target of targets) {
188
+ aliasToMain.set(key, target);
189
+ if (!mainToAliases.has(target)) mainToAliases.set(target, []);
190
+ mainToAliases.get(target).push(key);
191
+ aliasToMain.set(target, key);
192
+ if (!mainToAliases.has(key)) mainToAliases.set(key, []);
193
+ mainToAliases.get(key).push(target);
194
+ }
600
195
  }
601
- /**
602
- * Subscribe to an event
603
- * @param event - The event name
604
- * @param cb - The callback
605
- */
606
- on(t3, e2) {
607
- this.setSubscriber(t3, { cb: e2 });
196
+ const options = {};
197
+ function getType(name) {
198
+ if (booleans.has(name)) return "boolean";
199
+ const aliases = mainToAliases.get(name) || [];
200
+ for (const alias of aliases) if (booleans.has(alias)) return "boolean";
201
+ return "string";
608
202
  }
609
- /**
610
- * Subscribe to an event once
611
- * @param event - The event name
612
- * @param cb - The callback
613
- */
614
- once(t3, e2) {
615
- this.setSubscriber(t3, { cb: e2, once: true });
203
+ function isStringType(name) {
204
+ if (strings.has(name)) return true;
205
+ const aliases = mainToAliases.get(name) || [];
206
+ for (const alias of aliases) if (strings.has(alias)) return true;
207
+ return false;
616
208
  }
617
- /**
618
- * Emit an event with data
619
- * @param event - The event name
620
- * @param data - The data to pass to the callback
621
- */
622
- emit(t3, ...e2) {
623
- const i3 = this._subscribers.get(t3) ?? [], n4 = [];
624
- for (const s2 of i3)
625
- s2.cb(...e2), s2.once && n4.push(() => i3.splice(i3.indexOf(s2), 1));
626
- for (const s2 of n4)
627
- s2();
209
+ const allOptions = /* @__PURE__ */ new Set([
210
+ ...booleans,
211
+ ...strings,
212
+ ...Object.keys(aliasMap),
213
+ ...Object.values(aliasMap).flat(),
214
+ ...Object.keys(defaults)
215
+ ]);
216
+ for (const name of allOptions) if (!options[name]) options[name] = {
217
+ type: getType(name),
218
+ default: defaults[name]
219
+ };
220
+ for (const [alias, main2] of aliasToMain.entries()) if (alias.length === 1 && options[main2] && !options[main2].short) options[main2].short = alias;
221
+ const processedArgs = [];
222
+ const negatedFlags = {};
223
+ for (let i3 = 0; i3 < args.length; i3++) {
224
+ const arg = args[i3];
225
+ if (arg === "--") {
226
+ processedArgs.push(...args.slice(i3));
227
+ break;
228
+ }
229
+ if (arg.startsWith("--no-")) {
230
+ const flagName = arg.slice(5);
231
+ negatedFlags[flagName] = true;
232
+ continue;
233
+ }
234
+ processedArgs.push(arg);
628
235
  }
629
- prompt() {
630
- return new Promise((t3) => {
631
- if (this._abortSignal) {
632
- if (this._abortSignal.aborted)
633
- return this.state = "cancel", this.close(), t3(CANCEL_SYMBOL);
634
- this._abortSignal.addEventListener(
635
- "abort",
636
- () => {
637
- this.state = "cancel", this.close();
638
- },
639
- { once: true }
640
- );
641
- }
642
- this.rl = l__default.createInterface({
643
- input: this.input,
644
- tabSize: 2,
645
- prompt: "",
646
- escapeCodeTimeout: 50,
647
- terminal: true
648
- }), this.rl.prompt(), this.opts.initialUserInput !== void 0 && this._setUserInput(this.opts.initialUserInput, true), this.input.on("keypress", this.onKeypress), setRawMode(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => {
649
- this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t3(this.value);
650
- }), this.once("cancel", () => {
651
- this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t3(CANCEL_SYMBOL);
652
- });
236
+ let parsed;
237
+ try {
238
+ parsed = parseArgs$1({
239
+ args: processedArgs,
240
+ options: Object.keys(options).length > 0 ? options : void 0,
241
+ allowPositionals: true,
242
+ strict: false
653
243
  });
244
+ } catch {
245
+ parsed = {
246
+ values: {},
247
+ positionals: processedArgs
248
+ };
654
249
  }
655
- _isActionKey(t3, e2) {
656
- return t3 === " ";
657
- }
658
- _shouldSubmit(t3, e2) {
659
- return true;
250
+ const out = { _: [] };
251
+ out._ = parsed.positionals;
252
+ for (const [key, value] of Object.entries(parsed.values)) {
253
+ let coerced = value;
254
+ if (getType(key) === "boolean" && typeof value === "string") coerced = value !== "false";
255
+ else if (isStringType(key) && typeof value === "boolean") coerced = "";
256
+ out[key] = coerced;
660
257
  }
661
- _setValue(t3) {
662
- this.value = t3, this.emit("value", this.value);
258
+ for (const [name] of Object.entries(negatedFlags)) {
259
+ out[name] = false;
260
+ const mainName = aliasToMain.get(name);
261
+ if (mainName) out[mainName] = false;
262
+ const aliases = mainToAliases.get(name);
263
+ if (aliases) for (const alias of aliases) out[alias] = false;
663
264
  }
664
- _setUserInput(t3, e2) {
665
- this.userInput = t3 ?? "", this.emit("userInput", this.userInput), e2 && this._track && this.rl && (this.rl.write(this.userInput), this._cursor = this.rl.cursor);
265
+ for (const [alias, main2] of aliasToMain.entries()) {
266
+ if (out[alias] !== void 0 && out[main2] === void 0) out[main2] = out[alias];
267
+ if (out[main2] !== void 0 && out[alias] === void 0) out[alias] = out[main2];
268
+ if (out[alias] !== out[main2] && defaults[main2] === out[main2]) out[main2] = out[alias];
666
269
  }
667
- _clearUserInput() {
668
- this.rl?.write(null, { ctrl: true, name: "u" }), this._setUserInput("");
270
+ return out;
271
+ }
272
+ var noColor = /* @__PURE__ */ (() => {
273
+ const env = globalThis.process?.env ?? {};
274
+ return env.NO_COLOR === "1" || env.TERM === "dumb" || env.TEST || env.CI;
275
+ })();
276
+ var _c = (c3, r3 = 39) => (t3) => noColor ? t3 : `\x1B[${c3}m${t3}\x1B[${r3}m`;
277
+ var bold = /* @__PURE__ */ _c(1, 22);
278
+ var cyan = /* @__PURE__ */ _c(36);
279
+ var gray = /* @__PURE__ */ _c(90);
280
+ var underline = /* @__PURE__ */ _c(4, 24);
281
+ function parseArgs(rawArgs, argsDef) {
282
+ const parseOptions = {
283
+ boolean: [],
284
+ string: [],
285
+ alias: {},
286
+ default: {}
287
+ };
288
+ const args = resolveArgs(argsDef);
289
+ for (const arg of args) {
290
+ if (arg.type === "positional") continue;
291
+ if (arg.type === "string" || arg.type === "enum") parseOptions.string.push(arg.name);
292
+ else if (arg.type === "boolean") parseOptions.boolean.push(arg.name);
293
+ if (arg.default !== void 0) parseOptions.default[arg.name] = arg.default;
294
+ if (arg.alias) parseOptions.alias[arg.name] = arg.alias;
295
+ const camelName = camelCase(arg.name);
296
+ const kebabName = kebabCase(arg.name);
297
+ if (camelName !== arg.name || kebabName !== arg.name) {
298
+ const existingAliases = toArray(parseOptions.alias[arg.name] || []);
299
+ if (camelName !== arg.name && !existingAliases.includes(camelName)) existingAliases.push(camelName);
300
+ if (kebabName !== arg.name && !existingAliases.includes(kebabName)) existingAliases.push(kebabName);
301
+ if (existingAliases.length > 0) parseOptions.alias[arg.name] = existingAliases;
302
+ }
669
303
  }
670
- onKeypress(t3, e2) {
671
- if (this._track && e2.name !== "return" && (e2.name && this._isActionKey(t3, e2) && this.rl?.write(null, { ctrl: true, name: "h" }), this._cursor = this.rl?.cursor ?? 0, this._setUserInput(this.rl?.line)), this.state === "error" && (this.state = "active"), e2?.name && (!this._track && settings.aliases.has(e2.name) && this.emit("cursor", settings.aliases.get(e2.name)), settings.actions.has(e2.name) && this.emit("cursor", e2.name)), t3 && (t3.toLowerCase() === "y" || t3.toLowerCase() === "n") && this.emit("confirm", t3.toLowerCase() === "y"), this.emit("key", t3, e2), e2?.name === "return" && this._shouldSubmit(t3, e2)) {
672
- if (this.opts.validate) {
673
- const i3 = runValidation(this.opts.validate, this.value);
674
- i3 && (this.error = i3 instanceof Error ? i3.message : i3, this.state = "error", this.rl?.write(this.userInput));
304
+ const parsed = parseRawArgs(rawArgs, parseOptions);
305
+ const [...positionalArguments] = parsed._;
306
+ const parsedArgsProxy = new Proxy(parsed, { get(target, prop) {
307
+ return target[prop] ?? target[camelCase(prop)] ?? target[kebabCase(prop)];
308
+ } });
309
+ for (const [, arg] of args.entries()) if (arg.type === "positional") {
310
+ const nextPositionalArgument = positionalArguments.shift();
311
+ if (nextPositionalArgument !== void 0) parsedArgsProxy[arg.name] = nextPositionalArgument;
312
+ else if (arg.default === void 0 && arg.required !== false) throw new CLIError(`Missing required positional argument: ${arg.name.toUpperCase()}`, "EARG");
313
+ else parsedArgsProxy[arg.name] = arg.default;
314
+ } else if (arg.type === "enum") {
315
+ const argument = parsedArgsProxy[arg.name];
316
+ const options = arg.options || [];
317
+ if (argument !== void 0 && options.length > 0 && !options.includes(argument)) throw new CLIError(`Invalid value for argument: ${cyan(`--${arg.name}`)} (${cyan(argument)}). Expected one of: ${options.map((o2) => cyan(o2)).join(", ")}.`, "EARG");
318
+ } else if (arg.required && parsedArgsProxy[arg.name] === void 0) throw new CLIError(`Missing required argument: --${arg.name}`, "EARG");
319
+ return parsedArgsProxy;
320
+ }
321
+ function resolveArgs(argsDef) {
322
+ const args = [];
323
+ for (const [name, argDef] of Object.entries(argsDef || {})) args.push({
324
+ ...argDef,
325
+ name,
326
+ alias: toArray(argDef.alias)
327
+ });
328
+ return args;
329
+ }
330
+ async function resolvePlugins(plugins) {
331
+ return Promise.all(plugins.map((p2) => resolveValue(p2)));
332
+ }
333
+ function defineCommand(def) {
334
+ return def;
335
+ }
336
+ async function runCommand(cmd, opts) {
337
+ const cmdArgs = await resolveValue(cmd.args || {});
338
+ const parsedArgs = parseArgs(opts.rawArgs, cmdArgs);
339
+ const context = {
340
+ rawArgs: opts.rawArgs,
341
+ args: parsedArgs,
342
+ data: opts.data,
343
+ cmd
344
+ };
345
+ const plugins = await resolvePlugins(cmd.plugins ?? []);
346
+ let result;
347
+ let runError;
348
+ try {
349
+ for (const plugin of plugins) await plugin.setup?.(context);
350
+ if (typeof cmd.setup === "function") await cmd.setup(context);
351
+ const subCommands = await resolveValue(cmd.subCommands);
352
+ if (subCommands && Object.keys(subCommands).length > 0) {
353
+ const subCommandArgIndex = findSubCommandIndex(opts.rawArgs, cmdArgs);
354
+ const explicitName = opts.rawArgs[subCommandArgIndex];
355
+ if (explicitName) {
356
+ const subCommand = await _findSubCommand(subCommands, explicitName);
357
+ if (!subCommand) throw new CLIError(`Unknown command ${cyan(explicitName)}`, "E_UNKNOWN_COMMAND");
358
+ await runCommand(subCommand, { rawArgs: opts.rawArgs.slice(subCommandArgIndex + 1) });
359
+ } else {
360
+ const defaultSubCommand = await resolveValue(cmd.default);
361
+ if (defaultSubCommand) {
362
+ if (cmd.run) throw new CLIError(`Cannot specify both 'run' and 'default' on the same command.`, "E_DEFAULT_CONFLICT");
363
+ const subCommand = await _findSubCommand(subCommands, defaultSubCommand);
364
+ if (!subCommand) throw new CLIError(`Default sub command ${cyan(defaultSubCommand)} not found in subCommands.`, "E_UNKNOWN_COMMAND");
365
+ await runCommand(subCommand, { rawArgs: opts.rawArgs });
366
+ } else if (!cmd.run) throw new CLIError(`No command specified.`, "E_NO_COMMAND");
675
367
  }
676
- this.state !== "error" && (this.state = "submit");
677
368
  }
678
- isActionKey([t3, e2?.name, e2?.sequence], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
679
- }
680
- close() {
681
- this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
682
- `), setRawMode(this.input, false), this.rl?.close(), this.rl = void 0, this.emit(`${this.state}`, this.value), this.unsubscribe();
369
+ if (typeof cmd.run === "function") result = await cmd.run(context);
370
+ } catch (error) {
371
+ runError = error;
683
372
  }
684
- restoreCursor() {
685
- const t3 = wrapAnsi(this._prevFrame, process.stdout.columns, { hard: true, trim: false }).split(`
686
- `).length - 1;
687
- this.output.write(import_sisteransi.cursor.move(-999, t3 * -1));
373
+ const cleanupErrors = [];
374
+ if (typeof cmd.cleanup === "function") try {
375
+ await cmd.cleanup(context);
376
+ } catch (error) {
377
+ cleanupErrors.push(error);
688
378
  }
689
- render() {
690
- const t3 = wrapAnsi(this._render(this) ?? "", process.stdout.columns, {
691
- hard: true,
692
- trim: false
693
- });
694
- if (t3 !== this._prevFrame) {
695
- if (this.state === "initial")
696
- this.output.write(import_sisteransi.cursor.hide);
697
- else {
698
- const e2 = diffLines(this._prevFrame, t3), i3 = getRows(this.output);
699
- if (this.restoreCursor(), e2) {
700
- const n4 = Math.max(0, e2.numLinesAfter - i3), s2 = Math.max(0, e2.numLinesBefore - i3);
701
- let r3 = e2.lines.find((o2) => o2 >= n4);
702
- if (r3 === void 0) {
703
- this._prevFrame = t3;
704
- return;
705
- }
706
- if (e2.lines.length === 1) {
707
- this.output.write(import_sisteransi.cursor.move(0, r3 - s2)), this.output.write(import_sisteransi.erase.lines(1));
708
- const o2 = t3.split(`
709
- `);
710
- this.output.write(o2[r3]), this._prevFrame = t3, this.output.write(import_sisteransi.cursor.move(0, o2.length - r3 - 1));
711
- return;
712
- } else if (e2.lines.length > 1) {
713
- if (n4 < s2)
714
- r3 = n4;
715
- else {
716
- const h3 = r3 - s2;
717
- h3 > 0 && this.output.write(import_sisteransi.cursor.move(0, h3));
718
- }
719
- this.output.write(import_sisteransi.erase.down());
720
- const f2 = t3.split(`
721
- `).slice(r3);
722
- this.output.write(f2.join(`
723
- `)), this._prevFrame = t3;
724
- return;
725
- }
726
- }
727
- this.output.write(import_sisteransi.erase.down());
728
- }
729
- this.output.write(t3), this.state === "initial" && (this.state = "active"), this._prevFrame = t3;
730
- }
379
+ for (const plugin of [...plugins].reverse()) try {
380
+ await plugin.cleanup?.(context);
381
+ } catch (error) {
382
+ cleanupErrors.push(error);
731
383
  }
732
- };
733
- var r = class extends V {
734
- get cursor() {
735
- return this.value ? 0 : 1;
384
+ if (runError) throw runError;
385
+ if (cleanupErrors.length === 1) throw cleanupErrors[0];
386
+ if (cleanupErrors.length > 1) throw new Error("Multiple cleanup errors", { cause: cleanupErrors });
387
+ return { result };
388
+ }
389
+ async function resolveSubCommand(cmd, rawArgs, parent) {
390
+ const subCommands = await resolveValue(cmd.subCommands);
391
+ if (subCommands && Object.keys(subCommands).length > 0) {
392
+ const subCommandArgIndex = findSubCommandIndex(rawArgs, await resolveValue(cmd.args || {}));
393
+ const subCommandName = rawArgs[subCommandArgIndex];
394
+ const subCommand = await _findSubCommand(subCommands, subCommandName);
395
+ if (subCommand) return resolveSubCommand(subCommand, rawArgs.slice(subCommandArgIndex + 1), cmd);
736
396
  }
737
- get _value() {
738
- return this.cursor === 0;
397
+ return [cmd, parent];
398
+ }
399
+ async function _findSubCommand(subCommands, name) {
400
+ if (name in subCommands) return resolveValue(subCommands[name]);
401
+ for (const sub of Object.values(subCommands)) {
402
+ const resolved = await resolveValue(sub);
403
+ const meta = await resolveValue(resolved?.meta);
404
+ if (meta?.alias) {
405
+ if (toArray(meta.alias).includes(name)) return resolved;
406
+ }
739
407
  }
740
- constructor(t3) {
741
- super(t3, false), this.value = !!t3.initialValue, this.on("userInput", () => {
742
- this.value = this._value;
743
- }), this.on("confirm", (i3) => {
744
- this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = i3, this.state = "submit", this.close();
745
- }), this.on("cursor", () => {
746
- this.value = !this.value;
747
- });
408
+ }
409
+ function findSubCommandIndex(rawArgs, argsDef) {
410
+ for (let i3 = 0; i3 < rawArgs.length; i3++) {
411
+ const arg = rawArgs[i3];
412
+ if (arg === "--") return -1;
413
+ if (arg.startsWith("-")) {
414
+ if (!arg.includes("=") && _isValueFlag(arg, argsDef)) i3++;
415
+ continue;
416
+ }
417
+ return i3;
748
418
  }
749
- };
750
- var n$1 = class n extends V {
751
- options;
752
- cursor = 0;
753
- get _selectedValue() {
754
- return this.options[this.cursor];
419
+ return -1;
420
+ }
421
+ function _isValueFlag(flag, argsDef) {
422
+ const name = flag.replace(/^-{1,2}/, "");
423
+ const normalized = camelCase(name);
424
+ for (const [key, def] of Object.entries(argsDef)) {
425
+ if (def.type !== "string" && def.type !== "enum") continue;
426
+ if (normalized === camelCase(key)) return true;
427
+ if ((Array.isArray(def.alias) ? def.alias : def.alias ? [def.alias] : []).includes(name)) return true;
755
428
  }
756
- changeValue() {
757
- const e2 = this._selectedValue;
758
- this.value = e2 === void 0 ? void 0 : e2.value;
429
+ return false;
430
+ }
431
+ async function showUsage(cmd, parent) {
432
+ try {
433
+ console.log(await renderUsage(cmd, parent) + "\n");
434
+ } catch (error) {
435
+ console.error(error);
759
436
  }
760
- constructor(e2) {
761
- super(e2, false), this.options = e2.options;
762
- const o2 = this.options.findIndex(({ value: s2 }) => s2 === e2.initialValue), t3 = o2 === -1 ? 0 : o2;
763
- this.cursor = this.options[t3]?.disabled ? findCursor(t3, 1, this.options) : t3, this.changeValue(), this.on("cursor", (s2) => {
764
- switch (s2) {
765
- case "left":
766
- case "up":
767
- this.cursor = findCursor(this.cursor, -1, this.options);
768
- break;
769
- case "down":
770
- case "right":
771
- this.cursor = findCursor(this.cursor, 1, this.options);
772
- break;
773
- }
774
- this.changeValue();
775
- });
437
+ }
438
+ var negativePrefixRe = /^no[-A-Z]/;
439
+ async function renderUsage(cmd, parent) {
440
+ const cmdMeta = await resolveValue(cmd.meta || {});
441
+ const cmdArgs = resolveArgs(await resolveValue(cmd.args || {}));
442
+ const parentMeta = await resolveValue(parent?.meta || {});
443
+ const commandName = `${parentMeta.name ? `${parentMeta.name} ` : ""}` + (cmdMeta.name || process.argv[1]);
444
+ const argLines = [];
445
+ const posLines = [];
446
+ const commandsLines = [];
447
+ const usageLine = [];
448
+ for (const arg of cmdArgs) if (arg.type === "positional") {
449
+ const name = arg.name.toUpperCase();
450
+ const isRequired = arg.required !== false && arg.default === void 0;
451
+ posLines.push([cyan(name + renderValueHint(arg)), renderDescription(arg, isRequired)]);
452
+ usageLine.push(isRequired ? `<${name}>` : `[${name}]`);
453
+ } else {
454
+ const isRequired = arg.required === true && arg.default === void 0;
455
+ const argStr = [...(arg.alias || []).map((a3) => `-${a3}`), `--${arg.name}`].join(", ") + renderValueHint(arg);
456
+ argLines.push([cyan(argStr), renderDescription(arg, isRequired)]);
457
+ if (arg.type === "boolean" && (arg.default === true || arg.negativeDescription) && !negativePrefixRe.test(arg.name)) {
458
+ const negativeArgStr = [...(arg.alias || []).map((a3) => `--no-${a3}`), `--no-${arg.name}`].join(", ");
459
+ argLines.push([cyan(negativeArgStr), [arg.negativeDescription, isRequired ? gray("(Required)") : ""].filter(Boolean).join(" ")]);
460
+ }
461
+ if (isRequired) usageLine.push(`--${arg.name}` + renderValueHint(arg));
776
462
  }
777
- };
778
- var n2 = class extends V {
779
- get userInputWithCursor() {
780
- if (this.state === "submit")
781
- return this.userInput;
782
- const t3 = this.userInput;
783
- if (this.cursor >= t3.length)
784
- return `${this.userInput}\u2588`;
785
- const r3 = t3.slice(0, this.cursor), s2 = t3.slice(this.cursor, this.cursor + 1), e2 = t3.slice(this.cursor + 1);
786
- return `${r3}${styleText("inverse", s2)}${e2}`;
463
+ if (cmd.subCommands) {
464
+ const commandNames = [];
465
+ const subCommands = await resolveValue(cmd.subCommands);
466
+ for (const [name, sub] of Object.entries(subCommands)) {
467
+ const meta = await resolveValue((await resolveValue(sub))?.meta);
468
+ if (meta?.hidden) continue;
469
+ const aliases = toArray(meta?.alias);
470
+ const label = [name, ...aliases].join(", ");
471
+ commandsLines.push([cyan(label), meta?.description || ""]);
472
+ commandNames.push(name, ...aliases);
473
+ }
474
+ usageLine.push(commandNames.join("|"));
787
475
  }
788
- get cursor() {
789
- return this._cursor;
476
+ const usageLines = [];
477
+ const version = cmdMeta.version || parentMeta.version;
478
+ usageLines.push(gray(`${cmdMeta.description} (${commandName + (version ? ` v${version}` : "")})`), "");
479
+ const hasOptions = argLines.length > 0 || posLines.length > 0;
480
+ usageLines.push(`${underline(bold("USAGE"))} ${cyan(`${commandName}${hasOptions ? " [OPTIONS]" : ""} ${usageLine.join(" ")}`)}`, "");
481
+ if (posLines.length > 0) {
482
+ usageLines.push(underline(bold("ARGUMENTS")), "");
483
+ usageLines.push(formatLineColumns(posLines, " "));
484
+ usageLines.push("");
790
485
  }
791
- constructor(t3) {
792
- super({
793
- ...t3,
794
- initialUserInput: t3.initialUserInput ?? t3.initialValue
795
- }), this.on("userInput", (r3) => {
796
- this._setValue(r3);
797
- }), this.on("finalize", () => {
798
- this.value || (this.value = t3.defaultValue), this.value === void 0 && (this.value = "");
799
- });
486
+ if (argLines.length > 0) {
487
+ usageLines.push(underline(bold("OPTIONS")), "");
488
+ usageLines.push(formatLineColumns(argLines, " "));
489
+ usageLines.push("");
800
490
  }
801
- };
802
-
803
- // node_modules/@clack/prompts/dist/index.mjs
804
- import { styleText as styleText2, stripVTControlCharacters } from "node:util";
805
- import process$1 from "node:process";
806
- var import_sisteransi2 = __toESM(require_src(), 1);
807
- function isUnicodeSupported() {
808
- if (process$1.platform !== "win32") {
809
- return process$1.env.TERM !== "linux";
491
+ if (commandsLines.length > 0) {
492
+ usageLines.push(underline(bold("COMMANDS")), "");
493
+ usageLines.push(formatLineColumns(commandsLines, " "));
494
+ usageLines.push("", `Use ${cyan(`${commandName} <command> --help`)} for more information about a command.`);
810
495
  }
811
- return Boolean(process$1.env.CI) || Boolean(process$1.env.WT_SESSION) || Boolean(process$1.env.TERMINUS_SUBLIME) || process$1.env.ConEmuTask === "{cmd::Cmder}" || process$1.env.TERM_PROGRAM === "Terminus-Sublime" || process$1.env.TERM_PROGRAM === "vscode" || process$1.env.TERM === "xterm-256color" || process$1.env.TERM === "alacritty" || process$1.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
496
+ return usageLines.filter((l3) => typeof l3 === "string").join("\n");
812
497
  }
813
- var unicode = isUnicodeSupported();
814
- var isCI = () => process.env.CI === "true";
815
- var unicodeOr = (o2, e2) => unicode ? o2 : e2;
816
- var S_STEP_ACTIVE = unicodeOr("\u25C6", "*");
817
- var S_STEP_CANCEL = unicodeOr("\u25A0", "x");
818
- var S_STEP_ERROR = unicodeOr("\u25B2", "x");
819
- var S_STEP_SUBMIT = unicodeOr("\u25C7", "o");
820
- var S_BAR_START = unicodeOr("\u250C", "T");
821
- var S_BAR = unicodeOr("\u2502", "|");
822
- var S_BAR_END = unicodeOr("\u2514", "\u2014");
823
- var S_BAR_START_RIGHT = unicodeOr("\u2510", "T");
824
- var S_BAR_END_RIGHT = unicodeOr("\u2518", "\u2014");
825
- var S_RADIO_ACTIVE = unicodeOr("\u25CF", ">");
826
- var S_RADIO_INACTIVE = unicodeOr("\u25CB", " ");
827
- var S_CHECKBOX_ACTIVE = unicodeOr("\u25FB", "[\u2022]");
828
- var S_CHECKBOX_SELECTED = unicodeOr("\u25FC", "[+]");
829
- var S_CHECKBOX_INACTIVE = unicodeOr("\u25FB", "[ ]");
830
- var S_PASSWORD_MASK = unicodeOr("\u25AA", "\u2022");
831
- var S_BAR_H = unicodeOr("\u2500", "-");
832
- var S_CORNER_TOP_RIGHT = unicodeOr("\u256E", "+");
833
- var S_CONNECT_LEFT = unicodeOr("\u251C", "+");
834
- var S_CORNER_BOTTOM_RIGHT = unicodeOr("\u256F", "+");
835
- var S_CORNER_BOTTOM_LEFT = unicodeOr("\u2570", "+");
836
- var S_CORNER_TOP_LEFT = unicodeOr("\u256D", "+");
837
- var S_INFO = unicodeOr("\u25CF", "\u2022");
838
- var S_SUCCESS = unicodeOr("\u25C6", "*");
839
- var S_WARN = unicodeOr("\u25B2", "!");
840
- var S_ERROR = unicodeOr("\u25A0", "x");
841
- var symbol = (o2) => {
842
- switch (o2) {
843
- case "initial":
844
- case "active":
845
- return styleText2("cyan", S_STEP_ACTIVE);
846
- case "cancel":
847
- return styleText2("red", S_STEP_CANCEL);
848
- case "error":
849
- return styleText2("yellow", S_STEP_ERROR);
850
- case "submit":
851
- return styleText2("green", S_STEP_SUBMIT);
498
+ function renderValueHint(arg) {
499
+ const valueHint = arg.valueHint ? `=<${arg.valueHint}>` : "";
500
+ const fallbackValueHint = valueHint || `=<${snakeCase(arg.name)}>`;
501
+ if (!arg.type || arg.type === "positional" || arg.type === "boolean") return valueHint;
502
+ if (arg.type === "enum" && arg.options?.length) return `=<${arg.options.join("|")}>`;
503
+ return fallbackValueHint;
504
+ }
505
+ function renderDescription(arg, required) {
506
+ const requiredHint = required ? gray("(Required)") : "";
507
+ const defaultHint = arg.default === void 0 ? "" : gray(`(Default: ${arg.default})`);
508
+ return [
509
+ arg.description,
510
+ requiredHint,
511
+ defaultHint
512
+ ].filter(Boolean).join(" ");
513
+ }
514
+ async function runMain(cmd, opts = {}) {
515
+ const rawArgs = opts.rawArgs || process.argv.slice(2);
516
+ const showUsage$1 = opts.showUsage || showUsage;
517
+ try {
518
+ const builtinFlags = await _resolveBuiltinFlags(cmd);
519
+ if (builtinFlags.help.length > 0 && rawArgs.some((arg) => builtinFlags.help.includes(arg))) {
520
+ await showUsage$1(...await resolveSubCommand(cmd, rawArgs));
521
+ process.exit(0);
522
+ } else if (rawArgs.length === 1 && builtinFlags.version.includes(rawArgs[0])) {
523
+ const meta = typeof cmd.meta === "function" ? await cmd.meta() : await cmd.meta;
524
+ if (!meta?.version) throw new CLIError("No version specified", "E_NO_VERSION");
525
+ console.log(meta.version);
526
+ } else await runCommand(cmd, { rawArgs });
527
+ } catch (error) {
528
+ if (error instanceof CLIError) {
529
+ await showUsage$1(...await resolveSubCommand(cmd, rawArgs));
530
+ console.error(error.message);
531
+ } else console.error(error, "\n");
532
+ process.exit(1);
852
533
  }
853
- };
854
- var symbolBar = (o2) => {
855
- switch (o2) {
856
- case "initial":
857
- case "active":
858
- return styleText2("cyan", S_BAR);
859
- case "cancel":
860
- return styleText2("red", S_BAR);
861
- case "error":
862
- return styleText2("yellow", S_BAR);
863
- case "submit":
864
- return styleText2("green", S_BAR);
534
+ }
535
+ async function _resolveBuiltinFlags(cmd) {
536
+ const argsDef = await resolveValue(cmd.args || {});
537
+ const userNames = /* @__PURE__ */ new Set();
538
+ const userAliases = /* @__PURE__ */ new Set();
539
+ for (const [name, def] of Object.entries(argsDef)) {
540
+ userNames.add(name);
541
+ for (const alias of toArray(def.alias)) userAliases.add(alias);
865
542
  }
866
- };
867
- function formatInstructionFooter(o2, e2) {
868
- const r3 = [`${e2 ? `${styleText2("cyan", S_BAR)} ` : ""}${o2.join(" \u2022 ")}`];
869
- return e2 && r3.push(styleText2("cyan", S_BAR_END)), r3;
543
+ return {
544
+ help: _getBuiltinFlags("help", "h", userNames, userAliases),
545
+ version: _getBuiltinFlags("version", "v", userNames, userAliases)
546
+ };
870
547
  }
871
- var I = (l3, e2, w2, p2, b2, C2 = false) => {
872
- let r3 = e2, O2 = 0;
873
- if (C2)
874
- for (let i3 = p2 - 1; i3 >= w2; i3--) {
875
- const m2 = l3[i3];
876
- if (m2 && (r3 -= m2.length), O2++, r3 <= b2) break;
877
- }
878
- else
879
- for (let i3 = w2; i3 < p2; i3++) {
880
- const m2 = l3[i3];
881
- if (m2 && (r3 -= m2.length), O2++, r3 <= b2) break;
548
+ function _getBuiltinFlags(long, short, userNames, userAliases) {
549
+ if (userNames.has(long) || userAliases.has(long)) return [];
550
+ if (userNames.has(short) || userAliases.has(short)) return [`--${long}`];
551
+ return [`--${long}`, `-${short}`];
552
+ }
553
+
554
+ // package.json
555
+ var package_default = {
556
+ name: "zapdev",
557
+ version: "1.1.1",
558
+ description: "Fast, performant and lightweight git chores and dev tools using your terminal and an OpenAI-compatible LLM endpoint.",
559
+ type: "module",
560
+ bin: {
561
+ zapdev: "./dist/index.js"
562
+ },
563
+ files: [
564
+ "dist"
565
+ ],
566
+ engines: {
567
+ node: ">=20"
568
+ },
569
+ keywords: [
570
+ "git",
571
+ "cli",
572
+ "commit",
573
+ "conventional-commits",
574
+ "llm",
575
+ "ai"
576
+ ],
577
+ author: "Matthieu Vagnon <hi@mvagnon.dev>",
578
+ license: "MIT",
579
+ repository: {
580
+ type: "git",
581
+ url: "git+https://github.com/mvagnon/zapdev.git"
582
+ },
583
+ homepage: "https://github.com/mvagnon/zapdev#readme",
584
+ bugs: {
585
+ url: "https://github.com/mvagnon/zapdev/issues"
586
+ },
587
+ publishConfig: {
588
+ access: "public"
589
+ },
590
+ scripts: {
591
+ zapdev: "npm run build && node dist/index.js",
592
+ build: "esbuild src/cli.ts --bundle --platform=node --format=esm --target=node20 --loader:.md=text --outfile=dist/cli.js && esbuild src/index.ts --platform=node --format=esm --target=node20 --outfile=dist/index.js",
593
+ lint: "eslint .",
594
+ typecheck: "tsc --noEmit",
595
+ test: "vitest run",
596
+ prepack: "npm run build"
597
+ },
598
+ devDependencies: {
599
+ "@clack/prompts": "^1.6.0",
600
+ "@eslint/js": "^10.0.1",
601
+ "@eslint/json": "^2.0.0",
602
+ "@eslint/markdown": "^8.0.2",
603
+ "@types/node": "^26.1.1",
604
+ citty: "^0.2.2",
605
+ esbuild: "^0.28.1",
606
+ eslint: "^10.6.0",
607
+ jiti: "^2.7.0",
608
+ tinyexec: "^1.2.4",
609
+ typescript: "^6.0.3",
610
+ "typescript-eslint": "^8.62.1",
611
+ vitest: "^4.1.9"
612
+ }
613
+ };
614
+
615
+ // src/commands/commit.ts
616
+ import { basename } from "node:path";
617
+
618
+ // node_modules/@clack/core/dist/index.mjs
619
+ import { styleText } from "node:util";
620
+ import { stdout, stdin } from "node:process";
621
+ import * as l from "node:readline";
622
+ import l__default from "node:readline";
623
+
624
+ // node_modules/fast-string-truncated-width/dist/utils.js
625
+ var getCodePointsLength = /* @__PURE__ */ (() => {
626
+ const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
627
+ return (input) => {
628
+ let surrogatePairsNr = 0;
629
+ SURROGATE_PAIR_RE.lastIndex = 0;
630
+ while (SURROGATE_PAIR_RE.test(input)) {
631
+ surrogatePairsNr += 1;
882
632
  }
883
- return { lineCount: r3, removals: O2 };
633
+ return input.length - surrogatePairsNr;
634
+ };
635
+ })();
636
+ var isFullWidth = (x2) => {
637
+ return x2 === 12288 || x2 >= 65281 && x2 <= 65376 || x2 >= 65504 && x2 <= 65510;
884
638
  };
885
- var limitOptions = ({
886
- cursor: l3,
887
- options: e2,
888
- style: w2,
889
- output: p2 = process.stdout,
890
- maxItems: b2 = Number.POSITIVE_INFINITY,
891
- columnPadding: C2 = 0,
892
- rowPadding: r3 = 4
893
- }) => {
894
- const i3 = getColumns(p2) - C2, m2 = getRows(p2), M = styleText2("dim", "..."), v2 = Math.max(m2 - r3, 0), a3 = Math.max(Math.min(b2, v2), 5);
895
- let f2 = 0;
896
- l3 >= a3 - 3 && (f2 = Math.max(
897
- Math.min(l3 - a3 + 3, e2.length - a3),
898
- 0
899
- ));
900
- let d2 = a3 < e2.length && f2 > 0, c3 = a3 < e2.length && f2 + a3 < e2.length;
901
- const W2 = Math.min(
902
- f2 + a3,
903
- e2.length
904
- ), s2 = [];
905
- let g2 = 0;
906
- d2 && g2++, c3 && g2++;
907
- const T2 = f2 + (d2 ? 1 : 0), y2 = W2 - (c3 ? 1 : 0);
908
- for (let t3 = T2; t3 < y2; t3++) {
909
- const n4 = e2[t3], o2 = n4 ? w2(n4, t3 === l3) : "", h3 = wrapAnsi(o2, i3, {
910
- hard: true,
911
- trim: false
912
- }).split(`
913
- `);
914
- s2.push(h3), g2 += h3.length;
915
- }
916
- if (g2 > v2) {
917
- let t3 = 0, n4 = 0, o2 = g2;
918
- const h3 = l3 - T2;
919
- let u4 = v2;
920
- const L = () => I(s2, o2, 0, h3, u4), E2 = () => I(
921
- s2,
922
- o2,
923
- h3 + 1,
924
- s2.length,
925
- u4,
926
- true
927
- );
928
- d2 ? ({ lineCount: o2, removals: t3 } = L(), o2 > u4 && (c3 || (u4 -= 1), { lineCount: o2, removals: n4 } = E2())) : (c3 || (u4 -= 1), { lineCount: o2, removals: n4 } = E2(), o2 > u4 && (u4 -= 1, { lineCount: o2, removals: t3 } = L())), t3 > 0 && (d2 = true, s2.splice(0, t3)), n4 > 0 && (c3 = true, s2.splice(s2.length - n4, n4));
929
- }
930
- const x2 = [];
931
- d2 && x2.push(M);
932
- for (const t3 of s2)
933
- for (const n4 of t3)
934
- x2.push(n4);
935
- return c3 && x2.push(M), x2;
639
+ var isWideNotCJKTNotEmoji = (x2) => {
640
+ return x2 === 8987 || x2 === 9001 || x2 >= 12272 && x2 <= 12287 || x2 >= 12289 && x2 <= 12350 || x2 >= 12441 && x2 <= 12543 || x2 >= 12549 && x2 <= 12591 || x2 >= 12593 && x2 <= 12686 || x2 >= 12688 && x2 <= 12771 || x2 >= 12783 && x2 <= 12830 || x2 >= 12832 && x2 <= 12871 || x2 >= 12880 && x2 <= 19903 || x2 >= 65040 && x2 <= 65049 || x2 >= 65072 && x2 <= 65106 || x2 >= 65108 && x2 <= 65126 || x2 >= 65128 && x2 <= 65131 || x2 >= 127488 && x2 <= 127490 || x2 >= 127504 && x2 <= 127547 || x2 >= 127552 && x2 <= 127560 || x2 >= 131072 && x2 <= 196605 || x2 >= 196608 && x2 <= 262141;
936
641
  };
937
- var confirm = (i3) => {
938
- const a3 = i3.active ?? "Yes", s2 = i3.inactive ?? "No";
939
- return new r({
940
- active: a3,
941
- inactive: s2,
942
- signal: i3.signal,
943
- input: i3.input,
944
- output: i3.output,
945
- initialValue: i3.initialValue ?? true,
946
- render() {
947
- const e2 = i3.withGuide ?? settings.withGuide, u4 = `${symbol(this.state)} `, l3 = e2 ? `${styleText2("gray", S_BAR)} ` : "", f2 = wrapTextWithPrefix(
948
- i3.output,
949
- i3.message,
950
- l3,
951
- u4
952
- ), o2 = `${e2 ? `${styleText2("gray", S_BAR)}
953
- ` : ""}${f2}
954
- `, c3 = this.value ? a3 : s2;
955
- switch (this.state) {
956
- case "submit": {
957
- const r3 = e2 ? `${styleText2("gray", S_BAR)} ` : "";
958
- return `${o2}${r3}${styleText2("dim", c3)}`;
642
+
643
+ // node_modules/fast-string-truncated-width/dist/index.js
644
+ var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
645
+ var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
646
+ var CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu;
647
+ var TAB_RE = /\t{1,1000}/y;
648
+ var EMOJI_RE = new RegExp("[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F\\u20E3?))*", "yu");
649
+ var LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
650
+ var MODIFIER_RE = new RegExp("\\p{M}+", "gu");
651
+ var NO_TRUNCATION = { limit: Infinity, ellipsis: "" };
652
+ var getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
653
+ const LIMIT = truncationOptions.limit ?? Infinity;
654
+ const ELLIPSIS = truncationOptions.ellipsis ?? "";
655
+ const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION, widthOptions).width : 0);
656
+ const ANSI_WIDTH = 0;
657
+ const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
658
+ const TAB_WIDTH = widthOptions.tabWidth ?? 8;
659
+ const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
660
+ const FULL_WIDTH_WIDTH = 2;
661
+ const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
662
+ const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
663
+ const PARSE_BLOCKS = [
664
+ [LATIN_RE, REGULAR_WIDTH],
665
+ [ANSI_RE, ANSI_WIDTH],
666
+ [CONTROL_RE, CONTROL_WIDTH],
667
+ [TAB_RE, TAB_WIDTH],
668
+ [EMOJI_RE, EMOJI_WIDTH],
669
+ [CJKT_WIDE_RE, WIDE_WIDTH]
670
+ ];
671
+ let indexPrev = 0;
672
+ let index = 0;
673
+ let length = input.length;
674
+ let lengthExtra = 0;
675
+ let truncationEnabled = false;
676
+ let truncationIndex = length;
677
+ let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
678
+ let unmatchedStart = 0;
679
+ let unmatchedEnd = 0;
680
+ let width = 0;
681
+ let widthExtra = 0;
682
+ outer: while (true) {
683
+ if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
684
+ const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
685
+ lengthExtra = 0;
686
+ for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
687
+ const codePoint = char.codePointAt(0) || 0;
688
+ if (isFullWidth(codePoint)) {
689
+ widthExtra = FULL_WIDTH_WIDTH;
690
+ } else if (isWideNotCJKTNotEmoji(codePoint)) {
691
+ widthExtra = WIDE_WIDTH;
692
+ } else {
693
+ widthExtra = REGULAR_WIDTH;
959
694
  }
960
- case "cancel": {
961
- const r3 = e2 ? `${styleText2("gray", S_BAR)} ` : "";
962
- return `${o2}${r3}${styleText2(["strikethrough", "dim"], c3)}${e2 ? `
963
- ${styleText2("gray", S_BAR)}` : ""}`;
695
+ if (width + widthExtra > truncationLimit) {
696
+ truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
964
697
  }
965
- default: {
966
- const r3 = e2 ? `${styleText2("cyan", S_BAR)} ` : "", g2 = e2 ? styleText2("cyan", S_BAR_END) : "";
967
- return `${o2}${r3}${this.value ? `${styleText2("green", S_RADIO_ACTIVE)} ${a3}` : `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", a3)}`}${i3.vertical ? e2 ? `
968
- ${styleText2("cyan", S_BAR)} ` : `
969
- ` : ` ${styleText2("dim", "/")} `}${this.value ? `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", s2)}` : `${styleText2("green", S_RADIO_ACTIVE)} ${s2}`}
970
- ${g2}
971
- `;
698
+ if (width + widthExtra > LIMIT) {
699
+ truncationEnabled = true;
700
+ break outer;
972
701
  }
702
+ lengthExtra += char.length;
703
+ width += widthExtra;
973
704
  }
705
+ unmatchedStart = unmatchedEnd = 0;
974
706
  }
975
- }).prompt();
976
- };
977
- var MULTISELECT_INSTRUCTIONS = [
978
- `${styleText2("dim", "\u2191/\u2193")} to navigate`,
979
- `${styleText2("dim", "Space:")} select`,
980
- `${styleText2("dim", "Enter:")} confirm`
981
- ];
982
- var log = {
983
- message: (s2 = [], {
984
- symbol: e2 = styleText2("gray", S_BAR),
985
- secondarySymbol: r3 = styleText2("gray", S_BAR),
986
- output: m2 = process.stdout,
987
- spacing: l3 = 1,
988
- withGuide: c3
989
- } = {}) => {
990
- const t3 = [], o2 = c3 ?? settings.withGuide, f2 = o2 ? r3 : "", O2 = o2 ? `${e2} ` : "", u4 = o2 ? `${r3} ` : "";
991
- for (let i3 = 0; i3 < l3; i3++)
992
- t3.push(f2);
993
- const g2 = Array.isArray(s2) ? s2 : s2.split(`
994
- `);
995
- if (g2.length > 0) {
996
- const [i3, ...y2] = g2;
997
- i3.length > 0 ? t3.push(`${O2}${i3}`) : t3.push(o2 ? e2 : "");
998
- for (const p2 of y2)
999
- p2.length > 0 ? t3.push(`${u4}${p2}`) : t3.push(o2 ? r3 : "");
707
+ if (index >= length) {
708
+ break outer;
1000
709
  }
1001
- m2.write(`${t3.join(`
1002
- `)}
1003
- `);
1004
- },
1005
- info: (s2, e2) => {
1006
- log.message(s2, { ...e2, symbol: styleText2("blue", S_INFO) });
1007
- },
1008
- success: (s2, e2) => {
1009
- log.message(s2, { ...e2, symbol: styleText2("green", S_SUCCESS) });
1010
- },
1011
- step: (s2, e2) => {
1012
- log.message(s2, { ...e2, symbol: styleText2("green", S_STEP_SUBMIT) });
1013
- },
1014
- warn: (s2, e2) => {
1015
- log.message(s2, { ...e2, symbol: styleText2("yellow", S_WARN) });
1016
- },
1017
- /** alias for `log.warn()`. */
1018
- warning: (s2, e2) => {
1019
- log.warn(s2, e2);
1020
- },
1021
- error: (s2, e2) => {
1022
- log.message(s2, { ...e2, symbol: styleText2("red", S_ERROR) });
710
+ for (let i3 = 0, l3 = PARSE_BLOCKS.length; i3 < l3; i3++) {
711
+ const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i3];
712
+ BLOCK_RE.lastIndex = index;
713
+ if (BLOCK_RE.test(input)) {
714
+ lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
715
+ widthExtra = lengthExtra * BLOCK_WIDTH;
716
+ if (width + widthExtra > truncationLimit) {
717
+ truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
718
+ }
719
+ if (width + widthExtra > LIMIT) {
720
+ truncationEnabled = true;
721
+ break outer;
722
+ }
723
+ width += widthExtra;
724
+ unmatchedStart = indexPrev;
725
+ unmatchedEnd = index;
726
+ index = indexPrev = BLOCK_RE.lastIndex;
727
+ continue outer;
728
+ }
729
+ }
730
+ index += 1;
1023
731
  }
732
+ return {
733
+ width: truncationEnabled ? truncationLimit : width,
734
+ index: truncationEnabled ? truncationIndex : length,
735
+ truncated: truncationEnabled,
736
+ ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
737
+ };
1024
738
  };
1025
- var cancel = (o2 = "", t3) => {
1026
- const i3 = t3?.output ?? process.stdout, e2 = t3?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_END)} ` : "";
1027
- i3.write(`${e2}${styleText2("red", o2)}
739
+ var dist_default = getStringTruncatedWidth;
1028
740
 
1029
- `);
741
+ // node_modules/fast-string-width/dist/index.js
742
+ var NO_TRUNCATION2 = {
743
+ limit: Infinity,
744
+ ellipsis: "",
745
+ ellipsisWidth: 0
1030
746
  };
1031
- var intro = (o2 = "", t3) => {
1032
- const i3 = t3?.output ?? process.stdout, e2 = t3?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_START)} ` : "";
1033
- i3.write(`${e2}${o2}
1034
- `);
747
+ var fastStringWidth = (input, options = {}) => {
748
+ return dist_default(input, NO_TRUNCATION2, options).width;
1035
749
  };
1036
- var outro = (o2 = "", t3) => {
1037
- const i3 = t3?.output ?? process.stdout, e2 = t3?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR)}
1038
- ${styleText2("gray", S_BAR_END)} ` : "";
1039
- i3.write(`${e2}${o2}
750
+ var dist_default2 = fastStringWidth;
1040
751
 
1041
- `);
752
+ // node_modules/fast-wrap-ansi/lib/main.js
753
+ var ESC = "\x1B";
754
+ var CSI = "\x9B";
755
+ var END_CODE = 39;
756
+ var ANSI_ESCAPE_BELL = "\x07";
757
+ var ANSI_CSI = "[";
758
+ var ANSI_OSC = "]";
759
+ var ANSI_SGR_TERMINATOR = "m";
760
+ var ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
761
+ var GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
762
+ var getClosingCode = (openingCode) => {
763
+ if (openingCode >= 30 && openingCode <= 37)
764
+ return 39;
765
+ if (openingCode >= 90 && openingCode <= 97)
766
+ return 39;
767
+ if (openingCode >= 40 && openingCode <= 47)
768
+ return 49;
769
+ if (openingCode >= 100 && openingCode <= 107)
770
+ return 49;
771
+ if (openingCode === 1 || openingCode === 2)
772
+ return 22;
773
+ if (openingCode === 3)
774
+ return 23;
775
+ if (openingCode === 4)
776
+ return 24;
777
+ if (openingCode === 7)
778
+ return 27;
779
+ if (openingCode === 8)
780
+ return 28;
781
+ if (openingCode === 9)
782
+ return 29;
783
+ if (openingCode === 0)
784
+ return 0;
785
+ return void 0;
1042
786
  };
1043
- var W = (l3) => styleText2("magenta", l3);
1044
- var spinner = ({
1045
- indicator: l3 = "dots",
1046
- onCancel: h3,
1047
- output: n4 = process.stdout,
1048
- cancelMessage: G,
1049
- errorMessage: O2,
1050
- frames: E2 = unicode ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"],
1051
- delay: F2 = unicode ? 80 : 120,
1052
- signal: m2,
1053
- ...I3
1054
- } = {}) => {
1055
- const u4 = isCI();
1056
- let M, T2, d2 = false, S2 = false, s2 = "", p2, w2 = performance.now();
1057
- const x2 = getColumns(n4), k2 = I3?.styleFrame ?? W, g2 = (e2) => {
1058
- const r3 = e2 > 1 ? O2 ?? settings.messages.error : G ?? settings.messages.cancel;
1059
- S2 = e2 === 1, d2 && (a3(r3, e2), S2 && typeof h3 == "function" && h3());
1060
- }, f2 = () => g2(2), i3 = () => g2(1), A = () => {
1061
- process.on("uncaughtExceptionMonitor", f2), process.on("unhandledRejection", f2), process.on("SIGINT", i3), process.on("SIGTERM", i3), process.on("exit", g2), m2 && m2.addEventListener("abort", i3);
1062
- }, H = () => {
1063
- process.removeListener("uncaughtExceptionMonitor", f2), process.removeListener("unhandledRejection", f2), process.removeListener("SIGINT", i3), process.removeListener("SIGTERM", i3), process.removeListener("exit", g2), m2 && m2.removeEventListener("abort", i3);
1064
- }, y2 = () => {
1065
- if (p2 === void 0) return;
1066
- u4 && n4.write(`
1067
- `);
1068
- const r3 = wrapAnsi(p2, x2, {
1069
- hard: true,
1070
- trim: false
1071
- }).split(`
1072
- `);
1073
- r3.length > 1 && n4.write(import_sisteransi2.cursor.up(r3.length - 1)), n4.write(import_sisteransi2.cursor.to(0)), n4.write(import_sisteransi2.erase.down());
1074
- }, C2 = (e2) => e2.replace(/\.+$/, ""), _2 = (e2) => {
1075
- const r3 = (performance.now() - e2) / 1e3, t3 = Math.floor(r3 / 60), o2 = Math.floor(r3 % 60);
1076
- return t3 > 0 ? `[${t3}m ${o2}s]` : `[${o2}s]`;
1077
- }, N2 = I3.withGuide ?? settings.withGuide, P2 = (e2 = "") => {
1078
- d2 = true, M = block({ output: n4 }), s2 = C2(e2), w2 = performance.now(), N2 && n4.write(`${styleText2("gray", S_BAR)}
1079
- `);
1080
- let r3 = 0, t3 = 0;
1081
- A(), T2 = setInterval(() => {
1082
- if (u4 && s2 === p2)
1083
- return;
1084
- y2(), p2 = s2;
1085
- const o2 = k2(E2[r3]);
1086
- let v2;
1087
- if (u4)
1088
- v2 = `${o2} ${s2}...`;
1089
- else if (l3 === "timer")
1090
- v2 = `${o2} ${s2} ${_2(w2)}`;
1091
- else {
1092
- const B = ".".repeat(Math.floor(t3)).slice(0, 3);
1093
- v2 = `${o2} ${s2}${B}`;
1094
- }
1095
- const j2 = wrapAnsi(v2, x2, {
1096
- hard: true,
1097
- trim: false
1098
- });
1099
- n4.write(j2), r3 = r3 + 1 < E2.length ? r3 + 1 : 0, t3 = t3 < 4 ? t3 + 0.125 : 0;
1100
- }, F2);
1101
- }, a3 = (e2 = "", r3 = 0, t3 = false) => {
1102
- if (!d2) return;
1103
- d2 = false, clearInterval(T2), y2();
1104
- const o2 = r3 === 0 ? styleText2("green", S_STEP_SUBMIT) : r3 === 1 ? styleText2("red", S_STEP_CANCEL) : styleText2("red", S_STEP_ERROR);
1105
- s2 = e2 ?? s2, t3 || (l3 === "timer" ? n4.write(`${o2} ${s2} ${_2(w2)}
1106
- `) : n4.write(`${o2} ${s2}
1107
- `)), H(), M();
1108
- };
1109
- return {
1110
- start: P2,
1111
- stop: (e2 = "") => a3(e2, 0),
1112
- message: (e2 = "") => {
1113
- s2 = C2(e2 ?? s2);
1114
- },
1115
- cancel: (e2 = "") => a3(e2, 1),
1116
- error: (e2 = "") => a3(e2, 2),
1117
- clear: () => a3("", 0, true),
1118
- get isCancelled() {
1119
- return S2;
787
+ var wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
788
+ var wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
789
+ var wrapWord = (rows, word, columns) => {
790
+ const characters = word[Symbol.iterator]();
791
+ let isInsideEscape = false;
792
+ let isInsideLinkEscape = false;
793
+ let lastRow = rows.at(-1);
794
+ let visible = lastRow === void 0 ? 0 : dist_default2(lastRow);
795
+ let currentCharacter = characters.next();
796
+ let nextCharacter = characters.next();
797
+ let rawCharacterIndex = 0;
798
+ while (!currentCharacter.done) {
799
+ const character = currentCharacter.value;
800
+ const characterLength = dist_default2(character);
801
+ if (visible + characterLength <= columns) {
802
+ rows[rows.length - 1] += character;
803
+ } else {
804
+ rows.push(character);
805
+ visible = 0;
1120
806
  }
1121
- };
1122
- };
1123
- var u2 = {
1124
- light: unicodeOr("\u2500", "-"),
1125
- heavy: unicodeOr("\u2501", "="),
1126
- block: unicodeOr("\u2588", "#")
1127
- };
1128
- var SELECT_INSTRUCTIONS = [
1129
- `${styleText2("dim", "\u2191/\u2193")} to navigate`,
1130
- `${styleText2("dim", "Enter:")} confirm`
1131
- ];
1132
- var c = (t3, o2) => t3.includes(`
1133
- `) ? t3.split(`
1134
- `).map((d2) => o2(d2)).join(`
1135
- `) : o2(t3);
1136
- var select = (t3) => {
1137
- const o2 = (n4, m2) => {
1138
- if (n4 === void 0)
1139
- return "";
1140
- const s2 = n4.label ?? String(n4.value);
1141
- switch (m2) {
1142
- case "disabled":
1143
- return `${styleText2("gray", S_RADIO_INACTIVE)} ${c(s2, (i3) => styleText2("gray", i3))}${n4.hint ? ` ${styleText2("dim", `(${n4.hint ?? "disabled"})`)}` : ""}`;
1144
- case "selected":
1145
- return `${c(s2, (i3) => styleText2("dim", i3))}`;
1146
- case "active":
1147
- return `${styleText2("green", S_RADIO_ACTIVE)} ${s2}${n4.hint ? ` ${styleText2("dim", `(${n4.hint})`)}` : ""}`;
1148
- case "cancelled":
1149
- return `${c(s2, (i3) => styleText2(["strikethrough", "dim"], i3))}`;
1150
- default:
1151
- return `${styleText2("dim", S_RADIO_INACTIVE)} ${c(s2, (i3) => styleText2("dim", i3))}`;
807
+ if (character === ESC || character === CSI) {
808
+ isInsideEscape = true;
809
+ isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
1152
810
  }
1153
- }, d2 = t3.showInstructions ?? true;
1154
- return new n$1({
1155
- options: t3.options,
1156
- signal: t3.signal,
1157
- input: t3.input,
1158
- output: t3.output,
1159
- initialValue: t3.initialValue,
1160
- render() {
1161
- const n4 = t3.withGuide ?? settings.withGuide, m2 = `${symbol(this.state)} `, s2 = `${symbolBar(this.state)} `, i3 = wrapTextWithPrefix(
1162
- t3.output,
1163
- t3.message,
1164
- s2,
1165
- m2
1166
- ), u4 = `${n4 ? `${styleText2("gray", S_BAR)}
1167
- ` : ""}${i3}
1168
- `;
1169
- switch (this.state) {
1170
- case "submit": {
1171
- const r3 = n4 ? `${styleText2("gray", S_BAR)} ` : "", a3 = wrapTextWithPrefix(
1172
- t3.output,
1173
- o2(this.options[this.cursor], "selected"),
1174
- r3
1175
- );
1176
- return `${u4}${a3}`;
1177
- }
1178
- case "cancel": {
1179
- const r3 = n4 ? `${styleText2("gray", S_BAR)} ` : "", a3 = wrapTextWithPrefix(
1180
- t3.output,
1181
- o2(this.options[this.cursor], "cancelled"),
1182
- r3
1183
- );
1184
- return `${u4}${a3}${n4 ? `
1185
- ${styleText2("gray", S_BAR)}` : ""}`;
1186
- }
1187
- default: {
1188
- const r3 = n4 ? `${styleText2("cyan", S_BAR)} ` : "", a3 = u4.split(`
1189
- `).length, p2 = d2 ? formatInstructionFooter(SELECT_INSTRUCTIONS, n4) : n4 ? [styleText2("cyan", S_BAR_END)] : [], b2 = p2.join(`
1190
- `), f2 = p2.length + 1;
1191
- return `${u4}${r3}${limitOptions({
1192
- output: t3.output,
1193
- cursor: this.cursor,
1194
- options: this.options,
1195
- maxItems: t3.maxItems,
1196
- columnPadding: r3.length,
1197
- rowPadding: a3 + f2,
1198
- style: (g2, x2) => o2(g2, g2.disabled ? "disabled" : x2 ? "active" : "inactive")
1199
- }).join(`
1200
- ${r3}`)}
1201
- ${b2}
1202
- `;
811
+ if (isInsideEscape) {
812
+ if (isInsideLinkEscape) {
813
+ if (character === ANSI_ESCAPE_BELL) {
814
+ isInsideEscape = false;
815
+ isInsideLinkEscape = false;
1203
816
  }
817
+ } else if (character === ANSI_SGR_TERMINATOR) {
818
+ isInsideEscape = false;
1204
819
  }
820
+ } else {
821
+ visible += characterLength;
822
+ if (visible === columns && !nextCharacter.done) {
823
+ rows.push("");
824
+ visible = 0;
825
+ }
826
+ }
827
+ currentCharacter = nextCharacter;
828
+ nextCharacter = characters.next();
829
+ rawCharacterIndex += character.length;
830
+ }
831
+ lastRow = rows.at(-1);
832
+ if (!visible && lastRow !== void 0 && lastRow.length && rows.length > 1) {
833
+ rows[rows.length - 2] += rows.pop();
834
+ }
835
+ };
836
+ var stringVisibleTrimSpacesRight = (string) => {
837
+ const words = string.split(" ");
838
+ let last = words.length;
839
+ while (last) {
840
+ if (dist_default2(words[last - 1])) {
841
+ break;
1205
842
  }
1206
- }).prompt();
843
+ last--;
844
+ }
845
+ if (last === words.length) {
846
+ return string;
847
+ }
848
+ return words.slice(0, last).join(" ") + words.slice(last).join("");
1207
849
  };
1208
- var i = `${styleText2("gray", S_BAR)} `;
1209
- var text = (e2) => new n2({
1210
- validate: e2.validate,
1211
- placeholder: e2.placeholder,
1212
- defaultValue: e2.defaultValue,
1213
- initialValue: e2.initialValue,
1214
- output: e2.output,
1215
- signal: e2.signal,
1216
- input: e2.input,
1217
- render() {
1218
- const i3 = e2?.withGuide ?? settings.withGuide, s2 = `${`${i3 ? `${styleText2("gray", S_BAR)}
1219
- ` : ""}${symbol(this.state)} `}${e2.message}
1220
- `, c3 = e2.placeholder && e2.placeholder.length > 0 ? (
1221
- // biome-ignore lint/style/noNonNullAssertion: guarded by placeholder.length > 0
1222
- styleText2("inverse", e2.placeholder[0]) + styleText2("dim", e2.placeholder.slice(1))
1223
- ) : styleText2(["inverse", "hidden"], "_"), o2 = this.userInput ? this.userInputWithCursor : c3, l3 = this.value ?? "";
1224
- switch (this.state) {
1225
- case "error": {
1226
- const n4 = this.error ? ` ${styleText2("yellow", this.error)}` : "", r3 = i3 ? `${styleText2("yellow", S_BAR)} ` : "", d2 = i3 ? styleText2("yellow", S_BAR_END) : "";
1227
- return `${s2.trim()}
1228
- ${r3}${o2}
1229
- ${d2}${n4}
1230
- `;
1231
- }
1232
- case "submit": {
1233
- const n4 = l3 ? ` ${styleText2("dim", l3)}` : "", r3 = i3 ? styleText2("gray", S_BAR) : "";
1234
- return `${s2}${r3}${n4}`;
850
+ var exec = (string, columns, options = {}) => {
851
+ if (options.trim !== false && string.trim() === "") {
852
+ return "";
853
+ }
854
+ let returnValue = "";
855
+ let escapeCode;
856
+ let escapeUrl;
857
+ const words = string.split(" ");
858
+ let rows = [""];
859
+ let rowLength = 0;
860
+ for (let index = 0; index < words.length; index++) {
861
+ const word = words[index];
862
+ if (options.trim !== false) {
863
+ const row = rows.at(-1) ?? "";
864
+ const trimmed = row.trimStart();
865
+ if (row.length !== trimmed.length) {
866
+ rows[rows.length - 1] = trimmed;
867
+ rowLength = dist_default2(trimmed);
1235
868
  }
1236
- case "cancel": {
1237
- const n4 = l3 ? ` ${styleText2(["strikethrough", "dim"], l3)}` : "", r3 = i3 ? styleText2("gray", S_BAR) : "";
1238
- return `${s2}${r3}${n4}${l3.trim() ? `
1239
- ${r3}` : ""}`;
869
+ }
870
+ if (index !== 0) {
871
+ if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
872
+ rows.push("");
873
+ rowLength = 0;
1240
874
  }
1241
- default: {
1242
- const n4 = i3 ? `${styleText2("cyan", S_BAR)} ` : "", r3 = i3 ? styleText2("cyan", S_BAR_END) : "";
1243
- return `${s2}${n4}${o2}
1244
- ${r3}
1245
- `;
875
+ if (rowLength || options.trim === false) {
876
+ rows[rows.length - 1] += " ";
877
+ rowLength++;
1246
878
  }
1247
879
  }
1248
- }
1249
- }).prompt();
1250
-
1251
- // node_modules/citty/dist/_chunks/libs/scule.mjs
1252
- var NUMBER_CHAR_RE = /\d/;
1253
- var STR_SPLITTERS = [
1254
- "-",
1255
- "_",
1256
- "/",
1257
- "."
1258
- ];
1259
- function isUppercase(char = "") {
1260
- if (NUMBER_CHAR_RE.test(char)) return;
1261
- return char !== char.toLowerCase();
1262
- }
1263
- function splitByCase(str, separators) {
1264
- const splitters = separators ?? STR_SPLITTERS;
1265
- const parts = [];
1266
- if (!str || typeof str !== "string") return parts;
1267
- let buff = "";
1268
- let previousUpper;
1269
- let previousSplitter;
1270
- for (const char of str) {
1271
- const isSplitter = splitters.includes(char);
1272
- if (isSplitter === true) {
1273
- parts.push(buff);
1274
- buff = "";
1275
- previousUpper = void 0;
880
+ const wordLength = dist_default2(word);
881
+ if (options.hard && wordLength > columns) {
882
+ const remainingColumns = columns - rowLength;
883
+ const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
884
+ const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);
885
+ if (breaksStartingNextLine < breaksStartingThisLine) {
886
+ rows.push("");
887
+ }
888
+ wrapWord(rows, word, columns);
889
+ rowLength = dist_default2(rows.at(-1) ?? "");
1276
890
  continue;
1277
891
  }
1278
- const isUpper = isUppercase(char);
1279
- if (previousSplitter === false) {
1280
- if (previousUpper === false && isUpper === true) {
1281
- parts.push(buff);
1282
- buff = char;
1283
- previousUpper = isUpper;
892
+ if (rowLength + wordLength > columns && rowLength && wordLength) {
893
+ if (options.wordWrap === false && rowLength < columns) {
894
+ wrapWord(rows, word, columns);
895
+ rowLength = dist_default2(rows.at(-1) ?? "");
1284
896
  continue;
1285
897
  }
1286
- if (previousUpper === true && isUpper === false && buff.length > 1) {
1287
- const lastChar = buff.at(-1);
1288
- parts.push(buff.slice(0, Math.max(0, buff.length - 1)));
1289
- buff = lastChar + char;
1290
- previousUpper = isUpper;
898
+ rows.push("");
899
+ rowLength = 0;
900
+ }
901
+ if (rowLength + wordLength > columns && options.wordWrap === false) {
902
+ wrapWord(rows, word, columns);
903
+ rowLength = dist_default2(rows.at(-1) ?? "");
904
+ continue;
905
+ }
906
+ rows[rows.length - 1] += word;
907
+ rowLength += wordLength;
908
+ }
909
+ if (options.trim !== false) {
910
+ rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
911
+ }
912
+ const preString = rows.join("\n");
913
+ let inSurrogate = false;
914
+ for (let i3 = 0; i3 < preString.length; i3++) {
915
+ const character = preString[i3];
916
+ returnValue += character;
917
+ if (!inSurrogate) {
918
+ inSurrogate = character >= "\uD800" && character <= "\uDBFF";
919
+ if (inSurrogate) {
1291
920
  continue;
1292
921
  }
922
+ } else {
923
+ inSurrogate = false;
924
+ }
925
+ if (character === ESC || character === CSI) {
926
+ GROUP_REGEX.lastIndex = i3 + 1;
927
+ const groupsResult = GROUP_REGEX.exec(preString);
928
+ const groups = groupsResult?.groups;
929
+ if (groups?.code !== void 0) {
930
+ const code = Number.parseFloat(groups.code);
931
+ escapeCode = code === END_CODE ? void 0 : code;
932
+ } else if (groups?.uri !== void 0) {
933
+ escapeUrl = groups.uri.length === 0 ? void 0 : groups.uri;
934
+ }
935
+ }
936
+ if (preString[i3 + 1] === "\n") {
937
+ if (escapeUrl) {
938
+ returnValue += wrapAnsiHyperlink("");
939
+ }
940
+ const closingCode = escapeCode ? getClosingCode(escapeCode) : void 0;
941
+ if (escapeCode && closingCode) {
942
+ returnValue += wrapAnsiCode(closingCode);
943
+ }
944
+ } else if (character === "\n") {
945
+ if (escapeCode && getClosingCode(escapeCode)) {
946
+ returnValue += wrapAnsiCode(escapeCode);
947
+ }
948
+ if (escapeUrl) {
949
+ returnValue += wrapAnsiHyperlink(escapeUrl);
950
+ }
1293
951
  }
1294
- buff += char;
1295
- previousUpper = isUpper;
1296
- previousSplitter = isSplitter;
1297
952
  }
1298
- parts.push(buff);
1299
- return parts;
1300
- }
1301
- function upperFirst(str) {
1302
- return str ? str[0].toUpperCase() + str.slice(1) : "";
1303
- }
1304
- function lowerFirst(str) {
1305
- return str ? str[0].toLowerCase() + str.slice(1) : "";
1306
- }
1307
- function pascalCase(str, opts) {
1308
- return str ? (Array.isArray(str) ? str : splitByCase(str)).map((p2) => upperFirst(opts?.normalize ? p2.toLowerCase() : p2)).join("") : "";
1309
- }
1310
- function camelCase(str, opts) {
1311
- return lowerFirst(pascalCase(str || "", opts));
953
+ return returnValue;
954
+ };
955
+ var CRLF_OR_LF = /\r?\n/;
956
+ function wrapAnsi(string, columns, options) {
957
+ return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join("\n");
1312
958
  }
1313
- function kebabCase(str, joiner) {
1314
- return str ? (Array.isArray(str) ? str : splitByCase(str)).map((p2) => p2.toLowerCase()).join(joiner ?? "-") : "";
959
+
960
+ // node_modules/@clack/core/dist/index.mjs
961
+ var import_sisteransi = __toESM(require_src(), 1);
962
+ import { ReadStream } from "node:tty";
963
+ function findCursor(s2, o2, l3) {
964
+ if (!l3.some((r3) => !r3.disabled))
965
+ return s2;
966
+ const t3 = s2 + o2, n4 = Math.max(l3.length - 1, 0), e2 = t3 < 0 ? n4 : t3 > n4 ? 0 : t3;
967
+ return l3[e2]?.disabled ? findCursor(e2, o2 < 0 ? -1 : 1, l3) : e2;
1315
968
  }
1316
- function snakeCase(str) {
1317
- return kebabCase(str || "", "_");
969
+ var a$1 = ["up", "down", "left", "right", "space", "enter", "cancel"];
970
+ var t = [
971
+ "January",
972
+ "February",
973
+ "March",
974
+ "April",
975
+ "May",
976
+ "June",
977
+ "July",
978
+ "August",
979
+ "September",
980
+ "October",
981
+ "November",
982
+ "December"
983
+ ];
984
+ var settings = {
985
+ actions: new Set(a$1),
986
+ aliases: /* @__PURE__ */ new Map([
987
+ // vim support
988
+ ["k", "up"],
989
+ ["j", "down"],
990
+ ["h", "left"],
991
+ ["l", "right"],
992
+ ["", "cancel"],
993
+ // opinionated defaults!
994
+ ["escape", "cancel"]
995
+ ]),
996
+ messages: {
997
+ cancel: "Canceled",
998
+ error: "Something went wrong"
999
+ },
1000
+ withGuide: true,
1001
+ date: {
1002
+ monthNames: [...t],
1003
+ messages: {
1004
+ required: "Please enter a valid date",
1005
+ invalidMonth: "There are only 12 months in a year",
1006
+ invalidDay: (n4, e2) => `There are only ${n4} days in ${e2}`,
1007
+ afterMin: (n4) => `Date must be on or after ${n4.toISOString().slice(0, 10)}`,
1008
+ beforeMax: (n4) => `Date must be on or before ${n4.toISOString().slice(0, 10)}`
1009
+ }
1010
+ }
1011
+ };
1012
+ function isActionKey(n4, e2) {
1013
+ if (typeof n4 == "string")
1014
+ return settings.aliases.get(n4) === e2;
1015
+ for (const s2 of n4)
1016
+ if (s2 !== void 0 && isActionKey(s2, e2))
1017
+ return true;
1018
+ return false;
1318
1019
  }
1319
-
1320
- // node_modules/citty/dist/index.mjs
1321
- import { parseArgs as parseArgs$1 } from "node:util";
1322
- function toArray(val) {
1323
- if (Array.isArray(val)) return val;
1324
- return val === void 0 ? [] : [val];
1020
+ function diffLines(i3, s2) {
1021
+ if (i3 === s2) return;
1022
+ const e2 = i3.split(`
1023
+ `), t3 = s2.split(`
1024
+ `), r3 = Math.max(e2.length, t3.length), f2 = [];
1025
+ for (let n4 = 0; n4 < r3; n4++)
1026
+ e2[n4] !== t3[n4] && f2.push(n4);
1027
+ return {
1028
+ lines: f2,
1029
+ numLinesBefore: e2.length,
1030
+ numLinesAfter: t3.length,
1031
+ numLines: r3
1032
+ };
1325
1033
  }
1326
- function formatLineColumns(lines, linePrefix = "") {
1327
- const maxLength = [];
1328
- for (const line of lines) for (const [i3, element] of line.entries()) maxLength[i3] = Math.max(maxLength[i3] || 0, element.length);
1329
- return lines.map((l3) => l3.map((c3, i3) => linePrefix + c3[i3 === 0 ? "padStart" : "padEnd"](maxLength[i3])).join(" ")).join("\n");
1034
+ var R = globalThis.process.platform.startsWith("win");
1035
+ var CANCEL_SYMBOL = /* @__PURE__ */ Symbol("clack:cancel");
1036
+ function isCancel(e2) {
1037
+ return e2 === CANCEL_SYMBOL;
1330
1038
  }
1331
- function resolveValue(input) {
1332
- return typeof input === "function" ? input() : input;
1039
+ function setRawMode(e2, r3) {
1040
+ const o2 = e2;
1041
+ o2.isTTY && o2.setRawMode(r3);
1333
1042
  }
1334
- var CLIError = class extends Error {
1335
- code;
1336
- constructor(message, code) {
1337
- super(message);
1338
- this.name = "CLIError";
1339
- this.code = code;
1340
- }
1341
- };
1342
- function parseRawArgs(args = [], opts = {}) {
1343
- const booleans = new Set(opts.boolean || []);
1344
- const strings = new Set(opts.string || []);
1345
- const aliasMap = opts.alias || {};
1346
- const defaults = opts.default || {};
1347
- const aliasToMain = /* @__PURE__ */ new Map();
1348
- const mainToAliases = /* @__PURE__ */ new Map();
1349
- for (const [key, value] of Object.entries(aliasMap)) {
1350
- const targets = value;
1351
- for (const target of targets) {
1352
- aliasToMain.set(key, target);
1353
- if (!mainToAliases.has(target)) mainToAliases.set(target, []);
1354
- mainToAliases.get(target).push(key);
1355
- aliasToMain.set(target, key);
1356
- if (!mainToAliases.has(key)) mainToAliases.set(key, []);
1357
- mainToAliases.get(key).push(target);
1043
+ function block({
1044
+ input: e2 = stdin,
1045
+ output: r3 = stdout,
1046
+ overwrite: o2 = true,
1047
+ hideCursor: t3 = true
1048
+ } = {}) {
1049
+ const s2 = l.createInterface({
1050
+ input: e2,
1051
+ output: r3,
1052
+ prompt: "",
1053
+ tabSize: 1
1054
+ });
1055
+ l.emitKeypressEvents(e2, s2), e2 instanceof ReadStream && e2.isTTY && e2.setRawMode(true);
1056
+ const n4 = (f2, { name: a3, sequence: p2 }) => {
1057
+ const c3 = String(f2);
1058
+ if (isActionKey([c3, a3, p2], "cancel")) {
1059
+ t3 && r3.write(import_sisteransi.cursor.show), process.exit(0);
1060
+ return;
1358
1061
  }
1359
- }
1360
- const options = {};
1361
- function getType(name) {
1362
- if (booleans.has(name)) return "boolean";
1363
- const aliases = mainToAliases.get(name) || [];
1364
- for (const alias of aliases) if (booleans.has(alias)) return "boolean";
1365
- return "string";
1366
- }
1367
- function isStringType(name) {
1368
- if (strings.has(name)) return true;
1369
- const aliases = mainToAliases.get(name) || [];
1370
- for (const alias of aliases) if (strings.has(alias)) return true;
1371
- return false;
1372
- }
1373
- const allOptions = /* @__PURE__ */ new Set([
1374
- ...booleans,
1375
- ...strings,
1376
- ...Object.keys(aliasMap),
1377
- ...Object.values(aliasMap).flat(),
1378
- ...Object.keys(defaults)
1379
- ]);
1380
- for (const name of allOptions) if (!options[name]) options[name] = {
1381
- type: getType(name),
1382
- default: defaults[name]
1062
+ if (!o2) return;
1063
+ const i3 = a3 === "return" ? 0 : -1, m2 = a3 === "return" ? -1 : 0;
1064
+ l.moveCursor(r3, i3, m2, () => {
1065
+ l.clearLine(r3, 1, () => {
1066
+ e2.once("keypress", n4);
1067
+ });
1068
+ });
1383
1069
  };
1384
- for (const [alias, main2] of aliasToMain.entries()) if (alias.length === 1 && options[main2] && !options[main2].short) options[main2].short = alias;
1385
- const processedArgs = [];
1386
- const negatedFlags = {};
1387
- for (let i3 = 0; i3 < args.length; i3++) {
1388
- const arg = args[i3];
1389
- if (arg === "--") {
1390
- processedArgs.push(...args.slice(i3));
1391
- break;
1392
- }
1393
- if (arg.startsWith("--no-")) {
1394
- const flagName = arg.slice(5);
1395
- negatedFlags[flagName] = true;
1396
- continue;
1397
- }
1398
- processedArgs.push(arg);
1070
+ return t3 && r3.write(import_sisteransi.cursor.hide), e2.once("keypress", n4), () => {
1071
+ e2.off("keypress", n4), t3 && r3.write(import_sisteransi.cursor.show), e2 instanceof ReadStream && e2.isTTY && !R && e2.setRawMode(false), s2.terminal = false, s2.close();
1072
+ };
1073
+ }
1074
+ var getColumns = (e2) => "columns" in e2 && typeof e2.columns == "number" ? e2.columns : 80;
1075
+ var getRows = (e2) => "rows" in e2 && typeof e2.rows == "number" ? e2.rows : 20;
1076
+ function wrapTextWithPrefix(e2, r3, o2, t3 = o2, s2 = o2, n4) {
1077
+ const f2 = getColumns(e2 ?? stdout);
1078
+ return wrapAnsi(r3, f2 - o2.length, {
1079
+ hard: true,
1080
+ trim: false
1081
+ }).split(`
1082
+ `).map((c3, i3, m2) => {
1083
+ const d2 = n4 ? n4(c3, i3) : c3;
1084
+ return i3 === 0 ? `${t3}${d2}` : i3 === m2.length - 1 ? `${s2}${d2}` : `${o2}${d2}`;
1085
+ }).join(`
1086
+ `);
1087
+ }
1088
+ function runValidation(e2, n4) {
1089
+ if ("~standard" in e2) {
1090
+ const a3 = e2["~standard"].validate(n4);
1091
+ if (a3 instanceof Promise)
1092
+ throw new TypeError(
1093
+ "Schema validation must be synchronous. Update `validate()` and remove any asynchronous logic."
1094
+ );
1095
+ return a3.issues?.at(0)?.message;
1399
1096
  }
1400
- let parsed;
1401
- try {
1402
- parsed = parseArgs$1({
1403
- args: processedArgs,
1404
- options: Object.keys(options).length > 0 ? options : void 0,
1405
- allowPositionals: true,
1406
- strict: false
1407
- });
1408
- } catch {
1409
- parsed = {
1410
- values: {},
1411
- positionals: processedArgs
1412
- };
1097
+ return e2(n4);
1098
+ }
1099
+ var V = class {
1100
+ input;
1101
+ output;
1102
+ _abortSignal;
1103
+ rl;
1104
+ opts;
1105
+ _render;
1106
+ _track = false;
1107
+ _prevFrame = "";
1108
+ _subscribers = /* @__PURE__ */ new Map();
1109
+ _cursor = 0;
1110
+ state = "initial";
1111
+ error = "";
1112
+ value;
1113
+ userInput = "";
1114
+ constructor(t3, e2 = true) {
1115
+ const { input: i3 = stdin, output: n4 = stdout, render: s2, signal: r3, ...o2 } = t3;
1116
+ this.opts = o2, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = s2.bind(this), this._track = e2, this._abortSignal = r3, this.input = i3, this.output = n4;
1413
1117
  }
1414
- const out = { _: [] };
1415
- out._ = parsed.positionals;
1416
- for (const [key, value] of Object.entries(parsed.values)) {
1417
- let coerced = value;
1418
- if (getType(key) === "boolean" && typeof value === "string") coerced = value !== "false";
1419
- else if (isStringType(key) && typeof value === "boolean") coerced = "";
1420
- out[key] = coerced;
1118
+ /**
1119
+ * Unsubscribe all listeners
1120
+ */
1121
+ unsubscribe() {
1122
+ this._subscribers.clear();
1421
1123
  }
1422
- for (const [name] of Object.entries(negatedFlags)) {
1423
- out[name] = false;
1424
- const mainName = aliasToMain.get(name);
1425
- if (mainName) out[mainName] = false;
1426
- const aliases = mainToAliases.get(name);
1427
- if (aliases) for (const alias of aliases) out[alias] = false;
1124
+ /**
1125
+ * Set a subscriber with opts
1126
+ * @param event - The event name
1127
+ */
1128
+ setSubscriber(t3, e2) {
1129
+ const i3 = this._subscribers.get(t3) ?? [];
1130
+ i3.push(e2), this._subscribers.set(t3, i3);
1428
1131
  }
1429
- for (const [alias, main2] of aliasToMain.entries()) {
1430
- if (out[alias] !== void 0 && out[main2] === void 0) out[main2] = out[alias];
1431
- if (out[main2] !== void 0 && out[alias] === void 0) out[alias] = out[main2];
1432
- if (out[alias] !== out[main2] && defaults[main2] === out[main2]) out[main2] = out[alias];
1132
+ /**
1133
+ * Subscribe to an event
1134
+ * @param event - The event name
1135
+ * @param cb - The callback
1136
+ */
1137
+ on(t3, e2) {
1138
+ this.setSubscriber(t3, { cb: e2 });
1433
1139
  }
1434
- return out;
1435
- }
1436
- var noColor = /* @__PURE__ */ (() => {
1437
- const env = globalThis.process?.env ?? {};
1438
- return env.NO_COLOR === "1" || env.TERM === "dumb" || env.TEST || env.CI;
1439
- })();
1440
- var _c = (c3, r3 = 39) => (t3) => noColor ? t3 : `\x1B[${c3}m${t3}\x1B[${r3}m`;
1441
- var bold = /* @__PURE__ */ _c(1, 22);
1442
- var cyan = /* @__PURE__ */ _c(36);
1443
- var gray = /* @__PURE__ */ _c(90);
1444
- var underline = /* @__PURE__ */ _c(4, 24);
1445
- function parseArgs(rawArgs, argsDef) {
1446
- const parseOptions = {
1447
- boolean: [],
1448
- string: [],
1449
- alias: {},
1450
- default: {}
1451
- };
1452
- const args = resolveArgs(argsDef);
1453
- for (const arg of args) {
1454
- if (arg.type === "positional") continue;
1455
- if (arg.type === "string" || arg.type === "enum") parseOptions.string.push(arg.name);
1456
- else if (arg.type === "boolean") parseOptions.boolean.push(arg.name);
1457
- if (arg.default !== void 0) parseOptions.default[arg.name] = arg.default;
1458
- if (arg.alias) parseOptions.alias[arg.name] = arg.alias;
1459
- const camelName = camelCase(arg.name);
1460
- const kebabName = kebabCase(arg.name);
1461
- if (camelName !== arg.name || kebabName !== arg.name) {
1462
- const existingAliases = toArray(parseOptions.alias[arg.name] || []);
1463
- if (camelName !== arg.name && !existingAliases.includes(camelName)) existingAliases.push(camelName);
1464
- if (kebabName !== arg.name && !existingAliases.includes(kebabName)) existingAliases.push(kebabName);
1465
- if (existingAliases.length > 0) parseOptions.alias[arg.name] = existingAliases;
1466
- }
1140
+ /**
1141
+ * Subscribe to an event once
1142
+ * @param event - The event name
1143
+ * @param cb - The callback
1144
+ */
1145
+ once(t3, e2) {
1146
+ this.setSubscriber(t3, { cb: e2, once: true });
1467
1147
  }
1468
- const parsed = parseRawArgs(rawArgs, parseOptions);
1469
- const [...positionalArguments] = parsed._;
1470
- const parsedArgsProxy = new Proxy(parsed, { get(target, prop) {
1471
- return target[prop] ?? target[camelCase(prop)] ?? target[kebabCase(prop)];
1472
- } });
1473
- for (const [, arg] of args.entries()) if (arg.type === "positional") {
1474
- const nextPositionalArgument = positionalArguments.shift();
1475
- if (nextPositionalArgument !== void 0) parsedArgsProxy[arg.name] = nextPositionalArgument;
1476
- else if (arg.default === void 0 && arg.required !== false) throw new CLIError(`Missing required positional argument: ${arg.name.toUpperCase()}`, "EARG");
1477
- else parsedArgsProxy[arg.name] = arg.default;
1478
- } else if (arg.type === "enum") {
1479
- const argument = parsedArgsProxy[arg.name];
1480
- const options = arg.options || [];
1481
- if (argument !== void 0 && options.length > 0 && !options.includes(argument)) throw new CLIError(`Invalid value for argument: ${cyan(`--${arg.name}`)} (${cyan(argument)}). Expected one of: ${options.map((o2) => cyan(o2)).join(", ")}.`, "EARG");
1482
- } else if (arg.required && parsedArgsProxy[arg.name] === void 0) throw new CLIError(`Missing required argument: --${arg.name}`, "EARG");
1483
- return parsedArgsProxy;
1484
- }
1485
- function resolveArgs(argsDef) {
1486
- const args = [];
1487
- for (const [name, argDef] of Object.entries(argsDef || {})) args.push({
1488
- ...argDef,
1489
- name,
1490
- alias: toArray(argDef.alias)
1491
- });
1492
- return args;
1493
- }
1494
- async function resolvePlugins(plugins) {
1495
- return Promise.all(plugins.map((p2) => resolveValue(p2)));
1496
- }
1497
- function defineCommand(def) {
1498
- return def;
1499
- }
1500
- async function runCommand(cmd, opts) {
1501
- const cmdArgs = await resolveValue(cmd.args || {});
1502
- const parsedArgs = parseArgs(opts.rawArgs, cmdArgs);
1503
- const context = {
1504
- rawArgs: opts.rawArgs,
1505
- args: parsedArgs,
1506
- data: opts.data,
1507
- cmd
1508
- };
1509
- const plugins = await resolvePlugins(cmd.plugins ?? []);
1510
- let result;
1511
- let runError;
1512
- try {
1513
- for (const plugin of plugins) await plugin.setup?.(context);
1514
- if (typeof cmd.setup === "function") await cmd.setup(context);
1515
- const subCommands = await resolveValue(cmd.subCommands);
1516
- if (subCommands && Object.keys(subCommands).length > 0) {
1517
- const subCommandArgIndex = findSubCommandIndex(opts.rawArgs, cmdArgs);
1518
- const explicitName = opts.rawArgs[subCommandArgIndex];
1519
- if (explicitName) {
1520
- const subCommand = await _findSubCommand(subCommands, explicitName);
1521
- if (!subCommand) throw new CLIError(`Unknown command ${cyan(explicitName)}`, "E_UNKNOWN_COMMAND");
1522
- await runCommand(subCommand, { rawArgs: opts.rawArgs.slice(subCommandArgIndex + 1) });
1523
- } else {
1524
- const defaultSubCommand = await resolveValue(cmd.default);
1525
- if (defaultSubCommand) {
1526
- if (cmd.run) throw new CLIError(`Cannot specify both 'run' and 'default' on the same command.`, "E_DEFAULT_CONFLICT");
1527
- const subCommand = await _findSubCommand(subCommands, defaultSubCommand);
1528
- if (!subCommand) throw new CLIError(`Default sub command ${cyan(defaultSubCommand)} not found in subCommands.`, "E_UNKNOWN_COMMAND");
1529
- await runCommand(subCommand, { rawArgs: opts.rawArgs });
1530
- } else if (!cmd.run) throw new CLIError(`No command specified.`, "E_NO_COMMAND");
1148
+ /**
1149
+ * Emit an event with data
1150
+ * @param event - The event name
1151
+ * @param data - The data to pass to the callback
1152
+ */
1153
+ emit(t3, ...e2) {
1154
+ const i3 = this._subscribers.get(t3) ?? [], n4 = [];
1155
+ for (const s2 of i3)
1156
+ s2.cb(...e2), s2.once && n4.push(() => i3.splice(i3.indexOf(s2), 1));
1157
+ for (const s2 of n4)
1158
+ s2();
1159
+ }
1160
+ prompt() {
1161
+ return new Promise((t3) => {
1162
+ if (this._abortSignal) {
1163
+ if (this._abortSignal.aborted)
1164
+ return this.state = "cancel", this.close(), t3(CANCEL_SYMBOL);
1165
+ this._abortSignal.addEventListener(
1166
+ "abort",
1167
+ () => {
1168
+ this.state = "cancel", this.close();
1169
+ },
1170
+ { once: true }
1171
+ );
1531
1172
  }
1532
- }
1533
- if (typeof cmd.run === "function") result = await cmd.run(context);
1534
- } catch (error) {
1535
- runError = error;
1173
+ this.rl = l__default.createInterface({
1174
+ input: this.input,
1175
+ tabSize: 2,
1176
+ prompt: "",
1177
+ escapeCodeTimeout: 50,
1178
+ terminal: true
1179
+ }), this.rl.prompt(), this.opts.initialUserInput !== void 0 && this._setUserInput(this.opts.initialUserInput, true), this.input.on("keypress", this.onKeypress), setRawMode(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => {
1180
+ this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t3(this.value);
1181
+ }), this.once("cancel", () => {
1182
+ this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t3(CANCEL_SYMBOL);
1183
+ });
1184
+ });
1536
1185
  }
1537
- const cleanupErrors = [];
1538
- if (typeof cmd.cleanup === "function") try {
1539
- await cmd.cleanup(context);
1540
- } catch (error) {
1541
- cleanupErrors.push(error);
1186
+ _isActionKey(t3, e2) {
1187
+ return t3 === " ";
1542
1188
  }
1543
- for (const plugin of [...plugins].reverse()) try {
1544
- await plugin.cleanup?.(context);
1545
- } catch (error) {
1546
- cleanupErrors.push(error);
1189
+ _shouldSubmit(t3, e2) {
1190
+ return true;
1547
1191
  }
1548
- if (runError) throw runError;
1549
- if (cleanupErrors.length === 1) throw cleanupErrors[0];
1550
- if (cleanupErrors.length > 1) throw new Error("Multiple cleanup errors", { cause: cleanupErrors });
1551
- return { result };
1552
- }
1553
- async function resolveSubCommand(cmd, rawArgs, parent) {
1554
- const subCommands = await resolveValue(cmd.subCommands);
1555
- if (subCommands && Object.keys(subCommands).length > 0) {
1556
- const subCommandArgIndex = findSubCommandIndex(rawArgs, await resolveValue(cmd.args || {}));
1557
- const subCommandName = rawArgs[subCommandArgIndex];
1558
- const subCommand = await _findSubCommand(subCommands, subCommandName);
1559
- if (subCommand) return resolveSubCommand(subCommand, rawArgs.slice(subCommandArgIndex + 1), cmd);
1192
+ _setValue(t3) {
1193
+ this.value = t3, this.emit("value", this.value);
1560
1194
  }
1561
- return [cmd, parent];
1562
- }
1563
- async function _findSubCommand(subCommands, name) {
1564
- if (name in subCommands) return resolveValue(subCommands[name]);
1565
- for (const sub of Object.values(subCommands)) {
1566
- const resolved = await resolveValue(sub);
1567
- const meta = await resolveValue(resolved?.meta);
1568
- if (meta?.alias) {
1569
- if (toArray(meta.alias).includes(name)) return resolved;
1570
- }
1195
+ _setUserInput(t3, e2) {
1196
+ this.userInput = t3 ?? "", this.emit("userInput", this.userInput), e2 && this._track && this.rl && (this.rl.write(this.userInput), this._cursor = this.rl.cursor);
1571
1197
  }
1572
- }
1573
- function findSubCommandIndex(rawArgs, argsDef) {
1574
- for (let i3 = 0; i3 < rawArgs.length; i3++) {
1575
- const arg = rawArgs[i3];
1576
- if (arg === "--") return -1;
1577
- if (arg.startsWith("-")) {
1578
- if (!arg.includes("=") && _isValueFlag(arg, argsDef)) i3++;
1579
- continue;
1198
+ _clearUserInput() {
1199
+ this.rl?.write(null, { ctrl: true, name: "u" }), this._setUserInput("");
1200
+ }
1201
+ onKeypress(t3, e2) {
1202
+ if (this._track && e2.name !== "return" && (e2.name && this._isActionKey(t3, e2) && this.rl?.write(null, { ctrl: true, name: "h" }), this._cursor = this.rl?.cursor ?? 0, this._setUserInput(this.rl?.line)), this.state === "error" && (this.state = "active"), e2?.name && (!this._track && settings.aliases.has(e2.name) && this.emit("cursor", settings.aliases.get(e2.name)), settings.actions.has(e2.name) && this.emit("cursor", e2.name)), t3 && (t3.toLowerCase() === "y" || t3.toLowerCase() === "n") && this.emit("confirm", t3.toLowerCase() === "y"), this.emit("key", t3, e2), e2?.name === "return" && this._shouldSubmit(t3, e2)) {
1203
+ if (this.opts.validate) {
1204
+ const i3 = runValidation(this.opts.validate, this.value);
1205
+ i3 && (this.error = i3 instanceof Error ? i3.message : i3, this.state = "error", this.rl?.write(this.userInput));
1206
+ }
1207
+ this.state !== "error" && (this.state = "submit");
1580
1208
  }
1581
- return i3;
1209
+ isActionKey([t3, e2?.name, e2?.sequence], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
1582
1210
  }
1583
- return -1;
1584
- }
1585
- function _isValueFlag(flag, argsDef) {
1586
- const name = flag.replace(/^-{1,2}/, "");
1587
- const normalized = camelCase(name);
1588
- for (const [key, def] of Object.entries(argsDef)) {
1589
- if (def.type !== "string" && def.type !== "enum") continue;
1590
- if (normalized === camelCase(key)) return true;
1591
- if ((Array.isArray(def.alias) ? def.alias : def.alias ? [def.alias] : []).includes(name)) return true;
1211
+ close() {
1212
+ this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
1213
+ `), setRawMode(this.input, false), this.rl?.close(), this.rl = void 0, this.emit(`${this.state}`, this.value), this.unsubscribe();
1592
1214
  }
1593
- return false;
1594
- }
1595
- async function showUsage(cmd, parent) {
1596
- try {
1597
- console.log(await renderUsage(cmd, parent) + "\n");
1598
- } catch (error) {
1599
- console.error(error);
1215
+ restoreCursor() {
1216
+ const t3 = wrapAnsi(this._prevFrame, process.stdout.columns, { hard: true, trim: false }).split(`
1217
+ `).length - 1;
1218
+ this.output.write(import_sisteransi.cursor.move(-999, t3 * -1));
1600
1219
  }
1601
- }
1602
- var negativePrefixRe = /^no[-A-Z]/;
1603
- async function renderUsage(cmd, parent) {
1604
- const cmdMeta = await resolveValue(cmd.meta || {});
1605
- const cmdArgs = resolveArgs(await resolveValue(cmd.args || {}));
1606
- const parentMeta = await resolveValue(parent?.meta || {});
1607
- const commandName = `${parentMeta.name ? `${parentMeta.name} ` : ""}` + (cmdMeta.name || process.argv[1]);
1608
- const argLines = [];
1609
- const posLines = [];
1610
- const commandsLines = [];
1611
- const usageLine = [];
1612
- for (const arg of cmdArgs) if (arg.type === "positional") {
1613
- const name = arg.name.toUpperCase();
1614
- const isRequired = arg.required !== false && arg.default === void 0;
1615
- posLines.push([cyan(name + renderValueHint(arg)), renderDescription(arg, isRequired)]);
1616
- usageLine.push(isRequired ? `<${name}>` : `[${name}]`);
1617
- } else {
1618
- const isRequired = arg.required === true && arg.default === void 0;
1619
- const argStr = [...(arg.alias || []).map((a3) => `-${a3}`), `--${arg.name}`].join(", ") + renderValueHint(arg);
1620
- argLines.push([cyan(argStr), renderDescription(arg, isRequired)]);
1621
- if (arg.type === "boolean" && (arg.default === true || arg.negativeDescription) && !negativePrefixRe.test(arg.name)) {
1622
- const negativeArgStr = [...(arg.alias || []).map((a3) => `--no-${a3}`), `--no-${arg.name}`].join(", ");
1623
- argLines.push([cyan(negativeArgStr), [arg.negativeDescription, isRequired ? gray("(Required)") : ""].filter(Boolean).join(" ")]);
1220
+ render() {
1221
+ const t3 = wrapAnsi(this._render(this) ?? "", process.stdout.columns, {
1222
+ hard: true,
1223
+ trim: false
1224
+ });
1225
+ if (t3 !== this._prevFrame) {
1226
+ if (this.state === "initial")
1227
+ this.output.write(import_sisteransi.cursor.hide);
1228
+ else {
1229
+ const e2 = diffLines(this._prevFrame, t3), i3 = getRows(this.output);
1230
+ if (this.restoreCursor(), e2) {
1231
+ const n4 = Math.max(0, e2.numLinesAfter - i3), s2 = Math.max(0, e2.numLinesBefore - i3);
1232
+ let r3 = e2.lines.find((o2) => o2 >= n4);
1233
+ if (r3 === void 0) {
1234
+ this._prevFrame = t3;
1235
+ return;
1236
+ }
1237
+ if (e2.lines.length === 1) {
1238
+ this.output.write(import_sisteransi.cursor.move(0, r3 - s2)), this.output.write(import_sisteransi.erase.lines(1));
1239
+ const o2 = t3.split(`
1240
+ `);
1241
+ this.output.write(o2[r3]), this._prevFrame = t3, this.output.write(import_sisteransi.cursor.move(0, o2.length - r3 - 1));
1242
+ return;
1243
+ } else if (e2.lines.length > 1) {
1244
+ if (n4 < s2)
1245
+ r3 = n4;
1246
+ else {
1247
+ const h3 = r3 - s2;
1248
+ h3 > 0 && this.output.write(import_sisteransi.cursor.move(0, h3));
1249
+ }
1250
+ this.output.write(import_sisteransi.erase.down());
1251
+ const f2 = t3.split(`
1252
+ `).slice(r3);
1253
+ this.output.write(f2.join(`
1254
+ `)), this._prevFrame = t3;
1255
+ return;
1256
+ }
1257
+ }
1258
+ this.output.write(import_sisteransi.erase.down());
1259
+ }
1260
+ this.output.write(t3), this.state === "initial" && (this.state = "active"), this._prevFrame = t3;
1624
1261
  }
1625
- if (isRequired) usageLine.push(`--${arg.name}` + renderValueHint(arg));
1626
1262
  }
1627
- if (cmd.subCommands) {
1628
- const commandNames = [];
1629
- const subCommands = await resolveValue(cmd.subCommands);
1630
- for (const [name, sub] of Object.entries(subCommands)) {
1631
- const meta = await resolveValue((await resolveValue(sub))?.meta);
1632
- if (meta?.hidden) continue;
1633
- const aliases = toArray(meta?.alias);
1634
- const label = [name, ...aliases].join(", ");
1635
- commandsLines.push([cyan(label), meta?.description || ""]);
1636
- commandNames.push(name, ...aliases);
1637
- }
1638
- usageLine.push(commandNames.join("|"));
1263
+ };
1264
+ var r = class extends V {
1265
+ get cursor() {
1266
+ return this.value ? 0 : 1;
1639
1267
  }
1640
- const usageLines = [];
1641
- const version = cmdMeta.version || parentMeta.version;
1642
- usageLines.push(gray(`${cmdMeta.description} (${commandName + (version ? ` v${version}` : "")})`), "");
1643
- const hasOptions = argLines.length > 0 || posLines.length > 0;
1644
- usageLines.push(`${underline(bold("USAGE"))} ${cyan(`${commandName}${hasOptions ? " [OPTIONS]" : ""} ${usageLine.join(" ")}`)}`, "");
1645
- if (posLines.length > 0) {
1646
- usageLines.push(underline(bold("ARGUMENTS")), "");
1647
- usageLines.push(formatLineColumns(posLines, " "));
1648
- usageLines.push("");
1268
+ get _value() {
1269
+ return this.cursor === 0;
1649
1270
  }
1650
- if (argLines.length > 0) {
1651
- usageLines.push(underline(bold("OPTIONS")), "");
1652
- usageLines.push(formatLineColumns(argLines, " "));
1653
- usageLines.push("");
1271
+ constructor(t3) {
1272
+ super(t3, false), this.value = !!t3.initialValue, this.on("userInput", () => {
1273
+ this.value = this._value;
1274
+ }), this.on("confirm", (i3) => {
1275
+ this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = i3, this.state = "submit", this.close();
1276
+ }), this.on("cursor", () => {
1277
+ this.value = !this.value;
1278
+ });
1654
1279
  }
1655
- if (commandsLines.length > 0) {
1656
- usageLines.push(underline(bold("COMMANDS")), "");
1657
- usageLines.push(formatLineColumns(commandsLines, " "));
1658
- usageLines.push("", `Use ${cyan(`${commandName} <command> --help`)} for more information about a command.`);
1280
+ };
1281
+ var n$1 = class n extends V {
1282
+ options;
1283
+ cursor = 0;
1284
+ get _selectedValue() {
1285
+ return this.options[this.cursor];
1659
1286
  }
1660
- return usageLines.filter((l3) => typeof l3 === "string").join("\n");
1661
- }
1662
- function renderValueHint(arg) {
1663
- const valueHint = arg.valueHint ? `=<${arg.valueHint}>` : "";
1664
- const fallbackValueHint = valueHint || `=<${snakeCase(arg.name)}>`;
1665
- if (!arg.type || arg.type === "positional" || arg.type === "boolean") return valueHint;
1666
- if (arg.type === "enum" && arg.options?.length) return `=<${arg.options.join("|")}>`;
1667
- return fallbackValueHint;
1668
- }
1669
- function renderDescription(arg, required) {
1670
- const requiredHint = required ? gray("(Required)") : "";
1671
- const defaultHint = arg.default === void 0 ? "" : gray(`(Default: ${arg.default})`);
1672
- return [
1673
- arg.description,
1674
- requiredHint,
1675
- defaultHint
1676
- ].filter(Boolean).join(" ");
1287
+ changeValue() {
1288
+ const e2 = this._selectedValue;
1289
+ this.value = e2 === void 0 ? void 0 : e2.value;
1290
+ }
1291
+ constructor(e2) {
1292
+ super(e2, false), this.options = e2.options;
1293
+ const o2 = this.options.findIndex(({ value: s2 }) => s2 === e2.initialValue), t3 = o2 === -1 ? 0 : o2;
1294
+ this.cursor = this.options[t3]?.disabled ? findCursor(t3, 1, this.options) : t3, this.changeValue(), this.on("cursor", (s2) => {
1295
+ switch (s2) {
1296
+ case "left":
1297
+ case "up":
1298
+ this.cursor = findCursor(this.cursor, -1, this.options);
1299
+ break;
1300
+ case "down":
1301
+ case "right":
1302
+ this.cursor = findCursor(this.cursor, 1, this.options);
1303
+ break;
1304
+ }
1305
+ this.changeValue();
1306
+ });
1307
+ }
1308
+ };
1309
+ var n2 = class extends V {
1310
+ get userInputWithCursor() {
1311
+ if (this.state === "submit")
1312
+ return this.userInput;
1313
+ const t3 = this.userInput;
1314
+ if (this.cursor >= t3.length)
1315
+ return `${this.userInput}\u2588`;
1316
+ const r3 = t3.slice(0, this.cursor), s2 = t3.slice(this.cursor, this.cursor + 1), e2 = t3.slice(this.cursor + 1);
1317
+ return `${r3}${styleText("inverse", s2)}${e2}`;
1318
+ }
1319
+ get cursor() {
1320
+ return this._cursor;
1321
+ }
1322
+ constructor(t3) {
1323
+ super({
1324
+ ...t3,
1325
+ initialUserInput: t3.initialUserInput ?? t3.initialValue
1326
+ }), this.on("userInput", (r3) => {
1327
+ this._setValue(r3);
1328
+ }), this.on("finalize", () => {
1329
+ this.value || (this.value = t3.defaultValue), this.value === void 0 && (this.value = "");
1330
+ });
1331
+ }
1332
+ };
1333
+
1334
+ // node_modules/@clack/prompts/dist/index.mjs
1335
+ import { styleText as styleText2, stripVTControlCharacters } from "node:util";
1336
+ import process$1 from "node:process";
1337
+ var import_sisteransi2 = __toESM(require_src(), 1);
1338
+ function isUnicodeSupported() {
1339
+ if (process$1.platform !== "win32") {
1340
+ return process$1.env.TERM !== "linux";
1341
+ }
1342
+ return Boolean(process$1.env.CI) || Boolean(process$1.env.WT_SESSION) || Boolean(process$1.env.TERMINUS_SUBLIME) || process$1.env.ConEmuTask === "{cmd::Cmder}" || process$1.env.TERM_PROGRAM === "Terminus-Sublime" || process$1.env.TERM_PROGRAM === "vscode" || process$1.env.TERM === "xterm-256color" || process$1.env.TERM === "alacritty" || process$1.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
1677
1343
  }
1678
- async function runMain(cmd, opts = {}) {
1679
- const rawArgs = opts.rawArgs || process.argv.slice(2);
1680
- const showUsage$1 = opts.showUsage || showUsage;
1681
- try {
1682
- const builtinFlags = await _resolveBuiltinFlags(cmd);
1683
- if (builtinFlags.help.length > 0 && rawArgs.some((arg) => builtinFlags.help.includes(arg))) {
1684
- await showUsage$1(...await resolveSubCommand(cmd, rawArgs));
1685
- process.exit(0);
1686
- } else if (rawArgs.length === 1 && builtinFlags.version.includes(rawArgs[0])) {
1687
- const meta = typeof cmd.meta === "function" ? await cmd.meta() : await cmd.meta;
1688
- if (!meta?.version) throw new CLIError("No version specified", "E_NO_VERSION");
1689
- console.log(meta.version);
1690
- } else await runCommand(cmd, { rawArgs });
1691
- } catch (error) {
1692
- if (error instanceof CLIError) {
1693
- await showUsage$1(...await resolveSubCommand(cmd, rawArgs));
1694
- console.error(error.message);
1695
- } else console.error(error, "\n");
1696
- process.exit(1);
1344
+ var unicode = isUnicodeSupported();
1345
+ var isCI = () => process.env.CI === "true";
1346
+ var unicodeOr = (o2, e2) => unicode ? o2 : e2;
1347
+ var S_STEP_ACTIVE = unicodeOr("\u25C6", "*");
1348
+ var S_STEP_CANCEL = unicodeOr("\u25A0", "x");
1349
+ var S_STEP_ERROR = unicodeOr("\u25B2", "x");
1350
+ var S_STEP_SUBMIT = unicodeOr("\u25C7", "o");
1351
+ var S_BAR_START = unicodeOr("\u250C", "T");
1352
+ var S_BAR = unicodeOr("\u2502", "|");
1353
+ var S_BAR_END = unicodeOr("\u2514", "\u2014");
1354
+ var S_BAR_START_RIGHT = unicodeOr("\u2510", "T");
1355
+ var S_BAR_END_RIGHT = unicodeOr("\u2518", "\u2014");
1356
+ var S_RADIO_ACTIVE = unicodeOr("\u25CF", ">");
1357
+ var S_RADIO_INACTIVE = unicodeOr("\u25CB", " ");
1358
+ var S_CHECKBOX_ACTIVE = unicodeOr("\u25FB", "[\u2022]");
1359
+ var S_CHECKBOX_SELECTED = unicodeOr("\u25FC", "[+]");
1360
+ var S_CHECKBOX_INACTIVE = unicodeOr("\u25FB", "[ ]");
1361
+ var S_PASSWORD_MASK = unicodeOr("\u25AA", "\u2022");
1362
+ var S_BAR_H = unicodeOr("\u2500", "-");
1363
+ var S_CORNER_TOP_RIGHT = unicodeOr("\u256E", "+");
1364
+ var S_CONNECT_LEFT = unicodeOr("\u251C", "+");
1365
+ var S_CORNER_BOTTOM_RIGHT = unicodeOr("\u256F", "+");
1366
+ var S_CORNER_BOTTOM_LEFT = unicodeOr("\u2570", "+");
1367
+ var S_CORNER_TOP_LEFT = unicodeOr("\u256D", "+");
1368
+ var S_INFO = unicodeOr("\u25CF", "\u2022");
1369
+ var S_SUCCESS = unicodeOr("\u25C6", "*");
1370
+ var S_WARN = unicodeOr("\u25B2", "!");
1371
+ var S_ERROR = unicodeOr("\u25A0", "x");
1372
+ var symbol = (o2) => {
1373
+ switch (o2) {
1374
+ case "initial":
1375
+ case "active":
1376
+ return styleText2("cyan", S_STEP_ACTIVE);
1377
+ case "cancel":
1378
+ return styleText2("red", S_STEP_CANCEL);
1379
+ case "error":
1380
+ return styleText2("yellow", S_STEP_ERROR);
1381
+ case "submit":
1382
+ return styleText2("green", S_STEP_SUBMIT);
1383
+ }
1384
+ };
1385
+ var symbolBar = (o2) => {
1386
+ switch (o2) {
1387
+ case "initial":
1388
+ case "active":
1389
+ return styleText2("cyan", S_BAR);
1390
+ case "cancel":
1391
+ return styleText2("red", S_BAR);
1392
+ case "error":
1393
+ return styleText2("yellow", S_BAR);
1394
+ case "submit":
1395
+ return styleText2("green", S_BAR);
1697
1396
  }
1397
+ };
1398
+ function formatInstructionFooter(o2, e2) {
1399
+ const r3 = [`${e2 ? `${styleText2("cyan", S_BAR)} ` : ""}${o2.join(" \u2022 ")}`];
1400
+ return e2 && r3.push(styleText2("cyan", S_BAR_END)), r3;
1698
1401
  }
1699
- async function _resolveBuiltinFlags(cmd) {
1700
- const argsDef = await resolveValue(cmd.args || {});
1701
- const userNames = /* @__PURE__ */ new Set();
1702
- const userAliases = /* @__PURE__ */ new Set();
1703
- for (const [name, def] of Object.entries(argsDef)) {
1704
- userNames.add(name);
1705
- for (const alias of toArray(def.alias)) userAliases.add(alias);
1402
+ var I = (l3, e2, w2, p2, b2, C2 = false) => {
1403
+ let r3 = e2, O2 = 0;
1404
+ if (C2)
1405
+ for (let i3 = p2 - 1; i3 >= w2; i3--) {
1406
+ const m2 = l3[i3];
1407
+ if (m2 && (r3 -= m2.length), O2++, r3 <= b2) break;
1408
+ }
1409
+ else
1410
+ for (let i3 = w2; i3 < p2; i3++) {
1411
+ const m2 = l3[i3];
1412
+ if (m2 && (r3 -= m2.length), O2++, r3 <= b2) break;
1413
+ }
1414
+ return { lineCount: r3, removals: O2 };
1415
+ };
1416
+ var limitOptions = ({
1417
+ cursor: l3,
1418
+ options: e2,
1419
+ style: w2,
1420
+ output: p2 = process.stdout,
1421
+ maxItems: b2 = Number.POSITIVE_INFINITY,
1422
+ columnPadding: C2 = 0,
1423
+ rowPadding: r3 = 4
1424
+ }) => {
1425
+ const i3 = getColumns(p2) - C2, m2 = getRows(p2), M = styleText2("dim", "..."), v2 = Math.max(m2 - r3, 0), a3 = Math.max(Math.min(b2, v2), 5);
1426
+ let f2 = 0;
1427
+ l3 >= a3 - 3 && (f2 = Math.max(
1428
+ Math.min(l3 - a3 + 3, e2.length - a3),
1429
+ 0
1430
+ ));
1431
+ let d2 = a3 < e2.length && f2 > 0, c3 = a3 < e2.length && f2 + a3 < e2.length;
1432
+ const W2 = Math.min(
1433
+ f2 + a3,
1434
+ e2.length
1435
+ ), s2 = [];
1436
+ let g2 = 0;
1437
+ d2 && g2++, c3 && g2++;
1438
+ const T2 = f2 + (d2 ? 1 : 0), y2 = W2 - (c3 ? 1 : 0);
1439
+ for (let t3 = T2; t3 < y2; t3++) {
1440
+ const n4 = e2[t3], o2 = n4 ? w2(n4, t3 === l3) : "", h3 = wrapAnsi(o2, i3, {
1441
+ hard: true,
1442
+ trim: false
1443
+ }).split(`
1444
+ `);
1445
+ s2.push(h3), g2 += h3.length;
1446
+ }
1447
+ if (g2 > v2) {
1448
+ let t3 = 0, n4 = 0, o2 = g2;
1449
+ const h3 = l3 - T2;
1450
+ let u4 = v2;
1451
+ const L = () => I(s2, o2, 0, h3, u4), E2 = () => I(
1452
+ s2,
1453
+ o2,
1454
+ h3 + 1,
1455
+ s2.length,
1456
+ u4,
1457
+ true
1458
+ );
1459
+ d2 ? ({ lineCount: o2, removals: t3 } = L(), o2 > u4 && (c3 || (u4 -= 1), { lineCount: o2, removals: n4 } = E2())) : (c3 || (u4 -= 1), { lineCount: o2, removals: n4 } = E2(), o2 > u4 && (u4 -= 1, { lineCount: o2, removals: t3 } = L())), t3 > 0 && (d2 = true, s2.splice(0, t3)), n4 > 0 && (c3 = true, s2.splice(s2.length - n4, n4));
1706
1460
  }
1707
- return {
1708
- help: _getBuiltinFlags("help", "h", userNames, userAliases),
1709
- version: _getBuiltinFlags("version", "v", userNames, userAliases)
1710
- };
1711
- }
1712
- function _getBuiltinFlags(long, short, userNames, userAliases) {
1713
- if (userNames.has(long) || userAliases.has(long)) return [];
1714
- if (userNames.has(short) || userAliases.has(short)) return [`--${long}`];
1715
- return [`--${long}`, `-${short}`];
1716
- }
1717
-
1718
- // package.json
1719
- var package_default = {
1720
- name: "zapdev",
1721
- version: "1.0.0",
1722
- description: "Fast, performant and lightweight git chores and dev tools using your terminal and an OpenAI-compatible LLM endpoint.",
1723
- type: "module",
1724
- bin: {
1725
- zapdev: "./dist/index.js"
1461
+ const x2 = [];
1462
+ d2 && x2.push(M);
1463
+ for (const t3 of s2)
1464
+ for (const n4 of t3)
1465
+ x2.push(n4);
1466
+ return c3 && x2.push(M), x2;
1467
+ };
1468
+ var confirm = (i3) => {
1469
+ const a3 = i3.active ?? "Yes", s2 = i3.inactive ?? "No";
1470
+ return new r({
1471
+ active: a3,
1472
+ inactive: s2,
1473
+ signal: i3.signal,
1474
+ input: i3.input,
1475
+ output: i3.output,
1476
+ initialValue: i3.initialValue ?? true,
1477
+ render() {
1478
+ const e2 = i3.withGuide ?? settings.withGuide, u4 = `${symbol(this.state)} `, l3 = e2 ? `${styleText2("gray", S_BAR)} ` : "", f2 = wrapTextWithPrefix(
1479
+ i3.output,
1480
+ i3.message,
1481
+ l3,
1482
+ u4
1483
+ ), o2 = `${e2 ? `${styleText2("gray", S_BAR)}
1484
+ ` : ""}${f2}
1485
+ `, c3 = this.value ? a3 : s2;
1486
+ switch (this.state) {
1487
+ case "submit": {
1488
+ const r3 = e2 ? `${styleText2("gray", S_BAR)} ` : "";
1489
+ return `${o2}${r3}${styleText2("dim", c3)}`;
1490
+ }
1491
+ case "cancel": {
1492
+ const r3 = e2 ? `${styleText2("gray", S_BAR)} ` : "";
1493
+ return `${o2}${r3}${styleText2(["strikethrough", "dim"], c3)}${e2 ? `
1494
+ ${styleText2("gray", S_BAR)}` : ""}`;
1495
+ }
1496
+ default: {
1497
+ const r3 = e2 ? `${styleText2("cyan", S_BAR)} ` : "", g2 = e2 ? styleText2("cyan", S_BAR_END) : "";
1498
+ return `${o2}${r3}${this.value ? `${styleText2("green", S_RADIO_ACTIVE)} ${a3}` : `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", a3)}`}${i3.vertical ? e2 ? `
1499
+ ${styleText2("cyan", S_BAR)} ` : `
1500
+ ` : ` ${styleText2("dim", "/")} `}${this.value ? `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", s2)}` : `${styleText2("green", S_RADIO_ACTIVE)} ${s2}`}
1501
+ ${g2}
1502
+ `;
1503
+ }
1504
+ }
1505
+ }
1506
+ }).prompt();
1507
+ };
1508
+ var MULTISELECT_INSTRUCTIONS = [
1509
+ `${styleText2("dim", "\u2191/\u2193")} to navigate`,
1510
+ `${styleText2("dim", "Space:")} select`,
1511
+ `${styleText2("dim", "Enter:")} confirm`
1512
+ ];
1513
+ var log = {
1514
+ message: (s2 = [], {
1515
+ symbol: e2 = styleText2("gray", S_BAR),
1516
+ secondarySymbol: r3 = styleText2("gray", S_BAR),
1517
+ output: m2 = process.stdout,
1518
+ spacing: l3 = 1,
1519
+ withGuide: c3
1520
+ } = {}) => {
1521
+ const t3 = [], o2 = c3 ?? settings.withGuide, f2 = o2 ? r3 : "", O2 = o2 ? `${e2} ` : "", u4 = o2 ? `${r3} ` : "";
1522
+ for (let i3 = 0; i3 < l3; i3++)
1523
+ t3.push(f2);
1524
+ const g2 = Array.isArray(s2) ? s2 : s2.split(`
1525
+ `);
1526
+ if (g2.length > 0) {
1527
+ const [i3, ...y2] = g2;
1528
+ i3.length > 0 ? t3.push(`${O2}${i3}`) : t3.push(o2 ? e2 : "");
1529
+ for (const p2 of y2)
1530
+ p2.length > 0 ? t3.push(`${u4}${p2}`) : t3.push(o2 ? r3 : "");
1531
+ }
1532
+ m2.write(`${t3.join(`
1533
+ `)}
1534
+ `);
1726
1535
  },
1727
- files: [
1728
- "dist"
1729
- ],
1730
- engines: {
1731
- node: ">=20"
1536
+ info: (s2, e2) => {
1537
+ log.message(s2, { ...e2, symbol: styleText2("blue", S_INFO) });
1732
1538
  },
1733
- keywords: [
1734
- "git",
1735
- "cli",
1736
- "commit",
1737
- "conventional-commits",
1738
- "llm",
1739
- "ai"
1740
- ],
1741
- author: "Matthieu Vagnon <hi@mvagnon.dev>",
1742
- license: "MIT",
1743
- repository: {
1744
- type: "git",
1745
- url: "git+https://github.com/mvagnon/zapdev.git"
1539
+ success: (s2, e2) => {
1540
+ log.message(s2, { ...e2, symbol: styleText2("green", S_SUCCESS) });
1746
1541
  },
1747
- homepage: "https://github.com/mvagnon/zapdev#readme",
1748
- bugs: {
1749
- url: "https://github.com/mvagnon/zapdev/issues"
1542
+ step: (s2, e2) => {
1543
+ log.message(s2, { ...e2, symbol: styleText2("green", S_STEP_SUBMIT) });
1750
1544
  },
1751
- publishConfig: {
1752
- access: "public"
1545
+ warn: (s2, e2) => {
1546
+ log.message(s2, { ...e2, symbol: styleText2("yellow", S_WARN) });
1753
1547
  },
1754
- scripts: {
1755
- zapdev: "npm run build && node dist/index.js",
1756
- build: "esbuild src/cli.ts --bundle --platform=node --format=esm --target=node20 --loader:.md=text --outfile=dist/cli.js && esbuild src/index.ts --platform=node --format=esm --target=node20 --outfile=dist/index.js",
1757
- lint: "eslint .",
1758
- typecheck: "tsc --noEmit",
1759
- test: "vitest run",
1760
- prepack: "npm run build"
1548
+ /** alias for `log.warn()`. */
1549
+ warning: (s2, e2) => {
1550
+ log.warn(s2, e2);
1761
1551
  },
1762
- devDependencies: {
1763
- "@clack/prompts": "^1.6.0",
1764
- "@eslint/js": "^10.0.1",
1765
- "@eslint/json": "^2.0.0",
1766
- "@eslint/markdown": "^8.0.2",
1767
- "@types/node": "^26.1.1",
1768
- citty: "^0.2.2",
1769
- esbuild: "^0.28.1",
1770
- eslint: "^10.6.0",
1771
- jiti: "^2.7.0",
1772
- tinyexec: "^1.2.4",
1773
- typescript: "^6.0.3",
1774
- "typescript-eslint": "^8.62.1",
1775
- vitest: "^4.1.9"
1552
+ error: (s2, e2) => {
1553
+ log.message(s2, { ...e2, symbol: styleText2("red", S_ERROR) });
1776
1554
  }
1777
1555
  };
1556
+ var cancel = (o2 = "", t3) => {
1557
+ const i3 = t3?.output ?? process.stdout, e2 = t3?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_END)} ` : "";
1558
+ i3.write(`${e2}${styleText2("red", o2)}
1559
+
1560
+ `);
1561
+ };
1562
+ var intro = (o2 = "", t3) => {
1563
+ const i3 = t3?.output ?? process.stdout, e2 = t3?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_START)} ` : "";
1564
+ i3.write(`${e2}${o2}
1565
+ `);
1566
+ };
1567
+ var outro = (o2 = "", t3) => {
1568
+ const i3 = t3?.output ?? process.stdout, e2 = t3?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR)}
1569
+ ${styleText2("gray", S_BAR_END)} ` : "";
1570
+ i3.write(`${e2}${o2}
1571
+
1572
+ `);
1573
+ };
1574
+ var W = (l3) => styleText2("magenta", l3);
1575
+ var spinner = ({
1576
+ indicator: l3 = "dots",
1577
+ onCancel: h3,
1578
+ output: n4 = process.stdout,
1579
+ cancelMessage: G,
1580
+ errorMessage: O2,
1581
+ frames: E2 = unicode ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"],
1582
+ delay: F2 = unicode ? 80 : 120,
1583
+ signal: m2,
1584
+ ...I3
1585
+ } = {}) => {
1586
+ const u4 = isCI();
1587
+ let M, T2, d2 = false, S2 = false, s2 = "", p2, w2 = performance.now();
1588
+ const x2 = getColumns(n4), k2 = I3?.styleFrame ?? W, g2 = (e2) => {
1589
+ const r3 = e2 > 1 ? O2 ?? settings.messages.error : G ?? settings.messages.cancel;
1590
+ S2 = e2 === 1, d2 && (a3(r3, e2), S2 && typeof h3 == "function" && h3());
1591
+ }, f2 = () => g2(2), i3 = () => g2(1), A = () => {
1592
+ process.on("uncaughtExceptionMonitor", f2), process.on("unhandledRejection", f2), process.on("SIGINT", i3), process.on("SIGTERM", i3), process.on("exit", g2), m2 && m2.addEventListener("abort", i3);
1593
+ }, H = () => {
1594
+ process.removeListener("uncaughtExceptionMonitor", f2), process.removeListener("unhandledRejection", f2), process.removeListener("SIGINT", i3), process.removeListener("SIGTERM", i3), process.removeListener("exit", g2), m2 && m2.removeEventListener("abort", i3);
1595
+ }, y2 = () => {
1596
+ if (p2 === void 0) return;
1597
+ u4 && n4.write(`
1598
+ `);
1599
+ const r3 = wrapAnsi(p2, x2, {
1600
+ hard: true,
1601
+ trim: false
1602
+ }).split(`
1603
+ `);
1604
+ r3.length > 1 && n4.write(import_sisteransi2.cursor.up(r3.length - 1)), n4.write(import_sisteransi2.cursor.to(0)), n4.write(import_sisteransi2.erase.down());
1605
+ }, C2 = (e2) => e2.replace(/\.+$/, ""), _2 = (e2) => {
1606
+ const r3 = (performance.now() - e2) / 1e3, t3 = Math.floor(r3 / 60), o2 = Math.floor(r3 % 60);
1607
+ return t3 > 0 ? `[${t3}m ${o2}s]` : `[${o2}s]`;
1608
+ }, N2 = I3.withGuide ?? settings.withGuide, P2 = (e2 = "") => {
1609
+ d2 = true, M = block({ output: n4 }), s2 = C2(e2), w2 = performance.now(), N2 && n4.write(`${styleText2("gray", S_BAR)}
1610
+ `);
1611
+ let r3 = 0, t3 = 0;
1612
+ A(), T2 = setInterval(() => {
1613
+ if (u4 && s2 === p2)
1614
+ return;
1615
+ y2(), p2 = s2;
1616
+ const o2 = k2(E2[r3]);
1617
+ let v2;
1618
+ if (u4)
1619
+ v2 = `${o2} ${s2}...`;
1620
+ else if (l3 === "timer")
1621
+ v2 = `${o2} ${s2} ${_2(w2)}`;
1622
+ else {
1623
+ const B = ".".repeat(Math.floor(t3)).slice(0, 3);
1624
+ v2 = `${o2} ${s2}${B}`;
1625
+ }
1626
+ const j2 = wrapAnsi(v2, x2, {
1627
+ hard: true,
1628
+ trim: false
1629
+ });
1630
+ n4.write(j2), r3 = r3 + 1 < E2.length ? r3 + 1 : 0, t3 = t3 < 4 ? t3 + 0.125 : 0;
1631
+ }, F2);
1632
+ }, a3 = (e2 = "", r3 = 0, t3 = false) => {
1633
+ if (!d2) return;
1634
+ d2 = false, clearInterval(T2), y2();
1635
+ const o2 = r3 === 0 ? styleText2("green", S_STEP_SUBMIT) : r3 === 1 ? styleText2("red", S_STEP_CANCEL) : styleText2("red", S_STEP_ERROR);
1636
+ s2 = e2 ?? s2, t3 || (l3 === "timer" ? n4.write(`${o2} ${s2} ${_2(w2)}
1637
+ `) : n4.write(`${o2} ${s2}
1638
+ `)), H(), M();
1639
+ };
1640
+ return {
1641
+ start: P2,
1642
+ stop: (e2 = "") => a3(e2, 0),
1643
+ message: (e2 = "") => {
1644
+ s2 = C2(e2 ?? s2);
1645
+ },
1646
+ cancel: (e2 = "") => a3(e2, 1),
1647
+ error: (e2 = "") => a3(e2, 2),
1648
+ clear: () => a3("", 0, true),
1649
+ get isCancelled() {
1650
+ return S2;
1651
+ }
1652
+ };
1653
+ };
1654
+ var u2 = {
1655
+ light: unicodeOr("\u2500", "-"),
1656
+ heavy: unicodeOr("\u2501", "="),
1657
+ block: unicodeOr("\u2588", "#")
1658
+ };
1659
+ var SELECT_INSTRUCTIONS = [
1660
+ `${styleText2("dim", "\u2191/\u2193")} to navigate`,
1661
+ `${styleText2("dim", "Enter:")} confirm`
1662
+ ];
1663
+ var c = (t3, o2) => t3.includes(`
1664
+ `) ? t3.split(`
1665
+ `).map((d2) => o2(d2)).join(`
1666
+ `) : o2(t3);
1667
+ var select = (t3) => {
1668
+ const o2 = (n4, m2) => {
1669
+ if (n4 === void 0)
1670
+ return "";
1671
+ const s2 = n4.label ?? String(n4.value);
1672
+ switch (m2) {
1673
+ case "disabled":
1674
+ return `${styleText2("gray", S_RADIO_INACTIVE)} ${c(s2, (i3) => styleText2("gray", i3))}${n4.hint ? ` ${styleText2("dim", `(${n4.hint ?? "disabled"})`)}` : ""}`;
1675
+ case "selected":
1676
+ return `${c(s2, (i3) => styleText2("dim", i3))}`;
1677
+ case "active":
1678
+ return `${styleText2("green", S_RADIO_ACTIVE)} ${s2}${n4.hint ? ` ${styleText2("dim", `(${n4.hint})`)}` : ""}`;
1679
+ case "cancelled":
1680
+ return `${c(s2, (i3) => styleText2(["strikethrough", "dim"], i3))}`;
1681
+ default:
1682
+ return `${styleText2("dim", S_RADIO_INACTIVE)} ${c(s2, (i3) => styleText2("dim", i3))}`;
1683
+ }
1684
+ }, d2 = t3.showInstructions ?? true;
1685
+ return new n$1({
1686
+ options: t3.options,
1687
+ signal: t3.signal,
1688
+ input: t3.input,
1689
+ output: t3.output,
1690
+ initialValue: t3.initialValue,
1691
+ render() {
1692
+ const n4 = t3.withGuide ?? settings.withGuide, m2 = `${symbol(this.state)} `, s2 = `${symbolBar(this.state)} `, i3 = wrapTextWithPrefix(
1693
+ t3.output,
1694
+ t3.message,
1695
+ s2,
1696
+ m2
1697
+ ), u4 = `${n4 ? `${styleText2("gray", S_BAR)}
1698
+ ` : ""}${i3}
1699
+ `;
1700
+ switch (this.state) {
1701
+ case "submit": {
1702
+ const r3 = n4 ? `${styleText2("gray", S_BAR)} ` : "", a3 = wrapTextWithPrefix(
1703
+ t3.output,
1704
+ o2(this.options[this.cursor], "selected"),
1705
+ r3
1706
+ );
1707
+ return `${u4}${a3}`;
1708
+ }
1709
+ case "cancel": {
1710
+ const r3 = n4 ? `${styleText2("gray", S_BAR)} ` : "", a3 = wrapTextWithPrefix(
1711
+ t3.output,
1712
+ o2(this.options[this.cursor], "cancelled"),
1713
+ r3
1714
+ );
1715
+ return `${u4}${a3}${n4 ? `
1716
+ ${styleText2("gray", S_BAR)}` : ""}`;
1717
+ }
1718
+ default: {
1719
+ const r3 = n4 ? `${styleText2("cyan", S_BAR)} ` : "", a3 = u4.split(`
1720
+ `).length, p2 = d2 ? formatInstructionFooter(SELECT_INSTRUCTIONS, n4) : n4 ? [styleText2("cyan", S_BAR_END)] : [], b2 = p2.join(`
1721
+ `), f2 = p2.length + 1;
1722
+ return `${u4}${r3}${limitOptions({
1723
+ output: t3.output,
1724
+ cursor: this.cursor,
1725
+ options: this.options,
1726
+ maxItems: t3.maxItems,
1727
+ columnPadding: r3.length,
1728
+ rowPadding: a3 + f2,
1729
+ style: (g2, x2) => o2(g2, g2.disabled ? "disabled" : x2 ? "active" : "inactive")
1730
+ }).join(`
1731
+ ${r3}`)}
1732
+ ${b2}
1733
+ `;
1734
+ }
1735
+ }
1736
+ }
1737
+ }).prompt();
1738
+ };
1739
+ var i = `${styleText2("gray", S_BAR)} `;
1740
+ var text = (e2) => new n2({
1741
+ validate: e2.validate,
1742
+ placeholder: e2.placeholder,
1743
+ defaultValue: e2.defaultValue,
1744
+ initialValue: e2.initialValue,
1745
+ output: e2.output,
1746
+ signal: e2.signal,
1747
+ input: e2.input,
1748
+ render() {
1749
+ const i3 = e2?.withGuide ?? settings.withGuide, s2 = `${`${i3 ? `${styleText2("gray", S_BAR)}
1750
+ ` : ""}${symbol(this.state)} `}${e2.message}
1751
+ `, c3 = e2.placeholder && e2.placeholder.length > 0 ? (
1752
+ // biome-ignore lint/style/noNonNullAssertion: guarded by placeholder.length > 0
1753
+ styleText2("inverse", e2.placeholder[0]) + styleText2("dim", e2.placeholder.slice(1))
1754
+ ) : styleText2(["inverse", "hidden"], "_"), o2 = this.userInput ? this.userInputWithCursor : c3, l3 = this.value ?? "";
1755
+ switch (this.state) {
1756
+ case "error": {
1757
+ const n4 = this.error ? ` ${styleText2("yellow", this.error)}` : "", r3 = i3 ? `${styleText2("yellow", S_BAR)} ` : "", d2 = i3 ? styleText2("yellow", S_BAR_END) : "";
1758
+ return `${s2.trim()}
1759
+ ${r3}${o2}
1760
+ ${d2}${n4}
1761
+ `;
1762
+ }
1763
+ case "submit": {
1764
+ const n4 = l3 ? ` ${styleText2("dim", l3)}` : "", r3 = i3 ? styleText2("gray", S_BAR) : "";
1765
+ return `${s2}${r3}${n4}`;
1766
+ }
1767
+ case "cancel": {
1768
+ const n4 = l3 ? ` ${styleText2(["strikethrough", "dim"], l3)}` : "", r3 = i3 ? styleText2("gray", S_BAR) : "";
1769
+ return `${s2}${r3}${n4}${l3.trim() ? `
1770
+ ${r3}` : ""}`;
1771
+ }
1772
+ default: {
1773
+ const n4 = i3 ? `${styleText2("cyan", S_BAR)} ` : "", r3 = i3 ? styleText2("cyan", S_BAR_END) : "";
1774
+ return `${s2}${n4}${o2}
1775
+ ${r3}
1776
+ `;
1777
+ }
1778
+ }
1779
+ }
1780
+ }).prompt();
1778
1781
 
1779
1782
  // src/types/commit.ts
1780
1783
  var COMMIT_TYPES = [
@@ -2162,40 +2165,8 @@ var R2 = (e2, t3, n4) => {
2162
2165
  };
2163
2166
  var z = R2;
2164
2167
 
2165
- // src/lib/branches.ts
2166
- function parseDefaultBranch(originHead) {
2167
- const trimmed = originHead.trim();
2168
- if (!trimmed) return null;
2169
- return trimmed.replace(/^origin\//, "");
2170
- }
2171
- function parseBranches(raw) {
2172
- return raw.split("\n").map((branch) => branch.trim()).filter(Boolean);
2173
- }
2174
- function deletableBranches(all, protectedBranches) {
2175
- const kept = new Set(protectedBranches.filter(Boolean));
2176
- return all.filter((branch) => !kept.has(branch));
2177
- }
2178
-
2179
- // src/lib/worktrees.ts
2180
- var WORKTREE_PREFIX = "worktree ";
2181
- var BRANCH_PREFIX = "branch ";
2182
- function parseWorktrees(porcelain) {
2183
- const worktrees = [];
2184
- let current = null;
2185
- for (const line of porcelain.split("\n")) {
2186
- if (line.startsWith(WORKTREE_PREFIX)) {
2187
- current = { path: line.slice(WORKTREE_PREFIX.length).trim(), branch: null };
2188
- worktrees.push(current);
2189
- } else if (current && line.startsWith(BRANCH_PREFIX)) {
2190
- current.branch = line.slice(BRANCH_PREFIX.length).trim().replace(/^refs\/heads\//, "");
2191
- }
2192
- }
2193
- return worktrees;
2194
- }
2195
-
2196
2168
  // src/lib/git.ts
2197
2169
  var UPSTREAM_REF = "@{upstream}";
2198
- var BRANCH_FORMAT = "%(refname:short)";
2199
2170
  async function git(args, cwd) {
2200
2171
  const result = await R2("git", args, { nodeOptions: { cwd } });
2201
2172
  if (result.exitCode !== 0) {
@@ -2207,98 +2178,52 @@ async function tryGit(args, cwd) {
2207
2178
  const result = await R2("git", args, { nodeOptions: { cwd } });
2208
2179
  return result.exitCode === 0 ? result.stdout : null;
2209
2180
  }
2210
- async function stageAll() {
2211
- await git(["add", "-A"]);
2181
+ async function stageAll(repo) {
2182
+ await git(["add", "-A"], repo);
2212
2183
  }
2213
- async function getStagedDiff() {
2214
- return git(["diff", "--cached"]);
2184
+ async function getStagedDiff(repo) {
2185
+ return git(["diff", "--cached"], repo);
2215
2186
  }
2216
- async function commit(message) {
2217
- await git(["commit", "-m", message]);
2187
+ async function commit(repo, message) {
2188
+ await git(["commit", "-m", message], repo);
2218
2189
  }
2219
- async function currentBranch() {
2220
- return (await git(["symbolic-ref", "--short", "HEAD"])).trim();
2190
+ async function currentBranch(repo) {
2191
+ return (await git(["symbolic-ref", "--short", "HEAD"], repo)).trim();
2221
2192
  }
2222
- async function hasUpstream() {
2223
- const result = await tryGit(["rev-parse", "--abbrev-ref", "--symbolic-full-name", UPSTREAM_REF]);
2193
+ async function hasUpstream(repo) {
2194
+ const result = await tryGit(["rev-parse", "--abbrev-ref", "--symbolic-full-name", UPSTREAM_REF], repo);
2224
2195
  return result !== null;
2225
2196
  }
2226
- async function push() {
2227
- await git(["push"]);
2197
+ async function push(repo) {
2198
+ await git(["push"], repo);
2228
2199
  }
2229
- async function pushSetUpstream(branch) {
2230
- await git(["push", "-u", "origin", branch]);
2200
+ async function pushSetUpstream(repo, branch) {
2201
+ await git(["push", "-u", "origin", branch], repo);
2231
2202
  }
2232
- async function pullRebase() {
2233
- await git(["pull", "--rebase"]);
2203
+ async function pullRebase(repo) {
2204
+ await git(["pull", "--rebase"], repo);
2234
2205
  }
2235
- async function pullMerge() {
2236
- await git(["pull", "--no-rebase", "--no-edit"]);
2206
+ async function pullMerge(repo) {
2207
+ await git(["pull", "--no-rebase", "--no-edit"], repo);
2237
2208
  }
2238
- async function fetchRemote() {
2239
- await git(["fetch"]);
2209
+ async function fetchRemote(repo) {
2210
+ await git(["fetch"], repo);
2240
2211
  }
2241
- async function behindCount() {
2242
- const out = await tryGit(["rev-list", "--count", `HEAD..${UPSTREAM_REF}`]);
2212
+ async function behindCount(repo) {
2213
+ const out = await tryGit(["rev-list", "--count", `HEAD..${UPSTREAM_REF}`], repo);
2243
2214
  return out === null ? 0 : Number(out.trim()) || 0;
2244
2215
  }
2245
2216
  async function findRepos(path) {
2246
- if (await isGitRepo(path)) return [path];
2217
+ const root = await repoRoot(path);
2218
+ if (root) return [root];
2247
2219
  const entries = await readdir(path, { withFileTypes: true }).catch(() => null);
2248
2220
  if (!entries) return [];
2249
2221
  const dirs = entries.filter((entry) => entry.isDirectory() && entry.name !== "node_modules");
2250
- const repos = await Promise.all(
2251
- dirs.map(async (entry) => {
2252
- const dir = join(path, entry.name);
2253
- return await isGitRepo(dir) ? dir : null;
2254
- })
2255
- );
2222
+ const repos = await Promise.all(dirs.map((entry) => repoRoot(join(path, entry.name))));
2256
2223
  return repos.filter((dir) => dir !== null).sort();
2257
2224
  }
2258
- async function isGitRepo(dir) {
2259
- const entries = await readdir(dir, { withFileTypes: true }).catch(() => null);
2260
- return entries?.some((entry) => entry.name === ".git" && entry.isDirectory()) ?? false;
2261
- }
2262
- async function fetchPrune(repo) {
2263
- await git(["fetch", "--prune"], repo);
2264
- }
2265
- async function defaultBranch(repo) {
2266
- const output = await tryGit(
2267
- ["symbolic-ref", "--quiet", "--short", "refs/remotes/origin/HEAD"],
2268
- repo
2269
- );
2270
- return output === null ? null : parseDefaultBranch(output);
2271
- }
2272
- async function currentBranchAt(repo) {
2273
- const output = await tryGit(["symbolic-ref", "--quiet", "--short", "HEAD"], repo);
2274
- return output === null ? null : output.trim();
2275
- }
2276
- async function localBranches(repo) {
2277
- return parseBranches(await git(["branch", `--format=${BRANCH_FORMAT}`], repo));
2278
- }
2279
- async function branchExists(repo, branch) {
2280
- const local = await tryGit(["show-ref", "--verify", "--quiet", `refs/heads/${branch}`], repo);
2281
- if (local !== null) return true;
2282
- const remote = await tryGit(
2283
- ["show-ref", "--verify", "--quiet", `refs/remotes/origin/${branch}`],
2284
- repo
2285
- );
2286
- return remote !== null;
2287
- }
2288
- async function listWorktrees(repo) {
2289
- return parseWorktrees(await git(["worktree", "list", "--porcelain"], repo));
2290
- }
2291
- async function removeWorktree(repo, path) {
2292
- await git(["worktree", "remove", "--force", path], repo);
2293
- }
2294
- async function switchBranch(repo, branch) {
2295
- await git(["switch", branch], repo);
2296
- }
2297
- async function deleteBranch(repo, branch) {
2298
- await git(["branch", "-D", branch], repo);
2299
- }
2300
- async function pull(repo) {
2301
- await git(["pull"], repo);
2225
+ async function repoRoot(dir) {
2226
+ return (await tryGit(["rev-parse", "--show-toplevel"], dir))?.trim() ?? null;
2302
2227
  }
2303
2228
 
2304
2229
  // src/lib/errors.ts
@@ -2318,8 +2243,11 @@ async function hasGitleaks() {
2318
2243
  throw error;
2319
2244
  }
2320
2245
  }
2321
- async function scanStagedChanges() {
2322
- const result = await R2("gitleaks", ["git", "--staged"], { nodePath: false });
2246
+ async function scanStagedChanges(repo) {
2247
+ const result = await R2("gitleaks", ["git", "--staged", "--verbose"], {
2248
+ nodePath: false,
2249
+ nodeOptions: { cwd: repo }
2250
+ });
2323
2251
  if (result.exitCode === 0) return;
2324
2252
  const output = result.stderr.trim() || result.stdout.trim();
2325
2253
  throw new Error(output || "gitleaks git --staged failed");
@@ -2402,7 +2330,7 @@ function messageContent(body) {
2402
2330
  var commitCommand = defineCommand({
2403
2331
  meta: {
2404
2332
  name: "commit",
2405
- description: "Stage all changes and commit with an LLM-generated Conventional Commits message."
2333
+ description: "Generate and review commit messages for the current repo or direct child repos."
2406
2334
  },
2407
2335
  args: {
2408
2336
  url: {
@@ -2477,144 +2405,165 @@ var commitCommand = defineCommand({
2477
2405
  return;
2478
2406
  }
2479
2407
  if (interactive) intro("zapdev commit");
2480
- if (!args.staged) await stageAll();
2481
- const diff = await getStagedDiff();
2482
- if (!diff.trim()) {
2483
- log.warn("Nothing to commit.");
2408
+ const repos = await findRepos(process.cwd());
2409
+ if (repos.length === 0) {
2410
+ log.warn("No git repository found here or in direct children.");
2484
2411
  if (interactive) outro("Nothing to do.");
2485
2412
  return;
2486
2413
  }
2414
+ let scan;
2487
2415
  try {
2488
- if (await hasGitleaks()) {
2489
- const scanLoader = interactive ? spinner() : void 0;
2490
- scanLoader?.start("Scanning staged changes with Gitleaks");
2491
- try {
2492
- await scanStagedChanges();
2493
- scanLoader?.stop("No leaks found");
2494
- } catch (error) {
2495
- scanLoader?.error("Gitleaks check failed");
2496
- throw error;
2497
- }
2498
- } else {
2499
- log.info("Gitleaks not found, skipping secret scan.");
2500
- }
2416
+ scan = await hasGitleaks();
2501
2417
  } catch (error) {
2502
2418
  log.error(`Gitleaks check failed: ${errorMessage(error)}`);
2503
2419
  process.exitCode = 1;
2504
2420
  return;
2505
2421
  }
2422
+ if (!scan) log.info("Gitleaks not found, skipping secret scan.");
2506
2423
  const loader = interactive ? spinner() : void 0;
2507
- loader?.start("Generating commit message");
2508
- let message;
2509
- try {
2510
- message = await generateCommitMessage(diff, config, type);
2511
- } catch (error) {
2512
- loader?.error("Generation failed");
2513
- log.error(`Generation failed: ${errorMessage(error)}`);
2514
- process.exitCode = 1;
2424
+ loader?.start("Preparing repositories and generating commit messages in parallel");
2425
+ const results = await Promise.allSettled(repos.map(async (repo) => {
2426
+ if (!args.staged) await stageAll(repo);
2427
+ const diff = await getStagedDiff(repo);
2428
+ if (!diff.trim()) return null;
2429
+ if (scan) await scanStagedChanges(repo);
2430
+ const message = await generateCommitMessage(diff, config, type);
2431
+ if (!message) throw new Error("The model returned an empty message.");
2432
+ return { repo, message };
2433
+ }));
2434
+ loader?.stop("Repositories prepared");
2435
+ const drafts = [];
2436
+ for (const [index, result] of results.entries()) {
2437
+ if (result.status === "rejected") {
2438
+ log.error(`${basename(repos[index])}: ${errorMessage(result.reason)}`);
2439
+ process.exitCode = 1;
2440
+ } else if (result.value) {
2441
+ drafts.push(result.value);
2442
+ } else {
2443
+ log.info(`${basename(repos[index])}: nothing to commit.`);
2444
+ }
2445
+ }
2446
+ if (drafts.length === 0) {
2447
+ if (interactive) outro("No commits prepared.");
2515
2448
  return;
2516
2449
  }
2517
- if (!message) {
2518
- loader?.error("Generation failed");
2519
- log.error("Generation failed: the model returned an empty message.");
2520
- process.exitCode = 1;
2450
+ const selected = await reviewMessages(drafts, interactive && !args.yes);
2451
+ if (!selected) {
2452
+ cancel("Cancelled (changes left staged).");
2521
2453
  return;
2522
2454
  }
2523
- if (loader) loader.stop(message);
2524
- else log.message(message);
2525
- let finalMessage = message;
2526
- if (interactive && !args.yes) {
2527
- const action = await select({
2528
- message: "Action",
2529
- initialValue: "commit",
2530
- options: [
2531
- { value: "commit", label: "Commit" },
2532
- { value: "edit", label: "Edit message" },
2533
- { value: "cancel", label: "Cancel" }
2534
- ]
2535
- });
2536
- if (isCancel(action) || action === "cancel") {
2537
- cancel("Cancelled (changes left staged).");
2538
- return;
2539
- }
2540
- if (action === "edit") {
2541
- const edited = await text({
2542
- message: "Edit message",
2543
- initialValue: message
2544
- });
2545
- if (isCancel(edited)) {
2546
- cancel("Cancelled (changes left staged).");
2547
- return;
2548
- }
2549
- finalMessage = edited.trim();
2550
- if (!finalMessage) {
2551
- cancel("Empty message, cancelled.");
2552
- return;
2553
- }
2455
+ const committed = [];
2456
+ for (const draft of selected) {
2457
+ try {
2458
+ await commit(draft.repo, draft.message);
2459
+ committed.push(draft);
2460
+ log.success(`${basename(draft.repo)}: committed ${draft.message}`);
2461
+ } catch (error) {
2462
+ log.error(`${basename(draft.repo)}: commit failed: ${errorMessage(error)}`);
2463
+ process.exitCode = 1;
2554
2464
  }
2555
2465
  }
2556
- await commit(finalMessage);
2557
- if (interactive) log.success(`Committed: ${finalMessage}`);
2466
+ if (committed.length === 0) return;
2558
2467
  let shouldPush = Boolean(args.push);
2559
2468
  if (!shouldPush && interactive && !args.yes) {
2560
- const answer = await confirm({ message: "Push?", initialValue: false });
2469
+ const answer = await confirm({
2470
+ message: `Push ${committed.map(({ repo }) => basename(repo)).join(", ")}?`,
2471
+ initialValue: false
2472
+ });
2561
2473
  if (isCancel(answer)) {
2562
- if (interactive) outro("Committed. Not pushed.");
2474
+ outro("Committed. Not pushed.");
2563
2475
  return;
2564
2476
  }
2565
2477
  shouldPush = answer;
2566
2478
  }
2567
2479
  if (shouldPush) {
2568
- const pushed = await pushOptimistic(
2569
- interactive,
2570
- interactive && !args.yes,
2571
- syncStrategy
2572
- );
2573
- if (!pushed) {
2574
- process.exitCode = 1;
2575
- return;
2480
+ for (const { repo } of committed) {
2481
+ try {
2482
+ const pushed = await pushOptimistic(
2483
+ repo,
2484
+ interactive,
2485
+ interactive && !args.yes,
2486
+ syncStrategy
2487
+ );
2488
+ if (!pushed) process.exitCode = 1;
2489
+ } catch (error) {
2490
+ log.error(`${basename(repo)}: push failed: ${errorMessage(error)}`);
2491
+ process.exitCode = 1;
2492
+ }
2576
2493
  }
2577
2494
  }
2578
- if (interactive) outro("Done.");
2495
+ if (interactive) outro(process.exitCode ? "Finished with errors." : "Done.");
2579
2496
  }
2580
2497
  });
2581
- async function syncWithUpstream(strategy, interactive) {
2498
+ async function reviewMessages(drafts, canPrompt) {
2499
+ while (true) {
2500
+ for (const draft of drafts) log.message(`${basename(draft.repo)}: ${draft.message}`);
2501
+ if (!canPrompt) return drafts;
2502
+ const action = await select({
2503
+ message: "Action",
2504
+ initialValue: "all",
2505
+ options: [
2506
+ { value: "all", label: drafts.length > 1 ? "Commit all" : "Commit" },
2507
+ ...drafts.length > 1 ? drafts.map((draft) => ({
2508
+ value: { action: "commit", draft },
2509
+ label: `Commit only "${basename(draft.repo)}"`
2510
+ })) : [],
2511
+ ...drafts.map((draft) => ({
2512
+ value: { action: "edit", draft },
2513
+ label: `Edit message for "${basename(draft.repo)}"`
2514
+ })),
2515
+ { value: "cancel", label: "Cancel" }
2516
+ ]
2517
+ });
2518
+ if (isCancel(action) || action === "cancel") return null;
2519
+ if (action === "all") return drafts;
2520
+ if (action.action === "commit") return [action.draft];
2521
+ const edited = await text({
2522
+ message: `Edit message for "${basename(action.draft.repo)}"`,
2523
+ initialValue: action.draft.message,
2524
+ validate: (value) => value?.trim() ? void 0 : "Message cannot be empty."
2525
+ });
2526
+ if (isCancel(edited)) return null;
2527
+ action.draft.message = edited.trim();
2528
+ }
2529
+ }
2530
+ async function syncWithUpstream(repo, strategy, interactive) {
2582
2531
  const loader = interactive ? spinner() : void 0;
2583
2532
  const label = strategy === "rebase" ? "Rebase" : "Merge";
2584
- loader?.start(`Pulling --${strategy === "rebase" ? "rebase" : "no-rebase"}`);
2533
+ loader?.start(`${basename(repo)}: pulling --${strategy === "rebase" ? "rebase" : "no-rebase"}`);
2585
2534
  try {
2586
- await (strategy === "rebase" ? pullRebase() : pullMerge());
2535
+ await (strategy === "rebase" ? pullRebase(repo) : pullMerge(repo));
2587
2536
  loader?.stop(strategy === "rebase" ? "\u2713 Rebased on upstream" : "\u2713 Merged upstream");
2588
2537
  return true;
2589
2538
  } catch (error) {
2590
2539
  loader?.error(`${label} failed`);
2591
- log.error(`${label} failed (resolve conflicts, then push): ${errorMessage(error)}`);
2540
+ log.error(`${basename(repo)}: ${label} failed (resolve conflicts, then push): ${errorMessage(error)}`);
2592
2541
  return false;
2593
2542
  }
2594
2543
  }
2595
- async function pushOptimistic(interactive, canPrompt, strategy) {
2596
- const [upstream, branch] = await Promise.all([hasUpstream(), currentBranch()]);
2597
- const doPush = () => upstream ? push() : pushSetUpstream(branch);
2598
- const first = await tryPush(interactive, doPush);
2544
+ async function pushOptimistic(repo, interactive, canPrompt, strategy) {
2545
+ const [upstream, branch] = await Promise.all([hasUpstream(repo), currentBranch(repo)]);
2546
+ const doPush = () => upstream ? push(repo) : pushSetUpstream(repo, branch);
2547
+ const first = await tryPush(repo, interactive, doPush);
2599
2548
  if (first.ok) return true;
2600
- if (upstream && await isBehind(interactive)) {
2601
- const syncStrategy = strategy ?? await chooseSyncStrategy(canPrompt);
2602
- if (!syncStrategy || !await syncWithUpstream(syncStrategy, interactive)) return false;
2603
- const retry = await tryPush(interactive, doPush);
2549
+ if (upstream && await isBehind(repo, interactive)) {
2550
+ const syncStrategy = strategy ?? await chooseSyncStrategy(repo, canPrompt);
2551
+ if (!syncStrategy || !await syncWithUpstream(repo, syncStrategy, interactive)) return false;
2552
+ const retry = await tryPush(repo, interactive, doPush);
2604
2553
  if (retry.ok) return true;
2605
- log.error(`Push failed: ${errorMessage(retry.error)}`);
2554
+ log.error(`${basename(repo)}: push failed: ${errorMessage(retry.error)}`);
2606
2555
  return false;
2607
2556
  }
2608
- log.error(`Push failed: ${errorMessage(first.error)}`);
2557
+ log.error(`${basename(repo)}: push failed: ${errorMessage(first.error)}`);
2609
2558
  return false;
2610
2559
  }
2611
- async function chooseSyncStrategy(interactive) {
2560
+ async function chooseSyncStrategy(repo, interactive) {
2612
2561
  if (!interactive) {
2613
- log.error("Branch is behind upstream. Re-run with --rebase or --merge.");
2562
+ log.error(`${basename(repo)}: branch is behind upstream. Re-run with --rebase or --merge.`);
2614
2563
  return null;
2615
2564
  }
2616
2565
  const action = await select({
2617
- message: "Branch is behind upstream. How should zapdev sync it?",
2566
+ message: `${basename(repo)}: branch is behind upstream. How should zapdev sync it?`,
2618
2567
  options: [
2619
2568
  { value: "rebase", label: "Rebase" },
2620
2569
  { value: "merge", label: "Merge" },
@@ -2627,9 +2576,9 @@ async function chooseSyncStrategy(interactive) {
2627
2576
  }
2628
2577
  return action;
2629
2578
  }
2630
- async function tryPush(interactive, doPush) {
2579
+ async function tryPush(repo, interactive, doPush) {
2631
2580
  const loader = interactive ? spinner() : void 0;
2632
- loader?.start("Pushing");
2581
+ loader?.start(`${basename(repo)}: pushing`);
2633
2582
  try {
2634
2583
  await doPush();
2635
2584
  loader?.stop("\u2713 Pushed");
@@ -2639,252 +2588,32 @@ async function tryPush(interactive, doPush) {
2639
2588
  return { ok: false, error };
2640
2589
  }
2641
2590
  }
2642
- async function isBehind(interactive) {
2591
+ async function isBehind(repo, interactive) {
2643
2592
  const loader = interactive ? spinner() : void 0;
2644
- loader?.start("Checking upstream");
2593
+ loader?.start(`${basename(repo)}: checking upstream`);
2645
2594
  try {
2646
- await fetchRemote();
2647
- const behind = await behindCount();
2595
+ await fetchRemote(repo);
2596
+ const behind = await behindCount(repo);
2648
2597
  loader?.stop(
2649
2598
  behind > 0 ? `Behind upstream by ${behind} commit${behind > 1 ? "s" : ""}` : "Up to date with upstream"
2650
2599
  );
2651
2600
  return behind > 0;
2652
2601
  } catch (error) {
2653
2602
  loader?.error("Could not check upstream");
2654
- log.warn(`Could not check upstream: ${errorMessage(error)}`);
2655
- return false;
2656
- }
2657
- }
2658
-
2659
- // src/commands/reset.ts
2660
- var CANCEL = /* @__PURE__ */ Symbol("cancel");
2661
- var resetCommand = defineCommand({
2662
- meta: {
2663
- name: "reset",
2664
- description: "Switch each repo to a branch, then delete all other local branches and worktrees."
2665
- },
2666
- args: {
2667
- path: {
2668
- type: "positional",
2669
- required: false,
2670
- default: ".",
2671
- description: "A git repo to reset, or a directory whose direct child repos are reset."
2672
- },
2673
- principal: {
2674
- type: "boolean",
2675
- alias: "p",
2676
- description: "Switch every repo to its resolved principal branch (origin/HEAD)."
2677
- },
2678
- target: {
2679
- type: "string",
2680
- alias: "t",
2681
- description: "Switch every repo to this branch, falling back to the principal one."
2682
- },
2683
- pull: {
2684
- type: "boolean",
2685
- description: "Pull the checked-out branch after reset without asking."
2686
- },
2687
- yes: {
2688
- type: "boolean",
2689
- alias: "y",
2690
- description: "Non-interactive: switch and delete without confirmation."
2691
- }
2692
- },
2693
- async run({ args }) {
2694
- const assumeYes = Boolean(args.yes);
2695
- const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY) && !assumeYes;
2696
- const options = {
2697
- principal: Boolean(args.principal),
2698
- target: typeof args.target === "string" ? args.target.trim() : "",
2699
- pull: Boolean(args.pull)
2700
- };
2701
- const path = args.path || ".";
2702
- if (interactive) intro("zapdev reset");
2703
- const repos = await findRepos(path);
2704
- if (repos.length === 0) {
2705
- log.warn(`No git repository found at or under ${path}.`);
2706
- if (interactive) outro("Nothing to do.");
2707
- return;
2708
- }
2709
- for (const repo of repos) {
2710
- try {
2711
- const cancelled = await resetRepo(repo, options, interactive, assumeYes);
2712
- if (cancelled) {
2713
- cancel("Cancelled.");
2714
- return;
2715
- }
2716
- } catch (error) {
2717
- log.error(`Skipped ${repo}: ${errorMessage(error)}`);
2718
- }
2719
- }
2720
- if (interactive) outro(`Done (${repos.length} repo${repos.length > 1 ? "s" : ""}).`);
2721
- }
2722
- });
2723
- async function resetRepo(repo, options, interactive, assumeYes) {
2724
- log.step(`Resetting ${repo}`);
2725
- const fetchLoader = interactive ? spinner() : void 0;
2726
- fetchLoader?.start("Fetching + pruning\u2026");
2727
- try {
2728
- await fetchPrune(repo);
2729
- fetchLoader?.stop("Fetched + pruned");
2730
- } catch (error) {
2731
- fetchLoader?.error("Fetch failed");
2732
- log.warn(` Fetch failed, continuing: ${errorMessage(error)}`);
2733
- }
2734
- const [principal, current] = await Promise.all([defaultBranch(repo), currentBranchAt(repo)]);
2735
- const endBranch = await resolveEndBranch(repo, principal, current, options, interactive);
2736
- if (endBranch === CANCEL) return true;
2737
- if (endBranch === null) return false;
2738
- const [branches, worktrees] = await Promise.all([localBranches(repo), listWorktrees(repo)]);
2739
- const branchesToDelete = deletableBranches(branches, [principal ?? "", endBranch]);
2740
- const worktreesToRemove = worktrees.slice(1);
2741
- if (branchesToDelete.length > 0 || worktreesToRemove.length > 0) {
2742
- if (!assumeYes) {
2743
- if (!interactive) {
2744
- log.warn(" Refusing to delete non-interactively; pass --yes.");
2745
- return false;
2746
- }
2747
- announcePlan(endBranch, branchesToDelete, worktreesToRemove);
2748
- const ok = await confirm({ message: "Delete permanently?", initialValue: false });
2749
- if (isCancel(ok)) return true;
2750
- if (!ok) {
2751
- log.info(" Skipped.");
2752
- return false;
2753
- }
2754
- }
2755
- await removeWorktrees(repo, worktreesToRemove);
2756
- }
2757
- if (!await switchTo(repo, current, endBranch)) return false;
2758
- if (branchesToDelete.length > 0) await deleteBranches(repo, branchesToDelete);
2759
- return maybePull(repo, endBranch, options, interactive);
2760
- }
2761
- async function resolveEndBranch(repo, principal, current, options, interactive) {
2762
- if (options.target) {
2763
- if (await branchExists(repo, options.target)) return options.target;
2764
- if (principal) return principal;
2765
- log.warn(` Target "${options.target}" not found and no origin/HEAD; skipped.`);
2766
- return null;
2767
- }
2768
- if (options.principal || !interactive) {
2769
- if (principal) return principal;
2770
- log.warn(" No origin/HEAD to resolve the principal branch; skipped.");
2771
- return null;
2772
- }
2773
- const branches = await localBranches(repo);
2774
- if (branches.length === 0) return principal;
2775
- const choice = await select({
2776
- message: "Switch to:",
2777
- initialValue: principal ?? current ?? branches[0],
2778
- options: branches.map((branch) => ({
2779
- value: branch,
2780
- label: branch === principal ? `${branch} (principal)` : branch
2781
- }))
2782
- });
2783
- if (isCancel(choice)) return CANCEL;
2784
- return choice;
2785
- }
2786
- function announcePlan(endBranch, branches, worktrees) {
2787
- log.info(` Switch to ${endBranch}`);
2788
- if (branches.length > 0) {
2789
- const label = branches.length > 1 ? "branches" : "branch";
2790
- log.warn(` Delete ${branches.length} ${label}: ${branches.join(", ")}`);
2791
- }
2792
- if (worktrees.length > 0) {
2793
- const label = worktrees.length > 1 ? "worktrees" : "worktree";
2794
- const paths = worktrees.map((worktree) => worktree.path).join(", ");
2795
- log.warn(` Remove ${worktrees.length} ${label}: ${paths}`);
2796
- }
2797
- }
2798
- async function removeWorktrees(repo, worktrees) {
2799
- let removed = 0;
2800
- for (const worktree of worktrees) {
2801
- try {
2802
- await removeWorktree(repo, worktree.path);
2803
- removed += 1;
2804
- } catch (error) {
2805
- log.error(` Could not remove worktree ${worktree.path}: ${errorMessage(error)}`);
2806
- }
2807
- }
2808
- if (removed > 0) log.success(` Removed ${removed} worktree${removed > 1 ? "s" : ""}.`);
2809
- }
2810
- async function switchTo(repo, current, endBranch) {
2811
- if (current === endBranch) return true;
2812
- try {
2813
- await switchBranch(repo, endBranch);
2814
- return true;
2815
- } catch (error) {
2816
- log.error(` Could not switch to ${endBranch}: ${errorMessage(error)}`);
2603
+ log.warn(`${basename(repo)}: could not check upstream: ${errorMessage(error)}`);
2817
2604
  return false;
2818
2605
  }
2819
2606
  }
2820
- async function deleteBranches(repo, branches) {
2821
- let deleted = 0;
2822
- for (const branch of branches) {
2823
- try {
2824
- await deleteBranch(repo, branch);
2825
- deleted += 1;
2826
- } catch (error) {
2827
- log.error(` Could not delete ${branch}: ${errorMessage(error)}`);
2828
- }
2829
- }
2830
- if (deleted > 0) log.success(` Deleted ${deleted} branch${deleted > 1 ? "es" : ""}.`);
2831
- }
2832
- async function maybePull(repo, endBranch, options, interactive) {
2833
- let shouldPull = options.pull;
2834
- if (!shouldPull && interactive) {
2835
- const answer = await confirm({ message: `Pull ${endBranch}?`, initialValue: false });
2836
- if (isCancel(answer)) return true;
2837
- shouldPull = answer;
2838
- }
2839
- if (shouldPull) {
2840
- const loader = interactive ? spinner() : void 0;
2841
- loader?.start(`Pulling ${endBranch}\u2026`);
2842
- try {
2843
- await pull(repo);
2844
- loader?.stop(`\u2713 Pulled ${endBranch}`);
2845
- } catch (error) {
2846
- loader?.error("Pull failed");
2847
- log.error(` Pull failed: ${errorMessage(error)}`);
2848
- }
2849
- }
2850
- return false;
2851
- }
2852
2607
 
2853
2608
  // src/cli.ts
2854
- var commands = {
2855
- commit: commitCommand,
2856
- reset: resetCommand
2857
- };
2858
- var MENU = {
2859
- commit: "Stage all changes and commit with an AI-generated message",
2860
- reset: "Switch repos to a branch and delete the other branches and worktrees"
2861
- };
2862
- var menuOptions = Object.keys(MENU).map((value) => ({
2863
- value,
2864
- label: value,
2865
- hint: MENU[value]
2866
- }));
2867
2609
  var main = defineCommand({
2868
2610
  meta: {
2869
2611
  name: "zapdev",
2870
2612
  version: package_default.version,
2871
2613
  description: "Fast, precise git chores from your terminal."
2872
2614
  },
2873
- subCommands: commands,
2874
- // citty runs this after a matched subcommand too, so bail out when one already ran.
2875
- async run({ args, cmd }) {
2876
- const selected = args._[0];
2877
- if (selected && selected in commands) return;
2878
- if (!(process.stdin.isTTY && process.stdout.isTTY)) {
2879
- await showUsage(cmd);
2880
- return;
2881
- }
2882
- const choice = await select({ message: "Which command?", options: menuOptions });
2883
- if (isCancel(choice)) {
2884
- cancel("Cancelled.");
2885
- return;
2886
- }
2887
- await runCommand(commands[choice], { rawArgs: [] });
2888
- }
2615
+ args: commitCommand.args,
2616
+ subCommands: { commit: commitCommand },
2617
+ default: "commit"
2889
2618
  });
2890
2619
  await runMain(main);