superslate 0.2.1 → 0.4.0

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 (4) hide show
  1. package/LICENSE +63 -4
  2. package/README.md +34 -9
  3. package/dist/cli.js +2599 -206
  4. package/package.json +14 -11
package/dist/cli.js CHANGED
@@ -1,15 +1,1691 @@
1
1
  #!/usr/bin/env node
2
2
  // @bun
3
+ var __create = Object.create;
4
+ var __getProtoOf = Object.getPrototypeOf;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ function __accessProp(key) {
9
+ return this[key];
10
+ }
11
+ var __toESMCache_node;
12
+ var __toESMCache_esm;
13
+ var __toESM = (mod, isNodeMode, target) => {
14
+ var canCache = mod != null && typeof mod === "object";
15
+ if (canCache) {
16
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
17
+ var cached = cache.get(mod);
18
+ if (cached)
19
+ return cached;
20
+ }
21
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
22
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
23
+ for (let key of __getOwnPropNames(mod))
24
+ if (!__hasOwnProp.call(to, key))
25
+ __defProp(to, key, {
26
+ get: __accessProp.bind(mod, key),
27
+ enumerable: true
28
+ });
29
+ if (canCache)
30
+ cache.set(mod, to);
31
+ return to;
32
+ };
33
+ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
34
+
35
+ // node_modules/sisteransi/src/index.js
36
+ var require_src = __commonJS((exports, module) => {
37
+ var ESC2 = "\x1B";
38
+ var CSI2 = `${ESC2}[`;
39
+ var beep = "\x07";
40
+ var cursor = {
41
+ to(x, y) {
42
+ if (!y)
43
+ return `${CSI2}${x + 1}G`;
44
+ return `${CSI2}${y + 1};${x + 1}H`;
45
+ },
46
+ move(x, y) {
47
+ let ret = "";
48
+ if (x < 0)
49
+ ret += `${CSI2}${-x}D`;
50
+ else if (x > 0)
51
+ ret += `${CSI2}${x}C`;
52
+ if (y < 0)
53
+ ret += `${CSI2}${-y}A`;
54
+ else if (y > 0)
55
+ ret += `${CSI2}${y}B`;
56
+ return ret;
57
+ },
58
+ up: (count = 1) => `${CSI2}${count}A`,
59
+ down: (count = 1) => `${CSI2}${count}B`,
60
+ forward: (count = 1) => `${CSI2}${count}C`,
61
+ backward: (count = 1) => `${CSI2}${count}D`,
62
+ nextLine: (count = 1) => `${CSI2}E`.repeat(count),
63
+ prevLine: (count = 1) => `${CSI2}F`.repeat(count),
64
+ left: `${CSI2}G`,
65
+ hide: `${CSI2}?25l`,
66
+ show: `${CSI2}?25h`,
67
+ save: `${ESC2}7`,
68
+ restore: `${ESC2}8`
69
+ };
70
+ var scroll = {
71
+ up: (count = 1) => `${CSI2}S`.repeat(count),
72
+ down: (count = 1) => `${CSI2}T`.repeat(count)
73
+ };
74
+ var erase = {
75
+ screen: `${CSI2}2J`,
76
+ up: (count = 1) => `${CSI2}1J`.repeat(count),
77
+ down: (count = 1) => `${CSI2}J`.repeat(count),
78
+ line: `${CSI2}2K`,
79
+ lineEnd: `${CSI2}K`,
80
+ lineStart: `${CSI2}1K`,
81
+ lines(count) {
82
+ let clear = "";
83
+ for (let i = 0;i < count; i++)
84
+ clear += this.line + (i < count - 1 ? cursor.up() : "");
85
+ if (count)
86
+ clear += cursor.left;
87
+ return clear;
88
+ }
89
+ };
90
+ module.exports = { cursor, scroll, erase, beep };
91
+ });
92
+
93
+ // node_modules/@clack/core/dist/index.mjs
94
+ import { styleText } from "node:util";
95
+ import { stdout, stdin } from "node:process";
96
+ import * as l from "node:readline";
97
+ import l__default from "node:readline";
98
+
99
+ // node_modules/fast-string-truncated-width/dist/utils.js
100
+ var getCodePointsLength = (() => {
101
+ const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
102
+ return (input) => {
103
+ let surrogatePairsNr = 0;
104
+ SURROGATE_PAIR_RE.lastIndex = 0;
105
+ while (SURROGATE_PAIR_RE.test(input)) {
106
+ surrogatePairsNr += 1;
107
+ }
108
+ return input.length - surrogatePairsNr;
109
+ };
110
+ })();
111
+ var isFullWidth = (x) => {
112
+ return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
113
+ };
114
+ var isWideNotCJKTNotEmoji = (x) => {
115
+ return x === 8987 || x === 9001 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
116
+ };
117
+
118
+ // node_modules/fast-string-truncated-width/dist/index.js
119
+ var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
120
+ var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
121
+ 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;
122
+ var TAB_RE = /\t{1,1000}/y;
123
+ var EMOJI_RE = /[\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;
124
+ var LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
125
+ var MODIFIER_RE = /\p{M}+/gu;
126
+ var NO_TRUNCATION = { limit: Infinity, ellipsis: "" };
127
+ var getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
128
+ const LIMIT = truncationOptions.limit ?? Infinity;
129
+ const ELLIPSIS = truncationOptions.ellipsis ?? "";
130
+ const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION, widthOptions).width : 0);
131
+ const ANSI_WIDTH = 0;
132
+ const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
133
+ const TAB_WIDTH = widthOptions.tabWidth ?? 8;
134
+ const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
135
+ const FULL_WIDTH_WIDTH = 2;
136
+ const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
137
+ const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
138
+ const PARSE_BLOCKS = [
139
+ [LATIN_RE, REGULAR_WIDTH],
140
+ [ANSI_RE, ANSI_WIDTH],
141
+ [CONTROL_RE, CONTROL_WIDTH],
142
+ [TAB_RE, TAB_WIDTH],
143
+ [EMOJI_RE, EMOJI_WIDTH],
144
+ [CJKT_WIDE_RE, WIDE_WIDTH]
145
+ ];
146
+ let indexPrev = 0;
147
+ let index = 0;
148
+ let length = input.length;
149
+ let lengthExtra = 0;
150
+ let truncationEnabled = false;
151
+ let truncationIndex = length;
152
+ let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
153
+ let unmatchedStart = 0;
154
+ let unmatchedEnd = 0;
155
+ let width = 0;
156
+ let widthExtra = 0;
157
+ outer:
158
+ while (true) {
159
+ if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
160
+ const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
161
+ lengthExtra = 0;
162
+ for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
163
+ const codePoint = char.codePointAt(0) || 0;
164
+ if (isFullWidth(codePoint)) {
165
+ widthExtra = FULL_WIDTH_WIDTH;
166
+ } else if (isWideNotCJKTNotEmoji(codePoint)) {
167
+ widthExtra = WIDE_WIDTH;
168
+ } else {
169
+ widthExtra = REGULAR_WIDTH;
170
+ }
171
+ if (width + widthExtra > truncationLimit) {
172
+ truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
173
+ }
174
+ if (width + widthExtra > LIMIT) {
175
+ truncationEnabled = true;
176
+ break outer;
177
+ }
178
+ lengthExtra += char.length;
179
+ width += widthExtra;
180
+ }
181
+ unmatchedStart = unmatchedEnd = 0;
182
+ }
183
+ if (index >= length) {
184
+ break outer;
185
+ }
186
+ for (let i = 0, l = PARSE_BLOCKS.length;i < l; i++) {
187
+ const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i];
188
+ BLOCK_RE.lastIndex = index;
189
+ if (BLOCK_RE.test(input)) {
190
+ lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
191
+ widthExtra = lengthExtra * BLOCK_WIDTH;
192
+ if (width + widthExtra > truncationLimit) {
193
+ truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
194
+ }
195
+ if (width + widthExtra > LIMIT) {
196
+ truncationEnabled = true;
197
+ break outer;
198
+ }
199
+ width += widthExtra;
200
+ unmatchedStart = indexPrev;
201
+ unmatchedEnd = index;
202
+ index = indexPrev = BLOCK_RE.lastIndex;
203
+ continue outer;
204
+ }
205
+ }
206
+ index += 1;
207
+ }
208
+ return {
209
+ width: truncationEnabled ? truncationLimit : width,
210
+ index: truncationEnabled ? truncationIndex : length,
211
+ truncated: truncationEnabled,
212
+ ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
213
+ };
214
+ };
215
+ var dist_default = getStringTruncatedWidth;
216
+
217
+ // node_modules/fast-string-width/dist/index.js
218
+ var NO_TRUNCATION2 = {
219
+ limit: Infinity,
220
+ ellipsis: "",
221
+ ellipsisWidth: 0
222
+ };
223
+ var fastStringWidth = (input, options = {}) => {
224
+ return dist_default(input, NO_TRUNCATION2, options).width;
225
+ };
226
+ var dist_default2 = fastStringWidth;
227
+
228
+ // node_modules/fast-wrap-ansi/lib/main.js
229
+ var ESC = "\x1B";
230
+ var CSI = "›";
231
+ var END_CODE = 39;
232
+ var ANSI_ESCAPE_BELL = "\x07";
233
+ var ANSI_CSI = "[";
234
+ var ANSI_OSC = "]";
235
+ var ANSI_SGR_TERMINATOR = "m";
236
+ var ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
237
+ var GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
238
+ var getClosingCode = (openingCode) => {
239
+ if (openingCode >= 30 && openingCode <= 37)
240
+ return 39;
241
+ if (openingCode >= 90 && openingCode <= 97)
242
+ return 39;
243
+ if (openingCode >= 40 && openingCode <= 47)
244
+ return 49;
245
+ if (openingCode >= 100 && openingCode <= 107)
246
+ return 49;
247
+ if (openingCode === 1 || openingCode === 2)
248
+ return 22;
249
+ if (openingCode === 3)
250
+ return 23;
251
+ if (openingCode === 4)
252
+ return 24;
253
+ if (openingCode === 7)
254
+ return 27;
255
+ if (openingCode === 8)
256
+ return 28;
257
+ if (openingCode === 9)
258
+ return 29;
259
+ if (openingCode === 0)
260
+ return 0;
261
+ return;
262
+ };
263
+ var wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
264
+ var wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
265
+ var wrapWord = (rows, word, columns) => {
266
+ const characters = word[Symbol.iterator]();
267
+ let isInsideEscape = false;
268
+ let isInsideLinkEscape = false;
269
+ let lastRow = rows.at(-1);
270
+ let visible = lastRow === undefined ? 0 : dist_default2(lastRow);
271
+ let currentCharacter = characters.next();
272
+ let nextCharacter = characters.next();
273
+ let rawCharacterIndex = 0;
274
+ while (!currentCharacter.done) {
275
+ const character = currentCharacter.value;
276
+ const characterLength = dist_default2(character);
277
+ if (visible + characterLength <= columns) {
278
+ rows[rows.length - 1] += character;
279
+ } else {
280
+ rows.push(character);
281
+ visible = 0;
282
+ }
283
+ if (character === ESC || character === CSI) {
284
+ isInsideEscape = true;
285
+ isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
286
+ }
287
+ if (isInsideEscape) {
288
+ if (isInsideLinkEscape) {
289
+ if (character === ANSI_ESCAPE_BELL) {
290
+ isInsideEscape = false;
291
+ isInsideLinkEscape = false;
292
+ }
293
+ } else if (character === ANSI_SGR_TERMINATOR) {
294
+ isInsideEscape = false;
295
+ }
296
+ } else {
297
+ visible += characterLength;
298
+ if (visible === columns && !nextCharacter.done) {
299
+ rows.push("");
300
+ visible = 0;
301
+ }
302
+ }
303
+ currentCharacter = nextCharacter;
304
+ nextCharacter = characters.next();
305
+ rawCharacterIndex += character.length;
306
+ }
307
+ lastRow = rows.at(-1);
308
+ if (!visible && lastRow !== undefined && lastRow.length && rows.length > 1) {
309
+ rows[rows.length - 2] += rows.pop();
310
+ }
311
+ };
312
+ var stringVisibleTrimSpacesRight = (string) => {
313
+ const words = string.split(" ");
314
+ let last = words.length;
315
+ while (last) {
316
+ if (dist_default2(words[last - 1])) {
317
+ break;
318
+ }
319
+ last--;
320
+ }
321
+ if (last === words.length) {
322
+ return string;
323
+ }
324
+ return words.slice(0, last).join(" ") + words.slice(last).join("");
325
+ };
326
+ var exec = (string, columns, options = {}) => {
327
+ if (options.trim !== false && string.trim() === "") {
328
+ return "";
329
+ }
330
+ let returnValue = "";
331
+ let escapeCode;
332
+ let escapeUrl;
333
+ const words = string.split(" ");
334
+ let rows = [""];
335
+ let rowLength = 0;
336
+ for (let index = 0;index < words.length; index++) {
337
+ const word = words[index];
338
+ if (options.trim !== false) {
339
+ const row = rows.at(-1) ?? "";
340
+ const trimmed = row.trimStart();
341
+ if (row.length !== trimmed.length) {
342
+ rows[rows.length - 1] = trimmed;
343
+ rowLength = dist_default2(trimmed);
344
+ }
345
+ }
346
+ if (index !== 0) {
347
+ if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
348
+ rows.push("");
349
+ rowLength = 0;
350
+ }
351
+ if (rowLength || options.trim === false) {
352
+ rows[rows.length - 1] += " ";
353
+ rowLength++;
354
+ }
355
+ }
356
+ const wordLength = dist_default2(word);
357
+ if (options.hard && wordLength > columns) {
358
+ const remainingColumns = columns - rowLength;
359
+ const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
360
+ const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);
361
+ if (breaksStartingNextLine < breaksStartingThisLine) {
362
+ rows.push("");
363
+ }
364
+ wrapWord(rows, word, columns);
365
+ rowLength = dist_default2(rows.at(-1) ?? "");
366
+ continue;
367
+ }
368
+ if (rowLength + wordLength > columns && rowLength && wordLength) {
369
+ if (options.wordWrap === false && rowLength < columns) {
370
+ wrapWord(rows, word, columns);
371
+ rowLength = dist_default2(rows.at(-1) ?? "");
372
+ continue;
373
+ }
374
+ rows.push("");
375
+ rowLength = 0;
376
+ }
377
+ if (rowLength + wordLength > columns && options.wordWrap === false) {
378
+ wrapWord(rows, word, columns);
379
+ rowLength = dist_default2(rows.at(-1) ?? "");
380
+ continue;
381
+ }
382
+ rows[rows.length - 1] += word;
383
+ rowLength += wordLength;
384
+ }
385
+ if (options.trim !== false) {
386
+ rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
387
+ }
388
+ const preString = rows.join(`
389
+ `);
390
+ let inSurrogate = false;
391
+ for (let i = 0;i < preString.length; i++) {
392
+ const character = preString[i];
393
+ returnValue += character;
394
+ if (!inSurrogate) {
395
+ inSurrogate = character >= "\uD800" && character <= "\uDBFF";
396
+ if (inSurrogate) {
397
+ continue;
398
+ }
399
+ } else {
400
+ inSurrogate = false;
401
+ }
402
+ if (character === ESC || character === CSI) {
403
+ GROUP_REGEX.lastIndex = i + 1;
404
+ const groupsResult = GROUP_REGEX.exec(preString);
405
+ const groups = groupsResult?.groups;
406
+ if (groups?.code !== undefined) {
407
+ const code = Number.parseFloat(groups.code);
408
+ escapeCode = code === END_CODE ? undefined : code;
409
+ } else if (groups?.uri !== undefined) {
410
+ escapeUrl = groups.uri.length === 0 ? undefined : groups.uri;
411
+ }
412
+ }
413
+ if (preString[i + 1] === `
414
+ `) {
415
+ if (escapeUrl) {
416
+ returnValue += wrapAnsiHyperlink("");
417
+ }
418
+ const closingCode = escapeCode ? getClosingCode(escapeCode) : undefined;
419
+ if (escapeCode && closingCode) {
420
+ returnValue += wrapAnsiCode(closingCode);
421
+ }
422
+ } else if (character === `
423
+ `) {
424
+ if (escapeCode && getClosingCode(escapeCode)) {
425
+ returnValue += wrapAnsiCode(escapeCode);
426
+ }
427
+ if (escapeUrl) {
428
+ returnValue += wrapAnsiHyperlink(escapeUrl);
429
+ }
430
+ }
431
+ }
432
+ return returnValue;
433
+ };
434
+ var CRLF_OR_LF = /\r?\n/;
435
+ function wrapAnsi(string, columns, options) {
436
+ return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join(`
437
+ `);
438
+ }
439
+
440
+ // node_modules/@clack/core/dist/index.mjs
441
+ var import_sisteransi = __toESM(require_src(), 1);
442
+ import { ReadStream } from "node:tty";
443
+ function findCursor(s, o, l2) {
444
+ if (!l2.some((r) => !r.disabled))
445
+ return s;
446
+ const t = s + o, n = Math.max(l2.length - 1, 0), e = t < 0 ? n : t > n ? 0 : t;
447
+ return l2[e]?.disabled ? findCursor(e, o < 0 ? -1 : 1, l2) : e;
448
+ }
449
+ function findTextCursor(s, o, l2, i) {
450
+ const t = i.split(`
451
+ `);
452
+ let n = 0, e = s;
453
+ for (const r of t) {
454
+ if (e <= r.length)
455
+ break;
456
+ e -= r.length + 1, n++;
457
+ }
458
+ for (n = Math.max(0, Math.min(t.length - 1, n + l2)), e = Math.min(e, t[n].length) + o;e < 0 && n > 0; )
459
+ n--, e += t[n].length + 1;
460
+ for (;e > t[n].length && n < t.length - 1; )
461
+ e -= t[n].length + 1, n++;
462
+ e = Math.max(0, Math.min(t[n].length, e));
463
+ let h = 0;
464
+ for (let r = 0;r < n; r++)
465
+ h += t[r].length + 1;
466
+ return h + e;
467
+ }
468
+ var a$1 = ["up", "down", "left", "right", "space", "enter", "cancel"];
469
+ var t = [
470
+ "January",
471
+ "February",
472
+ "March",
473
+ "April",
474
+ "May",
475
+ "June",
476
+ "July",
477
+ "August",
478
+ "September",
479
+ "October",
480
+ "November",
481
+ "December"
482
+ ];
483
+ var settings = {
484
+ actions: new Set(a$1),
485
+ aliases: /* @__PURE__ */ new Map([
486
+ ["k", "up"],
487
+ ["j", "down"],
488
+ ["h", "left"],
489
+ ["l", "right"],
490
+ ["\x03", "cancel"],
491
+ ["escape", "cancel"]
492
+ ]),
493
+ messages: {
494
+ cancel: "Canceled",
495
+ error: "Something went wrong"
496
+ },
497
+ withGuide: true,
498
+ date: {
499
+ monthNames: [...t],
500
+ messages: {
501
+ required: "Please enter a valid date",
502
+ invalidMonth: "There are only 12 months in a year",
503
+ invalidDay: (n, e) => `There are only ${n} days in ${e}`,
504
+ afterMin: (n) => `Date must be on or after ${n.toISOString().slice(0, 10)}`,
505
+ beforeMax: (n) => `Date must be on or before ${n.toISOString().slice(0, 10)}`
506
+ }
507
+ }
508
+ };
509
+ function isActionKey(n, e) {
510
+ if (typeof n == "string")
511
+ return settings.aliases.get(n) === e;
512
+ for (const s of n)
513
+ if (s !== undefined && isActionKey(s, e))
514
+ return true;
515
+ return false;
516
+ }
517
+ function diffLines(i, s) {
518
+ if (i === s)
519
+ return;
520
+ const e = i.split(`
521
+ `), t2 = s.split(`
522
+ `), r = Math.max(e.length, t2.length), f = [];
523
+ for (let n = 0;n < r; n++)
524
+ e[n] !== t2[n] && f.push(n);
525
+ return {
526
+ lines: f,
527
+ numLinesBefore: e.length,
528
+ numLinesAfter: t2.length,
529
+ numLines: r
530
+ };
531
+ }
532
+ var R = globalThis.process.platform.startsWith("win");
533
+ var CANCEL_SYMBOL = Symbol("clack:cancel");
534
+ function isCancel(e) {
535
+ return e === CANCEL_SYMBOL;
536
+ }
537
+ function setRawMode(e, r) {
538
+ const o = e;
539
+ o.isTTY && o.setRawMode(r);
540
+ }
541
+ function block({
542
+ input: e = stdin,
543
+ output: r = stdout,
544
+ overwrite: o = true,
545
+ hideCursor: t2 = true
546
+ } = {}) {
547
+ const s = l.createInterface({
548
+ input: e,
549
+ output: r,
550
+ prompt: "",
551
+ tabSize: 1
552
+ });
553
+ l.emitKeypressEvents(e, s), e instanceof ReadStream && e.isTTY && e.setRawMode(true);
554
+ const n = (f, { name: a, sequence: p }) => {
555
+ const c = String(f);
556
+ if (isActionKey([c, a, p], "cancel")) {
557
+ t2 && r.write(import_sisteransi.cursor.show), process.exit(0);
558
+ return;
559
+ }
560
+ if (!o)
561
+ return;
562
+ const i = a === "return" ? 0 : -1, m = a === "return" ? -1 : 0;
563
+ l.moveCursor(r, i, m, () => {
564
+ l.clearLine(r, 1, () => {
565
+ e.once("keypress", n);
566
+ });
567
+ });
568
+ };
569
+ return t2 && r.write(import_sisteransi.cursor.hide), e.once("keypress", n), () => {
570
+ e.off("keypress", n), t2 && r.write(import_sisteransi.cursor.show), e instanceof ReadStream && e.isTTY && !R && e.setRawMode(false), s.terminal = false, s.close();
571
+ };
572
+ }
573
+ var getColumns = (e) => ("columns" in e) && typeof e.columns == "number" ? e.columns : 80;
574
+ var getRows = (e) => ("rows" in e) && typeof e.rows == "number" ? e.rows : 20;
575
+ function wrapTextWithPrefix(e, r, o, t2 = o, s = o, n) {
576
+ const f = getColumns(e ?? stdout);
577
+ return wrapAnsi(r, f - o.length, {
578
+ hard: true,
579
+ trim: false
580
+ }).split(`
581
+ `).map((c, i, m) => {
582
+ const d = n ? n(c, i) : c;
583
+ return i === 0 ? `${t2}${d}` : i === m.length - 1 ? `${s}${d}` : `${o}${d}`;
584
+ }).join(`
585
+ `);
586
+ }
587
+ function runValidation(e, n) {
588
+ if ("~standard" in e) {
589
+ const a = e["~standard"].validate(n);
590
+ if (a instanceof Promise)
591
+ throw new TypeError("Schema validation must be synchronous. Update `validate()` and remove any asynchronous logic.");
592
+ return a.issues?.at(0)?.message;
593
+ }
594
+ return e(n);
595
+ }
596
+
597
+ class V {
598
+ input;
599
+ output;
600
+ _abortSignal;
601
+ rl;
602
+ opts;
603
+ _render;
604
+ _track = false;
605
+ _prevFrame = "";
606
+ _subscribers = /* @__PURE__ */ new Map;
607
+ _cursor = 0;
608
+ state = "initial";
609
+ error = "";
610
+ value;
611
+ userInput = "";
612
+ constructor(t2, e = true) {
613
+ const { input: i = stdin, output: n = stdout, render: s, signal: r, ...o } = t2;
614
+ this.opts = o, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = s.bind(this), this._track = e, this._abortSignal = r, this.input = i, this.output = n;
615
+ }
616
+ unsubscribe() {
617
+ this._subscribers.clear();
618
+ }
619
+ setSubscriber(t2, e) {
620
+ const i = this._subscribers.get(t2) ?? [];
621
+ i.push(e), this._subscribers.set(t2, i);
622
+ }
623
+ on(t2, e) {
624
+ this.setSubscriber(t2, { cb: e });
625
+ }
626
+ once(t2, e) {
627
+ this.setSubscriber(t2, { cb: e, once: true });
628
+ }
629
+ emit(t2, ...e) {
630
+ const i = this._subscribers.get(t2) ?? [], n = [];
631
+ for (const s of i)
632
+ s.cb(...e), s.once && n.push(() => i.splice(i.indexOf(s), 1));
633
+ for (const s of n)
634
+ s();
635
+ }
636
+ prompt() {
637
+ return new Promise((t2) => {
638
+ if (this._abortSignal) {
639
+ if (this._abortSignal.aborted)
640
+ return this.state = "cancel", this.close(), t2(CANCEL_SYMBOL);
641
+ this._abortSignal.addEventListener("abort", () => {
642
+ this.state = "cancel", this.close();
643
+ }, { once: true });
644
+ }
645
+ this.rl = l__default.createInterface({
646
+ input: this.input,
647
+ tabSize: 2,
648
+ prompt: "",
649
+ escapeCodeTimeout: 50,
650
+ terminal: true
651
+ }), this.rl.prompt(), this.opts.initialUserInput !== undefined && 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", () => {
652
+ this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t2(this.value);
653
+ }), this.once("cancel", () => {
654
+ this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t2(CANCEL_SYMBOL);
655
+ });
656
+ });
657
+ }
658
+ _isActionKey(t2, e) {
659
+ return t2 === "\t";
660
+ }
661
+ _shouldSubmit(t2, e) {
662
+ return true;
663
+ }
664
+ _setValue(t2) {
665
+ this.value = t2, this.emit("value", this.value);
666
+ }
667
+ _setUserInput(t2, e) {
668
+ this.userInput = t2 ?? "", this.emit("userInput", this.userInput), e && this._track && this.rl && (this.rl.write(this.userInput), this._cursor = this.rl.cursor);
669
+ }
670
+ _clearUserInput() {
671
+ this.rl?.write(null, { ctrl: true, name: "u" }), this._setUserInput("");
672
+ }
673
+ onKeypress(t2, e) {
674
+ if (this._track && e.name !== "return" && (e.name && this._isActionKey(t2, e) && 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"), e?.name && (!this._track && settings.aliases.has(e.name) && this.emit("cursor", settings.aliases.get(e.name)), settings.actions.has(e.name) && this.emit("cursor", e.name)), t2 && (t2.toLowerCase() === "y" || t2.toLowerCase() === "n") && this.emit("confirm", t2.toLowerCase() === "y"), this.emit("key", t2, e), e?.name === "return" && this._shouldSubmit(t2, e)) {
675
+ if (this.opts.validate) {
676
+ const i = runValidation(this.opts.validate, this.value);
677
+ i && (this.error = i instanceof Error ? i.message : i, this.state = "error", this.rl?.write(this.userInput));
678
+ }
679
+ this.state !== "error" && (this.state = "submit");
680
+ }
681
+ isActionKey([t2, e?.name, e?.sequence], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
682
+ }
683
+ close() {
684
+ this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
685
+ `), setRawMode(this.input, false), this.rl?.close(), this.rl = undefined, this.emit(`${this.state}`, this.value), this.unsubscribe();
686
+ }
687
+ restoreCursor() {
688
+ const t2 = wrapAnsi(this._prevFrame, process.stdout.columns, { hard: true, trim: false }).split(`
689
+ `).length - 1;
690
+ this.output.write(import_sisteransi.cursor.move(-999, t2 * -1));
691
+ }
692
+ render() {
693
+ const t2 = wrapAnsi(this._render(this) ?? "", process.stdout.columns, {
694
+ hard: true,
695
+ trim: false
696
+ });
697
+ if (t2 !== this._prevFrame) {
698
+ if (this.state === "initial")
699
+ this.output.write(import_sisteransi.cursor.hide);
700
+ else {
701
+ const e = diffLines(this._prevFrame, t2), i = getRows(this.output);
702
+ if (this.restoreCursor(), e) {
703
+ const n = Math.max(0, e.numLinesAfter - i), s = Math.max(0, e.numLinesBefore - i);
704
+ let r = e.lines.find((o) => o >= n);
705
+ if (r === undefined) {
706
+ this._prevFrame = t2;
707
+ return;
708
+ }
709
+ if (e.lines.length === 1) {
710
+ this.output.write(import_sisteransi.cursor.move(0, r - s)), this.output.write(import_sisteransi.erase.lines(1));
711
+ const o = t2.split(`
712
+ `);
713
+ this.output.write(o[r]), this._prevFrame = t2, this.output.write(import_sisteransi.cursor.move(0, o.length - r - 1));
714
+ return;
715
+ } else if (e.lines.length > 1) {
716
+ if (n < s)
717
+ r = n;
718
+ else {
719
+ const h = r - s;
720
+ h > 0 && this.output.write(import_sisteransi.cursor.move(0, h));
721
+ }
722
+ this.output.write(import_sisteransi.erase.down());
723
+ const f = t2.split(`
724
+ `).slice(r);
725
+ this.output.write(f.join(`
726
+ `)), this._prevFrame = t2;
727
+ return;
728
+ }
729
+ }
730
+ this.output.write(import_sisteransi.erase.down());
731
+ }
732
+ this.output.write(t2), this.state === "initial" && (this.state = "active"), this._prevFrame = t2;
733
+ }
734
+ }
735
+ }
736
+ function p$1(l2, e) {
737
+ if (l2 === undefined || e.length === 0)
738
+ return 0;
739
+ const i = e.findIndex((s) => s.value === l2);
740
+ return i !== -1 ? i : 0;
741
+ }
742
+ function g(l2, e) {
743
+ return (e.label ?? String(e.value)).toLowerCase().includes(l2.toLowerCase());
744
+ }
745
+ function m(l2, e) {
746
+ if (e)
747
+ return l2 ? e : e[0];
748
+ }
749
+ var T$1 = class T extends V {
750
+ filteredOptions;
751
+ multiple;
752
+ isNavigating = false;
753
+ selectedValues = [];
754
+ focusedValue;
755
+ #e = 0;
756
+ #s = "";
757
+ #t;
758
+ #i;
759
+ #n;
760
+ get cursor() {
761
+ return this.#e;
762
+ }
763
+ get userInputWithCursor() {
764
+ if (!this.userInput)
765
+ return styleText(["inverse", "hidden"], "_");
766
+ if (this._cursor >= this.userInput.length)
767
+ return `${this.userInput}█`;
768
+ const e = this.userInput.slice(0, this.cursor), t2 = this.userInput.slice(this.cursor, this.cursor + 1), i = this.userInput.slice(this.cursor + 1);
769
+ return `${e}${styleText("inverse", t2)}${i}`;
770
+ }
771
+ get options() {
772
+ return typeof this.#i == "function" ? this.#i() : this.#i;
773
+ }
774
+ constructor(e) {
775
+ super(e), this.#i = e.options, this.#n = e.placeholder;
776
+ const t2 = this.options;
777
+ this.filteredOptions = [...t2], this.multiple = e.multiple === true, this.#t = typeof e.options == "function" ? e.filter : e.filter ?? g;
778
+ let i;
779
+ if (e.initialValue && Array.isArray(e.initialValue) ? this.multiple ? i = e.initialValue : i = e.initialValue.slice(0, 1) : !this.multiple && this.options.length > 0 && (i = [this.options[0]?.value]), i)
780
+ for (const s of i) {
781
+ const n = t2.findIndex((o) => o.value === s);
782
+ n !== -1 && (this.toggleSelected(s), this.#e = n);
783
+ }
784
+ this.focusedValue = this.options[this.#e]?.value, this.on("key", (s, n) => this.#l(s, n)), this.on("userInput", (s) => this.#u(s));
785
+ }
786
+ _isActionKey(e, t2) {
787
+ return e === "\t" || this.multiple && this.isNavigating && t2.name === "space" && e !== undefined && e !== "";
788
+ }
789
+ #l(e, t2) {
790
+ const i = t2.name === "up", s = t2.name === "down", n = t2.name === "return", o = this.userInput === "" || this.userInput === "\t", u = this.#n, a = this.options, f = u !== undefined && u !== "" && a.some((r) => !r.disabled && (this.#t ? this.#t(u, r) : true));
791
+ if (t2.name === "tab" && o && f) {
792
+ this.userInput === "\t" && this._clearUserInput(), this._setUserInput(u, true), this.isNavigating = false;
793
+ return;
794
+ }
795
+ i || s ? (this.#e = findCursor(this.#e, i ? -1 : 1, this.filteredOptions), this.focusedValue = this.filteredOptions[this.#e]?.value, this.multiple || (this.selectedValues = [this.focusedValue]), this.isNavigating = true) : n ? this.value = m(this.multiple, this.selectedValues) : this.multiple ? this.focusedValue !== undefined && (t2.name === "tab" || this.isNavigating && t2.name === "space") ? this.toggleSelected(this.focusedValue) : this.isNavigating = false : (this.focusedValue && (this.selectedValues = [this.focusedValue]), this.isNavigating = false);
796
+ }
797
+ deselectAll() {
798
+ this.selectedValues = [];
799
+ }
800
+ toggleSelected(e) {
801
+ this.filteredOptions.length !== 0 && (this.multiple ? this.selectedValues.includes(e) ? this.selectedValues = this.selectedValues.filter((t2) => t2 !== e) : this.selectedValues = [...this.selectedValues, e] : this.selectedValues = [e]);
802
+ }
803
+ #u(e) {
804
+ if (e !== this.#s) {
805
+ this.#s = e;
806
+ const t2 = this.options;
807
+ e && this.#t ? this.filteredOptions = t2.filter((n) => this.#t?.(e, n)) : this.filteredOptions = [...t2];
808
+ const i = p$1(this.focusedValue, this.filteredOptions);
809
+ this.#e = findCursor(i, 0, this.filteredOptions);
810
+ const s = this.filteredOptions[this.#e];
811
+ s && !s.disabled ? this.focusedValue = s.value : this.focusedValue = undefined, this.multiple || (this.focusedValue !== undefined ? this.toggleSelected(this.focusedValue) : this.deselectAll());
812
+ }
813
+ }
814
+ };
815
+
816
+ class r extends V {
817
+ get cursor() {
818
+ return this.value ? 0 : 1;
819
+ }
820
+ get _value() {
821
+ return this.cursor === 0;
822
+ }
823
+ constructor(t2) {
824
+ super(t2, false), this.value = !!t2.initialValue, this.on("userInput", () => {
825
+ this.value = this._value;
826
+ }), this.on("confirm", (i) => {
827
+ this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = i, this.state = "submit", this.close();
828
+ }), this.on("cursor", () => {
829
+ this.value = !this.value;
830
+ });
831
+ }
832
+ }
833
+ var _ = {
834
+ Y: { type: "year", len: 4 },
835
+ M: { type: "month", len: 2 },
836
+ D: { type: "day", len: 2 }
837
+ };
838
+ function M(r2) {
839
+ return [...r2].map((t2) => _[t2]);
840
+ }
841
+ function P(r2) {
842
+ const i = new Intl.DateTimeFormat(r2, {
843
+ year: "numeric",
844
+ month: "2-digit",
845
+ day: "2-digit"
846
+ }).formatToParts(new Date(2000, 0, 15)), s = [];
847
+ let n = "/";
848
+ for (const e of i)
849
+ e.type === "literal" ? n = e.value.trim() || e.value : (e.type === "year" || e.type === "month" || e.type === "day") && s.push({ type: e.type, len: e.type === "year" ? 4 : 2 });
850
+ return { segments: s, separator: n };
851
+ }
852
+ function p(r2) {
853
+ return Number.parseInt((r2 || "0").replace(/_/g, "0"), 10) || 0;
854
+ }
855
+ function f(r2) {
856
+ return {
857
+ year: p(r2.year),
858
+ month: p(r2.month),
859
+ day: p(r2.day)
860
+ };
861
+ }
862
+ function c(r2, t2) {
863
+ return new Date(r2 || 2001, t2 || 1, 0).getDate();
864
+ }
865
+ function b(r2) {
866
+ const { year: t2, month: i, day: s } = f(r2);
867
+ if (!t2 || t2 < 0 || t2 > 9999 || !i || i < 1 || i > 12 || !s || s < 1)
868
+ return;
869
+ const n = new Date(Date.UTC(t2, i - 1, s));
870
+ if (!(n.getUTCFullYear() !== t2 || n.getUTCMonth() !== i - 1 || n.getUTCDate() !== s))
871
+ return { year: t2, month: i, day: s };
872
+ }
873
+ function C(r2) {
874
+ const t2 = b(r2);
875
+ return t2 ? new Date(Date.UTC(t2.year, t2.month - 1, t2.day)) : undefined;
876
+ }
877
+ function T2(r2, t2, i, s) {
878
+ const n = i ? {
879
+ year: i.getUTCFullYear(),
880
+ month: i.getUTCMonth() + 1,
881
+ day: i.getUTCDate()
882
+ } : null, e = s ? {
883
+ year: s.getUTCFullYear(),
884
+ month: s.getUTCMonth() + 1,
885
+ day: s.getUTCDate()
886
+ } : null;
887
+ return r2 === "year" ? { min: n?.year ?? 1, max: e?.year ?? 9999 } : r2 === "month" ? {
888
+ min: n && t2.year === n.year ? n.month : 1,
889
+ max: e && t2.year === e.year ? e.month : 12
890
+ } : {
891
+ min: n && t2.year === n.year && t2.month === n.month ? n.day : 1,
892
+ max: e && t2.year === e.year && t2.month === e.month ? e.day : c(t2.year, t2.month)
893
+ };
894
+ }
895
+
896
+ class U extends V {
897
+ #i;
898
+ #o;
899
+ #t;
900
+ #h;
901
+ #u;
902
+ #e = { segmentIndex: 0, positionInSegment: 0 };
903
+ #n = true;
904
+ #s = null;
905
+ inlineError = "";
906
+ get segmentCursor() {
907
+ return { ...this.#e };
908
+ }
909
+ get segmentValues() {
910
+ return { ...this.#t };
911
+ }
912
+ get segments() {
913
+ return this.#i;
914
+ }
915
+ get separator() {
916
+ return this.#o;
917
+ }
918
+ get formattedValue() {
919
+ return this.#l(this.#t);
920
+ }
921
+ #l(t2) {
922
+ return this.#i.map((i) => t2[i.type]).join(this.#o);
923
+ }
924
+ #r() {
925
+ this._setUserInput(this.#l(this.#t)), this._setValue(C(this.#t) ?? undefined);
926
+ }
927
+ constructor(t2) {
928
+ const i = t2.format ? { segments: M(t2.format), separator: t2.separator ?? "/" } : P(t2.locale), s = t2.separator ?? i.separator, n = t2.format ? M(t2.format) : i.segments, e = t2.initialValue ?? t2.defaultValue, m2 = e ? {
929
+ year: String(e.getUTCFullYear()).padStart(4, "0"),
930
+ month: String(e.getUTCMonth() + 1).padStart(2, "0"),
931
+ day: String(e.getUTCDate()).padStart(2, "0")
932
+ } : { year: "____", month: "__", day: "__" }, o = n.map((a) => m2[a.type]).join(s);
933
+ super({ ...t2, initialUserInput: o }, false), this.#i = n, this.#o = s, this.#t = m2, this.#h = t2.minDate, this.#u = t2.maxDate, this.#r(), this.on("cursor", (a) => this.#f(a)), this.on("key", (a, u) => this.#y(a, u)), this.on("finalize", () => this.#p(t2));
934
+ }
935
+ #a() {
936
+ const t2 = Math.max(0, Math.min(this.#e.segmentIndex, this.#i.length - 1)), i = this.#i[t2];
937
+ if (i)
938
+ return this.#e.positionInSegment = Math.max(0, Math.min(this.#e.positionInSegment, i.len - 1)), { segment: i, index: t2 };
939
+ }
940
+ #m(t2) {
941
+ this.inlineError = "", this.#s = null;
942
+ const i = this.#a();
943
+ i && (this.#e.segmentIndex = Math.max(0, Math.min(this.#i.length - 1, i.index + t2)), this.#e.positionInSegment = 0, this.#n = true);
944
+ }
945
+ #d(t2) {
946
+ const i = this.#a();
947
+ if (!i)
948
+ return;
949
+ const { segment: s } = i, n = this.#t[s.type], e = !n || n.replace(/_/g, "") === "", m2 = Number.parseInt((n || "0").replace(/_/g, "0"), 10) || 0, o = T2(s.type, f(this.#t), this.#h, this.#u);
950
+ let a;
951
+ e ? a = t2 === 1 ? o.min : o.max : a = Math.max(Math.min(o.max, m2 + t2), o.min), this.#t = {
952
+ ...this.#t,
953
+ [s.type]: a.toString().padStart(s.len, "0")
954
+ }, this.#n = true, this.#s = null, this.#r();
955
+ }
956
+ #f(t2) {
957
+ if (t2)
958
+ switch (t2) {
959
+ case "right":
960
+ return this.#m(1);
961
+ case "left":
962
+ return this.#m(-1);
963
+ case "up":
964
+ return this.#d(1);
965
+ case "down":
966
+ return this.#d(-1);
967
+ }
968
+ }
969
+ #y(t2, i) {
970
+ if (i?.name === "backspace" || i?.sequence === "" || i?.sequence === "\b" || t2 === "" || t2 === "\b") {
971
+ this.inlineError = "";
972
+ const n = this.#a();
973
+ if (!n)
974
+ return;
975
+ if (!this.#t[n.segment.type].replace(/_/g, "")) {
976
+ this.#m(-1);
977
+ return;
978
+ }
979
+ this.#t[n.segment.type] = "_".repeat(n.segment.len), this.#n = true, this.#e.positionInSegment = 0, this.#r();
980
+ return;
981
+ }
982
+ if (i?.name === "tab") {
983
+ this.inlineError = "";
984
+ const n = this.#a();
985
+ if (!n)
986
+ return;
987
+ const e = i.shift ? -1 : 1, m2 = n.index + e;
988
+ m2 >= 0 && m2 < this.#i.length && (this.#e.segmentIndex = m2, this.#e.positionInSegment = 0, this.#n = true);
989
+ return;
990
+ }
991
+ if (t2 && /^[0-9]$/.test(t2)) {
992
+ const n = this.#a();
993
+ if (!n)
994
+ return;
995
+ const { segment: e } = n, m2 = !this.#t[e.type].replace(/_/g, "");
996
+ if (this.#n && this.#s !== null && !m2) {
997
+ const h = this.#s + t2, d = { ...this.#t, [e.type]: h }, g2 = this.#g(d, e);
998
+ if (g2) {
999
+ this.inlineError = g2, this.#s = null, this.#n = false;
1000
+ return;
1001
+ }
1002
+ this.inlineError = "", this.#t[e.type] = h, this.#s = null, this.#n = false, this.#r(), n.index < this.#i.length - 1 && (this.#e.segmentIndex = n.index + 1, this.#e.positionInSegment = 0, this.#n = true);
1003
+ return;
1004
+ }
1005
+ this.#n && !m2 && (this.#t[e.type] = "_".repeat(e.len), this.#e.positionInSegment = 0), this.#n = false, this.#s = null;
1006
+ const o = this.#t[e.type], a = o.indexOf("_"), u = a >= 0 ? a : Math.min(this.#e.positionInSegment, e.len - 1);
1007
+ if (u < 0 || u >= e.len)
1008
+ return;
1009
+ let l2 = o.slice(0, u) + t2 + o.slice(u + 1), D = false;
1010
+ if (u === 0 && o === "__" && (e.type === "month" || e.type === "day")) {
1011
+ const h = Number.parseInt(t2, 10);
1012
+ l2 = `0${t2}`, D = h <= (e.type === "month" ? 1 : 2);
1013
+ }
1014
+ if (e.type === "year" && (l2 = (o.replace(/_/g, "") + t2).padStart(e.len, "_")), !l2.includes("_")) {
1015
+ const h = { ...this.#t, [e.type]: l2 }, d = this.#g(h, e);
1016
+ if (d) {
1017
+ this.inlineError = d;
1018
+ return;
1019
+ }
1020
+ }
1021
+ this.inlineError = "", this.#t[e.type] = l2;
1022
+ const y = l2.includes("_") ? undefined : b(this.#t);
1023
+ if (y) {
1024
+ const { year: h, month: d } = y, g2 = c(h, d);
1025
+ this.#t = {
1026
+ year: String(Math.max(0, Math.min(9999, h))).padStart(4, "0"),
1027
+ month: String(Math.max(1, Math.min(12, d))).padStart(2, "0"),
1028
+ day: String(Math.max(1, Math.min(g2, y.day))).padStart(2, "0")
1029
+ };
1030
+ }
1031
+ this.#r();
1032
+ const S = l2.indexOf("_");
1033
+ D ? (this.#n = true, this.#s = t2) : S >= 0 ? this.#e.positionInSegment = S : a >= 0 && n.index < this.#i.length - 1 ? (this.#e.segmentIndex = n.index + 1, this.#e.positionInSegment = 0, this.#n = true) : this.#e.positionInSegment = Math.min(u + 1, e.len - 1);
1034
+ }
1035
+ }
1036
+ #g(t2, i) {
1037
+ const { month: s, day: n } = f(t2);
1038
+ if (i.type === "month" && (s < 0 || s > 12))
1039
+ return settings.date.messages.invalidMonth;
1040
+ if (i.type === "day" && (n < 0 || n > 31))
1041
+ return settings.date.messages.invalidDay(31, "any month");
1042
+ }
1043
+ #p(t2) {
1044
+ const { year: i, month: s, day: n } = f(this.#t);
1045
+ if (i && s && n) {
1046
+ const e = c(i, s);
1047
+ this.#t = {
1048
+ ...this.#t,
1049
+ day: String(Math.min(n, e)).padStart(2, "0")
1050
+ };
1051
+ }
1052
+ this.value = C(this.#t) ?? t2.defaultValue ?? undefined;
1053
+ }
1054
+ }
1055
+ var u$2 = class u extends V {
1056
+ options;
1057
+ cursor = 0;
1058
+ #t;
1059
+ getGroupItems(t2) {
1060
+ return this.options.filter((r2) => r2.group === t2);
1061
+ }
1062
+ isGroupSelected(t2) {
1063
+ const r2 = this.getGroupItems(t2), e = this.value;
1064
+ return e === undefined ? false : r2.every((s) => e.includes(s.value));
1065
+ }
1066
+ toggleValue() {
1067
+ const t2 = this.options[this.cursor];
1068
+ if (t2 !== undefined)
1069
+ if (this.value === undefined && (this.value = []), t2.group === true) {
1070
+ const r2 = t2.value, e = this.getGroupItems(r2);
1071
+ this.isGroupSelected(r2) ? this.value = this.value.filter((s) => e.findIndex((i) => i.value === s) === -1) : this.value = [...this.value, ...e.map((s) => s.value)], this.value = Array.from(new Set(this.value));
1072
+ } else {
1073
+ const r2 = this.value.includes(t2.value);
1074
+ this.value = r2 ? this.value.filter((e) => e !== t2.value) : [...this.value, t2.value];
1075
+ }
1076
+ }
1077
+ constructor(t2) {
1078
+ super(t2, false);
1079
+ const { options: r2 } = t2;
1080
+ this.#t = t2.selectableGroups !== false, this.options = Object.entries(r2).flatMap(([e, s]) => [
1081
+ { value: e, group: true, label: e },
1082
+ ...s.map((i) => ({ ...i, group: e }))
1083
+ ]), this.value = [...t2.initialValues ?? []], this.cursor = Math.max(this.options.findIndex(({ value: e }) => e === t2.cursorAt), this.#t ? 0 : 1), this.on("cursor", (e) => {
1084
+ switch (e) {
1085
+ case "left":
1086
+ case "up": {
1087
+ this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
1088
+ const s = this.options[this.cursor]?.group === true;
1089
+ !this.#t && s && (this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1);
1090
+ break;
1091
+ }
1092
+ case "down":
1093
+ case "right": {
1094
+ this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
1095
+ const s = this.options[this.cursor]?.group === true;
1096
+ !this.#t && s && (this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1);
1097
+ break;
1098
+ }
1099
+ case "space":
1100
+ this.toggleValue();
1101
+ break;
1102
+ }
1103
+ });
1104
+ }
1105
+ };
1106
+ var o = /* @__PURE__ */ new Set(["up", "down", "left", "right"]);
1107
+
1108
+ class h extends V {
1109
+ #t = false;
1110
+ #s;
1111
+ focused = "editor";
1112
+ get userInputWithCursor() {
1113
+ if (this.state === "submit")
1114
+ return this.userInput;
1115
+ const t2 = this.userInput;
1116
+ if (this.cursor >= t2.length)
1117
+ return `${t2}█`;
1118
+ const s = t2.slice(0, this.cursor), r2 = t2.slice(this.cursor, this.cursor + 1), i = t2.slice(this.cursor + 1);
1119
+ return r2 === `
1120
+ ` ? `${s}█
1121
+ ${i}` : `${s}${styleText("inverse", r2)}${i}`;
1122
+ }
1123
+ get cursor() {
1124
+ return this._cursor;
1125
+ }
1126
+ #r(t2) {
1127
+ if (this.userInput.length === 0) {
1128
+ this._setUserInput(t2);
1129
+ return;
1130
+ }
1131
+ this._setUserInput(this.userInput.slice(0, this.cursor) + t2 + this.userInput.slice(this.cursor));
1132
+ }
1133
+ #i(t2) {
1134
+ const s = this.value ?? "";
1135
+ switch (t2) {
1136
+ case "up":
1137
+ this._cursor = findTextCursor(this._cursor, 0, -1, s);
1138
+ return;
1139
+ case "down":
1140
+ this._cursor = findTextCursor(this._cursor, 0, 1, s);
1141
+ return;
1142
+ case "left":
1143
+ this._cursor = findTextCursor(this._cursor, -1, 0, s);
1144
+ return;
1145
+ case "right":
1146
+ this._cursor = findTextCursor(this._cursor, 1, 0, s);
1147
+ return;
1148
+ }
1149
+ }
1150
+ _shouldSubmit(t2, s) {
1151
+ if (this.#s)
1152
+ return this.focused === "submit" ? true : (this.#r(`
1153
+ `), this._cursor++, false);
1154
+ const r2 = this.#t;
1155
+ return this.#t = true, r2 && this.cursor === this.userInput.length ? (this.userInput[this.cursor - 1] === `
1156
+ ` && (this._setUserInput(this.userInput.slice(0, this.cursor - 1) + this.userInput.slice(this.cursor)), this._cursor--), true) : (this.#r(`
1157
+ `), this._cursor++, false);
1158
+ }
1159
+ constructor(t2) {
1160
+ const s = t2.initialUserInput ?? t2.initialValue;
1161
+ super({
1162
+ ...t2,
1163
+ initialUserInput: s
1164
+ }, false), s !== undefined && (this._cursor = s.length), this.#s = t2.showSubmit ?? false, this.on("key", (r2, i) => {
1165
+ if (i?.name && o.has(i.name)) {
1166
+ this.#t = false, this.#i(i.name);
1167
+ return;
1168
+ }
1169
+ if (r2 === "\t" && this.#s) {
1170
+ this.focused = this.focused === "editor" ? "submit" : "editor";
1171
+ return;
1172
+ }
1173
+ if (i?.name !== "return") {
1174
+ if (this.#t = false, i?.name === "backspace" && this.cursor > 0) {
1175
+ this._setUserInput(this.userInput.slice(0, this.cursor - 1) + this.userInput.slice(this.cursor)), this._cursor--;
1176
+ return;
1177
+ }
1178
+ if (i?.name === "delete" && this.cursor < this.userInput.length) {
1179
+ this._setUserInput(this.userInput.slice(0, this.cursor) + this.userInput.slice(this.cursor + 1));
1180
+ return;
1181
+ }
1182
+ r2 && (this.#s && this.focused === "submit" && (this.focused = "editor"), this.#r(r2 ?? ""), this._cursor++);
1183
+ }
1184
+ }), this.on("userInput", (r2) => {
1185
+ this._setValue(r2);
1186
+ }), this.on("finalize", () => {
1187
+ this.value || (this.value = t2.defaultValue), this.value === undefined && (this.value = "");
1188
+ });
1189
+ }
1190
+ }
1191
+
1192
+ class a extends V {
1193
+ options;
1194
+ cursor = 0;
1195
+ get _value() {
1196
+ return this.options[this.cursor]?.value;
1197
+ }
1198
+ get _enabledOptions() {
1199
+ return this.options.filter((e) => e.disabled !== true);
1200
+ }
1201
+ toggleAll() {
1202
+ const e = this._enabledOptions, i = this.value !== undefined && this.value.length === e.length;
1203
+ this.value = i ? [] : e.map((t2) => t2.value);
1204
+ }
1205
+ toggleInvert() {
1206
+ const e = this.value;
1207
+ if (!e)
1208
+ return;
1209
+ const i = this._enabledOptions.filter((t2) => !e.includes(t2.value));
1210
+ this.value = i.map((t2) => t2.value);
1211
+ }
1212
+ toggleValue() {
1213
+ this.value === undefined && (this.value = []);
1214
+ const e = this.value.includes(this._value);
1215
+ this.value = e ? this.value.filter((i) => i !== this._value) : [...this.value, this._value];
1216
+ }
1217
+ constructor(e) {
1218
+ super(e, false), this.options = e.options, this.value = [...e.initialValues ?? []];
1219
+ const i = Math.max(this.options.findIndex(({ value: t2 }) => t2 === e.cursorAt), 0);
1220
+ this.cursor = this.options[i]?.disabled ? findCursor(i, 1, this.options) : i, this.on("key", (t2, l2) => {
1221
+ l2.name === "a" && this.toggleAll(), l2.name === "i" && this.toggleInvert();
1222
+ }), this.on("cursor", (t2) => {
1223
+ switch (t2) {
1224
+ case "left":
1225
+ case "up":
1226
+ this.cursor = findCursor(this.cursor, -1, this.options);
1227
+ break;
1228
+ case "down":
1229
+ case "right":
1230
+ this.cursor = findCursor(this.cursor, 1, this.options);
1231
+ break;
1232
+ case "space":
1233
+ this.toggleValue();
1234
+ break;
1235
+ }
1236
+ });
1237
+ }
1238
+ }
1239
+ var u$1 = class u2 extends V {
1240
+ _mask = "•";
1241
+ get cursor() {
1242
+ return this._cursor;
1243
+ }
1244
+ get masked() {
1245
+ return this.userInput.replaceAll(/./g, this._mask);
1246
+ }
1247
+ get userInputWithCursor() {
1248
+ if (this.state === "submit" || this.state === "cancel")
1249
+ return this.masked;
1250
+ const t2 = this.userInput;
1251
+ if (this.cursor >= t2.length)
1252
+ return `${this.masked}${styleText(["inverse", "hidden"], "_")}`;
1253
+ const s = this.masked, r2 = s.slice(0, this.cursor), i = s.slice(this.cursor, this.cursor + 1), o2 = s.slice(this.cursor + 1);
1254
+ return `${r2}${styleText("inverse", i)}${o2}`;
1255
+ }
1256
+ clear() {
1257
+ this._clearUserInput();
1258
+ }
1259
+ constructor({ mask: t2, ...s }) {
1260
+ super(s), this._mask = t2 ?? "•", this.on("userInput", (r2) => {
1261
+ this._setValue(r2);
1262
+ }), this.on("finalize", () => {
1263
+ this.value === undefined && (this.value = "");
1264
+ });
1265
+ }
1266
+ };
1267
+ var n$1 = class n extends V {
1268
+ options;
1269
+ cursor = 0;
1270
+ get _selectedValue() {
1271
+ return this.options[this.cursor];
1272
+ }
1273
+ changeValue() {
1274
+ const e = this._selectedValue;
1275
+ this.value = e === undefined ? undefined : e.value;
1276
+ }
1277
+ constructor(e) {
1278
+ super(e, false), this.options = e.options;
1279
+ const o2 = this.options.findIndex(({ value: s }) => s === e.initialValue), t2 = o2 === -1 ? 0 : o2;
1280
+ this.cursor = this.options[t2]?.disabled ? findCursor(t2, 1, this.options) : t2, this.changeValue(), this.on("cursor", (s) => {
1281
+ switch (s) {
1282
+ case "left":
1283
+ case "up":
1284
+ this.cursor = findCursor(this.cursor, -1, this.options);
1285
+ break;
1286
+ case "down":
1287
+ case "right":
1288
+ this.cursor = findCursor(this.cursor, 1, this.options);
1289
+ break;
1290
+ }
1291
+ this.changeValue();
1292
+ });
1293
+ }
1294
+ };
1295
+ class n2 extends V {
1296
+ get userInputWithCursor() {
1297
+ if (this.state === "submit")
1298
+ return this.userInput;
1299
+ const t2 = this.userInput;
1300
+ if (this.cursor >= t2.length)
1301
+ return `${this.userInput}█`;
1302
+ const r2 = t2.slice(0, this.cursor), s = t2.slice(this.cursor, this.cursor + 1), e = t2.slice(this.cursor + 1);
1303
+ return `${r2}${styleText("inverse", s)}${e}`;
1304
+ }
1305
+ get cursor() {
1306
+ return this._cursor;
1307
+ }
1308
+ constructor(t2) {
1309
+ super({
1310
+ ...t2,
1311
+ initialUserInput: t2.initialUserInput ?? t2.initialValue
1312
+ }), this.on("userInput", (r2) => {
1313
+ this._setValue(r2);
1314
+ }), this.on("finalize", () => {
1315
+ this.value || (this.value = t2.defaultValue), this.value === undefined && (this.value = "");
1316
+ });
1317
+ }
1318
+ }
1319
+
1320
+ // node_modules/@clack/prompts/dist/index.mjs
1321
+ import { styleText as styleText2, stripVTControlCharacters } from "node:util";
1322
+ import process$1 from "node:process";
1323
+ var import_sisteransi2 = __toESM(require_src(), 1);
1324
+ function isUnicodeSupported() {
1325
+ if (process$1.platform !== "win32") {
1326
+ return process$1.env.TERM !== "linux";
1327
+ }
1328
+ 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";
1329
+ }
1330
+ var unicode = isUnicodeSupported();
1331
+ var isCI = () => process.env.CI === "true";
1332
+ var isTTY = (o2) => o2.isTTY === true;
1333
+ var unicodeOr = (o2, e) => unicode ? o2 : e;
1334
+ var S_STEP_ACTIVE = unicodeOr("◆", "*");
1335
+ var S_STEP_CANCEL = unicodeOr("■", "x");
1336
+ var S_STEP_ERROR = unicodeOr("▲", "x");
1337
+ var S_STEP_SUBMIT = unicodeOr("◇", "o");
1338
+ var S_BAR_START = unicodeOr("┌", "T");
1339
+ var S_BAR = unicodeOr("│", "|");
1340
+ var S_BAR_END = unicodeOr("└", "—");
1341
+ var S_BAR_START_RIGHT = unicodeOr("┐", "T");
1342
+ var S_BAR_END_RIGHT = unicodeOr("┘", "—");
1343
+ var S_RADIO_ACTIVE = unicodeOr("●", ">");
1344
+ var S_RADIO_INACTIVE = unicodeOr("○", " ");
1345
+ var S_CHECKBOX_ACTIVE = unicodeOr("◻", "[•]");
1346
+ var S_CHECKBOX_SELECTED = unicodeOr("◼", "[+]");
1347
+ var S_CHECKBOX_INACTIVE = unicodeOr("◻", "[ ]");
1348
+ var S_PASSWORD_MASK = unicodeOr("▪", "•");
1349
+ var S_BAR_H = unicodeOr("─", "-");
1350
+ var S_CORNER_TOP_RIGHT = unicodeOr("╮", "+");
1351
+ var S_CONNECT_LEFT = unicodeOr("├", "+");
1352
+ var S_CORNER_BOTTOM_RIGHT = unicodeOr("╯", "+");
1353
+ var S_CORNER_BOTTOM_LEFT = unicodeOr("╰", "+");
1354
+ var S_CORNER_TOP_LEFT = unicodeOr("╭", "+");
1355
+ var S_INFO = unicodeOr("●", "•");
1356
+ var S_SUCCESS = unicodeOr("◆", "*");
1357
+ var S_WARN = unicodeOr("▲", "!");
1358
+ var S_ERROR = unicodeOr("■", "x");
1359
+ var symbol = (o2) => {
1360
+ switch (o2) {
1361
+ case "initial":
1362
+ case "active":
1363
+ return styleText2("cyan", S_STEP_ACTIVE);
1364
+ case "cancel":
1365
+ return styleText2("red", S_STEP_CANCEL);
1366
+ case "error":
1367
+ return styleText2("yellow", S_STEP_ERROR);
1368
+ case "submit":
1369
+ return styleText2("green", S_STEP_SUBMIT);
1370
+ }
1371
+ };
1372
+ var confirm = (i) => {
1373
+ const a2 = i.active ?? "Yes", s = i.inactive ?? "No";
1374
+ return new r({
1375
+ active: a2,
1376
+ inactive: s,
1377
+ signal: i.signal,
1378
+ input: i.input,
1379
+ output: i.output,
1380
+ initialValue: i.initialValue ?? true,
1381
+ render() {
1382
+ const e = i.withGuide ?? settings.withGuide, u4 = `${symbol(this.state)} `, l2 = e ? `${styleText2("gray", S_BAR)} ` : "", f2 = wrapTextWithPrefix(i.output, i.message, l2, u4), o2 = `${e ? `${styleText2("gray", S_BAR)}
1383
+ ` : ""}${f2}
1384
+ `, c2 = this.value ? a2 : s;
1385
+ switch (this.state) {
1386
+ case "submit": {
1387
+ const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
1388
+ return `${o2}${r2}${styleText2("dim", c2)}`;
1389
+ }
1390
+ case "cancel": {
1391
+ const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
1392
+ return `${o2}${r2}${styleText2(["strikethrough", "dim"], c2)}${e ? `
1393
+ ${styleText2("gray", S_BAR)}` : ""}`;
1394
+ }
1395
+ default: {
1396
+ const r2 = e ? `${styleText2("cyan", S_BAR)} ` : "", g2 = e ? styleText2("cyan", S_BAR_END) : "";
1397
+ return `${o2}${r2}${this.value ? `${styleText2("green", S_RADIO_ACTIVE)} ${a2}` : `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", a2)}`}${i.vertical ? e ? `
1398
+ ${styleText2("cyan", S_BAR)} ` : `
1399
+ ` : ` ${styleText2("dim", "/")} `}${this.value ? `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", s)}` : `${styleText2("green", S_RADIO_ACTIVE)} ${s}`}
1400
+ ${g2}
1401
+ `;
1402
+ }
1403
+ }
1404
+ }
1405
+ }).prompt();
1406
+ };
1407
+ var MULTISELECT_INSTRUCTIONS = [
1408
+ `${styleText2("dim", "↑/↓")} to navigate`,
1409
+ `${styleText2("dim", "Space:")} select`,
1410
+ `${styleText2("dim", "Enter:")} confirm`
1411
+ ];
1412
+ var log = {
1413
+ message: (s = [], {
1414
+ symbol: e = styleText2("gray", S_BAR),
1415
+ secondarySymbol: r2 = styleText2("gray", S_BAR),
1416
+ output: m2 = process.stdout,
1417
+ spacing: l2 = 1,
1418
+ withGuide: c2
1419
+ } = {}) => {
1420
+ const t2 = [], o2 = c2 ?? settings.withGuide, f2 = o2 ? r2 : "", O = o2 ? `${e} ` : "", u4 = o2 ? `${r2} ` : "";
1421
+ for (let i = 0;i < l2; i++)
1422
+ t2.push(f2);
1423
+ const g2 = Array.isArray(s) ? s : s.split(`
1424
+ `);
1425
+ if (g2.length > 0) {
1426
+ const [i, ...y] = g2;
1427
+ i.length > 0 ? t2.push(`${O}${i}`) : t2.push(o2 ? e : "");
1428
+ for (const p2 of y)
1429
+ p2.length > 0 ? t2.push(`${u4}${p2}`) : t2.push(o2 ? r2 : "");
1430
+ }
1431
+ m2.write(`${t2.join(`
1432
+ `)}
1433
+ `);
1434
+ },
1435
+ info: (s, e) => {
1436
+ log.message(s, { ...e, symbol: styleText2("blue", S_INFO) });
1437
+ },
1438
+ success: (s, e) => {
1439
+ log.message(s, { ...e, symbol: styleText2("green", S_SUCCESS) });
1440
+ },
1441
+ step: (s, e) => {
1442
+ log.message(s, { ...e, symbol: styleText2("green", S_STEP_SUBMIT) });
1443
+ },
1444
+ warn: (s, e) => {
1445
+ log.message(s, { ...e, symbol: styleText2("yellow", S_WARN) });
1446
+ },
1447
+ warning: (s, e) => {
1448
+ log.warn(s, e);
1449
+ },
1450
+ error: (s, e) => {
1451
+ log.message(s, { ...e, symbol: styleText2("red", S_ERROR) });
1452
+ }
1453
+ };
1454
+ var cancel = (o2 = "", t2) => {
1455
+ const i = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_END)} ` : "";
1456
+ i.write(`${e}${styleText2("red", o2)}
1457
+
1458
+ `);
1459
+ };
1460
+ var intro = (o2 = "", t2) => {
1461
+ const i = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_START)} ` : "";
1462
+ i.write(`${e}${o2}
1463
+ `);
1464
+ };
1465
+ var outro = (o2 = "", t2) => {
1466
+ const i = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR)}
1467
+ ${styleText2("gray", S_BAR_END)} ` : "";
1468
+ i.write(`${e}${o2}
1469
+
1470
+ `);
1471
+ };
1472
+ var password = (r2) => new u$1({
1473
+ validate: r2.validate,
1474
+ mask: r2.mask ?? S_PASSWORD_MASK,
1475
+ signal: r2.signal,
1476
+ input: r2.input,
1477
+ output: r2.output,
1478
+ render() {
1479
+ const e = r2.withGuide ?? settings.withGuide, o2 = `${e ? `${styleText2("gray", S_BAR)}
1480
+ ` : ""}${symbol(this.state)} ${r2.message}
1481
+ `, c2 = this.userInputWithCursor, i = this.masked;
1482
+ switch (this.state) {
1483
+ case "error": {
1484
+ const s = e ? `${styleText2("yellow", S_BAR)} ` : "", n3 = e ? `${styleText2("yellow", S_BAR_END)} ` : "", l2 = i ?? "";
1485
+ return r2.clearOnError && this.clear(), `${o2.trim()}
1486
+ ${s}${l2}
1487
+ ${n3}${styleText2("yellow", this.error)}
1488
+ `;
1489
+ }
1490
+ case "submit": {
1491
+ const s = e ? `${styleText2("gray", S_BAR)} ` : "", n3 = i ? styleText2("dim", i) : "";
1492
+ return `${o2}${s}${n3}`;
1493
+ }
1494
+ case "cancel": {
1495
+ const s = e ? `${styleText2("gray", S_BAR)} ` : "", n3 = i ? styleText2(["strikethrough", "dim"], i) : "";
1496
+ return `${o2}${s}${n3}${i && e ? `
1497
+ ${styleText2("gray", S_BAR)}` : ""}`;
1498
+ }
1499
+ default: {
1500
+ const s = e ? `${styleText2("cyan", S_BAR)} ` : "", n3 = e ? styleText2("cyan", S_BAR_END) : "";
1501
+ return `${o2}${s}${c2}
1502
+ ${n3}
1503
+ `;
1504
+ }
1505
+ }
1506
+ }
1507
+ }).prompt();
1508
+ var W = (l2) => styleText2("magenta", l2);
1509
+ var spinner = ({
1510
+ indicator: l2 = "dots",
1511
+ onCancel: h2,
1512
+ output: n3 = process.stdout,
1513
+ cancelMessage: G,
1514
+ errorMessage: O,
1515
+ frames: E = unicode ? ["◒", "◐", "◓", "◑"] : ["•", "o", "O", "0"],
1516
+ delay: F = unicode ? 80 : 120,
1517
+ signal: m2,
1518
+ ...I
1519
+ } = {}) => {
1520
+ const u4 = isCI();
1521
+ let M2, T3, d = false, S = false, s = "", p2, w = performance.now();
1522
+ const x = getColumns(n3), k = I?.styleFrame ?? W, g2 = (e) => {
1523
+ const r2 = e > 1 ? O ?? settings.messages.error : G ?? settings.messages.cancel;
1524
+ S = e === 1, d && (a2(r2, e), S && typeof h2 == "function" && h2());
1525
+ }, f2 = () => g2(2), i = () => g2(1), A = () => {
1526
+ process.on("uncaughtExceptionMonitor", f2), process.on("unhandledRejection", f2), process.on("SIGINT", i), process.on("SIGTERM", i), process.on("exit", g2), m2 && m2.addEventListener("abort", i);
1527
+ }, H = () => {
1528
+ process.removeListener("uncaughtExceptionMonitor", f2), process.removeListener("unhandledRejection", f2), process.removeListener("SIGINT", i), process.removeListener("SIGTERM", i), process.removeListener("exit", g2), m2 && m2.removeEventListener("abort", i);
1529
+ }, y = () => {
1530
+ if (p2 === undefined)
1531
+ return;
1532
+ u4 && n3.write(`
1533
+ `);
1534
+ const r2 = wrapAnsi(p2, x, {
1535
+ hard: true,
1536
+ trim: false
1537
+ }).split(`
1538
+ `);
1539
+ r2.length > 1 && n3.write(import_sisteransi2.cursor.up(r2.length - 1)), n3.write(import_sisteransi2.cursor.to(0)), n3.write(import_sisteransi2.erase.down());
1540
+ }, C2 = (e) => e.replace(/\.+$/, ""), _2 = (e) => {
1541
+ const r2 = (performance.now() - e) / 1000, t2 = Math.floor(r2 / 60), o2 = Math.floor(r2 % 60);
1542
+ return t2 > 0 ? `[${t2}m ${o2}s]` : `[${o2}s]`;
1543
+ }, N = I.withGuide ?? settings.withGuide, P2 = (e = "") => {
1544
+ d = true, M2 = block({ output: n3 }), s = C2(e), w = performance.now(), N && n3.write(`${styleText2("gray", S_BAR)}
1545
+ `);
1546
+ let r2 = 0, t2 = 0;
1547
+ A(), T3 = setInterval(() => {
1548
+ if (u4 && s === p2)
1549
+ return;
1550
+ y(), p2 = s;
1551
+ const o2 = k(E[r2]);
1552
+ let v;
1553
+ if (u4)
1554
+ v = `${o2} ${s}...`;
1555
+ else if (l2 === "timer")
1556
+ v = `${o2} ${s} ${_2(w)}`;
1557
+ else {
1558
+ const B = ".".repeat(Math.floor(t2)).slice(0, 3);
1559
+ v = `${o2} ${s}${B}`;
1560
+ }
1561
+ const j = wrapAnsi(v, x, {
1562
+ hard: true,
1563
+ trim: false
1564
+ });
1565
+ n3.write(j), r2 = r2 + 1 < E.length ? r2 + 1 : 0, t2 = t2 < 4 ? t2 + 0.125 : 0;
1566
+ }, F);
1567
+ }, a2 = (e = "", r2 = 0, t2 = false) => {
1568
+ if (!d)
1569
+ return;
1570
+ d = false, clearInterval(T3), y();
1571
+ const o2 = r2 === 0 ? styleText2("green", S_STEP_SUBMIT) : r2 === 1 ? styleText2("red", S_STEP_CANCEL) : styleText2("red", S_STEP_ERROR);
1572
+ s = e ?? s, t2 || (l2 === "timer" ? n3.write(`${o2} ${s} ${_2(w)}
1573
+ `) : n3.write(`${o2} ${s}
1574
+ `)), H(), M2();
1575
+ };
1576
+ return {
1577
+ start: P2,
1578
+ stop: (e = "") => a2(e, 0),
1579
+ message: (e = "") => {
1580
+ s = C2(e ?? s);
1581
+ },
1582
+ cancel: (e = "") => a2(e, 1),
1583
+ error: (e = "") => a2(e, 2),
1584
+ clear: () => a2("", 0, true),
1585
+ get isCancelled() {
1586
+ return S;
1587
+ }
1588
+ };
1589
+ };
1590
+ var u4 = {
1591
+ light: unicodeOr("─", "-"),
1592
+ heavy: unicodeOr("━", "="),
1593
+ block: unicodeOr("█", "#")
1594
+ };
1595
+ function progress({
1596
+ style: o2 = "heavy",
1597
+ max: d = 100,
1598
+ size: v = 40,
1599
+ ...x
1600
+ } = {}) {
1601
+ const r2 = spinner(x);
1602
+ let a2 = 0, n3 = "";
1603
+ const c2 = Math.max(1, d), l2 = Math.max(1, v), S = (t2) => {
1604
+ switch (t2) {
1605
+ case "initial":
1606
+ case "active":
1607
+ return (e) => styleText2("magenta", e);
1608
+ case "error":
1609
+ case "cancel":
1610
+ return (e) => styleText2("red", e);
1611
+ case "submit":
1612
+ return (e) => styleText2("green", e);
1613
+ default:
1614
+ return (e) => styleText2("magenta", e);
1615
+ }
1616
+ }, p2 = (t2, e) => {
1617
+ const m2 = Math.floor(a2 / c2 * l2);
1618
+ return `${S(t2)(u4[o2].repeat(m2))}${styleText2("dim", u4[o2].repeat(l2 - m2))} ${e}`;
1619
+ }, h2 = (t2 = "") => {
1620
+ n3 = t2, r2.start(p2("initial", t2));
1621
+ }, g2 = (t2 = 1, e) => {
1622
+ a2 = Math.min(c2, t2 + a2), r2.message(p2("active", e ?? n3)), n3 = e ?? n3;
1623
+ };
1624
+ return {
1625
+ start: h2,
1626
+ stop: r2.stop,
1627
+ cancel: r2.cancel,
1628
+ error: r2.error,
1629
+ clear: r2.clear,
1630
+ advance: g2,
1631
+ isCancelled: r2.isCancelled,
1632
+ message: (t2) => g2(0, t2)
1633
+ };
1634
+ }
1635
+ var SELECT_INSTRUCTIONS = [
1636
+ `${styleText2("dim", "↑/↓")} to navigate`,
1637
+ `${styleText2("dim", "Enter:")} confirm`
1638
+ ];
1639
+ var i = `${styleText2("gray", S_BAR)} `;
1640
+ var text = (e) => new n2({
1641
+ validate: e.validate,
1642
+ placeholder: e.placeholder,
1643
+ defaultValue: e.defaultValue,
1644
+ initialValue: e.initialValue,
1645
+ output: e.output,
1646
+ signal: e.signal,
1647
+ input: e.input,
1648
+ render() {
1649
+ const i2 = e?.withGuide ?? settings.withGuide, s = `${`${i2 ? `${styleText2("gray", S_BAR)}
1650
+ ` : ""}${symbol(this.state)} `}${e.message}
1651
+ `, c2 = e.placeholder && e.placeholder.length > 0 ? styleText2("inverse", e.placeholder[0]) + styleText2("dim", e.placeholder.slice(1)) : styleText2(["inverse", "hidden"], "_"), o2 = this.userInput ? this.userInputWithCursor : c2, l2 = this.value ?? "";
1652
+ switch (this.state) {
1653
+ case "error": {
1654
+ const n3 = this.error ? ` ${styleText2("yellow", this.error)}` : "", r2 = i2 ? `${styleText2("yellow", S_BAR)} ` : "", d = i2 ? styleText2("yellow", S_BAR_END) : "";
1655
+ return `${s.trim()}
1656
+ ${r2}${o2}
1657
+ ${d}${n3}
1658
+ `;
1659
+ }
1660
+ case "submit": {
1661
+ const n3 = l2 ? ` ${styleText2("dim", l2)}` : "", r2 = i2 ? styleText2("gray", S_BAR) : "";
1662
+ return `${s}${r2}${n3}`;
1663
+ }
1664
+ case "cancel": {
1665
+ const n3 = l2 ? ` ${styleText2(["strikethrough", "dim"], l2)}` : "", r2 = i2 ? styleText2("gray", S_BAR) : "";
1666
+ return `${s}${r2}${n3}${l2.trim() ? `
1667
+ ${r2}` : ""}`;
1668
+ }
1669
+ default: {
1670
+ const n3 = i2 ? `${styleText2("cyan", S_BAR)} ` : "", r2 = i2 ? styleText2("cyan", S_BAR_END) : "";
1671
+ return `${s}${n3}${o2}
1672
+ ${r2}
1673
+ `;
1674
+ }
1675
+ }
1676
+ }
1677
+ }).prompt();
3
1678
 
4
1679
  // src/cli.ts
5
- import * as prompts5 from "@clack/prompts";
6
- import { mkdir as mkdir5, mkdtemp as mkdtemp2, readFile as readFile6, readdir as readdir2, rename as rename2, rm as rm4, rmdir, stat as stat5 } from "fs/promises";
1680
+ import { existsSync, readdirSync, statSync } from "fs";
1681
+ import { mkdir as mkdir5, mkdtemp as mkdtemp2, readFile as readFile6, readdir as readdir2, rename as rename2, rm as rm5, rmdir, stat as stat5 } from "fs/promises";
7
1682
  import { createConnection, createServer } from "net";
8
1683
  import { fileURLToPath as fileURLToPath2 } from "url";
9
- import { dirname as dirname2, join as join7, relative as relative2, resolve as resolve4, sep } from "path";
1684
+ import { dirname as dirname2, join as join8, relative as relative2, resolve as resolve4, sep } from "path";
10
1685
 
11
1686
  // src/constants.ts
12
1687
  var CLI_NAME = "superslate";
1688
+ var LICENSE_KEY_VARIABLE = "SUPERSLATE_LICENSE_KEY";
13
1689
 
14
1690
  // src/constants.ts
15
1691
  var CLI_NAME2 = "superslate";
@@ -18,7 +1694,10 @@ var BUYER_CLI_NAME = "create-app";
18
1694
  var BUYER_CLI_PACKAGE_NAME = "create-app";
19
1695
  var DEFAULT_SCOPE = "@app";
20
1696
  var SOURCE_BRAND_NAME = "superslate";
21
- var TEMPLATE_REPOSITORY = "superslate-dev/superslate";
1697
+ var DELIVERY_BASE_URL = "https://dl.superslate.dev";
1698
+ var DELIVERY_URL_VARIABLE = "SUPERSLATE_DELIVERY_URL";
1699
+ var LICENSE_KEY_VARIABLE2 = "SUPERSLATE_LICENSE_KEY";
1700
+ var LICENSE_KEY_PREFIX = "SUPERSLATE-";
22
1701
 
23
1702
  // src/core.ts
24
1703
  function validateAppName(value) {
@@ -55,8 +1734,532 @@ function validateBrandName(value) {
55
1734
  }
56
1735
  var SCOPE_EXTENSIONS = new Set([".json", ".jsonc", ".md", ".ts", ".tsx", ".yaml", ".yml"]);
57
1736
 
1737
+ // src/delivery.ts
1738
+ var RELEASE_TAG_PATTERN = /^v\d+\.\d+\.\d+(?:-rc\.\d+)?$/;
1739
+ function validateLicenseKey(value) {
1740
+ const key = value.trim();
1741
+ if (!key)
1742
+ return "Enter the licence key from your purchase receipt.";
1743
+ if (/\s/.test(key))
1744
+ return "A licence key does not contain spaces.";
1745
+ if (!key.startsWith(LICENSE_KEY_PREFIX) || key.length === LICENSE_KEY_PREFIX.length) {
1746
+ return `A ${CLI_NAME2} licence key starts with ${LICENSE_KEY_PREFIX}. Copy it from your purchase receipt or the customer portal.`;
1747
+ }
1748
+ return;
1749
+ }
1750
+ function readLicenseKeyFromEnvironment(environment = process.env) {
1751
+ return environment[LICENSE_KEY_VARIABLE2]?.trim() || undefined;
1752
+ }
1753
+ function normalizeSourceVersion(value) {
1754
+ const trimmed = value.trim();
1755
+ const releaseTag = trimmed.startsWith("v") ? trimmed : `v${trimmed}`;
1756
+ if (!RELEASE_TAG_PATTERN.test(releaseTag)) {
1757
+ throw new Error(`Source version must be an immutable release such as 1.2.3: ${value}`);
1758
+ }
1759
+ return releaseTag;
1760
+ }
1761
+
1762
+ // node_modules/@clack/prompts/dist/index.mjs
1763
+ import { styleText as styleText3, stripVTControlCharacters as stripVTControlCharacters2 } from "node:util";
1764
+ import process$12 from "node:process";
1765
+ var import_sisteransi3 = __toESM(require_src(), 1);
1766
+ function isUnicodeSupported2() {
1767
+ if (process$12.platform !== "win32") {
1768
+ return process$12.env.TERM !== "linux";
1769
+ }
1770
+ return Boolean(process$12.env.CI) || Boolean(process$12.env.WT_SESSION) || Boolean(process$12.env.TERMINUS_SUBLIME) || process$12.env.ConEmuTask === "{cmd::Cmder}" || process$12.env.TERM_PROGRAM === "Terminus-Sublime" || process$12.env.TERM_PROGRAM === "vscode" || process$12.env.TERM === "xterm-256color" || process$12.env.TERM === "alacritty" || process$12.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
1771
+ }
1772
+ var unicode2 = isUnicodeSupported2();
1773
+ var isCI2 = () => process.env.CI === "true";
1774
+ var unicodeOr2 = (o2, e) => unicode2 ? o2 : e;
1775
+ var S_STEP_ACTIVE2 = unicodeOr2("◆", "*");
1776
+ var S_STEP_CANCEL2 = unicodeOr2("■", "x");
1777
+ var S_STEP_ERROR2 = unicodeOr2("▲", "x");
1778
+ var S_STEP_SUBMIT2 = unicodeOr2("◇", "o");
1779
+ var S_BAR_START2 = unicodeOr2("┌", "T");
1780
+ var S_BAR2 = unicodeOr2("│", "|");
1781
+ var S_BAR_END2 = unicodeOr2("└", "—");
1782
+ var S_BAR_START_RIGHT2 = unicodeOr2("┐", "T");
1783
+ var S_BAR_END_RIGHT2 = unicodeOr2("┘", "—");
1784
+ var S_RADIO_ACTIVE2 = unicodeOr2("●", ">");
1785
+ var S_RADIO_INACTIVE2 = unicodeOr2("○", " ");
1786
+ var S_CHECKBOX_ACTIVE2 = unicodeOr2("◻", "[•]");
1787
+ var S_CHECKBOX_SELECTED2 = unicodeOr2("◼", "[+]");
1788
+ var S_CHECKBOX_INACTIVE2 = unicodeOr2("◻", "[ ]");
1789
+ var S_PASSWORD_MASK2 = unicodeOr2("▪", "•");
1790
+ var S_BAR_H2 = unicodeOr2("─", "-");
1791
+ var S_CORNER_TOP_RIGHT2 = unicodeOr2("╮", "+");
1792
+ var S_CONNECT_LEFT2 = unicodeOr2("├", "+");
1793
+ var S_CORNER_BOTTOM_RIGHT2 = unicodeOr2("╯", "+");
1794
+ var S_CORNER_BOTTOM_LEFT2 = unicodeOr2("╰", "+");
1795
+ var S_CORNER_TOP_LEFT2 = unicodeOr2("╭", "+");
1796
+ var S_INFO2 = unicodeOr2("●", "•");
1797
+ var S_SUCCESS2 = unicodeOr2("◆", "*");
1798
+ var S_WARN2 = unicodeOr2("▲", "!");
1799
+ var S_ERROR2 = unicodeOr2("■", "x");
1800
+ var symbol2 = (o2) => {
1801
+ switch (o2) {
1802
+ case "initial":
1803
+ case "active":
1804
+ return styleText3("cyan", S_STEP_ACTIVE2);
1805
+ case "cancel":
1806
+ return styleText3("red", S_STEP_CANCEL2);
1807
+ case "error":
1808
+ return styleText3("yellow", S_STEP_ERROR2);
1809
+ case "submit":
1810
+ return styleText3("green", S_STEP_SUBMIT2);
1811
+ }
1812
+ };
1813
+ var symbolBar = (o2) => {
1814
+ switch (o2) {
1815
+ case "initial":
1816
+ case "active":
1817
+ return styleText3("cyan", S_BAR2);
1818
+ case "cancel":
1819
+ return styleText3("red", S_BAR2);
1820
+ case "error":
1821
+ return styleText3("yellow", S_BAR2);
1822
+ case "submit":
1823
+ return styleText3("green", S_BAR2);
1824
+ }
1825
+ };
1826
+ function formatInstructionFooter(o2, e) {
1827
+ const r2 = [`${e ? `${styleText3("cyan", S_BAR2)} ` : ""}${o2.join(" • ")}`];
1828
+ return e && r2.push(styleText3("cyan", S_BAR_END2)), r2;
1829
+ }
1830
+ var I = (l2, e, w, p2, b2, C2 = false) => {
1831
+ let r2 = e, O = 0;
1832
+ if (C2)
1833
+ for (let i2 = p2 - 1;i2 >= w; i2--) {
1834
+ const m2 = l2[i2];
1835
+ if (m2 && (r2 -= m2.length), O++, r2 <= b2)
1836
+ break;
1837
+ }
1838
+ else
1839
+ for (let i2 = w;i2 < p2; i2++) {
1840
+ const m2 = l2[i2];
1841
+ if (m2 && (r2 -= m2.length), O++, r2 <= b2)
1842
+ break;
1843
+ }
1844
+ return { lineCount: r2, removals: O };
1845
+ };
1846
+ var limitOptions = ({
1847
+ cursor: l2,
1848
+ options: e,
1849
+ style: w,
1850
+ output: p2 = process.stdout,
1851
+ maxItems: b2 = Number.POSITIVE_INFINITY,
1852
+ columnPadding: C2 = 0,
1853
+ rowPadding: r2 = 4
1854
+ }) => {
1855
+ const i2 = getColumns(p2) - C2, m2 = getRows(p2), M2 = styleText3("dim", "..."), v = Math.max(m2 - r2, 0), a2 = Math.max(Math.min(b2, v), 5);
1856
+ let f2 = 0;
1857
+ l2 >= a2 - 3 && (f2 = Math.max(Math.min(l2 - a2 + 3, e.length - a2), 0));
1858
+ let d = a2 < e.length && f2 > 0, c2 = a2 < e.length && f2 + a2 < e.length;
1859
+ const W2 = Math.min(f2 + a2, e.length), s = [];
1860
+ let g2 = 0;
1861
+ d && g2++, c2 && g2++;
1862
+ const T3 = f2 + (d ? 1 : 0), y = W2 - (c2 ? 1 : 0);
1863
+ for (let t2 = T3;t2 < y; t2++) {
1864
+ const n3 = e[t2], o2 = n3 ? w(n3, t2 === l2) : "", h2 = wrapAnsi(o2, i2, {
1865
+ hard: true,
1866
+ trim: false
1867
+ }).split(`
1868
+ `);
1869
+ s.push(h2), g2 += h2.length;
1870
+ }
1871
+ if (g2 > v) {
1872
+ let t2 = 0, n3 = 0, o2 = g2;
1873
+ const h2 = l2 - T3;
1874
+ let u5 = v;
1875
+ const L = () => I(s, o2, 0, h2, u5), E = () => I(s, o2, h2 + 1, s.length, u5, true);
1876
+ d ? ({ lineCount: o2, removals: t2 } = L(), o2 > u5 && (c2 || (u5 -= 1), { lineCount: o2, removals: n3 } = E())) : (c2 || (u5 -= 1), { lineCount: o2, removals: n3 } = E(), o2 > u5 && (u5 -= 1, { lineCount: o2, removals: t2 } = L())), t2 > 0 && (d = true, s.splice(0, t2)), n3 > 0 && (c2 = true, s.splice(s.length - n3, n3));
1877
+ }
1878
+ const x = [];
1879
+ d && x.push(M2);
1880
+ for (const t2 of s)
1881
+ for (const n3 of t2)
1882
+ x.push(n3);
1883
+ return c2 && x.push(M2), x;
1884
+ };
1885
+ var confirm2 = (i2) => {
1886
+ const a2 = i2.active ?? "Yes", s = i2.inactive ?? "No";
1887
+ return new r({
1888
+ active: a2,
1889
+ inactive: s,
1890
+ signal: i2.signal,
1891
+ input: i2.input,
1892
+ output: i2.output,
1893
+ initialValue: i2.initialValue ?? true,
1894
+ render() {
1895
+ const e = i2.withGuide ?? settings.withGuide, u5 = `${symbol2(this.state)} `, l2 = e ? `${styleText3("gray", S_BAR2)} ` : "", f2 = wrapTextWithPrefix(i2.output, i2.message, l2, u5), o2 = `${e ? `${styleText3("gray", S_BAR2)}
1896
+ ` : ""}${f2}
1897
+ `, c2 = this.value ? a2 : s;
1898
+ switch (this.state) {
1899
+ case "submit": {
1900
+ const r2 = e ? `${styleText3("gray", S_BAR2)} ` : "";
1901
+ return `${o2}${r2}${styleText3("dim", c2)}`;
1902
+ }
1903
+ case "cancel": {
1904
+ const r2 = e ? `${styleText3("gray", S_BAR2)} ` : "";
1905
+ return `${o2}${r2}${styleText3(["strikethrough", "dim"], c2)}${e ? `
1906
+ ${styleText3("gray", S_BAR2)}` : ""}`;
1907
+ }
1908
+ default: {
1909
+ const r2 = e ? `${styleText3("cyan", S_BAR2)} ` : "", g2 = e ? styleText3("cyan", S_BAR_END2) : "";
1910
+ return `${o2}${r2}${this.value ? `${styleText3("green", S_RADIO_ACTIVE2)} ${a2}` : `${styleText3("dim", S_RADIO_INACTIVE2)} ${styleText3("dim", a2)}`}${i2.vertical ? e ? `
1911
+ ${styleText3("cyan", S_BAR2)} ` : `
1912
+ ` : ` ${styleText3("dim", "/")} `}${this.value ? `${styleText3("dim", S_RADIO_INACTIVE2)} ${styleText3("dim", s)}` : `${styleText3("green", S_RADIO_ACTIVE2)} ${s}`}
1913
+ ${g2}
1914
+ `;
1915
+ }
1916
+ }
1917
+ }
1918
+ }).prompt();
1919
+ };
1920
+ var MULTISELECT_INSTRUCTIONS2 = [
1921
+ `${styleText3("dim", "↑/↓")} to navigate`,
1922
+ `${styleText3("dim", "Space:")} select`,
1923
+ `${styleText3("dim", "Enter:")} confirm`
1924
+ ];
1925
+ var m2 = (i2, u5) => i2.split(`
1926
+ `).map((d) => u5(d)).join(`
1927
+ `);
1928
+ var multiselect = (i2) => {
1929
+ const u5 = (t2, a2) => {
1930
+ const r2 = t2.label ?? String(t2.value);
1931
+ return a2 === "disabled" ? `${styleText3("gray", S_CHECKBOX_INACTIVE2)} ${m2(r2, (o2) => styleText3(["strikethrough", "gray"], o2))}${t2.hint ? ` ${styleText3("dim", `(${t2.hint ?? "disabled"})`)}` : ""}` : a2 === "active" ? `${styleText3("cyan", S_CHECKBOX_ACTIVE2)} ${r2}${t2.hint ? ` ${styleText3("dim", `(${t2.hint})`)}` : ""}` : a2 === "selected" ? `${styleText3("green", S_CHECKBOX_SELECTED2)} ${m2(r2, (o2) => styleText3("dim", o2))}${t2.hint ? ` ${styleText3("dim", `(${t2.hint})`)}` : ""}` : a2 === "cancelled" ? `${m2(r2, (o2) => styleText3(["strikethrough", "dim"], o2))}` : a2 === "active-selected" ? `${styleText3("green", S_CHECKBOX_SELECTED2)} ${r2}${t2.hint ? ` ${styleText3("dim", `(${t2.hint})`)}` : ""}` : a2 === "submitted" ? `${m2(r2, (o2) => styleText3("dim", o2))}` : `${styleText3("dim", S_CHECKBOX_INACTIVE2)} ${m2(r2, (o2) => styleText3("dim", o2))}`;
1932
+ }, d = i2.required ?? true, v = i2.showInstructions ?? true;
1933
+ return new a({
1934
+ options: i2.options,
1935
+ signal: i2.signal,
1936
+ input: i2.input,
1937
+ output: i2.output,
1938
+ initialValues: i2.initialValues,
1939
+ required: d,
1940
+ cursorAt: i2.cursorAt,
1941
+ validate(t2) {
1942
+ if (d && (t2 === undefined || t2.length === 0))
1943
+ return `Please select at least one option.
1944
+ ${styleText3("reset", styleText3("dim", `Press ${styleText3(["gray", "bgWhite", "inverse"], " space ")} to select, ${styleText3("gray", styleText3("bgWhite", styleText3("inverse", " enter ")))} to submit`))}`;
1945
+ },
1946
+ render() {
1947
+ const t2 = i2.withGuide ?? settings.withGuide, a2 = wrapTextWithPrefix(i2.output, i2.message, t2 ? `${symbolBar(this.state)} ` : "", `${symbol2(this.state)} `), r2 = `${t2 ? `${styleText3("gray", S_BAR2)}
1948
+ ` : ""}${a2}
1949
+ `, o2 = this.value ?? [], p2 = (n3, l2) => {
1950
+ if (n3.disabled)
1951
+ return u5(n3, "disabled");
1952
+ const s = o2.includes(n3.value);
1953
+ return l2 && s ? u5(n3, "active-selected") : s ? u5(n3, "selected") : u5(n3, l2 ? "active" : "inactive");
1954
+ };
1955
+ switch (this.state) {
1956
+ case "submit": {
1957
+ const n3 = this.options.filter(({ value: s }) => o2.includes(s)).map((s) => u5(s, "submitted")).join(styleText3("dim", ", ")) || styleText3("dim", "none"), l2 = wrapTextWithPrefix(i2.output, n3, t2 ? `${styleText3("gray", S_BAR2)} ` : "");
1958
+ return `${r2}${l2}`;
1959
+ }
1960
+ case "cancel": {
1961
+ const n3 = this.options.filter(({ value: s }) => o2.includes(s)).map((s) => u5(s, "cancelled")).join(styleText3("dim", ", "));
1962
+ if (n3.trim() === "")
1963
+ return `${r2}${styleText3("gray", S_BAR2)}`;
1964
+ const l2 = wrapTextWithPrefix(i2.output, n3, t2 ? `${styleText3("gray", S_BAR2)} ` : "");
1965
+ return `${r2}${l2}${t2 ? `
1966
+ ${styleText3("gray", S_BAR2)}` : ""}`;
1967
+ }
1968
+ case "error": {
1969
+ const n3 = t2 ? `${styleText3("yellow", S_BAR2)} ` : "", l2 = this.error.split(`
1970
+ `).map(($, C2) => C2 === 0 ? `${t2 ? `${styleText3("yellow", S_BAR_END2)} ` : ""}${styleText3("yellow", $)}` : ` ${$}`).join(`
1971
+ `), s = r2.split(`
1972
+ `).length, h2 = l2.split(`
1973
+ `).length + 1;
1974
+ return `${r2}${n3}${limitOptions({
1975
+ output: i2.output,
1976
+ options: this.options,
1977
+ cursor: this.cursor,
1978
+ maxItems: i2.maxItems,
1979
+ columnPadding: n3.length,
1980
+ rowPadding: s + h2,
1981
+ style: p2
1982
+ }).join(`
1983
+ ${n3}`)}
1984
+ ${l2}
1985
+ `;
1986
+ }
1987
+ default: {
1988
+ const n3 = t2 ? `${styleText3("cyan", S_BAR2)} ` : "", l2 = r2.split(`
1989
+ `).length, s = v ? formatInstructionFooter(MULTISELECT_INSTRUCTIONS2, t2) : t2 ? [styleText3("cyan", S_BAR_END2)] : [], h2 = s.join(`
1990
+ `), $ = s.length + 1;
1991
+ return `${r2}${n3}${limitOptions({
1992
+ output: i2.output,
1993
+ options: this.options,
1994
+ cursor: this.cursor,
1995
+ maxItems: i2.maxItems,
1996
+ columnPadding: n3.length,
1997
+ rowPadding: l2 + $,
1998
+ style: p2
1999
+ }).join(`
2000
+ ${n3}`)}
2001
+ ${h2}
2002
+ `;
2003
+ }
2004
+ }
2005
+ }
2006
+ }).prompt();
2007
+ };
2008
+ var log2 = {
2009
+ message: (s = [], {
2010
+ symbol: e = styleText3("gray", S_BAR2),
2011
+ secondarySymbol: r2 = styleText3("gray", S_BAR2),
2012
+ output: m3 = process.stdout,
2013
+ spacing: l2 = 1,
2014
+ withGuide: c2
2015
+ } = {}) => {
2016
+ const t2 = [], o2 = c2 ?? settings.withGuide, f2 = o2 ? r2 : "", O = o2 ? `${e} ` : "", u5 = o2 ? `${r2} ` : "";
2017
+ for (let i2 = 0;i2 < l2; i2++)
2018
+ t2.push(f2);
2019
+ const g2 = Array.isArray(s) ? s : s.split(`
2020
+ `);
2021
+ if (g2.length > 0) {
2022
+ const [i2, ...y] = g2;
2023
+ i2.length > 0 ? t2.push(`${O}${i2}`) : t2.push(o2 ? e : "");
2024
+ for (const p2 of y)
2025
+ p2.length > 0 ? t2.push(`${u5}${p2}`) : t2.push(o2 ? r2 : "");
2026
+ }
2027
+ m3.write(`${t2.join(`
2028
+ `)}
2029
+ `);
2030
+ },
2031
+ info: (s, e) => {
2032
+ log2.message(s, { ...e, symbol: styleText3("blue", S_INFO2) });
2033
+ },
2034
+ success: (s, e) => {
2035
+ log2.message(s, { ...e, symbol: styleText3("green", S_SUCCESS2) });
2036
+ },
2037
+ step: (s, e) => {
2038
+ log2.message(s, { ...e, symbol: styleText3("green", S_STEP_SUBMIT2) });
2039
+ },
2040
+ warn: (s, e) => {
2041
+ log2.message(s, { ...e, symbol: styleText3("yellow", S_WARN2) });
2042
+ },
2043
+ warning: (s, e) => {
2044
+ log2.warn(s, e);
2045
+ },
2046
+ error: (s, e) => {
2047
+ log2.message(s, { ...e, symbol: styleText3("red", S_ERROR2) });
2048
+ }
2049
+ };
2050
+ var cancel2 = (o2 = "", t2) => {
2051
+ const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText3("gray", S_BAR_END2)} ` : "";
2052
+ i2.write(`${e}${styleText3("red", o2)}
2053
+
2054
+ `);
2055
+ };
2056
+ var intro2 = (o2 = "", t2) => {
2057
+ const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText3("gray", S_BAR_START2)} ` : "";
2058
+ i2.write(`${e}${o2}
2059
+ `);
2060
+ };
2061
+ var outro2 = (o2 = "", t2) => {
2062
+ const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText3("gray", S_BAR2)}
2063
+ ${styleText3("gray", S_BAR_END2)} ` : "";
2064
+ i2.write(`${e}${o2}
2065
+
2066
+ `);
2067
+ };
2068
+ var W2 = (l2) => styleText3("magenta", l2);
2069
+ var spinner2 = ({
2070
+ indicator: l2 = "dots",
2071
+ onCancel: h2,
2072
+ output: n3 = process.stdout,
2073
+ cancelMessage: G,
2074
+ errorMessage: O,
2075
+ frames: E = unicode2 ? ["◒", "◐", "◓", "◑"] : ["•", "o", "O", "0"],
2076
+ delay: F = unicode2 ? 80 : 120,
2077
+ signal: m3,
2078
+ ...I2
2079
+ } = {}) => {
2080
+ const u5 = isCI2();
2081
+ let M2, T3, d = false, S = false, s = "", p2, w = performance.now();
2082
+ const x = getColumns(n3), k = I2?.styleFrame ?? W2, g2 = (e) => {
2083
+ const r2 = e > 1 ? O ?? settings.messages.error : G ?? settings.messages.cancel;
2084
+ S = e === 1, d && (a2(r2, e), S && typeof h2 == "function" && h2());
2085
+ }, f2 = () => g2(2), i2 = () => g2(1), A = () => {
2086
+ process.on("uncaughtExceptionMonitor", f2), process.on("unhandledRejection", f2), process.on("SIGINT", i2), process.on("SIGTERM", i2), process.on("exit", g2), m3 && m3.addEventListener("abort", i2);
2087
+ }, H = () => {
2088
+ process.removeListener("uncaughtExceptionMonitor", f2), process.removeListener("unhandledRejection", f2), process.removeListener("SIGINT", i2), process.removeListener("SIGTERM", i2), process.removeListener("exit", g2), m3 && m3.removeEventListener("abort", i2);
2089
+ }, y = () => {
2090
+ if (p2 === undefined)
2091
+ return;
2092
+ u5 && n3.write(`
2093
+ `);
2094
+ const r2 = wrapAnsi(p2, x, {
2095
+ hard: true,
2096
+ trim: false
2097
+ }).split(`
2098
+ `);
2099
+ r2.length > 1 && n3.write(import_sisteransi3.cursor.up(r2.length - 1)), n3.write(import_sisteransi3.cursor.to(0)), n3.write(import_sisteransi3.erase.down());
2100
+ }, C2 = (e) => e.replace(/\.+$/, ""), _2 = (e) => {
2101
+ const r2 = (performance.now() - e) / 1000, t2 = Math.floor(r2 / 60), o2 = Math.floor(r2 % 60);
2102
+ return t2 > 0 ? `[${t2}m ${o2}s]` : `[${o2}s]`;
2103
+ }, N = I2.withGuide ?? settings.withGuide, P2 = (e = "") => {
2104
+ d = true, M2 = block({ output: n3 }), s = C2(e), w = performance.now(), N && n3.write(`${styleText3("gray", S_BAR2)}
2105
+ `);
2106
+ let r2 = 0, t2 = 0;
2107
+ A(), T3 = setInterval(() => {
2108
+ if (u5 && s === p2)
2109
+ return;
2110
+ y(), p2 = s;
2111
+ const o2 = k(E[r2]);
2112
+ let v;
2113
+ if (u5)
2114
+ v = `${o2} ${s}...`;
2115
+ else if (l2 === "timer")
2116
+ v = `${o2} ${s} ${_2(w)}`;
2117
+ else {
2118
+ const B = ".".repeat(Math.floor(t2)).slice(0, 3);
2119
+ v = `${o2} ${s}${B}`;
2120
+ }
2121
+ const j = wrapAnsi(v, x, {
2122
+ hard: true,
2123
+ trim: false
2124
+ });
2125
+ n3.write(j), r2 = r2 + 1 < E.length ? r2 + 1 : 0, t2 = t2 < 4 ? t2 + 0.125 : 0;
2126
+ }, F);
2127
+ }, a2 = (e = "", r2 = 0, t2 = false) => {
2128
+ if (!d)
2129
+ return;
2130
+ d = false, clearInterval(T3), y();
2131
+ const o2 = r2 === 0 ? styleText3("green", S_STEP_SUBMIT2) : r2 === 1 ? styleText3("red", S_STEP_CANCEL2) : styleText3("red", S_STEP_ERROR2);
2132
+ s = e ?? s, t2 || (l2 === "timer" ? n3.write(`${o2} ${s} ${_2(w)}
2133
+ `) : n3.write(`${o2} ${s}
2134
+ `)), H(), M2();
2135
+ };
2136
+ return {
2137
+ start: P2,
2138
+ stop: (e = "") => a2(e, 0),
2139
+ message: (e = "") => {
2140
+ s = C2(e ?? s);
2141
+ },
2142
+ cancel: (e = "") => a2(e, 1),
2143
+ error: (e = "") => a2(e, 2),
2144
+ clear: () => a2("", 0, true),
2145
+ get isCancelled() {
2146
+ return S;
2147
+ }
2148
+ };
2149
+ };
2150
+ var u5 = {
2151
+ light: unicodeOr2("─", "-"),
2152
+ heavy: unicodeOr2("━", "="),
2153
+ block: unicodeOr2("█", "#")
2154
+ };
2155
+ var SELECT_INSTRUCTIONS2 = [
2156
+ `${styleText3("dim", "↑/↓")} to navigate`,
2157
+ `${styleText3("dim", "Enter:")} confirm`
2158
+ ];
2159
+ var c2 = (t2, o2) => t2.includes(`
2160
+ `) ? t2.split(`
2161
+ `).map((d) => o2(d)).join(`
2162
+ `) : o2(t2);
2163
+ var select = (t2) => {
2164
+ const o2 = (n3, m3) => {
2165
+ if (n3 === undefined)
2166
+ return "";
2167
+ const s = n3.label ?? String(n3.value);
2168
+ switch (m3) {
2169
+ case "disabled":
2170
+ return `${styleText3("gray", S_RADIO_INACTIVE2)} ${c2(s, (i2) => styleText3("gray", i2))}${n3.hint ? ` ${styleText3("dim", `(${n3.hint ?? "disabled"})`)}` : ""}`;
2171
+ case "selected":
2172
+ return `${c2(s, (i2) => styleText3("dim", i2))}`;
2173
+ case "active":
2174
+ return `${styleText3("green", S_RADIO_ACTIVE2)} ${s}${n3.hint ? ` ${styleText3("dim", `(${n3.hint})`)}` : ""}`;
2175
+ case "cancelled":
2176
+ return `${c2(s, (i2) => styleText3(["strikethrough", "dim"], i2))}`;
2177
+ default:
2178
+ return `${styleText3("dim", S_RADIO_INACTIVE2)} ${c2(s, (i2) => styleText3("dim", i2))}`;
2179
+ }
2180
+ }, d = t2.showInstructions ?? true;
2181
+ return new n$1({
2182
+ options: t2.options,
2183
+ signal: t2.signal,
2184
+ input: t2.input,
2185
+ output: t2.output,
2186
+ initialValue: t2.initialValue,
2187
+ render() {
2188
+ const n3 = t2.withGuide ?? settings.withGuide, m3 = `${symbol2(this.state)} `, s = `${symbolBar(this.state)} `, i2 = wrapTextWithPrefix(t2.output, t2.message, s, m3), u6 = `${n3 ? `${styleText3("gray", S_BAR2)}
2189
+ ` : ""}${i2}
2190
+ `;
2191
+ switch (this.state) {
2192
+ case "submit": {
2193
+ const r2 = n3 ? `${styleText3("gray", S_BAR2)} ` : "", a2 = wrapTextWithPrefix(t2.output, o2(this.options[this.cursor], "selected"), r2);
2194
+ return `${u6}${a2}`;
2195
+ }
2196
+ case "cancel": {
2197
+ const r2 = n3 ? `${styleText3("gray", S_BAR2)} ` : "", a2 = wrapTextWithPrefix(t2.output, o2(this.options[this.cursor], "cancelled"), r2);
2198
+ return `${u6}${a2}${n3 ? `
2199
+ ${styleText3("gray", S_BAR2)}` : ""}`;
2200
+ }
2201
+ default: {
2202
+ const r2 = n3 ? `${styleText3("cyan", S_BAR2)} ` : "", a2 = u6.split(`
2203
+ `).length, p2 = d ? formatInstructionFooter(SELECT_INSTRUCTIONS2, n3) : n3 ? [styleText3("cyan", S_BAR_END2)] : [], b2 = p2.join(`
2204
+ `), f2 = p2.length + 1;
2205
+ return `${u6}${r2}${limitOptions({
2206
+ output: t2.output,
2207
+ cursor: this.cursor,
2208
+ options: this.options,
2209
+ maxItems: t2.maxItems,
2210
+ columnPadding: r2.length,
2211
+ rowPadding: a2 + f2,
2212
+ style: (g2, x) => o2(g2, g2.disabled ? "disabled" : x ? "active" : "inactive")
2213
+ }).join(`
2214
+ ${r2}`)}
2215
+ ${b2}
2216
+ `;
2217
+ }
2218
+ }
2219
+ }
2220
+ }).prompt();
2221
+ };
2222
+ var i2 = `${styleText3("gray", S_BAR2)} `;
2223
+ var text2 = (e) => new n2({
2224
+ validate: e.validate,
2225
+ placeholder: e.placeholder,
2226
+ defaultValue: e.defaultValue,
2227
+ initialValue: e.initialValue,
2228
+ output: e.output,
2229
+ signal: e.signal,
2230
+ input: e.input,
2231
+ render() {
2232
+ const i3 = e?.withGuide ?? settings.withGuide, s = `${`${i3 ? `${styleText3("gray", S_BAR2)}
2233
+ ` : ""}${symbol2(this.state)} `}${e.message}
2234
+ `, c3 = e.placeholder && e.placeholder.length > 0 ? styleText3("inverse", e.placeholder[0]) + styleText3("dim", e.placeholder.slice(1)) : styleText3(["inverse", "hidden"], "_"), o2 = this.userInput ? this.userInputWithCursor : c3, l2 = this.value ?? "";
2235
+ switch (this.state) {
2236
+ case "error": {
2237
+ const n3 = this.error ? ` ${styleText3("yellow", this.error)}` : "", r2 = i3 ? `${styleText3("yellow", S_BAR2)} ` : "", d = i3 ? styleText3("yellow", S_BAR_END2) : "";
2238
+ return `${s.trim()}
2239
+ ${r2}${o2}
2240
+ ${d}${n3}
2241
+ `;
2242
+ }
2243
+ case "submit": {
2244
+ const n3 = l2 ? ` ${styleText3("dim", l2)}` : "", r2 = i3 ? styleText3("gray", S_BAR2) : "";
2245
+ return `${s}${r2}${n3}`;
2246
+ }
2247
+ case "cancel": {
2248
+ const n3 = l2 ? ` ${styleText3(["strikethrough", "dim"], l2)}` : "", r2 = i3 ? styleText3("gray", S_BAR2) : "";
2249
+ return `${s}${r2}${n3}${l2.trim() ? `
2250
+ ${r2}` : ""}`;
2251
+ }
2252
+ default: {
2253
+ const n3 = i3 ? `${styleText3("cyan", S_BAR2)} ` : "", r2 = i3 ? styleText3("cyan", S_BAR_END2) : "";
2254
+ return `${s}${n3}${o2}
2255
+ ${r2}
2256
+ `;
2257
+ }
2258
+ }
2259
+ }
2260
+ }).prompt();
2261
+
58
2262
  // src/agent-setup.ts
59
- import * as prompts from "@clack/prompts";
60
2263
  import { mkdir, readFile, rename, stat, writeFile } from "node:fs/promises";
61
2264
  import { dirname, join as join2, resolve } from "node:path";
62
2265
 
@@ -74,19 +2277,19 @@ function runCaptured(command, options) {
74
2277
  env: options.env ?? process.env,
75
2278
  stdio: ["ignore", "pipe", "pipe"]
76
2279
  });
77
- let stdout = "";
2280
+ let stdout2 = "";
78
2281
  let stderr = "";
79
2282
  child.stdout.setEncoding("utf8");
80
2283
  child.stderr.setEncoding("utf8");
81
2284
  child.stdout.on("data", (chunk) => {
82
- stdout += chunk;
2285
+ stdout2 += chunk;
83
2286
  });
84
2287
  child.stderr.on("data", (chunk) => {
85
2288
  stderr += chunk;
86
2289
  });
87
2290
  child.on("error", reject);
88
2291
  child.on("close", (code, signal) => {
89
- resolve({ exitCode: code ?? (signal ? 1 : 0), stdout, stderr });
2292
+ resolve({ exitCode: code ?? (signal ? 1 : 0), stdout: stdout2, stderr });
90
2293
  });
91
2294
  });
92
2295
  }
@@ -334,7 +2537,7 @@ async function chooseClients(parsed) {
334
2537
  if (!process.stdin.isTTY) {
335
2538
  throw new Error("Interactive setup needs a terminal. Pass --clients and --yes instead.");
336
2539
  }
337
- const selected = await prompts.multiselect({
2540
+ const selected = await multiselect({
338
2541
  message: "Connect which local coding clients?",
339
2542
  required: true,
340
2543
  options: CLIENTS.map((client) => ({
@@ -344,8 +2547,8 @@ async function chooseClients(parsed) {
344
2547
  })),
345
2548
  initialValues: detected
346
2549
  });
347
- if (prompts.isCancel(selected)) {
348
- prompts.cancel("No agent clients were configured.");
2550
+ if (isCancel(selected)) {
2551
+ cancel2("No agent clients were configured.");
349
2552
  return;
350
2553
  }
351
2554
  return selected;
@@ -379,29 +2582,28 @@ async function runAgentSetup(argv, cliName) {
379
2582
  const clients = await chooseClients(parsed);
380
2583
  if (!clients)
381
2584
  return;
382
- prompts.intro("superslate local agent context");
2585
+ intro2("superslate local agent context");
383
2586
  if (parsed.dryRun) {
384
2587
  for (const client of clients) {
385
- prompts.log.info(`${client}
2588
+ log2.info(`${client}
386
2589
  ${dryRunDescription(client, root)}`);
387
2590
  }
388
- prompts.outro("Dry run complete. No client configuration was changed.");
2591
+ outro2("Dry run complete. No client configuration was changed.");
389
2592
  return;
390
2593
  }
391
- const progress = prompts.spinner();
392
- progress.start("Testing the local MCP server");
2594
+ const progress2 = spinner2();
2595
+ progress2.start("Testing the local MCP server");
393
2596
  await smokeServer(root);
394
- progress.stop("Local MCP server passed its protocol self-check");
2597
+ progress2.stop("Local MCP server passed its protocol self-check");
395
2598
  for (const client of clients) {
396
2599
  const result = client === "codex" ? await configureCodex(root) : client === "cursor" ? await configureCursor(root) : await configureClaude(root);
397
- prompts.log.success(`${client}: ${result}`);
2600
+ log2.success(`${client}: ${result}`);
398
2601
  }
399
- prompts.log.info("Restart configured clients, then ask: “Use plan_change for my next feature.”");
400
- prompts.outro("superslate agent context is ready.");
2602
+ log2.info("Restart configured clients, then ask: “Use plan_change for my next feature.”");
2603
+ outro2("superslate agent context is ready.");
401
2604
  }
402
2605
 
403
2606
  // src/deployment-cli.ts
404
- import * as prompts3 from "@clack/prompts";
405
2607
  import { readFile as readFile3 } from "node:fs/promises";
406
2608
  import { resolve as resolve2 } from "node:path";
407
2609
 
@@ -616,12 +2818,11 @@ async function applyDeploymentSelection(repositoryRoot, projectName, selection)
616
2818
  }
617
2819
 
618
2820
  // src/deployment-prompts.ts
619
- import * as prompts2 from "@clack/prompts";
620
2821
  class DeploymentPromptCancelled extends Error {
621
2822
  }
622
2823
  async function unwrap(value) {
623
- if (prompts2.isCancel(value)) {
624
- prompts2.cancel("Deployment configuration was not changed.");
2824
+ if (isCancel(value)) {
2825
+ cancel2("Deployment configuration was not changed.");
625
2826
  throw new DeploymentPromptCancelled;
626
2827
  }
627
2828
  return value;
@@ -642,7 +2843,7 @@ async function collectDeploymentSelection(defaults = {}, nonInteractive = false)
642
2843
  haEnabled: defaults.haEnabled ?? false
643
2844
  };
644
2845
  }
645
- const cloud = defaults.cloud ?? parseDeploymentCloud(await unwrap(await prompts2.select({
2846
+ const cloud = defaults.cloud ?? parseDeploymentCloud(await unwrap(await select({
646
2847
  message: "Backend cloud",
647
2848
  options: [
648
2849
  { value: "aws", label: "AWS", hint: "ECS Fargate + RDS PostgreSQL" },
@@ -650,7 +2851,7 @@ async function collectDeploymentSelection(defaults = {}, nonInteractive = false)
650
2851
  { value: "azure", label: "Azure", hint: "Container Apps + Flexible Server" }
651
2852
  ]
652
2853
  })));
653
- const frontendTarget = defaults.frontendTarget ?? parseFrontendTarget(await unwrap(await prompts2.select({
2854
+ const frontendTarget = defaults.frontendTarget ?? parseFrontendTarget(await unwrap(await select({
654
2855
  message: "Frontend host",
655
2856
  options: [
656
2857
  { value: "native", label: "Cloud native", hint: "Managed with the backend" },
@@ -662,7 +2863,7 @@ async function collectDeploymentSelection(defaults = {}, nonInteractive = false)
662
2863
  }
663
2864
  ]
664
2865
  })));
665
- const storageProvider = defaults.storageProvider ?? (storageProvidersByCloud[cloud].length === 1 ? storageProvidersByCloud[cloud][0] ?? defaultStorageProviders[cloud] : parseStorageProvider(await unwrap(await prompts2.select({
2866
+ const storageProvider = defaults.storageProvider ?? (storageProvidersByCloud[cloud].length === 1 ? storageProvidersByCloud[cloud][0] ?? defaultStorageProviders[cloud] : parseStorageProvider(await unwrap(await select({
666
2867
  message: "Object storage",
667
2868
  options: storageProvidersByCloud[cloud].map((provider) => ({
668
2869
  value: provider,
@@ -670,29 +2871,29 @@ async function collectDeploymentSelection(defaults = {}, nonInteractive = false)
670
2871
  hint: provider === defaultStorageProviders[cloud] ? "Cloud-native default" : ""
671
2872
  }))
672
2873
  }))));
673
- const environment = defaults.environment ?? await unwrap(await prompts2.text({
2874
+ const environment = defaults.environment ?? await unwrap(await text2({
674
2875
  message: "Deployment environment",
675
2876
  placeholder: "production",
676
2877
  defaultValue: "production",
677
2878
  validate: (value) => validateDeploymentEnvironment(value || "production")
678
2879
  }));
679
- const region = defaults.region ?? await unwrap(await prompts2.text({
2880
+ const region = defaults.region ?? await unwrap(await text2({
680
2881
  message: `${cloud.toUpperCase()} region`,
681
2882
  placeholder: defaultRegions[cloud],
682
2883
  defaultValue: defaultRegions[cloud],
683
2884
  validate: (value) => validateRegion(value || defaultRegions[cloud])
684
2885
  }));
685
- const apiDomain = defaults.apiDomain ?? await unwrap(await prompts2.text({
2886
+ const apiDomain = defaults.apiDomain ?? await unwrap(await text2({
686
2887
  message: "Production API domain",
687
2888
  placeholder: "api.example.com",
688
2889
  validate: (value) => validateDomain(value ?? "")
689
2890
  }));
690
- const frontendDomain = defaults.frontendDomain ?? await unwrap(await prompts2.text({
2891
+ const frontendDomain = defaults.frontendDomain ?? await unwrap(await text2({
691
2892
  message: "Production frontend domain",
692
2893
  placeholder: "app.example.com",
693
2894
  validate: (value) => validateDomain(value ?? "")
694
2895
  }));
695
- const haEnabled = defaults.haEnabled ?? await unwrap(await prompts2.confirm({
2896
+ const haEnabled = defaults.haEnabled ?? await unwrap(await confirm2({
696
2897
  message: "Enable the higher-availability profile?",
697
2898
  initialValue: false
698
2899
  }));
@@ -750,17 +2951,17 @@ async function runDeploymentConfigure(argv, productName, repositoryRoot = proces
750
2951
  const rootPackage = JSON.parse(await readFile3(`${root}/package.json`, "utf8"));
751
2952
  if (!rootPackage.name)
752
2953
  throw new Error("Root package name is required for deployment setup.");
753
- prompts3.intro(`${productName} deployment setup`);
2954
+ intro2(`${productName} deployment setup`);
754
2955
  try {
755
2956
  const selection = await collectDeploymentSelection(parsed, parsed.yes);
756
2957
  const removed = await applyDeploymentSelection(root, rootPackage.name, selection);
757
- prompts3.log.success(`${selection.cloud.toUpperCase()} + ${selection.storageProvider} + ${selection.frontendTarget} is locked for ${selection.environment}.`);
758
- prompts3.log.info(`${removed.length} unused deployment paths removed.`);
759
- prompts3.log.step("Next");
760
- prompts3.log.message(`Review deployment/config.json
2958
+ log2.success(`${selection.cloud.toUpperCase()} + ${selection.storageProvider} + ${selection.frontendTarget} is locked for ${selection.environment}.`);
2959
+ log2.info(`${removed.length} unused deployment paths removed.`);
2960
+ log2.step("Next");
2961
+ log2.message(`Review deployment/config.json
761
2962
  Configure the protected GitHub environment
762
2963
  Dispatch .github/workflows/deploy-cloud.yml`);
763
- prompts3.outro("Deployment configuration is ready to commit.");
2964
+ outro2("Deployment configuration is ready to commit.");
764
2965
  } catch (error) {
765
2966
  if (error instanceof DeploymentPromptCancelled)
766
2967
  return;
@@ -783,19 +2984,19 @@ function runCaptured2(command, options) {
783
2984
  env: options.env ?? process.env,
784
2985
  stdio: ["ignore", "pipe", "pipe"]
785
2986
  });
786
- let stdout = "";
2987
+ let stdout2 = "";
787
2988
  let stderr = "";
788
2989
  child.stdout.setEncoding("utf8");
789
2990
  child.stderr.setEncoding("utf8");
790
2991
  child.stdout.on("data", (chunk) => {
791
- stdout += chunk;
2992
+ stdout2 += chunk;
792
2993
  });
793
2994
  child.stderr.on("data", (chunk) => {
794
2995
  stderr += chunk;
795
2996
  });
796
2997
  child.on("error", reject);
797
2998
  child.on("close", (code, signal) => {
798
- resolve3({ exitCode: code ?? (signal ? 1 : 0), stdout, stderr });
2999
+ resolve3({ exitCode: code ?? (signal ? 1 : 0), stdout: stdout2, stderr });
799
3000
  });
800
3001
  });
801
3002
  }
@@ -834,12 +3035,11 @@ function isEntrypoint(moduleUrl) {
834
3035
  }
835
3036
 
836
3037
  // src/deployment-prompts.ts
837
- import * as prompts4 from "@clack/prompts";
838
3038
  class DeploymentPromptCancelled2 extends Error {
839
3039
  }
840
3040
  async function unwrap2(value) {
841
- if (prompts4.isCancel(value)) {
842
- prompts4.cancel("Deployment configuration was not changed.");
3041
+ if (isCancel(value)) {
3042
+ cancel2("Deployment configuration was not changed.");
843
3043
  throw new DeploymentPromptCancelled2;
844
3044
  }
845
3045
  return value;
@@ -860,7 +3060,7 @@ async function collectDeploymentSelection2(defaults = {}, nonInteractive = false
860
3060
  haEnabled: defaults.haEnabled ?? false
861
3061
  };
862
3062
  }
863
- const cloud = defaults.cloud ?? parseDeploymentCloud(await unwrap2(await prompts4.select({
3063
+ const cloud = defaults.cloud ?? parseDeploymentCloud(await unwrap2(await select({
864
3064
  message: "Backend cloud",
865
3065
  options: [
866
3066
  { value: "aws", label: "AWS", hint: "ECS Fargate + RDS PostgreSQL" },
@@ -868,7 +3068,7 @@ async function collectDeploymentSelection2(defaults = {}, nonInteractive = false
868
3068
  { value: "azure", label: "Azure", hint: "Container Apps + Flexible Server" }
869
3069
  ]
870
3070
  })));
871
- const frontendTarget = defaults.frontendTarget ?? parseFrontendTarget(await unwrap2(await prompts4.select({
3071
+ const frontendTarget = defaults.frontendTarget ?? parseFrontendTarget(await unwrap2(await select({
872
3072
  message: "Frontend host",
873
3073
  options: [
874
3074
  { value: "native", label: "Cloud native", hint: "Managed with the backend" },
@@ -880,7 +3080,7 @@ async function collectDeploymentSelection2(defaults = {}, nonInteractive = false
880
3080
  }
881
3081
  ]
882
3082
  })));
883
- const storageProvider = defaults.storageProvider ?? (storageProvidersByCloud[cloud].length === 1 ? storageProvidersByCloud[cloud][0] ?? defaultStorageProviders[cloud] : parseStorageProvider(await unwrap2(await prompts4.select({
3083
+ const storageProvider = defaults.storageProvider ?? (storageProvidersByCloud[cloud].length === 1 ? storageProvidersByCloud[cloud][0] ?? defaultStorageProviders[cloud] : parseStorageProvider(await unwrap2(await select({
884
3084
  message: "Object storage",
885
3085
  options: storageProvidersByCloud[cloud].map((provider) => ({
886
3086
  value: provider,
@@ -888,29 +3088,29 @@ async function collectDeploymentSelection2(defaults = {}, nonInteractive = false
888
3088
  hint: provider === defaultStorageProviders[cloud] ? "Cloud-native default" : ""
889
3089
  }))
890
3090
  }))));
891
- const environment = defaults.environment ?? await unwrap2(await prompts4.text({
3091
+ const environment = defaults.environment ?? await unwrap2(await text2({
892
3092
  message: "Deployment environment",
893
3093
  placeholder: "production",
894
3094
  defaultValue: "production",
895
3095
  validate: (value) => validateDeploymentEnvironment(value || "production")
896
3096
  }));
897
- const region = defaults.region ?? await unwrap2(await prompts4.text({
3097
+ const region = defaults.region ?? await unwrap2(await text2({
898
3098
  message: `${cloud.toUpperCase()} region`,
899
3099
  placeholder: defaultRegions[cloud],
900
3100
  defaultValue: defaultRegions[cloud],
901
3101
  validate: (value) => validateRegion(value || defaultRegions[cloud])
902
3102
  }));
903
- const apiDomain = defaults.apiDomain ?? await unwrap2(await prompts4.text({
3103
+ const apiDomain = defaults.apiDomain ?? await unwrap2(await text2({
904
3104
  message: "Production API domain",
905
3105
  placeholder: "api.example.com",
906
3106
  validate: (value) => validateDomain(value ?? "")
907
3107
  }));
908
- const frontendDomain = defaults.frontendDomain ?? await unwrap2(await prompts4.text({
3108
+ const frontendDomain = defaults.frontendDomain ?? await unwrap2(await text2({
909
3109
  message: "Production frontend domain",
910
3110
  placeholder: "app.example.com",
911
3111
  validate: (value) => validateDomain(value ?? "")
912
3112
  }));
913
- const haEnabled = defaults.haEnabled ?? await unwrap2(await prompts4.confirm({
3113
+ const haEnabled = defaults.haEnabled ?? await unwrap2(await confirm2({
914
3114
  message: "Enable the higher-availability profile?",
915
3115
  initialValue: false
916
3116
  }));
@@ -1129,11 +3329,114 @@ async function applyDeploymentSelection2(repositoryRoot, projectName, selection)
1129
3329
  // src/scaffold.ts
1130
3330
  import { execFile } from "node:child_process";
1131
3331
  import { createHash } from "node:crypto";
1132
- import { cp, lstat, mkdir as mkdir4, mkdtemp, readFile as readFile5, readdir, rm as rm3, stat as stat4, writeFile as writeFile4 } from "node:fs/promises";
3332
+ import { cp, lstat, mkdir as mkdir4, mkdtemp, readFile as readFile5, readdir, rm as rm4, stat as stat4, writeFile as writeFile4 } from "node:fs/promises";
1133
3333
  import { tmpdir } from "node:os";
1134
- import { basename, join as join6, relative, resolve as resolve3 } from "node:path";
3334
+ import { basename, join as join7, relative, resolve as resolve3 } from "node:path";
1135
3335
  import { promisify } from "node:util";
1136
3336
 
3337
+ // src/delivery.ts
3338
+ import { createWriteStream } from "node:fs";
3339
+ import { rm as rm3 } from "node:fs/promises";
3340
+ import { join as join6 } from "node:path";
3341
+ import { Readable, Transform } from "node:stream";
3342
+ import { pipeline } from "node:stream/promises";
3343
+ var RELEASE_TAG_PATTERN2 = /^v\d+\.\d+\.\d+(?:-rc\.\d+)?$/;
3344
+ var INDEX_TIMEOUT_MS = 15000;
3345
+ var DOWNLOAD_TIMEOUT_MS = 300000;
3346
+ function deliveryBaseUrl(environment = process.env) {
3347
+ const configured = environment[DELIVERY_URL_VARIABLE]?.trim();
3348
+ return (configured || DELIVERY_BASE_URL).replace(/\/+$/, "");
3349
+ }
3350
+ function releaseAssetNames(releaseTag) {
3351
+ const artifact = `foundation-source-${releaseTag}.tar.gz`;
3352
+ return {
3353
+ artifact,
3354
+ checksum: `${artifact}.sha256`,
3355
+ manifest: `foundation-source-${releaseTag}.manifest.json`
3356
+ };
3357
+ }
3358
+ function describeFailure(status, subject) {
3359
+ if (status === 401) {
3360
+ return "That licence key was not accepted. Copy it exactly from your purchase receipt or the customer portal (polar.sh).";
3361
+ }
3362
+ if (status === 429) {
3363
+ return "Too many download requests for this licence key. Wait a minute and try again.";
3364
+ }
3365
+ if (status === 404)
3366
+ return `${subject} is not available for download.`;
3367
+ if (status >= 500) {
3368
+ return "Source delivery is temporarily unavailable. Wait a few minutes and try again.";
3369
+ }
3370
+ return `Source delivery refused the request (HTTP ${status}).`;
3371
+ }
3372
+ async function requestDelivery(url, init, subject) {
3373
+ let response;
3374
+ try {
3375
+ response = await fetch(url, init);
3376
+ } catch {
3377
+ throw new Error("Could not reach source delivery. Check your network connection and try again.");
3378
+ }
3379
+ if (!response.ok)
3380
+ throw new Error(describeFailure(response.status, subject));
3381
+ return response;
3382
+ }
3383
+ async function resolveRelease(licenseKey, baseUrl = deliveryBaseUrl()) {
3384
+ const response = await requestDelivery(`${baseUrl}/v1/releases`, {
3385
+ method: "POST",
3386
+ headers: { "content-type": "application/json" },
3387
+ body: JSON.stringify({ key: licenseKey }),
3388
+ signal: AbortSignal.timeout(INDEX_TIMEOUT_MS)
3389
+ }, "The release index");
3390
+ let index;
3391
+ try {
3392
+ index = await response.json();
3393
+ } catch {
3394
+ index = undefined;
3395
+ }
3396
+ if (!index || !RELEASE_TAG_PATTERN2.test(index.latest) || !Array.isArray(index.versions)) {
3397
+ throw new Error(`Source delivery returned an unreadable release index.`);
3398
+ }
3399
+ return index;
3400
+ }
3401
+ function readContentLength(response) {
3402
+ const header = response.headers.get("content-length");
3403
+ if (!header)
3404
+ return;
3405
+ const total = Number(header);
3406
+ return Number.isSafeInteger(total) && total > 0 ? total : undefined;
3407
+ }
3408
+ function countBytes(total, onBytes) {
3409
+ let received = 0;
3410
+ return new Transform({
3411
+ transform(chunk, _encoding, done) {
3412
+ received += chunk.length;
3413
+ onBytes(received, total);
3414
+ done(null, chunk);
3415
+ }
3416
+ });
3417
+ }
3418
+ async function downloadAsset(licenseKey, releaseTag, assetName, directory, baseUrl = deliveryBaseUrl(), onBytes) {
3419
+ const response = await requestDelivery(`${baseUrl}/v1/source/${encodeURIComponent(releaseTag)}/${encodeURIComponent(assetName)}`, {
3420
+ headers: { authorization: `Bearer ${licenseKey}` },
3421
+ signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS)
3422
+ }, releaseTag);
3423
+ if (!response.body)
3424
+ throw new Error(`Source delivery returned an empty ${assetName}.`);
3425
+ const path = join6(directory, assetName);
3426
+ const source = Readable.fromWeb(response.body);
3427
+ try {
3428
+ if (onBytes) {
3429
+ await pipeline(source, countBytes(readContentLength(response), onBytes), createWriteStream(path));
3430
+ } else {
3431
+ await pipeline(source, createWriteStream(path));
3432
+ }
3433
+ } catch {
3434
+ await rm3(path, { force: true });
3435
+ throw new Error(`Downloading ${assetName} was interrupted. Try again in a few minutes.`);
3436
+ }
3437
+ return path;
3438
+ }
3439
+
1137
3440
  // src/core.ts
1138
3441
  import { randomBytes } from "node:crypto";
1139
3442
  import { extname } from "node:path";
@@ -1364,7 +3667,49 @@ into this repository.
1364
3667
  }
1365
3668
  return rewritten;
1366
3669
  }
1367
- var SELLER_ONLY_ROOT_SCRIPTS = ["release:distribute"];
3670
+ var REQUIRED_BUYER_CLI_CONSTANTS = ["CLI_NAME", "CLI_PACKAGE_NAME", "DEFAULT_SCOPE"];
3671
+ function rewriteBuyerCliConstants(content, scope, brandName) {
3672
+ const buyerVariablePrefix = BUYER_CLI_NAME.toUpperCase().replaceAll("-", "_");
3673
+ const buyerConstants = [
3674
+ ["CLI_NAME", BUYER_CLI_NAME],
3675
+ ["CLI_PACKAGE_NAME", BUYER_CLI_PACKAGE_NAME],
3676
+ ["DEFAULT_SCOPE", normalizeScope2(scope)],
3677
+ ["SOURCE_BRAND_NAME", brandName],
3678
+ ["TEMPLATE_REPOSITORY", "OWNER/REPOSITORY"],
3679
+ ["DELIVERY_BASE_URL", "https://releases.example.com"],
3680
+ ["DELIVERY_URL_VARIABLE", `${buyerVariablePrefix}_DELIVERY_URL`],
3681
+ ["LICENSE_KEY_VARIABLE", `${buyerVariablePrefix}_LICENSE_KEY`],
3682
+ ["LICENSE_KEY_PREFIX", "LICENSE-"]
3683
+ ];
3684
+ let rewritten = content;
3685
+ for (const [name, value] of buyerConstants) {
3686
+ const declaration = new RegExp(`^export const ${name} = '[^']*'$`, "m");
3687
+ if (!declaration.test(rewritten)) {
3688
+ if (REQUIRED_BUYER_CLI_CONSTANTS.includes(name)) {
3689
+ throw new Error(`Source CLI constants are missing ${name}.`);
3690
+ }
3691
+ continue;
3692
+ }
3693
+ rewritten = rewritten.replace(declaration, `export const ${name} = '${value}'`);
3694
+ }
3695
+ const leaked = [
3696
+ CLI_PACKAGE_NAME,
3697
+ SOURCE_BRAND_NAME,
3698
+ DELIVERY_BASE_URL,
3699
+ DELIVERY_URL_VARIABLE,
3700
+ LICENSE_KEY_VARIABLE2,
3701
+ LICENSE_KEY_PREFIX
3702
+ ].filter((identity) => rewritten.includes(identity));
3703
+ if (leaked.length > 0) {
3704
+ throw new Error(`Buyer CLI constants still name the source product: ${leaked.join(", ")}`);
3705
+ }
3706
+ return rewritten;
3707
+ }
3708
+ var SELLER_ONLY_ROOT_SCRIPTS = [
3709
+ "release:distribute",
3710
+ "release:publish-cli",
3711
+ "release:upload"
3712
+ ];
1368
3713
  function stripSellerOnlyRootScripts(content) {
1369
3714
  const manifest = JSON.parse(content);
1370
3715
  for (const script of SELLER_ONLY_ROOT_SCRIPTS)
@@ -1434,14 +3779,14 @@ function isTemplatePathExcluded(relativePath) {
1434
3779
  return true;
1435
3780
  if (normalized === "internal" || normalized.startsWith("internal/"))
1436
3781
  return true;
1437
- if (normalized === ".github/workflows/publish-npm.yml")
1438
- return true;
1439
3782
  if (normalized === ".github/workflows/internal-commercial.yml")
1440
3783
  return true;
1441
3784
  if (normalized === "apps/worker" || normalized.startsWith("apps/worker/"))
1442
3785
  return true;
1443
3786
  if (parts.includes("dist") || parts.includes("out"))
1444
3787
  return true;
3788
+ if (parts.includes(".next") || parts.includes(".source") || parts.includes(".turbo"))
3789
+ return true;
1445
3790
  if (normalized === "bun.lock")
1446
3791
  return true;
1447
3792
  if (normalized === ".vercelignore")
@@ -1503,7 +3848,7 @@ async function copyLocalTemplate(source, target) {
1503
3848
  async function assertNoSymbolicLinks(directory, root = directory, skipExcludedPaths = false) {
1504
3849
  const entries = await readdir(directory, { withFileTypes: true });
1505
3850
  for (const entry of entries) {
1506
- const path = join6(directory, entry.name);
3851
+ const path = join7(directory, entry.name);
1507
3852
  const relativePath = relative(root, path);
1508
3853
  if (skipExcludedPaths && isTemplatePathExcluded(relativePath))
1509
3854
  continue;
@@ -1526,57 +3871,33 @@ function verifyReleaseMetadata(checksum, manifest, artifactName, digest, templat
1526
3871
  throw new Error(`${CLI_NAME2} release manifest does not match the downloaded source artifact.`);
1527
3872
  }
1528
3873
  }
1529
- async function downloadReleaseAsset(templateRef, fileName, directory) {
3874
+ async function downloadLicensedTemplate(target, licenseKey, sourceVersion, onDownloadProgress) {
3875
+ const baseUrl = deliveryBaseUrl();
3876
+ const releaseTag = sourceVersion ?? (await resolveRelease(licenseKey, baseUrl)).latest;
3877
+ const { artifact, checksum: checksumName, manifest: manifestName } = releaseAssetNames(releaseTag);
3878
+ const temporaryDirectory = await mkdtemp(join7(tmpdir(), `${CLI_NAME2}-`));
3879
+ const extractedPath = join7(temporaryDirectory, "template");
1530
3880
  try {
1531
- await execFileAsync("gh", [
1532
- "release",
1533
- "download",
1534
- templateRef,
1535
- "--repo",
1536
- TEMPLATE_REPOSITORY,
1537
- "--pattern",
1538
- fileName,
1539
- "--dir",
1540
- directory
1541
- ]);
1542
- } catch {
1543
- throw new Error(`Unable to download ${templateRef}. Confirm that GitHub CLI is installed, run ` + `\`gh auth login\`, and accept your ${CLI_NAME2} repository invitation.`);
1544
- }
1545
- }
1546
- async function downloadGitHubTemplate(target, templateRef) {
1547
- if (!/^v\d+\.\d+\.\d+(?:-rc\.\d+)?$/.test(templateRef)) {
1548
- throw new Error(`${CLI_NAME2} template reference must be an immutable release tag: ${templateRef}`);
1549
- }
1550
- const temporaryDirectory = await mkdtemp(join6(tmpdir(), `${CLI_NAME2}-`));
1551
- const artifactName = `foundation-source-${templateRef}.tar.gz`;
1552
- const checksumName = `${artifactName}.sha256`;
1553
- const manifestName = `foundation-source-${templateRef}.manifest.json`;
1554
- const archivePath = join6(temporaryDirectory, artifactName);
1555
- const extractedPath = join6(temporaryDirectory, "template");
1556
- try {
1557
- await execFileAsync("gh", ["auth", "status", "--hostname", "github.com"]).catch(() => {
1558
- throw new Error(`${CLI_NAME2} source access requires GitHub CLI authentication. Run \`gh auth login\` first.`);
1559
- });
1560
- await downloadReleaseAsset(templateRef, artifactName, temporaryDirectory);
1561
- await downloadReleaseAsset(templateRef, checksumName, temporaryDirectory);
1562
- await downloadReleaseAsset(templateRef, manifestName, temporaryDirectory);
3881
+ const archivePath = await downloadAsset(licenseKey, releaseTag, artifact, temporaryDirectory, baseUrl, onDownloadProgress);
3882
+ await downloadAsset(licenseKey, releaseTag, checksumName, temporaryDirectory, baseUrl);
3883
+ await downloadAsset(licenseKey, releaseTag, manifestName, temporaryDirectory, baseUrl);
1563
3884
  const archive = await readFile5(archivePath);
1564
3885
  const digest = createHash("sha256").update(archive).digest("hex");
1565
- const checksum = await readFile5(join6(temporaryDirectory, checksumName), "utf8");
1566
- const manifest = JSON.parse(await readFile5(join6(temporaryDirectory, manifestName), "utf8"));
1567
- verifyReleaseMetadata(checksum, manifest, artifactName, digest, templateRef);
3886
+ const checksum = await readFile5(join7(temporaryDirectory, checksumName), "utf8");
3887
+ const manifest = JSON.parse(await readFile5(join7(temporaryDirectory, manifestName), "utf8"));
3888
+ verifyReleaseMetadata(checksum, manifest, artifact, digest, releaseTag);
1568
3889
  await mkdir4(extractedPath);
1569
3890
  await execFileAsync("tar", ["-xzf", archivePath, "-C", extractedPath, "--strip-components=1"]);
1570
3891
  await copyLocalTemplate(extractedPath, target);
1571
3892
  } finally {
1572
- await rm3(temporaryDirectory, { recursive: true, force: true });
3893
+ await rm4(temporaryDirectory, { recursive: true, force: true });
1573
3894
  }
1574
3895
  }
1575
3896
  async function walk(directory) {
1576
3897
  const entries = await readdir(directory, { withFileTypes: true });
1577
3898
  const paths = [];
1578
3899
  for (const entry of entries) {
1579
- const path = join6(directory, entry.name);
3900
+ const path = join7(directory, entry.name);
1580
3901
  if (entry.isSymbolicLink()) {
1581
3902
  throw new Error(`Generated template contains a symbolic link: ${path}`);
1582
3903
  }
@@ -1618,7 +3939,7 @@ async function applyScopeRewrite(target, scope) {
1618
3939
  async function applyBrandRewrite(target, brandName) {
1619
3940
  const report = { files: 0, replacements: 0 };
1620
3941
  for (const entry of BRAND_MANIFEST) {
1621
- const path = join6(target, entry.path);
3942
+ const path = join7(target, entry.path);
1622
3943
  const replacements = await rewriteFile(path, (content) => {
1623
3944
  const result = rewriteBrandContent(content, brandName);
1624
3945
  if (result.replacements > 0 && path.endsWith(".tsx")) {
@@ -1633,27 +3954,27 @@ async function applyBrandRewrite(target, brandName) {
1633
3954
  return report;
1634
3955
  }
1635
3956
  async function generateEnvironmentFiles(target, databasePort = 5432) {
1636
- const serverExample = await readFile5(join6(target, "apps/server/.env.example"), "utf8");
1637
- await writeFile4(join6(target, "apps/server/.env"), generateServerEnv(serverExample, undefined, databasePort));
1638
- const webExample = await readFile5(join6(target, "apps/web/.env.example"), "utf8");
1639
- await writeFile4(join6(target, "apps/web/.env"), webExample);
1640
- const docsExample = await readFile5(join6(target, "apps/docs/.env.example"), "utf8");
1641
- await writeFile4(join6(target, "apps/docs/.env"), docsExample);
1642
- await writeFile4(join6(target, ".env"), `POSTGRES_PORT=${databasePort}
3957
+ const serverExample = await readFile5(join7(target, "apps/server/.env.example"), "utf8");
3958
+ await writeFile4(join7(target, "apps/server/.env"), generateServerEnv(serverExample, undefined, databasePort));
3959
+ const webExample = await readFile5(join7(target, "apps/web/.env.example"), "utf8");
3960
+ await writeFile4(join7(target, "apps/web/.env"), webExample);
3961
+ const docsExample = await readFile5(join7(target, "apps/docs/.env.example"), "utf8");
3962
+ await writeFile4(join7(target, "apps/docs/.env"), docsExample);
3963
+ await writeFile4(join7(target, ".env"), `POSTGRES_PORT=${databasePort}
1643
3964
  `);
1644
3965
  }
1645
3966
  async function neutralizeAgentInstructions(target) {
1646
- const agentPath = join6(target, "AGENTS.md");
1647
- const claudePath = join6(target, "CLAUDE.md");
3967
+ const agentPath = join7(target, "AGENTS.md");
3968
+ const claudePath = join7(target, "CLAUDE.md");
1648
3969
  await writeFile4(agentPath, rewriteBuyerAgentInstructions(await readFile5(agentPath, "utf8")));
1649
3970
  await writeFile4(claudePath, rewriteBuyerClaudeInstructions(await readFile5(claudePath, "utf8")));
1650
- const rootPackagePath = join6(target, "package.json");
3971
+ const rootPackagePath = join7(target, "package.json");
1651
3972
  await writeFile4(rootPackagePath, stripSellerOnlyRootScripts(await readFile5(rootPackagePath, "utf8")));
1652
3973
  }
1653
3974
  async function neutralizeSourceCli(target, scope, brandName) {
1654
3975
  if (String(CLI_NAME2) === BUYER_CLI_NAME && String(CLI_PACKAGE_NAME) === BUYER_CLI_PACKAGE_NAME)
1655
3976
  return;
1656
- const rootPackagePath = join6(target, "package.json");
3977
+ const rootPackagePath = join7(target, "package.json");
1657
3978
  const rootPackage = JSON.parse(await readFile5(rootPackagePath, "utf8"));
1658
3979
  const sourceScript = rootPackage.scripts?.[CLI_NAME2];
1659
3980
  if (!sourceScript)
@@ -1662,7 +3983,7 @@ async function neutralizeSourceCli(target, scope, brandName) {
1662
3983
  delete rootPackage.scripts[CLI_NAME2];
1663
3984
  await writeFile4(rootPackagePath, `${JSON.stringify(rootPackage, null, 2)}
1664
3985
  `);
1665
- const cliPackagePath = join6(target, "packages/create-app/package.json");
3986
+ const cliPackagePath = join7(target, "packages/create-app/package.json");
1666
3987
  const cliPackage = JSON.parse(await readFile5(cliPackagePath, "utf8"));
1667
3988
  if (cliPackage.name !== CLI_PACKAGE_NAME || !cliPackage.bin?.[CLI_NAME2]) {
1668
3989
  throw new Error(`Source CLI package must expose ${CLI_PACKAGE_NAME} as ${CLI_NAME2}.`);
@@ -1670,6 +3991,8 @@ async function neutralizeSourceCli(target, scope, brandName) {
1670
3991
  cliPackage.bin = { [BUYER_CLI_NAME]: "./src/cli.ts" };
1671
3992
  delete cliPackage.description;
1672
3993
  delete cliPackage.homepage;
3994
+ delete cliPackage.bugs;
3995
+ delete cliPackage.author;
1673
3996
  delete cliPackage.repository;
1674
3997
  delete cliPackage.keywords;
1675
3998
  delete cliPackage.files;
@@ -1677,23 +4000,14 @@ async function neutralizeSourceCli(target, scope, brandName) {
1677
4000
  const { name: _sourceName, version: cliVersion, ...cliPackageRemainder } = cliPackage;
1678
4001
  await writeFile4(cliPackagePath, `${JSON.stringify({ name: BUYER_CLI_PACKAGE_NAME, version: cliVersion, private: true, ...cliPackageRemainder }, null, 2)}
1679
4002
  `);
1680
- const constantsPath = join6(target, "packages/create-app/src/constants.ts");
1681
- const constants3 = await readFile5(constantsPath, "utf8");
1682
- const cliDeclaration = `export const CLI_NAME = '${CLI_NAME2}'`;
1683
- const packageDeclaration = `export const CLI_PACKAGE_NAME = '${CLI_PACKAGE_NAME}'`;
1684
- const scopeDeclaration = `export const DEFAULT_SCOPE = '@app'`;
1685
- const repositoryDeclaration = `export const TEMPLATE_REPOSITORY = '${TEMPLATE_REPOSITORY}'`;
1686
- const brandDeclaration = `export const SOURCE_BRAND_NAME = '${SOURCE_BRAND_NAME}'`;
1687
- if (!constants3.includes(cliDeclaration) || !constants3.includes(packageDeclaration) || !constants3.includes(scopeDeclaration) || !constants3.includes(repositoryDeclaration) || !constants3.includes(brandDeclaration)) {
1688
- throw new Error("Source CLI constants do not match the package identity.");
1689
- }
1690
- await writeFile4(constantsPath, constants3.replace(cliDeclaration, `export const CLI_NAME = '${BUYER_CLI_NAME}'`).replace(packageDeclaration, `export const CLI_PACKAGE_NAME = '${BUYER_CLI_PACKAGE_NAME}'`).replace(scopeDeclaration, `export const DEFAULT_SCOPE = '${normalizeScope2(scope)}'`).replace(repositoryDeclaration, "export const TEMPLATE_REPOSITORY = 'OWNER/REPOSITORY'").replace(brandDeclaration, `export const SOURCE_BRAND_NAME = '${brandName}'`));
1691
- const brandingPath = join6(target, "docs/golden-paths/customize-branding-design-tokens.md");
4003
+ const constantsPath = join7(target, "packages/create-app/src/constants.ts");
4004
+ await writeFile4(constantsPath, rewriteBuyerCliConstants(await readFile5(constantsPath, "utf8"), scope, brandName));
4005
+ const brandingPath = join7(target, "docs/golden-paths/customize-branding-design-tokens.md");
1692
4006
  const branding = await readFile5(brandingPath, "utf8");
1693
4007
  await writeFile4(brandingPath, branding.replaceAll(`pnpm ${CLI_NAME2}`, `pnpm ${BUYER_CLI_NAME}`));
1694
- const setupPath = join6(target, "docs/setup.md");
4008
+ const setupPath = join7(target, "docs/setup.md");
1695
4009
  await writeFile4(setupPath, rewriteBuyerSetupInstructions(await readFile5(setupPath, "utf8")));
1696
- const releasesPath = join6(target, "docs/releases.md");
4010
+ const releasesPath = join7(target, "docs/releases.md");
1697
4011
  await writeFile4(releasesPath, rewriteBuyerReleaseInstructions(await readFile5(releasesPath, "utf8")));
1698
4012
  }
1699
4013
  async function initializeRepository(target) {
@@ -1715,12 +4029,12 @@ async function scaffold(options) {
1715
4029
  try {
1716
4030
  if (options.from)
1717
4031
  await copyLocalTemplate(options.from, target);
1718
- else if (options.templateRef)
1719
- await downloadGitHubTemplate(target, options.templateRef);
1720
- else {
1721
- throw new Error(`A local source path or immutable ${CLI_NAME2} release is required.`);
4032
+ else if (options.licenseKey) {
4033
+ await downloadLicensedTemplate(target, options.licenseKey, options.sourceVersion, options.onDownloadProgress);
4034
+ } else {
4035
+ throw new Error(`A local source path or a ${CLI_NAME2} licence key is required.`);
1722
4036
  }
1723
- const packagePath = join6(target, "package.json");
4037
+ const packagePath = join7(target, "package.json");
1724
4038
  const packageReplacements = await rewriteFile(packagePath, (content) => rewriteRootPackageName(content, options.appName));
1725
4039
  const scope = await applyScopeRewrite(target, options.scope);
1726
4040
  await neutralizeAgentInstructions(target);
@@ -1741,7 +4055,7 @@ async function scaffold(options) {
1741
4055
  }))?.isDirectory()) {
1742
4056
  const entries = await readdir(target);
1743
4057
  if (entries.length === 0)
1744
- await rm3(target, { recursive: true, force: true });
4058
+ await rm4(target, { recursive: true, force: true });
1745
4059
  }
1746
4060
  throw error;
1747
4061
  }
@@ -1758,6 +4072,8 @@ function usage() {
1758
4072
  Create a buyer-owned SaaS application from your licensed ${suggestBrandName(CLI_NAME)} release.
1759
4073
 
1760
4074
  Options:
4075
+ --license-key <key> Licence key from your purchase (or set ${LICENSE_KEY_VARIABLE})
4076
+ --source-version <version> Pin an immutable release (default: the latest you are entitled to)
1761
4077
  --from <path> Use a local source checkout (maintainer/testing)
1762
4078
  --scope <namespace> Advanced workspace namespace override (default: derived from brand)
1763
4079
  --brand <name> Display name (default: derived from app name)
@@ -1802,7 +4118,11 @@ function parseArguments(argv) {
1802
4118
  const argument = argv[index];
1803
4119
  if (argument === "--from")
1804
4120
  parsed.from = takeValue3(argv, index++, argument);
1805
- else if (argument === "--scope")
4121
+ else if (argument === "--license-key")
4122
+ parsed.licenseKey = takeValue3(argv, index++, argument);
4123
+ else if (argument === "--source-version") {
4124
+ parsed.sourceVersion = normalizeSourceVersion(takeValue3(argv, index++, argument));
4125
+ } else if (argument === "--scope")
1806
4126
  parsed.scope = takeValue3(argv, index++, argument);
1807
4127
  else if (argument === "--brand")
1808
4128
  parsed.brandName = takeValue3(argv, index++, argument);
@@ -1870,28 +4190,60 @@ function suggestScope(brandName, fallbackAppName) {
1870
4190
  return namespace || fallbackAppName;
1871
4191
  }
1872
4192
  async function unwrapPrompt(value) {
1873
- if (prompts5.isCancel(value)) {
1874
- prompts5.cancel("No project was created.");
4193
+ if (isCancel(value)) {
4194
+ cancel("No project was created.");
1875
4195
  throw new CliCancelled;
1876
4196
  }
1877
4197
  return value;
1878
4198
  }
4199
+ function describeTargetConflict(appName) {
4200
+ const target = resolve4(process.cwd(), appName);
4201
+ if (!existsSync(target))
4202
+ return;
4203
+ if (!statSync(target).isDirectory())
4204
+ return `./${appName} already exists as a file.`;
4205
+ if (readdirSync(target).length > 0) {
4206
+ return `./${appName} already exists and is not empty. Pick another name, or remove it first.`;
4207
+ }
4208
+ return;
4209
+ }
4210
+ async function collectLicenseKey(parsed) {
4211
+ const supplied = parsed.licenseKey?.trim() ?? readLicenseKeyFromEnvironment();
4212
+ if (supplied) {
4213
+ const error = validateLicenseKey(supplied);
4214
+ if (error)
4215
+ throw new Error(error);
4216
+ return supplied.trim();
4217
+ }
4218
+ if (parsed.yes || !process.stdin.isTTY) {
4219
+ throw new Error(`A licence key is required. Pass --license-key or set ${LICENSE_KEY_VARIABLE}.`);
4220
+ }
4221
+ const entered = await unwrapPrompt(await password({
4222
+ message: "Licence key",
4223
+ validate: (value) => validateLicenseKey(value ?? "")
4224
+ }));
4225
+ return entered.trim();
4226
+ }
1879
4227
  async function collectOptions(parsed) {
1880
4228
  if (parsed.yes && !parsed.appName)
1881
4229
  throw new Error("Pass an app name when using --yes.");
1882
4230
  if (!parsed.yes && !process.stdin.isTTY && !parsed.appName) {
1883
4231
  throw new Error("Interactive prompts need a terminal. Pass an app name and --yes instead.");
1884
4232
  }
1885
- const appName = parsed.appName ?? await unwrapPrompt(await prompts5.text({
4233
+ const appName = parsed.appName ?? await unwrapPrompt(await text({
1886
4234
  message: "App name",
1887
4235
  placeholder: "my-saas",
1888
- validate: (value) => validateAppName(value ?? "")
4236
+ validate: (value) => validateAppName(value ?? "") ?? describeTargetConflict(value ?? "")
1889
4237
  }));
1890
4238
  const appNameError = validateAppName(appName);
1891
4239
  if (appNameError)
1892
4240
  throw new Error(appNameError);
4241
+ const targetConflict = describeTargetConflict(appName);
4242
+ if (targetConflict)
4243
+ throw new Error(targetConflict);
4244
+ const licenseKey = parsed.from ? undefined : await collectLicenseKey(parsed);
1893
4245
  const suggestedBrand = suggestBrandName(appName);
1894
- const brandName = parsed.brandName ?? (parsed.yes ? suggestedBrand : await unwrapPrompt(await prompts5.text({
4246
+ const brandName = parsed.brandName ?? (parsed.yes ? suggestedBrand : await unwrapPrompt(await text({
1895
4247
  message: "Brand name",
1896
4248
  placeholder: suggestedBrand,
1897
4249
  defaultValue: suggestedBrand,
@@ -1901,22 +4253,22 @@ async function collectOptions(parsed) {
1901
4253
  if (brandError)
1902
4254
  throw new Error(brandError);
1903
4255
  const scope = normalizeScope(parsed.scope ?? suggestScope(brandName, appName));
1904
- const initializeGit = parsed.initializeGit ?? (parsed.yes ? true : await unwrapPrompt(await prompts5.confirm({
4256
+ const initializeGit = parsed.initializeGit ?? (parsed.yes ? true : await unwrapPrompt(await confirm({
1905
4257
  message: "Initialize a Git repository?",
1906
4258
  initialValue: true
1907
4259
  })));
1908
- const installDependencies = parsed.installDependencies ?? (parsed.yes ? true : await unwrapPrompt(await prompts5.confirm({
4260
+ const installDependencies = parsed.installDependencies ?? (parsed.yes ? true : await unwrapPrompt(await confirm({
1909
4261
  message: "Install dependencies with pnpm?",
1910
4262
  initialValue: true
1911
4263
  })));
1912
4264
  if (parsed.startDevelopment && !installDependencies) {
1913
4265
  throw new Error("--start requires dependency installation. Remove --no-install.");
1914
4266
  }
1915
- const startDevelopment = parsed.startDevelopment ?? (parsed.yes || !installDependencies ? false : await unwrapPrompt(await prompts5.confirm({
4267
+ const startDevelopment = parsed.startDevelopment ?? (parsed.yes || !installDependencies ? false : await unwrapPrompt(await confirm({
1916
4268
  message: "Start local development now?",
1917
4269
  initialValue: true
1918
4270
  })));
1919
- const setupDeployment = parsed.setupDeployment ?? (parsed.yes ? false : await unwrapPrompt(await prompts5.confirm({
4271
+ const setupDeployment = parsed.setupDeployment ?? (parsed.yes ? false : await unwrapPrompt(await confirm({
1920
4272
  message: "Set up cloud deployment now?",
1921
4273
  initialValue: false
1922
4274
  })));
@@ -1924,6 +4276,8 @@ async function collectOptions(parsed) {
1924
4276
  return {
1925
4277
  appName,
1926
4278
  from: parsed.from ? resolve4(parsed.from) : undefined,
4279
+ licenseKey,
4280
+ sourceVersion: parsed.sourceVersion,
1927
4281
  scope,
1928
4282
  brandName,
1929
4283
  initializeGit,
@@ -1938,15 +4292,6 @@ async function readCliVersion() {
1938
4292
  throw new Error(`${CLI_NAME} package version is missing.`);
1939
4293
  return packageJson.version;
1940
4294
  }
1941
- function templateRefForVersion(version) {
1942
- if (!/^\d+\.\d+\.\d+(?:-rc\.\d+)?$/.test(version)) {
1943
- throw new Error(`${CLI_NAME} package version is not release-compatible: ${version}`);
1944
- }
1945
- if (version === "0.0.0") {
1946
- throw new Error(`This pre-release ${CLI_NAME} checkout requires --from <local-source-path>.`);
1947
- }
1948
- return `v${version}`;
1949
- }
1950
4295
  async function assertTargetAvailable(target) {
1951
4296
  const targetStat = await stat5(target).catch(() => {
1952
4297
  return;
@@ -2008,8 +4353,8 @@ function assertSiblingTarget(source, target) {
2008
4353
  throw new Error(`Create the new app beside the ${CLI_NAME} source checkout, not inside it.`);
2009
4354
  }
2010
4355
  }
2011
- function commandFailureOutput(stdout, stderr) {
2012
- const output = (stderr.trim() || stdout.trim()).split(`
4356
+ function commandFailureOutput(stdout2, stderr) {
4357
+ const output = (stderr.trim() || stdout2.trim()).split(`
2013
4358
  `).slice(-12).join(`
2014
4359
  `);
2015
4360
  return output ? `
@@ -2017,73 +4362,109 @@ function commandFailureOutput(stdout, stderr) {
2017
4362
  ${output}` : "";
2018
4363
  }
2019
4364
  async function installDependencies(target) {
2020
- const { stdout, stderr, exitCode } = await runCaptured2(["pnpm", "install", "--frozen-lockfile"], {
4365
+ const { stdout: stdout2, stderr, exitCode } = await runCaptured2(["pnpm", "install", "--frozen-lockfile"], {
2021
4366
  cwd: target,
2022
4367
  env: { ...process.env, CI: "1" }
2023
4368
  });
2024
4369
  if (exitCode !== 0) {
2025
- throw new Error(`Dependency installation failed.${commandFailureOutput(stdout, stderr)}`);
4370
+ throw new Error(`Dependency installation failed.${commandFailureOutput(stdout2, stderr)}`);
2026
4371
  }
2027
4372
  }
2028
- async function runCapturedCommand(command, target) {
2029
- const { stdout, stderr, exitCode } = await runCaptured2(command, { cwd: target });
2030
- if (exitCode !== 0) {
2031
- throw new Error(`${command.join(" ")} failed.${commandFailureOutput(stdout, stderr)}`);
2032
- }
4373
+ async function occupiedDevelopmentPorts() {
4374
+ const results = await Promise.all([5173, 8000].map(async (port) => ({ port, available: await isPortAvailable(port) })));
4375
+ return results.filter((result) => !result.available).map((result) => result.port);
2033
4376
  }
2034
4377
  async function startDevelopment(target) {
2035
- const occupiedPorts = (await Promise.all([5173, 8000].map(async (port) => ({
2036
- port,
2037
- available: await isPortAvailable(port)
2038
- })))).filter((result) => !result.available).map((result) => result.port);
2039
- if (occupiedPorts.length > 0) {
2040
- throw new Error(`Cannot start development because port ${occupiedPorts.join(", ")} is in use.`);
2041
- }
2042
- await runStep("Starting local Postgres", "Local Postgres is ready", () => runCapturedCommand(["docker", "compose", "up", "-d", "--wait", "postgres"], target));
2043
- prompts5.log.info(`Web http://localhost:5173
4378
+ log.info(`Web http://localhost:5173
2044
4379
  API http://localhost:8000`);
2045
- prompts5.outro("Development servers are starting. Ctrl+C stops app servers; Postgres stays running.");
2046
- const exitCode = await runInherited(["vp", "run", "-r", "--parallel", "dev"], { cwd: target });
4380
+ outro("Development servers are starting. Ctrl+C stops app servers; Postgres stays running.");
4381
+ const exitCode = await runInherited(["pnpm", "run", "dev"], { cwd: target });
2047
4382
  if (exitCode !== 0 && exitCode !== 130) {
2048
4383
  throw new Error(`Development servers exited with code ${exitCode}.`);
2049
4384
  }
2050
4385
  }
2051
- async function runStep(pending, complete, action, indicator = "dots") {
2052
- const progress = prompts5.spinner({ indicator });
2053
- progress.start(pending);
4386
+ var BYTE_UNITS = ["B", "KB", "MB", "GB"];
4387
+ var BYTE_SCALE = 1024;
4388
+ var PROGRESS_MAX = 100;
4389
+ var PROGRESS_BAR_WIDTH = 40;
4390
+ var PROGRESS_MIN_INTERVAL_MS = 80;
4391
+ var PROGRESS_MIN_DELTA = 0.5;
4392
+ function formatBytes(bytes) {
4393
+ let value = bytes;
4394
+ let unit = 0;
4395
+ while (value >= BYTE_SCALE && unit < BYTE_UNITS.length - 1) {
4396
+ value /= BYTE_SCALE;
4397
+ unit += 1;
4398
+ }
4399
+ return `${unit === 0 ? value : value.toFixed(1)} ${BYTE_UNITS[unit]}`;
4400
+ }
4401
+ function supportsAnimation() {
4402
+ return isTTY(process.stdout) && !isCI();
4403
+ }
4404
+ function createScaffoldReporter(pending, expectsDownload) {
4405
+ if (!expectsDownload || !supportsAnimation())
4406
+ return { handle: spinner() };
4407
+ const bar = progress({
4408
+ style: "heavy",
4409
+ size: PROGRESS_BAR_WIDTH,
4410
+ max: PROGRESS_MAX
4411
+ });
4412
+ let shown = 0;
4413
+ let emittedAt = 0;
4414
+ return {
4415
+ handle: bar,
4416
+ onDownloadProgress: (received, total) => {
4417
+ const percent = total ? Math.min(PROGRESS_MAX, received / total * PROGRESS_MAX) : shown;
4418
+ const finished = total !== undefined && received >= total;
4419
+ const now = performance.now();
4420
+ if (!finished && now - emittedAt < PROGRESS_MIN_INTERVAL_MS && percent - shown < PROGRESS_MIN_DELTA) {
4421
+ return;
4422
+ }
4423
+ emittedAt = now;
4424
+ const label = finished ? pending : total === undefined ? `Downloading source ${formatBytes(received)}` : `Downloading source ${formatBytes(received)} / ${formatBytes(total)}`;
4425
+ bar.advance(percent - shown, label);
4426
+ shown = percent;
4427
+ }
4428
+ };
4429
+ }
4430
+ async function runStep(pending, complete, action, handle) {
4431
+ handle.start(pending);
2054
4432
  try {
2055
4433
  const result = await action();
2056
- progress.stop(complete);
4434
+ handle.stop(complete);
2057
4435
  return result;
2058
4436
  } catch (error) {
2059
- progress.error(`${pending} failed`);
4437
+ handle.error(`${pending} failed`);
2060
4438
  throw error;
2061
4439
  }
2062
4440
  }
2063
- async function createApplication(options, version) {
4441
+ async function createApplication(options) {
2064
4442
  const target = resolve4(process.cwd(), options.appName);
2065
4443
  await assertTargetAvailable(target);
2066
4444
  assertSiblingTarget(options.from, target);
2067
4445
  const databasePort = await findAvailablePort();
2068
4446
  await mkdir5(dirname2(target), { recursive: true });
2069
- const staging = await mkdtemp2(join7(dirname2(target), `.${options.appName}-${CLI_NAME}-`));
4447
+ const staging = await mkdtemp2(join8(dirname2(target), `.${options.appName}-${CLI_NAME}-`));
4448
+ const preparing = "Preparing your application";
4449
+ const reporter = createScaffoldReporter(preparing, Boolean(options.licenseKey));
2070
4450
  try {
2071
- const templateRef = options.from ? undefined : templateRefForVersion(version);
2072
- await runStep("Preparing your application", "Application source prepared", () => scaffold({
4451
+ await runStep(preparing, "Application source prepared", () => scaffold({
2073
4452
  appName: options.appName,
2074
4453
  scope: options.scope,
2075
4454
  brandName: options.brandName,
2076
4455
  targetDirectory: staging,
2077
4456
  from: options.from,
2078
- templateRef,
4457
+ licenseKey: options.licenseKey,
4458
+ sourceVersion: options.sourceVersion,
2079
4459
  initializeGit: options.initializeGit,
2080
- databasePort
2081
- }));
4460
+ databasePort,
4461
+ onDownloadProgress: reporter.onDownloadProgress
4462
+ }), reporter.handle);
2082
4463
  if (options.deployment) {
2083
- await runStep("Configuring deployment", "Deployment target locked", () => applyDeploymentSelection2(staging, options.appName, options.deployment));
4464
+ await runStep("Configuring deployment", "Deployment target locked", () => applyDeploymentSelection2(staging, options.appName, options.deployment), spinner());
2084
4465
  }
2085
4466
  if (options.installDependencies) {
2086
- await runStep("Installing dependencies with pnpm", "Dependencies installed with pnpm", () => installDependencies(staging), "timer");
4467
+ await runStep("Installing dependencies with pnpm", "Dependencies installed with pnpm", () => installDependencies(staging), spinner({ indicator: "timer" }));
2087
4468
  }
2088
4469
  if (await stat5(target).catch(() => {
2089
4470
  return;
@@ -2092,7 +4473,7 @@ async function createApplication(options, version) {
2092
4473
  await rename2(staging, target);
2093
4474
  return { target, databasePort };
2094
4475
  } catch (error) {
2095
- await rm4(staging, { recursive: true, force: true });
4476
+ await rm5(staging, { recursive: true, force: true });
2096
4477
  throw error;
2097
4478
  }
2098
4479
  }
@@ -2101,16 +4482,16 @@ function completionDetails(target, options, databasePort) {
2101
4482
  const install = options.installDependencies ? [] : ["vp install --frozen-lockfile"];
2102
4483
  return {
2103
4484
  directory: `./${targetName}`,
2104
- commands: [
2105
- `cd ${targetName}`,
2106
- ...install,
2107
- "docker compose up -d postgres",
2108
- "vp run -r --parallel dev"
2109
- ].join(`
4485
+ commands: [`cd ${targetName}`, ...install, "pnpm dev"].join(`
2110
4486
  `),
2111
4487
  database: `Postgres localhost:${databasePort}`
2112
4488
  };
2113
4489
  }
4490
+ function printRunnableCommands(commands) {
4491
+ console.log(`
4492
+ ${commands}
4493
+ `);
4494
+ }
2114
4495
  async function main() {
2115
4496
  const argv = process.argv.slice(2);
2116
4497
  if (argv[0] === "agent") {
@@ -2135,32 +4516,40 @@ async function main() {
2135
4516
  console.log(version);
2136
4517
  return;
2137
4518
  }
2138
- prompts5.intro(`${suggestBrandName(CLI_NAME)} ${version} \xB7 production SaaS foundation`);
4519
+ intro(`${suggestBrandName(CLI_NAME)} ${version} \xB7 production SaaS foundation`);
2139
4520
  const options = await collectOptions(parsed);
2140
- const { target, databasePort } = await createApplication(options, version);
4521
+ const { target, databasePort } = await createApplication(options);
2141
4522
  const completion = completionDetails(target, options, databasePort);
2142
- prompts5.log.success(`Created ${completion.directory}`);
4523
+ log.success(`Created ${completion.directory}`);
2143
4524
  if (!options.startDevelopment) {
2144
- prompts5.log.step("Run locally");
2145
- prompts5.log.message(completion.commands);
2146
- prompts5.log.info(`Web http://localhost:5173
4525
+ log.step("Run locally");
4526
+ log.info(`Web http://localhost:5173
2147
4527
  API http://localhost:8000
2148
4528
  ${completion.database}`);
2149
4529
  if (options.deployment) {
2150
- prompts5.log.info(`Deployment ${options.deployment.cloud.toUpperCase()} + ${options.deployment.storageProvider} + ${options.deployment.frontendTarget} locked. Review deployment/README.md.`);
4530
+ log.info(`Deployment ${options.deployment.cloud.toUpperCase()} + ${options.deployment.storageProvider} + ${options.deployment.frontendTarget} locked. Review deployment/README.md.`);
2151
4531
  } else {
2152
- prompts5.log.info("Deployment deferred. Run `pnpm deploy:configure` when you are ready.");
4532
+ log.info("Deployment deferred. Run `pnpm deploy:configure` when you are ready.");
2153
4533
  }
2154
- prompts5.outro(`${options.brandName} is ready.`);
4534
+ outro(`${options.brandName} is ready.`);
4535
+ printRunnableCommands(completion.commands);
4536
+ return;
4537
+ }
4538
+ const occupiedPorts = await occupiedDevelopmentPorts();
4539
+ if (occupiedPorts.length > 0) {
4540
+ log.warn(`Port ${occupiedPorts.join(" and ")} already in use, so the development servers were not started.`);
4541
+ log.step("Free the port, then run");
4542
+ outro(`${options.brandName} is ready at ${completion.directory}.`);
4543
+ printRunnableCommands(completion.commands);
2155
4544
  return;
2156
4545
  }
2157
4546
  try {
2158
4547
  await startDevelopment(target);
2159
4548
  } catch (error) {
2160
- prompts5.log.error(error instanceof Error ? error.message : String(error));
2161
- prompts5.log.info(`The application was created at ${completion.directory}.`);
2162
- prompts5.log.step("Start it manually");
2163
- prompts5.log.message(completion.commands);
4549
+ log.error(error instanceof Error ? error.message : String(error));
4550
+ log.step("Start it manually");
4551
+ outro(`${options.brandName} is ready at ${completion.directory}.`);
4552
+ printRunnableCommands(completion.commands);
2164
4553
  process.exitCode = 1;
2165
4554
  }
2166
4555
  }
@@ -2168,16 +4557,20 @@ if (isEntrypoint(import.meta.url)) {
2168
4557
  main().catch((error) => {
2169
4558
  if (error instanceof CliCancelled)
2170
4559
  return;
2171
- prompts5.log.error(error instanceof Error ? error.message : String(error));
2172
- prompts5.outro("No project was created.");
4560
+ log.error(error instanceof Error ? error.message : String(error));
4561
+ outro("No project was created.");
2173
4562
  process.exitCode = 1;
2174
4563
  });
2175
4564
  }
2176
4565
  export {
2177
4566
  usage,
2178
- templateRefForVersion,
2179
4567
  suggestScope,
2180
4568
  suggestBrandName,
4569
+ printRunnableCommands,
2181
4570
  parseArguments,
2182
- findAvailablePort
4571
+ occupiedDevelopmentPorts,
4572
+ formatBytes,
4573
+ findAvailablePort,
4574
+ describeTargetConflict,
4575
+ collectLicenseKey
2183
4576
  };