superslate 0.2.0 → 0.3.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.
- package/LICENSE +63 -4
- package/README.md +34 -9
- package/dist/cli.js +2487 -180
- package/package.json +11 -9
package/dist/cli.js
CHANGED
|
@@ -1,15 +1,1650 @@
|
|
|
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 unicodeOr = (o2, e) => unicode ? o2 : e;
|
|
1333
|
+
var S_STEP_ACTIVE = unicodeOr("◆", "*");
|
|
1334
|
+
var S_STEP_CANCEL = unicodeOr("■", "x");
|
|
1335
|
+
var S_STEP_ERROR = unicodeOr("▲", "x");
|
|
1336
|
+
var S_STEP_SUBMIT = unicodeOr("◇", "o");
|
|
1337
|
+
var S_BAR_START = unicodeOr("┌", "T");
|
|
1338
|
+
var S_BAR = unicodeOr("│", "|");
|
|
1339
|
+
var S_BAR_END = unicodeOr("└", "—");
|
|
1340
|
+
var S_BAR_START_RIGHT = unicodeOr("┐", "T");
|
|
1341
|
+
var S_BAR_END_RIGHT = unicodeOr("┘", "—");
|
|
1342
|
+
var S_RADIO_ACTIVE = unicodeOr("●", ">");
|
|
1343
|
+
var S_RADIO_INACTIVE = unicodeOr("○", " ");
|
|
1344
|
+
var S_CHECKBOX_ACTIVE = unicodeOr("◻", "[•]");
|
|
1345
|
+
var S_CHECKBOX_SELECTED = unicodeOr("◼", "[+]");
|
|
1346
|
+
var S_CHECKBOX_INACTIVE = unicodeOr("◻", "[ ]");
|
|
1347
|
+
var S_PASSWORD_MASK = unicodeOr("▪", "•");
|
|
1348
|
+
var S_BAR_H = unicodeOr("─", "-");
|
|
1349
|
+
var S_CORNER_TOP_RIGHT = unicodeOr("╮", "+");
|
|
1350
|
+
var S_CONNECT_LEFT = unicodeOr("├", "+");
|
|
1351
|
+
var S_CORNER_BOTTOM_RIGHT = unicodeOr("╯", "+");
|
|
1352
|
+
var S_CORNER_BOTTOM_LEFT = unicodeOr("╰", "+");
|
|
1353
|
+
var S_CORNER_TOP_LEFT = unicodeOr("╭", "+");
|
|
1354
|
+
var S_INFO = unicodeOr("●", "•");
|
|
1355
|
+
var S_SUCCESS = unicodeOr("◆", "*");
|
|
1356
|
+
var S_WARN = unicodeOr("▲", "!");
|
|
1357
|
+
var S_ERROR = unicodeOr("■", "x");
|
|
1358
|
+
var symbol = (o2) => {
|
|
1359
|
+
switch (o2) {
|
|
1360
|
+
case "initial":
|
|
1361
|
+
case "active":
|
|
1362
|
+
return styleText2("cyan", S_STEP_ACTIVE);
|
|
1363
|
+
case "cancel":
|
|
1364
|
+
return styleText2("red", S_STEP_CANCEL);
|
|
1365
|
+
case "error":
|
|
1366
|
+
return styleText2("yellow", S_STEP_ERROR);
|
|
1367
|
+
case "submit":
|
|
1368
|
+
return styleText2("green", S_STEP_SUBMIT);
|
|
1369
|
+
}
|
|
1370
|
+
};
|
|
1371
|
+
var confirm = (i) => {
|
|
1372
|
+
const a2 = i.active ?? "Yes", s = i.inactive ?? "No";
|
|
1373
|
+
return new r({
|
|
1374
|
+
active: a2,
|
|
1375
|
+
inactive: s,
|
|
1376
|
+
signal: i.signal,
|
|
1377
|
+
input: i.input,
|
|
1378
|
+
output: i.output,
|
|
1379
|
+
initialValue: i.initialValue ?? true,
|
|
1380
|
+
render() {
|
|
1381
|
+
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)}
|
|
1382
|
+
` : ""}${f2}
|
|
1383
|
+
`, c2 = this.value ? a2 : s;
|
|
1384
|
+
switch (this.state) {
|
|
1385
|
+
case "submit": {
|
|
1386
|
+
const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
|
|
1387
|
+
return `${o2}${r2}${styleText2("dim", c2)}`;
|
|
1388
|
+
}
|
|
1389
|
+
case "cancel": {
|
|
1390
|
+
const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
|
|
1391
|
+
return `${o2}${r2}${styleText2(["strikethrough", "dim"], c2)}${e ? `
|
|
1392
|
+
${styleText2("gray", S_BAR)}` : ""}`;
|
|
1393
|
+
}
|
|
1394
|
+
default: {
|
|
1395
|
+
const r2 = e ? `${styleText2("cyan", S_BAR)} ` : "", g2 = e ? styleText2("cyan", S_BAR_END) : "";
|
|
1396
|
+
return `${o2}${r2}${this.value ? `${styleText2("green", S_RADIO_ACTIVE)} ${a2}` : `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", a2)}`}${i.vertical ? e ? `
|
|
1397
|
+
${styleText2("cyan", S_BAR)} ` : `
|
|
1398
|
+
` : ` ${styleText2("dim", "/")} `}${this.value ? `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", s)}` : `${styleText2("green", S_RADIO_ACTIVE)} ${s}`}
|
|
1399
|
+
${g2}
|
|
1400
|
+
`;
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
}).prompt();
|
|
1405
|
+
};
|
|
1406
|
+
var MULTISELECT_INSTRUCTIONS = [
|
|
1407
|
+
`${styleText2("dim", "↑/↓")} to navigate`,
|
|
1408
|
+
`${styleText2("dim", "Space:")} select`,
|
|
1409
|
+
`${styleText2("dim", "Enter:")} confirm`
|
|
1410
|
+
];
|
|
1411
|
+
var log = {
|
|
1412
|
+
message: (s = [], {
|
|
1413
|
+
symbol: e = styleText2("gray", S_BAR),
|
|
1414
|
+
secondarySymbol: r2 = styleText2("gray", S_BAR),
|
|
1415
|
+
output: m2 = process.stdout,
|
|
1416
|
+
spacing: l2 = 1,
|
|
1417
|
+
withGuide: c2
|
|
1418
|
+
} = {}) => {
|
|
1419
|
+
const t2 = [], o2 = c2 ?? settings.withGuide, f2 = o2 ? r2 : "", O = o2 ? `${e} ` : "", u4 = o2 ? `${r2} ` : "";
|
|
1420
|
+
for (let i = 0;i < l2; i++)
|
|
1421
|
+
t2.push(f2);
|
|
1422
|
+
const g2 = Array.isArray(s) ? s : s.split(`
|
|
1423
|
+
`);
|
|
1424
|
+
if (g2.length > 0) {
|
|
1425
|
+
const [i, ...y] = g2;
|
|
1426
|
+
i.length > 0 ? t2.push(`${O}${i}`) : t2.push(o2 ? e : "");
|
|
1427
|
+
for (const p2 of y)
|
|
1428
|
+
p2.length > 0 ? t2.push(`${u4}${p2}`) : t2.push(o2 ? r2 : "");
|
|
1429
|
+
}
|
|
1430
|
+
m2.write(`${t2.join(`
|
|
1431
|
+
`)}
|
|
1432
|
+
`);
|
|
1433
|
+
},
|
|
1434
|
+
info: (s, e) => {
|
|
1435
|
+
log.message(s, { ...e, symbol: styleText2("blue", S_INFO) });
|
|
1436
|
+
},
|
|
1437
|
+
success: (s, e) => {
|
|
1438
|
+
log.message(s, { ...e, symbol: styleText2("green", S_SUCCESS) });
|
|
1439
|
+
},
|
|
1440
|
+
step: (s, e) => {
|
|
1441
|
+
log.message(s, { ...e, symbol: styleText2("green", S_STEP_SUBMIT) });
|
|
1442
|
+
},
|
|
1443
|
+
warn: (s, e) => {
|
|
1444
|
+
log.message(s, { ...e, symbol: styleText2("yellow", S_WARN) });
|
|
1445
|
+
},
|
|
1446
|
+
warning: (s, e) => {
|
|
1447
|
+
log.warn(s, e);
|
|
1448
|
+
},
|
|
1449
|
+
error: (s, e) => {
|
|
1450
|
+
log.message(s, { ...e, symbol: styleText2("red", S_ERROR) });
|
|
1451
|
+
}
|
|
1452
|
+
};
|
|
1453
|
+
var cancel = (o2 = "", t2) => {
|
|
1454
|
+
const i = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_END)} ` : "";
|
|
1455
|
+
i.write(`${e}${styleText2("red", o2)}
|
|
1456
|
+
|
|
1457
|
+
`);
|
|
1458
|
+
};
|
|
1459
|
+
var intro = (o2 = "", t2) => {
|
|
1460
|
+
const i = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_START)} ` : "";
|
|
1461
|
+
i.write(`${e}${o2}
|
|
1462
|
+
`);
|
|
1463
|
+
};
|
|
1464
|
+
var outro = (o2 = "", t2) => {
|
|
1465
|
+
const i = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR)}
|
|
1466
|
+
${styleText2("gray", S_BAR_END)} ` : "";
|
|
1467
|
+
i.write(`${e}${o2}
|
|
1468
|
+
|
|
1469
|
+
`);
|
|
1470
|
+
};
|
|
1471
|
+
var password = (r2) => new u$1({
|
|
1472
|
+
validate: r2.validate,
|
|
1473
|
+
mask: r2.mask ?? S_PASSWORD_MASK,
|
|
1474
|
+
signal: r2.signal,
|
|
1475
|
+
input: r2.input,
|
|
1476
|
+
output: r2.output,
|
|
1477
|
+
render() {
|
|
1478
|
+
const e = r2.withGuide ?? settings.withGuide, o2 = `${e ? `${styleText2("gray", S_BAR)}
|
|
1479
|
+
` : ""}${symbol(this.state)} ${r2.message}
|
|
1480
|
+
`, c2 = this.userInputWithCursor, i = this.masked;
|
|
1481
|
+
switch (this.state) {
|
|
1482
|
+
case "error": {
|
|
1483
|
+
const s = e ? `${styleText2("yellow", S_BAR)} ` : "", n3 = e ? `${styleText2("yellow", S_BAR_END)} ` : "", l2 = i ?? "";
|
|
1484
|
+
return r2.clearOnError && this.clear(), `${o2.trim()}
|
|
1485
|
+
${s}${l2}
|
|
1486
|
+
${n3}${styleText2("yellow", this.error)}
|
|
1487
|
+
`;
|
|
1488
|
+
}
|
|
1489
|
+
case "submit": {
|
|
1490
|
+
const s = e ? `${styleText2("gray", S_BAR)} ` : "", n3 = i ? styleText2("dim", i) : "";
|
|
1491
|
+
return `${o2}${s}${n3}`;
|
|
1492
|
+
}
|
|
1493
|
+
case "cancel": {
|
|
1494
|
+
const s = e ? `${styleText2("gray", S_BAR)} ` : "", n3 = i ? styleText2(["strikethrough", "dim"], i) : "";
|
|
1495
|
+
return `${o2}${s}${n3}${i && e ? `
|
|
1496
|
+
${styleText2("gray", S_BAR)}` : ""}`;
|
|
1497
|
+
}
|
|
1498
|
+
default: {
|
|
1499
|
+
const s = e ? `${styleText2("cyan", S_BAR)} ` : "", n3 = e ? styleText2("cyan", S_BAR_END) : "";
|
|
1500
|
+
return `${o2}${s}${c2}
|
|
1501
|
+
${n3}
|
|
1502
|
+
`;
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
}).prompt();
|
|
1507
|
+
var W = (l2) => styleText2("magenta", l2);
|
|
1508
|
+
var spinner = ({
|
|
1509
|
+
indicator: l2 = "dots",
|
|
1510
|
+
onCancel: h2,
|
|
1511
|
+
output: n3 = process.stdout,
|
|
1512
|
+
cancelMessage: G,
|
|
1513
|
+
errorMessage: O,
|
|
1514
|
+
frames: E = unicode ? ["◒", "◐", "◓", "◑"] : ["•", "o", "O", "0"],
|
|
1515
|
+
delay: F = unicode ? 80 : 120,
|
|
1516
|
+
signal: m2,
|
|
1517
|
+
...I
|
|
1518
|
+
} = {}) => {
|
|
1519
|
+
const u4 = isCI();
|
|
1520
|
+
let M2, T3, d = false, S = false, s = "", p2, w = performance.now();
|
|
1521
|
+
const x = getColumns(n3), k = I?.styleFrame ?? W, g2 = (e) => {
|
|
1522
|
+
const r2 = e > 1 ? O ?? settings.messages.error : G ?? settings.messages.cancel;
|
|
1523
|
+
S = e === 1, d && (a2(r2, e), S && typeof h2 == "function" && h2());
|
|
1524
|
+
}, f2 = () => g2(2), i = () => g2(1), A = () => {
|
|
1525
|
+
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);
|
|
1526
|
+
}, H = () => {
|
|
1527
|
+
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);
|
|
1528
|
+
}, y = () => {
|
|
1529
|
+
if (p2 === undefined)
|
|
1530
|
+
return;
|
|
1531
|
+
u4 && n3.write(`
|
|
1532
|
+
`);
|
|
1533
|
+
const r2 = wrapAnsi(p2, x, {
|
|
1534
|
+
hard: true,
|
|
1535
|
+
trim: false
|
|
1536
|
+
}).split(`
|
|
1537
|
+
`);
|
|
1538
|
+
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());
|
|
1539
|
+
}, C2 = (e) => e.replace(/\.+$/, ""), _2 = (e) => {
|
|
1540
|
+
const r2 = (performance.now() - e) / 1000, t2 = Math.floor(r2 / 60), o2 = Math.floor(r2 % 60);
|
|
1541
|
+
return t2 > 0 ? `[${t2}m ${o2}s]` : `[${o2}s]`;
|
|
1542
|
+
}, N = I.withGuide ?? settings.withGuide, P2 = (e = "") => {
|
|
1543
|
+
d = true, M2 = block({ output: n3 }), s = C2(e), w = performance.now(), N && n3.write(`${styleText2("gray", S_BAR)}
|
|
1544
|
+
`);
|
|
1545
|
+
let r2 = 0, t2 = 0;
|
|
1546
|
+
A(), T3 = setInterval(() => {
|
|
1547
|
+
if (u4 && s === p2)
|
|
1548
|
+
return;
|
|
1549
|
+
y(), p2 = s;
|
|
1550
|
+
const o2 = k(E[r2]);
|
|
1551
|
+
let v;
|
|
1552
|
+
if (u4)
|
|
1553
|
+
v = `${o2} ${s}...`;
|
|
1554
|
+
else if (l2 === "timer")
|
|
1555
|
+
v = `${o2} ${s} ${_2(w)}`;
|
|
1556
|
+
else {
|
|
1557
|
+
const B = ".".repeat(Math.floor(t2)).slice(0, 3);
|
|
1558
|
+
v = `${o2} ${s}${B}`;
|
|
1559
|
+
}
|
|
1560
|
+
const j = wrapAnsi(v, x, {
|
|
1561
|
+
hard: true,
|
|
1562
|
+
trim: false
|
|
1563
|
+
});
|
|
1564
|
+
n3.write(j), r2 = r2 + 1 < E.length ? r2 + 1 : 0, t2 = t2 < 4 ? t2 + 0.125 : 0;
|
|
1565
|
+
}, F);
|
|
1566
|
+
}, a2 = (e = "", r2 = 0, t2 = false) => {
|
|
1567
|
+
if (!d)
|
|
1568
|
+
return;
|
|
1569
|
+
d = false, clearInterval(T3), y();
|
|
1570
|
+
const o2 = r2 === 0 ? styleText2("green", S_STEP_SUBMIT) : r2 === 1 ? styleText2("red", S_STEP_CANCEL) : styleText2("red", S_STEP_ERROR);
|
|
1571
|
+
s = e ?? s, t2 || (l2 === "timer" ? n3.write(`${o2} ${s} ${_2(w)}
|
|
1572
|
+
`) : n3.write(`${o2} ${s}
|
|
1573
|
+
`)), H(), M2();
|
|
1574
|
+
};
|
|
1575
|
+
return {
|
|
1576
|
+
start: P2,
|
|
1577
|
+
stop: (e = "") => a2(e, 0),
|
|
1578
|
+
message: (e = "") => {
|
|
1579
|
+
s = C2(e ?? s);
|
|
1580
|
+
},
|
|
1581
|
+
cancel: (e = "") => a2(e, 1),
|
|
1582
|
+
error: (e = "") => a2(e, 2),
|
|
1583
|
+
clear: () => a2("", 0, true),
|
|
1584
|
+
get isCancelled() {
|
|
1585
|
+
return S;
|
|
1586
|
+
}
|
|
1587
|
+
};
|
|
1588
|
+
};
|
|
1589
|
+
var u4 = {
|
|
1590
|
+
light: unicodeOr("─", "-"),
|
|
1591
|
+
heavy: unicodeOr("━", "="),
|
|
1592
|
+
block: unicodeOr("█", "#")
|
|
1593
|
+
};
|
|
1594
|
+
var SELECT_INSTRUCTIONS = [
|
|
1595
|
+
`${styleText2("dim", "↑/↓")} to navigate`,
|
|
1596
|
+
`${styleText2("dim", "Enter:")} confirm`
|
|
1597
|
+
];
|
|
1598
|
+
var i = `${styleText2("gray", S_BAR)} `;
|
|
1599
|
+
var text = (e) => new n2({
|
|
1600
|
+
validate: e.validate,
|
|
1601
|
+
placeholder: e.placeholder,
|
|
1602
|
+
defaultValue: e.defaultValue,
|
|
1603
|
+
initialValue: e.initialValue,
|
|
1604
|
+
output: e.output,
|
|
1605
|
+
signal: e.signal,
|
|
1606
|
+
input: e.input,
|
|
1607
|
+
render() {
|
|
1608
|
+
const i2 = e?.withGuide ?? settings.withGuide, s = `${`${i2 ? `${styleText2("gray", S_BAR)}
|
|
1609
|
+
` : ""}${symbol(this.state)} `}${e.message}
|
|
1610
|
+
`, 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 ?? "";
|
|
1611
|
+
switch (this.state) {
|
|
1612
|
+
case "error": {
|
|
1613
|
+
const n3 = this.error ? ` ${styleText2("yellow", this.error)}` : "", r2 = i2 ? `${styleText2("yellow", S_BAR)} ` : "", d = i2 ? styleText2("yellow", S_BAR_END) : "";
|
|
1614
|
+
return `${s.trim()}
|
|
1615
|
+
${r2}${o2}
|
|
1616
|
+
${d}${n3}
|
|
1617
|
+
`;
|
|
1618
|
+
}
|
|
1619
|
+
case "submit": {
|
|
1620
|
+
const n3 = l2 ? ` ${styleText2("dim", l2)}` : "", r2 = i2 ? styleText2("gray", S_BAR) : "";
|
|
1621
|
+
return `${s}${r2}${n3}`;
|
|
1622
|
+
}
|
|
1623
|
+
case "cancel": {
|
|
1624
|
+
const n3 = l2 ? ` ${styleText2(["strikethrough", "dim"], l2)}` : "", r2 = i2 ? styleText2("gray", S_BAR) : "";
|
|
1625
|
+
return `${s}${r2}${n3}${l2.trim() ? `
|
|
1626
|
+
${r2}` : ""}`;
|
|
1627
|
+
}
|
|
1628
|
+
default: {
|
|
1629
|
+
const n3 = i2 ? `${styleText2("cyan", S_BAR)} ` : "", r2 = i2 ? styleText2("cyan", S_BAR_END) : "";
|
|
1630
|
+
return `${s}${n3}${o2}
|
|
1631
|
+
${r2}
|
|
1632
|
+
`;
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
}).prompt();
|
|
3
1637
|
|
|
4
1638
|
// src/cli.ts
|
|
5
|
-
import
|
|
6
|
-
import { mkdir as mkdir5, mkdtemp as mkdtemp2, readFile as readFile6, readdir as readdir2, rename as rename2, rm as
|
|
1639
|
+
import { existsSync, readdirSync, statSync } from "fs";
|
|
1640
|
+
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
1641
|
import { createConnection, createServer } from "net";
|
|
8
1642
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9
|
-
import { dirname as dirname2, join as
|
|
1643
|
+
import { dirname as dirname2, join as join8, relative as relative2, resolve as resolve4, sep } from "path";
|
|
10
1644
|
|
|
11
1645
|
// src/constants.ts
|
|
12
1646
|
var CLI_NAME = "superslate";
|
|
1647
|
+
var LICENSE_KEY_VARIABLE = "SUPERSLATE_LICENSE_KEY";
|
|
13
1648
|
|
|
14
1649
|
// src/constants.ts
|
|
15
1650
|
var CLI_NAME2 = "superslate";
|
|
@@ -18,7 +1653,10 @@ var BUYER_CLI_NAME = "create-app";
|
|
|
18
1653
|
var BUYER_CLI_PACKAGE_NAME = "create-app";
|
|
19
1654
|
var DEFAULT_SCOPE = "@app";
|
|
20
1655
|
var SOURCE_BRAND_NAME = "superslate";
|
|
21
|
-
var
|
|
1656
|
+
var DELIVERY_BASE_URL = "https://dl.superslate.dev";
|
|
1657
|
+
var DELIVERY_URL_VARIABLE = "SUPERSLATE_DELIVERY_URL";
|
|
1658
|
+
var LICENSE_KEY_VARIABLE2 = "SUPERSLATE_LICENSE_KEY";
|
|
1659
|
+
var LICENSE_KEY_PREFIX = "SUPERSLATE-";
|
|
22
1660
|
|
|
23
1661
|
// src/core.ts
|
|
24
1662
|
function validateAppName(value) {
|
|
@@ -55,8 +1693,532 @@ function validateBrandName(value) {
|
|
|
55
1693
|
}
|
|
56
1694
|
var SCOPE_EXTENSIONS = new Set([".json", ".jsonc", ".md", ".ts", ".tsx", ".yaml", ".yml"]);
|
|
57
1695
|
|
|
1696
|
+
// src/delivery.ts
|
|
1697
|
+
var RELEASE_TAG_PATTERN = /^v\d+\.\d+\.\d+(?:-rc\.\d+)?$/;
|
|
1698
|
+
function validateLicenseKey(value) {
|
|
1699
|
+
const key = value.trim();
|
|
1700
|
+
if (!key)
|
|
1701
|
+
return "Enter the licence key from your purchase receipt.";
|
|
1702
|
+
if (/\s/.test(key))
|
|
1703
|
+
return "A licence key does not contain spaces.";
|
|
1704
|
+
if (!key.startsWith(LICENSE_KEY_PREFIX) || key.length === LICENSE_KEY_PREFIX.length) {
|
|
1705
|
+
return `A ${CLI_NAME2} licence key starts with ${LICENSE_KEY_PREFIX}. Copy it from your purchase receipt or the customer portal.`;
|
|
1706
|
+
}
|
|
1707
|
+
return;
|
|
1708
|
+
}
|
|
1709
|
+
function readLicenseKeyFromEnvironment(environment = process.env) {
|
|
1710
|
+
return environment[LICENSE_KEY_VARIABLE2]?.trim() || undefined;
|
|
1711
|
+
}
|
|
1712
|
+
function normalizeSourceVersion(value) {
|
|
1713
|
+
const trimmed = value.trim();
|
|
1714
|
+
const releaseTag = trimmed.startsWith("v") ? trimmed : `v${trimmed}`;
|
|
1715
|
+
if (!RELEASE_TAG_PATTERN.test(releaseTag)) {
|
|
1716
|
+
throw new Error(`Source version must be an immutable release such as 1.2.3: ${value}`);
|
|
1717
|
+
}
|
|
1718
|
+
return releaseTag;
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
// node_modules/@clack/prompts/dist/index.mjs
|
|
1722
|
+
import { styleText as styleText3, stripVTControlCharacters as stripVTControlCharacters2 } from "node:util";
|
|
1723
|
+
import process$12 from "node:process";
|
|
1724
|
+
var import_sisteransi3 = __toESM(require_src(), 1);
|
|
1725
|
+
function isUnicodeSupported2() {
|
|
1726
|
+
if (process$12.platform !== "win32") {
|
|
1727
|
+
return process$12.env.TERM !== "linux";
|
|
1728
|
+
}
|
|
1729
|
+
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";
|
|
1730
|
+
}
|
|
1731
|
+
var unicode2 = isUnicodeSupported2();
|
|
1732
|
+
var isCI2 = () => process.env.CI === "true";
|
|
1733
|
+
var unicodeOr2 = (o2, e) => unicode2 ? o2 : e;
|
|
1734
|
+
var S_STEP_ACTIVE2 = unicodeOr2("◆", "*");
|
|
1735
|
+
var S_STEP_CANCEL2 = unicodeOr2("■", "x");
|
|
1736
|
+
var S_STEP_ERROR2 = unicodeOr2("▲", "x");
|
|
1737
|
+
var S_STEP_SUBMIT2 = unicodeOr2("◇", "o");
|
|
1738
|
+
var S_BAR_START2 = unicodeOr2("┌", "T");
|
|
1739
|
+
var S_BAR2 = unicodeOr2("│", "|");
|
|
1740
|
+
var S_BAR_END2 = unicodeOr2("└", "—");
|
|
1741
|
+
var S_BAR_START_RIGHT2 = unicodeOr2("┐", "T");
|
|
1742
|
+
var S_BAR_END_RIGHT2 = unicodeOr2("┘", "—");
|
|
1743
|
+
var S_RADIO_ACTIVE2 = unicodeOr2("●", ">");
|
|
1744
|
+
var S_RADIO_INACTIVE2 = unicodeOr2("○", " ");
|
|
1745
|
+
var S_CHECKBOX_ACTIVE2 = unicodeOr2("◻", "[•]");
|
|
1746
|
+
var S_CHECKBOX_SELECTED2 = unicodeOr2("◼", "[+]");
|
|
1747
|
+
var S_CHECKBOX_INACTIVE2 = unicodeOr2("◻", "[ ]");
|
|
1748
|
+
var S_PASSWORD_MASK2 = unicodeOr2("▪", "•");
|
|
1749
|
+
var S_BAR_H2 = unicodeOr2("─", "-");
|
|
1750
|
+
var S_CORNER_TOP_RIGHT2 = unicodeOr2("╮", "+");
|
|
1751
|
+
var S_CONNECT_LEFT2 = unicodeOr2("├", "+");
|
|
1752
|
+
var S_CORNER_BOTTOM_RIGHT2 = unicodeOr2("╯", "+");
|
|
1753
|
+
var S_CORNER_BOTTOM_LEFT2 = unicodeOr2("╰", "+");
|
|
1754
|
+
var S_CORNER_TOP_LEFT2 = unicodeOr2("╭", "+");
|
|
1755
|
+
var S_INFO2 = unicodeOr2("●", "•");
|
|
1756
|
+
var S_SUCCESS2 = unicodeOr2("◆", "*");
|
|
1757
|
+
var S_WARN2 = unicodeOr2("▲", "!");
|
|
1758
|
+
var S_ERROR2 = unicodeOr2("■", "x");
|
|
1759
|
+
var symbol2 = (o2) => {
|
|
1760
|
+
switch (o2) {
|
|
1761
|
+
case "initial":
|
|
1762
|
+
case "active":
|
|
1763
|
+
return styleText3("cyan", S_STEP_ACTIVE2);
|
|
1764
|
+
case "cancel":
|
|
1765
|
+
return styleText3("red", S_STEP_CANCEL2);
|
|
1766
|
+
case "error":
|
|
1767
|
+
return styleText3("yellow", S_STEP_ERROR2);
|
|
1768
|
+
case "submit":
|
|
1769
|
+
return styleText3("green", S_STEP_SUBMIT2);
|
|
1770
|
+
}
|
|
1771
|
+
};
|
|
1772
|
+
var symbolBar = (o2) => {
|
|
1773
|
+
switch (o2) {
|
|
1774
|
+
case "initial":
|
|
1775
|
+
case "active":
|
|
1776
|
+
return styleText3("cyan", S_BAR2);
|
|
1777
|
+
case "cancel":
|
|
1778
|
+
return styleText3("red", S_BAR2);
|
|
1779
|
+
case "error":
|
|
1780
|
+
return styleText3("yellow", S_BAR2);
|
|
1781
|
+
case "submit":
|
|
1782
|
+
return styleText3("green", S_BAR2);
|
|
1783
|
+
}
|
|
1784
|
+
};
|
|
1785
|
+
function formatInstructionFooter(o2, e) {
|
|
1786
|
+
const r2 = [`${e ? `${styleText3("cyan", S_BAR2)} ` : ""}${o2.join(" • ")}`];
|
|
1787
|
+
return e && r2.push(styleText3("cyan", S_BAR_END2)), r2;
|
|
1788
|
+
}
|
|
1789
|
+
var I = (l2, e, w, p2, b2, C2 = false) => {
|
|
1790
|
+
let r2 = e, O = 0;
|
|
1791
|
+
if (C2)
|
|
1792
|
+
for (let i2 = p2 - 1;i2 >= w; i2--) {
|
|
1793
|
+
const m2 = l2[i2];
|
|
1794
|
+
if (m2 && (r2 -= m2.length), O++, r2 <= b2)
|
|
1795
|
+
break;
|
|
1796
|
+
}
|
|
1797
|
+
else
|
|
1798
|
+
for (let i2 = w;i2 < p2; i2++) {
|
|
1799
|
+
const m2 = l2[i2];
|
|
1800
|
+
if (m2 && (r2 -= m2.length), O++, r2 <= b2)
|
|
1801
|
+
break;
|
|
1802
|
+
}
|
|
1803
|
+
return { lineCount: r2, removals: O };
|
|
1804
|
+
};
|
|
1805
|
+
var limitOptions = ({
|
|
1806
|
+
cursor: l2,
|
|
1807
|
+
options: e,
|
|
1808
|
+
style: w,
|
|
1809
|
+
output: p2 = process.stdout,
|
|
1810
|
+
maxItems: b2 = Number.POSITIVE_INFINITY,
|
|
1811
|
+
columnPadding: C2 = 0,
|
|
1812
|
+
rowPadding: r2 = 4
|
|
1813
|
+
}) => {
|
|
1814
|
+
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);
|
|
1815
|
+
let f2 = 0;
|
|
1816
|
+
l2 >= a2 - 3 && (f2 = Math.max(Math.min(l2 - a2 + 3, e.length - a2), 0));
|
|
1817
|
+
let d = a2 < e.length && f2 > 0, c2 = a2 < e.length && f2 + a2 < e.length;
|
|
1818
|
+
const W2 = Math.min(f2 + a2, e.length), s = [];
|
|
1819
|
+
let g2 = 0;
|
|
1820
|
+
d && g2++, c2 && g2++;
|
|
1821
|
+
const T3 = f2 + (d ? 1 : 0), y = W2 - (c2 ? 1 : 0);
|
|
1822
|
+
for (let t2 = T3;t2 < y; t2++) {
|
|
1823
|
+
const n3 = e[t2], o2 = n3 ? w(n3, t2 === l2) : "", h2 = wrapAnsi(o2, i2, {
|
|
1824
|
+
hard: true,
|
|
1825
|
+
trim: false
|
|
1826
|
+
}).split(`
|
|
1827
|
+
`);
|
|
1828
|
+
s.push(h2), g2 += h2.length;
|
|
1829
|
+
}
|
|
1830
|
+
if (g2 > v) {
|
|
1831
|
+
let t2 = 0, n3 = 0, o2 = g2;
|
|
1832
|
+
const h2 = l2 - T3;
|
|
1833
|
+
let u5 = v;
|
|
1834
|
+
const L = () => I(s, o2, 0, h2, u5), E = () => I(s, o2, h2 + 1, s.length, u5, true);
|
|
1835
|
+
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));
|
|
1836
|
+
}
|
|
1837
|
+
const x = [];
|
|
1838
|
+
d && x.push(M2);
|
|
1839
|
+
for (const t2 of s)
|
|
1840
|
+
for (const n3 of t2)
|
|
1841
|
+
x.push(n3);
|
|
1842
|
+
return c2 && x.push(M2), x;
|
|
1843
|
+
};
|
|
1844
|
+
var confirm2 = (i2) => {
|
|
1845
|
+
const a2 = i2.active ?? "Yes", s = i2.inactive ?? "No";
|
|
1846
|
+
return new r({
|
|
1847
|
+
active: a2,
|
|
1848
|
+
inactive: s,
|
|
1849
|
+
signal: i2.signal,
|
|
1850
|
+
input: i2.input,
|
|
1851
|
+
output: i2.output,
|
|
1852
|
+
initialValue: i2.initialValue ?? true,
|
|
1853
|
+
render() {
|
|
1854
|
+
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)}
|
|
1855
|
+
` : ""}${f2}
|
|
1856
|
+
`, c2 = this.value ? a2 : s;
|
|
1857
|
+
switch (this.state) {
|
|
1858
|
+
case "submit": {
|
|
1859
|
+
const r2 = e ? `${styleText3("gray", S_BAR2)} ` : "";
|
|
1860
|
+
return `${o2}${r2}${styleText3("dim", c2)}`;
|
|
1861
|
+
}
|
|
1862
|
+
case "cancel": {
|
|
1863
|
+
const r2 = e ? `${styleText3("gray", S_BAR2)} ` : "";
|
|
1864
|
+
return `${o2}${r2}${styleText3(["strikethrough", "dim"], c2)}${e ? `
|
|
1865
|
+
${styleText3("gray", S_BAR2)}` : ""}`;
|
|
1866
|
+
}
|
|
1867
|
+
default: {
|
|
1868
|
+
const r2 = e ? `${styleText3("cyan", S_BAR2)} ` : "", g2 = e ? styleText3("cyan", S_BAR_END2) : "";
|
|
1869
|
+
return `${o2}${r2}${this.value ? `${styleText3("green", S_RADIO_ACTIVE2)} ${a2}` : `${styleText3("dim", S_RADIO_INACTIVE2)} ${styleText3("dim", a2)}`}${i2.vertical ? e ? `
|
|
1870
|
+
${styleText3("cyan", S_BAR2)} ` : `
|
|
1871
|
+
` : ` ${styleText3("dim", "/")} `}${this.value ? `${styleText3("dim", S_RADIO_INACTIVE2)} ${styleText3("dim", s)}` : `${styleText3("green", S_RADIO_ACTIVE2)} ${s}`}
|
|
1872
|
+
${g2}
|
|
1873
|
+
`;
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
}).prompt();
|
|
1878
|
+
};
|
|
1879
|
+
var MULTISELECT_INSTRUCTIONS2 = [
|
|
1880
|
+
`${styleText3("dim", "↑/↓")} to navigate`,
|
|
1881
|
+
`${styleText3("dim", "Space:")} select`,
|
|
1882
|
+
`${styleText3("dim", "Enter:")} confirm`
|
|
1883
|
+
];
|
|
1884
|
+
var m2 = (i2, u5) => i2.split(`
|
|
1885
|
+
`).map((d) => u5(d)).join(`
|
|
1886
|
+
`);
|
|
1887
|
+
var multiselect = (i2) => {
|
|
1888
|
+
const u5 = (t2, a2) => {
|
|
1889
|
+
const r2 = t2.label ?? String(t2.value);
|
|
1890
|
+
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))}`;
|
|
1891
|
+
}, d = i2.required ?? true, v = i2.showInstructions ?? true;
|
|
1892
|
+
return new a({
|
|
1893
|
+
options: i2.options,
|
|
1894
|
+
signal: i2.signal,
|
|
1895
|
+
input: i2.input,
|
|
1896
|
+
output: i2.output,
|
|
1897
|
+
initialValues: i2.initialValues,
|
|
1898
|
+
required: d,
|
|
1899
|
+
cursorAt: i2.cursorAt,
|
|
1900
|
+
validate(t2) {
|
|
1901
|
+
if (d && (t2 === undefined || t2.length === 0))
|
|
1902
|
+
return `Please select at least one option.
|
|
1903
|
+
${styleText3("reset", styleText3("dim", `Press ${styleText3(["gray", "bgWhite", "inverse"], " space ")} to select, ${styleText3("gray", styleText3("bgWhite", styleText3("inverse", " enter ")))} to submit`))}`;
|
|
1904
|
+
},
|
|
1905
|
+
render() {
|
|
1906
|
+
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)}
|
|
1907
|
+
` : ""}${a2}
|
|
1908
|
+
`, o2 = this.value ?? [], p2 = (n3, l2) => {
|
|
1909
|
+
if (n3.disabled)
|
|
1910
|
+
return u5(n3, "disabled");
|
|
1911
|
+
const s = o2.includes(n3.value);
|
|
1912
|
+
return l2 && s ? u5(n3, "active-selected") : s ? u5(n3, "selected") : u5(n3, l2 ? "active" : "inactive");
|
|
1913
|
+
};
|
|
1914
|
+
switch (this.state) {
|
|
1915
|
+
case "submit": {
|
|
1916
|
+
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)} ` : "");
|
|
1917
|
+
return `${r2}${l2}`;
|
|
1918
|
+
}
|
|
1919
|
+
case "cancel": {
|
|
1920
|
+
const n3 = this.options.filter(({ value: s }) => o2.includes(s)).map((s) => u5(s, "cancelled")).join(styleText3("dim", ", "));
|
|
1921
|
+
if (n3.trim() === "")
|
|
1922
|
+
return `${r2}${styleText3("gray", S_BAR2)}`;
|
|
1923
|
+
const l2 = wrapTextWithPrefix(i2.output, n3, t2 ? `${styleText3("gray", S_BAR2)} ` : "");
|
|
1924
|
+
return `${r2}${l2}${t2 ? `
|
|
1925
|
+
${styleText3("gray", S_BAR2)}` : ""}`;
|
|
1926
|
+
}
|
|
1927
|
+
case "error": {
|
|
1928
|
+
const n3 = t2 ? `${styleText3("yellow", S_BAR2)} ` : "", l2 = this.error.split(`
|
|
1929
|
+
`).map(($, C2) => C2 === 0 ? `${t2 ? `${styleText3("yellow", S_BAR_END2)} ` : ""}${styleText3("yellow", $)}` : ` ${$}`).join(`
|
|
1930
|
+
`), s = r2.split(`
|
|
1931
|
+
`).length, h2 = l2.split(`
|
|
1932
|
+
`).length + 1;
|
|
1933
|
+
return `${r2}${n3}${limitOptions({
|
|
1934
|
+
output: i2.output,
|
|
1935
|
+
options: this.options,
|
|
1936
|
+
cursor: this.cursor,
|
|
1937
|
+
maxItems: i2.maxItems,
|
|
1938
|
+
columnPadding: n3.length,
|
|
1939
|
+
rowPadding: s + h2,
|
|
1940
|
+
style: p2
|
|
1941
|
+
}).join(`
|
|
1942
|
+
${n3}`)}
|
|
1943
|
+
${l2}
|
|
1944
|
+
`;
|
|
1945
|
+
}
|
|
1946
|
+
default: {
|
|
1947
|
+
const n3 = t2 ? `${styleText3("cyan", S_BAR2)} ` : "", l2 = r2.split(`
|
|
1948
|
+
`).length, s = v ? formatInstructionFooter(MULTISELECT_INSTRUCTIONS2, t2) : t2 ? [styleText3("cyan", S_BAR_END2)] : [], h2 = s.join(`
|
|
1949
|
+
`), $ = s.length + 1;
|
|
1950
|
+
return `${r2}${n3}${limitOptions({
|
|
1951
|
+
output: i2.output,
|
|
1952
|
+
options: this.options,
|
|
1953
|
+
cursor: this.cursor,
|
|
1954
|
+
maxItems: i2.maxItems,
|
|
1955
|
+
columnPadding: n3.length,
|
|
1956
|
+
rowPadding: l2 + $,
|
|
1957
|
+
style: p2
|
|
1958
|
+
}).join(`
|
|
1959
|
+
${n3}`)}
|
|
1960
|
+
${h2}
|
|
1961
|
+
`;
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
}).prompt();
|
|
1966
|
+
};
|
|
1967
|
+
var log2 = {
|
|
1968
|
+
message: (s = [], {
|
|
1969
|
+
symbol: e = styleText3("gray", S_BAR2),
|
|
1970
|
+
secondarySymbol: r2 = styleText3("gray", S_BAR2),
|
|
1971
|
+
output: m3 = process.stdout,
|
|
1972
|
+
spacing: l2 = 1,
|
|
1973
|
+
withGuide: c2
|
|
1974
|
+
} = {}) => {
|
|
1975
|
+
const t2 = [], o2 = c2 ?? settings.withGuide, f2 = o2 ? r2 : "", O = o2 ? `${e} ` : "", u5 = o2 ? `${r2} ` : "";
|
|
1976
|
+
for (let i2 = 0;i2 < l2; i2++)
|
|
1977
|
+
t2.push(f2);
|
|
1978
|
+
const g2 = Array.isArray(s) ? s : s.split(`
|
|
1979
|
+
`);
|
|
1980
|
+
if (g2.length > 0) {
|
|
1981
|
+
const [i2, ...y] = g2;
|
|
1982
|
+
i2.length > 0 ? t2.push(`${O}${i2}`) : t2.push(o2 ? e : "");
|
|
1983
|
+
for (const p2 of y)
|
|
1984
|
+
p2.length > 0 ? t2.push(`${u5}${p2}`) : t2.push(o2 ? r2 : "");
|
|
1985
|
+
}
|
|
1986
|
+
m3.write(`${t2.join(`
|
|
1987
|
+
`)}
|
|
1988
|
+
`);
|
|
1989
|
+
},
|
|
1990
|
+
info: (s, e) => {
|
|
1991
|
+
log2.message(s, { ...e, symbol: styleText3("blue", S_INFO2) });
|
|
1992
|
+
},
|
|
1993
|
+
success: (s, e) => {
|
|
1994
|
+
log2.message(s, { ...e, symbol: styleText3("green", S_SUCCESS2) });
|
|
1995
|
+
},
|
|
1996
|
+
step: (s, e) => {
|
|
1997
|
+
log2.message(s, { ...e, symbol: styleText3("green", S_STEP_SUBMIT2) });
|
|
1998
|
+
},
|
|
1999
|
+
warn: (s, e) => {
|
|
2000
|
+
log2.message(s, { ...e, symbol: styleText3("yellow", S_WARN2) });
|
|
2001
|
+
},
|
|
2002
|
+
warning: (s, e) => {
|
|
2003
|
+
log2.warn(s, e);
|
|
2004
|
+
},
|
|
2005
|
+
error: (s, e) => {
|
|
2006
|
+
log2.message(s, { ...e, symbol: styleText3("red", S_ERROR2) });
|
|
2007
|
+
}
|
|
2008
|
+
};
|
|
2009
|
+
var cancel2 = (o2 = "", t2) => {
|
|
2010
|
+
const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText3("gray", S_BAR_END2)} ` : "";
|
|
2011
|
+
i2.write(`${e}${styleText3("red", o2)}
|
|
2012
|
+
|
|
2013
|
+
`);
|
|
2014
|
+
};
|
|
2015
|
+
var intro2 = (o2 = "", t2) => {
|
|
2016
|
+
const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText3("gray", S_BAR_START2)} ` : "";
|
|
2017
|
+
i2.write(`${e}${o2}
|
|
2018
|
+
`);
|
|
2019
|
+
};
|
|
2020
|
+
var outro2 = (o2 = "", t2) => {
|
|
2021
|
+
const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText3("gray", S_BAR2)}
|
|
2022
|
+
${styleText3("gray", S_BAR_END2)} ` : "";
|
|
2023
|
+
i2.write(`${e}${o2}
|
|
2024
|
+
|
|
2025
|
+
`);
|
|
2026
|
+
};
|
|
2027
|
+
var W2 = (l2) => styleText3("magenta", l2);
|
|
2028
|
+
var spinner2 = ({
|
|
2029
|
+
indicator: l2 = "dots",
|
|
2030
|
+
onCancel: h2,
|
|
2031
|
+
output: n3 = process.stdout,
|
|
2032
|
+
cancelMessage: G,
|
|
2033
|
+
errorMessage: O,
|
|
2034
|
+
frames: E = unicode2 ? ["◒", "◐", "◓", "◑"] : ["•", "o", "O", "0"],
|
|
2035
|
+
delay: F = unicode2 ? 80 : 120,
|
|
2036
|
+
signal: m3,
|
|
2037
|
+
...I2
|
|
2038
|
+
} = {}) => {
|
|
2039
|
+
const u5 = isCI2();
|
|
2040
|
+
let M2, T3, d = false, S = false, s = "", p2, w = performance.now();
|
|
2041
|
+
const x = getColumns(n3), k = I2?.styleFrame ?? W2, g2 = (e) => {
|
|
2042
|
+
const r2 = e > 1 ? O ?? settings.messages.error : G ?? settings.messages.cancel;
|
|
2043
|
+
S = e === 1, d && (a2(r2, e), S && typeof h2 == "function" && h2());
|
|
2044
|
+
}, f2 = () => g2(2), i2 = () => g2(1), A = () => {
|
|
2045
|
+
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);
|
|
2046
|
+
}, H = () => {
|
|
2047
|
+
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);
|
|
2048
|
+
}, y = () => {
|
|
2049
|
+
if (p2 === undefined)
|
|
2050
|
+
return;
|
|
2051
|
+
u5 && n3.write(`
|
|
2052
|
+
`);
|
|
2053
|
+
const r2 = wrapAnsi(p2, x, {
|
|
2054
|
+
hard: true,
|
|
2055
|
+
trim: false
|
|
2056
|
+
}).split(`
|
|
2057
|
+
`);
|
|
2058
|
+
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());
|
|
2059
|
+
}, C2 = (e) => e.replace(/\.+$/, ""), _2 = (e) => {
|
|
2060
|
+
const r2 = (performance.now() - e) / 1000, t2 = Math.floor(r2 / 60), o2 = Math.floor(r2 % 60);
|
|
2061
|
+
return t2 > 0 ? `[${t2}m ${o2}s]` : `[${o2}s]`;
|
|
2062
|
+
}, N = I2.withGuide ?? settings.withGuide, P2 = (e = "") => {
|
|
2063
|
+
d = true, M2 = block({ output: n3 }), s = C2(e), w = performance.now(), N && n3.write(`${styleText3("gray", S_BAR2)}
|
|
2064
|
+
`);
|
|
2065
|
+
let r2 = 0, t2 = 0;
|
|
2066
|
+
A(), T3 = setInterval(() => {
|
|
2067
|
+
if (u5 && s === p2)
|
|
2068
|
+
return;
|
|
2069
|
+
y(), p2 = s;
|
|
2070
|
+
const o2 = k(E[r2]);
|
|
2071
|
+
let v;
|
|
2072
|
+
if (u5)
|
|
2073
|
+
v = `${o2} ${s}...`;
|
|
2074
|
+
else if (l2 === "timer")
|
|
2075
|
+
v = `${o2} ${s} ${_2(w)}`;
|
|
2076
|
+
else {
|
|
2077
|
+
const B = ".".repeat(Math.floor(t2)).slice(0, 3);
|
|
2078
|
+
v = `${o2} ${s}${B}`;
|
|
2079
|
+
}
|
|
2080
|
+
const j = wrapAnsi(v, x, {
|
|
2081
|
+
hard: true,
|
|
2082
|
+
trim: false
|
|
2083
|
+
});
|
|
2084
|
+
n3.write(j), r2 = r2 + 1 < E.length ? r2 + 1 : 0, t2 = t2 < 4 ? t2 + 0.125 : 0;
|
|
2085
|
+
}, F);
|
|
2086
|
+
}, a2 = (e = "", r2 = 0, t2 = false) => {
|
|
2087
|
+
if (!d)
|
|
2088
|
+
return;
|
|
2089
|
+
d = false, clearInterval(T3), y();
|
|
2090
|
+
const o2 = r2 === 0 ? styleText3("green", S_STEP_SUBMIT2) : r2 === 1 ? styleText3("red", S_STEP_CANCEL2) : styleText3("red", S_STEP_ERROR2);
|
|
2091
|
+
s = e ?? s, t2 || (l2 === "timer" ? n3.write(`${o2} ${s} ${_2(w)}
|
|
2092
|
+
`) : n3.write(`${o2} ${s}
|
|
2093
|
+
`)), H(), M2();
|
|
2094
|
+
};
|
|
2095
|
+
return {
|
|
2096
|
+
start: P2,
|
|
2097
|
+
stop: (e = "") => a2(e, 0),
|
|
2098
|
+
message: (e = "") => {
|
|
2099
|
+
s = C2(e ?? s);
|
|
2100
|
+
},
|
|
2101
|
+
cancel: (e = "") => a2(e, 1),
|
|
2102
|
+
error: (e = "") => a2(e, 2),
|
|
2103
|
+
clear: () => a2("", 0, true),
|
|
2104
|
+
get isCancelled() {
|
|
2105
|
+
return S;
|
|
2106
|
+
}
|
|
2107
|
+
};
|
|
2108
|
+
};
|
|
2109
|
+
var u5 = {
|
|
2110
|
+
light: unicodeOr2("─", "-"),
|
|
2111
|
+
heavy: unicodeOr2("━", "="),
|
|
2112
|
+
block: unicodeOr2("█", "#")
|
|
2113
|
+
};
|
|
2114
|
+
var SELECT_INSTRUCTIONS2 = [
|
|
2115
|
+
`${styleText3("dim", "↑/↓")} to navigate`,
|
|
2116
|
+
`${styleText3("dim", "Enter:")} confirm`
|
|
2117
|
+
];
|
|
2118
|
+
var c2 = (t2, o2) => t2.includes(`
|
|
2119
|
+
`) ? t2.split(`
|
|
2120
|
+
`).map((d) => o2(d)).join(`
|
|
2121
|
+
`) : o2(t2);
|
|
2122
|
+
var select = (t2) => {
|
|
2123
|
+
const o2 = (n3, m3) => {
|
|
2124
|
+
if (n3 === undefined)
|
|
2125
|
+
return "";
|
|
2126
|
+
const s = n3.label ?? String(n3.value);
|
|
2127
|
+
switch (m3) {
|
|
2128
|
+
case "disabled":
|
|
2129
|
+
return `${styleText3("gray", S_RADIO_INACTIVE2)} ${c2(s, (i2) => styleText3("gray", i2))}${n3.hint ? ` ${styleText3("dim", `(${n3.hint ?? "disabled"})`)}` : ""}`;
|
|
2130
|
+
case "selected":
|
|
2131
|
+
return `${c2(s, (i2) => styleText3("dim", i2))}`;
|
|
2132
|
+
case "active":
|
|
2133
|
+
return `${styleText3("green", S_RADIO_ACTIVE2)} ${s}${n3.hint ? ` ${styleText3("dim", `(${n3.hint})`)}` : ""}`;
|
|
2134
|
+
case "cancelled":
|
|
2135
|
+
return `${c2(s, (i2) => styleText3(["strikethrough", "dim"], i2))}`;
|
|
2136
|
+
default:
|
|
2137
|
+
return `${styleText3("dim", S_RADIO_INACTIVE2)} ${c2(s, (i2) => styleText3("dim", i2))}`;
|
|
2138
|
+
}
|
|
2139
|
+
}, d = t2.showInstructions ?? true;
|
|
2140
|
+
return new n$1({
|
|
2141
|
+
options: t2.options,
|
|
2142
|
+
signal: t2.signal,
|
|
2143
|
+
input: t2.input,
|
|
2144
|
+
output: t2.output,
|
|
2145
|
+
initialValue: t2.initialValue,
|
|
2146
|
+
render() {
|
|
2147
|
+
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)}
|
|
2148
|
+
` : ""}${i2}
|
|
2149
|
+
`;
|
|
2150
|
+
switch (this.state) {
|
|
2151
|
+
case "submit": {
|
|
2152
|
+
const r2 = n3 ? `${styleText3("gray", S_BAR2)} ` : "", a2 = wrapTextWithPrefix(t2.output, o2(this.options[this.cursor], "selected"), r2);
|
|
2153
|
+
return `${u6}${a2}`;
|
|
2154
|
+
}
|
|
2155
|
+
case "cancel": {
|
|
2156
|
+
const r2 = n3 ? `${styleText3("gray", S_BAR2)} ` : "", a2 = wrapTextWithPrefix(t2.output, o2(this.options[this.cursor], "cancelled"), r2);
|
|
2157
|
+
return `${u6}${a2}${n3 ? `
|
|
2158
|
+
${styleText3("gray", S_BAR2)}` : ""}`;
|
|
2159
|
+
}
|
|
2160
|
+
default: {
|
|
2161
|
+
const r2 = n3 ? `${styleText3("cyan", S_BAR2)} ` : "", a2 = u6.split(`
|
|
2162
|
+
`).length, p2 = d ? formatInstructionFooter(SELECT_INSTRUCTIONS2, n3) : n3 ? [styleText3("cyan", S_BAR_END2)] : [], b2 = p2.join(`
|
|
2163
|
+
`), f2 = p2.length + 1;
|
|
2164
|
+
return `${u6}${r2}${limitOptions({
|
|
2165
|
+
output: t2.output,
|
|
2166
|
+
cursor: this.cursor,
|
|
2167
|
+
options: this.options,
|
|
2168
|
+
maxItems: t2.maxItems,
|
|
2169
|
+
columnPadding: r2.length,
|
|
2170
|
+
rowPadding: a2 + f2,
|
|
2171
|
+
style: (g2, x) => o2(g2, g2.disabled ? "disabled" : x ? "active" : "inactive")
|
|
2172
|
+
}).join(`
|
|
2173
|
+
${r2}`)}
|
|
2174
|
+
${b2}
|
|
2175
|
+
`;
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
}).prompt();
|
|
2180
|
+
};
|
|
2181
|
+
var i2 = `${styleText3("gray", S_BAR2)} `;
|
|
2182
|
+
var text2 = (e) => new n2({
|
|
2183
|
+
validate: e.validate,
|
|
2184
|
+
placeholder: e.placeholder,
|
|
2185
|
+
defaultValue: e.defaultValue,
|
|
2186
|
+
initialValue: e.initialValue,
|
|
2187
|
+
output: e.output,
|
|
2188
|
+
signal: e.signal,
|
|
2189
|
+
input: e.input,
|
|
2190
|
+
render() {
|
|
2191
|
+
const i3 = e?.withGuide ?? settings.withGuide, s = `${`${i3 ? `${styleText3("gray", S_BAR2)}
|
|
2192
|
+
` : ""}${symbol2(this.state)} `}${e.message}
|
|
2193
|
+
`, 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 ?? "";
|
|
2194
|
+
switch (this.state) {
|
|
2195
|
+
case "error": {
|
|
2196
|
+
const n3 = this.error ? ` ${styleText3("yellow", this.error)}` : "", r2 = i3 ? `${styleText3("yellow", S_BAR2)} ` : "", d = i3 ? styleText3("yellow", S_BAR_END2) : "";
|
|
2197
|
+
return `${s.trim()}
|
|
2198
|
+
${r2}${o2}
|
|
2199
|
+
${d}${n3}
|
|
2200
|
+
`;
|
|
2201
|
+
}
|
|
2202
|
+
case "submit": {
|
|
2203
|
+
const n3 = l2 ? ` ${styleText3("dim", l2)}` : "", r2 = i3 ? styleText3("gray", S_BAR2) : "";
|
|
2204
|
+
return `${s}${r2}${n3}`;
|
|
2205
|
+
}
|
|
2206
|
+
case "cancel": {
|
|
2207
|
+
const n3 = l2 ? ` ${styleText3(["strikethrough", "dim"], l2)}` : "", r2 = i3 ? styleText3("gray", S_BAR2) : "";
|
|
2208
|
+
return `${s}${r2}${n3}${l2.trim() ? `
|
|
2209
|
+
${r2}` : ""}`;
|
|
2210
|
+
}
|
|
2211
|
+
default: {
|
|
2212
|
+
const n3 = i3 ? `${styleText3("cyan", S_BAR2)} ` : "", r2 = i3 ? styleText3("cyan", S_BAR_END2) : "";
|
|
2213
|
+
return `${s}${n3}${o2}
|
|
2214
|
+
${r2}
|
|
2215
|
+
`;
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
}
|
|
2219
|
+
}).prompt();
|
|
2220
|
+
|
|
58
2221
|
// src/agent-setup.ts
|
|
59
|
-
import * as prompts from "@clack/prompts";
|
|
60
2222
|
import { mkdir, readFile, rename, stat, writeFile } from "node:fs/promises";
|
|
61
2223
|
import { dirname, join as join2, resolve } from "node:path";
|
|
62
2224
|
|
|
@@ -74,19 +2236,19 @@ function runCaptured(command, options) {
|
|
|
74
2236
|
env: options.env ?? process.env,
|
|
75
2237
|
stdio: ["ignore", "pipe", "pipe"]
|
|
76
2238
|
});
|
|
77
|
-
let
|
|
2239
|
+
let stdout2 = "";
|
|
78
2240
|
let stderr = "";
|
|
79
2241
|
child.stdout.setEncoding("utf8");
|
|
80
2242
|
child.stderr.setEncoding("utf8");
|
|
81
2243
|
child.stdout.on("data", (chunk) => {
|
|
82
|
-
|
|
2244
|
+
stdout2 += chunk;
|
|
83
2245
|
});
|
|
84
2246
|
child.stderr.on("data", (chunk) => {
|
|
85
2247
|
stderr += chunk;
|
|
86
2248
|
});
|
|
87
2249
|
child.on("error", reject);
|
|
88
2250
|
child.on("close", (code, signal) => {
|
|
89
|
-
resolve({ exitCode: code ?? (signal ? 1 : 0), stdout, stderr });
|
|
2251
|
+
resolve({ exitCode: code ?? (signal ? 1 : 0), stdout: stdout2, stderr });
|
|
90
2252
|
});
|
|
91
2253
|
});
|
|
92
2254
|
}
|
|
@@ -334,7 +2496,7 @@ async function chooseClients(parsed) {
|
|
|
334
2496
|
if (!process.stdin.isTTY) {
|
|
335
2497
|
throw new Error("Interactive setup needs a terminal. Pass --clients and --yes instead.");
|
|
336
2498
|
}
|
|
337
|
-
const selected = await
|
|
2499
|
+
const selected = await multiselect({
|
|
338
2500
|
message: "Connect which local coding clients?",
|
|
339
2501
|
required: true,
|
|
340
2502
|
options: CLIENTS.map((client) => ({
|
|
@@ -344,8 +2506,8 @@ async function chooseClients(parsed) {
|
|
|
344
2506
|
})),
|
|
345
2507
|
initialValues: detected
|
|
346
2508
|
});
|
|
347
|
-
if (
|
|
348
|
-
|
|
2509
|
+
if (isCancel(selected)) {
|
|
2510
|
+
cancel2("No agent clients were configured.");
|
|
349
2511
|
return;
|
|
350
2512
|
}
|
|
351
2513
|
return selected;
|
|
@@ -379,29 +2541,28 @@ async function runAgentSetup(argv, cliName) {
|
|
|
379
2541
|
const clients = await chooseClients(parsed);
|
|
380
2542
|
if (!clients)
|
|
381
2543
|
return;
|
|
382
|
-
|
|
2544
|
+
intro2("superslate local agent context");
|
|
383
2545
|
if (parsed.dryRun) {
|
|
384
2546
|
for (const client of clients) {
|
|
385
|
-
|
|
2547
|
+
log2.info(`${client}
|
|
386
2548
|
${dryRunDescription(client, root)}`);
|
|
387
2549
|
}
|
|
388
|
-
|
|
2550
|
+
outro2("Dry run complete. No client configuration was changed.");
|
|
389
2551
|
return;
|
|
390
2552
|
}
|
|
391
|
-
const progress =
|
|
2553
|
+
const progress = spinner2();
|
|
392
2554
|
progress.start("Testing the local MCP server");
|
|
393
2555
|
await smokeServer(root);
|
|
394
2556
|
progress.stop("Local MCP server passed its protocol self-check");
|
|
395
2557
|
for (const client of clients) {
|
|
396
2558
|
const result = client === "codex" ? await configureCodex(root) : client === "cursor" ? await configureCursor(root) : await configureClaude(root);
|
|
397
|
-
|
|
2559
|
+
log2.success(`${client}: ${result}`);
|
|
398
2560
|
}
|
|
399
|
-
|
|
400
|
-
|
|
2561
|
+
log2.info("Restart configured clients, then ask: “Use plan_change for my next feature.”");
|
|
2562
|
+
outro2("superslate agent context is ready.");
|
|
401
2563
|
}
|
|
402
2564
|
|
|
403
2565
|
// src/deployment-cli.ts
|
|
404
|
-
import * as prompts3 from "@clack/prompts";
|
|
405
2566
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
406
2567
|
import { resolve as resolve2 } from "node:path";
|
|
407
2568
|
|
|
@@ -616,12 +2777,11 @@ async function applyDeploymentSelection(repositoryRoot, projectName, selection)
|
|
|
616
2777
|
}
|
|
617
2778
|
|
|
618
2779
|
// src/deployment-prompts.ts
|
|
619
|
-
import * as prompts2 from "@clack/prompts";
|
|
620
2780
|
class DeploymentPromptCancelled extends Error {
|
|
621
2781
|
}
|
|
622
2782
|
async function unwrap(value) {
|
|
623
|
-
if (
|
|
624
|
-
|
|
2783
|
+
if (isCancel(value)) {
|
|
2784
|
+
cancel2("Deployment configuration was not changed.");
|
|
625
2785
|
throw new DeploymentPromptCancelled;
|
|
626
2786
|
}
|
|
627
2787
|
return value;
|
|
@@ -642,7 +2802,7 @@ async function collectDeploymentSelection(defaults = {}, nonInteractive = false)
|
|
|
642
2802
|
haEnabled: defaults.haEnabled ?? false
|
|
643
2803
|
};
|
|
644
2804
|
}
|
|
645
|
-
const cloud = defaults.cloud ?? parseDeploymentCloud(await unwrap(await
|
|
2805
|
+
const cloud = defaults.cloud ?? parseDeploymentCloud(await unwrap(await select({
|
|
646
2806
|
message: "Backend cloud",
|
|
647
2807
|
options: [
|
|
648
2808
|
{ value: "aws", label: "AWS", hint: "ECS Fargate + RDS PostgreSQL" },
|
|
@@ -650,7 +2810,7 @@ async function collectDeploymentSelection(defaults = {}, nonInteractive = false)
|
|
|
650
2810
|
{ value: "azure", label: "Azure", hint: "Container Apps + Flexible Server" }
|
|
651
2811
|
]
|
|
652
2812
|
})));
|
|
653
|
-
const frontendTarget = defaults.frontendTarget ?? parseFrontendTarget(await unwrap(await
|
|
2813
|
+
const frontendTarget = defaults.frontendTarget ?? parseFrontendTarget(await unwrap(await select({
|
|
654
2814
|
message: "Frontend host",
|
|
655
2815
|
options: [
|
|
656
2816
|
{ value: "native", label: "Cloud native", hint: "Managed with the backend" },
|
|
@@ -662,7 +2822,7 @@ async function collectDeploymentSelection(defaults = {}, nonInteractive = false)
|
|
|
662
2822
|
}
|
|
663
2823
|
]
|
|
664
2824
|
})));
|
|
665
|
-
const storageProvider = defaults.storageProvider ?? (storageProvidersByCloud[cloud].length === 1 ? storageProvidersByCloud[cloud][0] ?? defaultStorageProviders[cloud] : parseStorageProvider(await unwrap(await
|
|
2825
|
+
const storageProvider = defaults.storageProvider ?? (storageProvidersByCloud[cloud].length === 1 ? storageProvidersByCloud[cloud][0] ?? defaultStorageProviders[cloud] : parseStorageProvider(await unwrap(await select({
|
|
666
2826
|
message: "Object storage",
|
|
667
2827
|
options: storageProvidersByCloud[cloud].map((provider) => ({
|
|
668
2828
|
value: provider,
|
|
@@ -670,29 +2830,29 @@ async function collectDeploymentSelection(defaults = {}, nonInteractive = false)
|
|
|
670
2830
|
hint: provider === defaultStorageProviders[cloud] ? "Cloud-native default" : ""
|
|
671
2831
|
}))
|
|
672
2832
|
}))));
|
|
673
|
-
const environment = defaults.environment ?? await unwrap(await
|
|
2833
|
+
const environment = defaults.environment ?? await unwrap(await text2({
|
|
674
2834
|
message: "Deployment environment",
|
|
675
2835
|
placeholder: "production",
|
|
676
2836
|
defaultValue: "production",
|
|
677
2837
|
validate: (value) => validateDeploymentEnvironment(value || "production")
|
|
678
2838
|
}));
|
|
679
|
-
const region = defaults.region ?? await unwrap(await
|
|
2839
|
+
const region = defaults.region ?? await unwrap(await text2({
|
|
680
2840
|
message: `${cloud.toUpperCase()} region`,
|
|
681
2841
|
placeholder: defaultRegions[cloud],
|
|
682
2842
|
defaultValue: defaultRegions[cloud],
|
|
683
2843
|
validate: (value) => validateRegion(value || defaultRegions[cloud])
|
|
684
2844
|
}));
|
|
685
|
-
const apiDomain = defaults.apiDomain ?? await unwrap(await
|
|
2845
|
+
const apiDomain = defaults.apiDomain ?? await unwrap(await text2({
|
|
686
2846
|
message: "Production API domain",
|
|
687
2847
|
placeholder: "api.example.com",
|
|
688
2848
|
validate: (value) => validateDomain(value ?? "")
|
|
689
2849
|
}));
|
|
690
|
-
const frontendDomain = defaults.frontendDomain ?? await unwrap(await
|
|
2850
|
+
const frontendDomain = defaults.frontendDomain ?? await unwrap(await text2({
|
|
691
2851
|
message: "Production frontend domain",
|
|
692
2852
|
placeholder: "app.example.com",
|
|
693
2853
|
validate: (value) => validateDomain(value ?? "")
|
|
694
2854
|
}));
|
|
695
|
-
const haEnabled = defaults.haEnabled ?? await unwrap(await
|
|
2855
|
+
const haEnabled = defaults.haEnabled ?? await unwrap(await confirm2({
|
|
696
2856
|
message: "Enable the higher-availability profile?",
|
|
697
2857
|
initialValue: false
|
|
698
2858
|
}));
|
|
@@ -750,17 +2910,17 @@ async function runDeploymentConfigure(argv, productName, repositoryRoot = proces
|
|
|
750
2910
|
const rootPackage = JSON.parse(await readFile3(`${root}/package.json`, "utf8"));
|
|
751
2911
|
if (!rootPackage.name)
|
|
752
2912
|
throw new Error("Root package name is required for deployment setup.");
|
|
753
|
-
|
|
2913
|
+
intro2(`${productName} deployment setup`);
|
|
754
2914
|
try {
|
|
755
2915
|
const selection = await collectDeploymentSelection(parsed, parsed.yes);
|
|
756
2916
|
const removed = await applyDeploymentSelection(root, rootPackage.name, selection);
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
2917
|
+
log2.success(`${selection.cloud.toUpperCase()} + ${selection.storageProvider} + ${selection.frontendTarget} is locked for ${selection.environment}.`);
|
|
2918
|
+
log2.info(`${removed.length} unused deployment paths removed.`);
|
|
2919
|
+
log2.step("Next");
|
|
2920
|
+
log2.message(`Review deployment/config.json
|
|
761
2921
|
Configure the protected GitHub environment
|
|
762
2922
|
Dispatch .github/workflows/deploy-cloud.yml`);
|
|
763
|
-
|
|
2923
|
+
outro2("Deployment configuration is ready to commit.");
|
|
764
2924
|
} catch (error) {
|
|
765
2925
|
if (error instanceof DeploymentPromptCancelled)
|
|
766
2926
|
return;
|
|
@@ -783,19 +2943,19 @@ function runCaptured2(command, options) {
|
|
|
783
2943
|
env: options.env ?? process.env,
|
|
784
2944
|
stdio: ["ignore", "pipe", "pipe"]
|
|
785
2945
|
});
|
|
786
|
-
let
|
|
2946
|
+
let stdout2 = "";
|
|
787
2947
|
let stderr = "";
|
|
788
2948
|
child.stdout.setEncoding("utf8");
|
|
789
2949
|
child.stderr.setEncoding("utf8");
|
|
790
2950
|
child.stdout.on("data", (chunk) => {
|
|
791
|
-
|
|
2951
|
+
stdout2 += chunk;
|
|
792
2952
|
});
|
|
793
2953
|
child.stderr.on("data", (chunk) => {
|
|
794
2954
|
stderr += chunk;
|
|
795
2955
|
});
|
|
796
2956
|
child.on("error", reject);
|
|
797
2957
|
child.on("close", (code, signal) => {
|
|
798
|
-
resolve3({ exitCode: code ?? (signal ? 1 : 0), stdout, stderr });
|
|
2958
|
+
resolve3({ exitCode: code ?? (signal ? 1 : 0), stdout: stdout2, stderr });
|
|
799
2959
|
});
|
|
800
2960
|
});
|
|
801
2961
|
}
|
|
@@ -834,12 +2994,11 @@ function isEntrypoint(moduleUrl) {
|
|
|
834
2994
|
}
|
|
835
2995
|
|
|
836
2996
|
// src/deployment-prompts.ts
|
|
837
|
-
import * as prompts4 from "@clack/prompts";
|
|
838
2997
|
class DeploymentPromptCancelled2 extends Error {
|
|
839
2998
|
}
|
|
840
2999
|
async function unwrap2(value) {
|
|
841
|
-
if (
|
|
842
|
-
|
|
3000
|
+
if (isCancel(value)) {
|
|
3001
|
+
cancel2("Deployment configuration was not changed.");
|
|
843
3002
|
throw new DeploymentPromptCancelled2;
|
|
844
3003
|
}
|
|
845
3004
|
return value;
|
|
@@ -860,7 +3019,7 @@ async function collectDeploymentSelection2(defaults = {}, nonInteractive = false
|
|
|
860
3019
|
haEnabled: defaults.haEnabled ?? false
|
|
861
3020
|
};
|
|
862
3021
|
}
|
|
863
|
-
const cloud = defaults.cloud ?? parseDeploymentCloud(await unwrap2(await
|
|
3022
|
+
const cloud = defaults.cloud ?? parseDeploymentCloud(await unwrap2(await select({
|
|
864
3023
|
message: "Backend cloud",
|
|
865
3024
|
options: [
|
|
866
3025
|
{ value: "aws", label: "AWS", hint: "ECS Fargate + RDS PostgreSQL" },
|
|
@@ -868,7 +3027,7 @@ async function collectDeploymentSelection2(defaults = {}, nonInteractive = false
|
|
|
868
3027
|
{ value: "azure", label: "Azure", hint: "Container Apps + Flexible Server" }
|
|
869
3028
|
]
|
|
870
3029
|
})));
|
|
871
|
-
const frontendTarget = defaults.frontendTarget ?? parseFrontendTarget(await unwrap2(await
|
|
3030
|
+
const frontendTarget = defaults.frontendTarget ?? parseFrontendTarget(await unwrap2(await select({
|
|
872
3031
|
message: "Frontend host",
|
|
873
3032
|
options: [
|
|
874
3033
|
{ value: "native", label: "Cloud native", hint: "Managed with the backend" },
|
|
@@ -880,7 +3039,7 @@ async function collectDeploymentSelection2(defaults = {}, nonInteractive = false
|
|
|
880
3039
|
}
|
|
881
3040
|
]
|
|
882
3041
|
})));
|
|
883
|
-
const storageProvider = defaults.storageProvider ?? (storageProvidersByCloud[cloud].length === 1 ? storageProvidersByCloud[cloud][0] ?? defaultStorageProviders[cloud] : parseStorageProvider(await unwrap2(await
|
|
3042
|
+
const storageProvider = defaults.storageProvider ?? (storageProvidersByCloud[cloud].length === 1 ? storageProvidersByCloud[cloud][0] ?? defaultStorageProviders[cloud] : parseStorageProvider(await unwrap2(await select({
|
|
884
3043
|
message: "Object storage",
|
|
885
3044
|
options: storageProvidersByCloud[cloud].map((provider) => ({
|
|
886
3045
|
value: provider,
|
|
@@ -888,29 +3047,29 @@ async function collectDeploymentSelection2(defaults = {}, nonInteractive = false
|
|
|
888
3047
|
hint: provider === defaultStorageProviders[cloud] ? "Cloud-native default" : ""
|
|
889
3048
|
}))
|
|
890
3049
|
}))));
|
|
891
|
-
const environment = defaults.environment ?? await unwrap2(await
|
|
3050
|
+
const environment = defaults.environment ?? await unwrap2(await text2({
|
|
892
3051
|
message: "Deployment environment",
|
|
893
3052
|
placeholder: "production",
|
|
894
3053
|
defaultValue: "production",
|
|
895
3054
|
validate: (value) => validateDeploymentEnvironment(value || "production")
|
|
896
3055
|
}));
|
|
897
|
-
const region = defaults.region ?? await unwrap2(await
|
|
3056
|
+
const region = defaults.region ?? await unwrap2(await text2({
|
|
898
3057
|
message: `${cloud.toUpperCase()} region`,
|
|
899
3058
|
placeholder: defaultRegions[cloud],
|
|
900
3059
|
defaultValue: defaultRegions[cloud],
|
|
901
3060
|
validate: (value) => validateRegion(value || defaultRegions[cloud])
|
|
902
3061
|
}));
|
|
903
|
-
const apiDomain = defaults.apiDomain ?? await unwrap2(await
|
|
3062
|
+
const apiDomain = defaults.apiDomain ?? await unwrap2(await text2({
|
|
904
3063
|
message: "Production API domain",
|
|
905
3064
|
placeholder: "api.example.com",
|
|
906
3065
|
validate: (value) => validateDomain(value ?? "")
|
|
907
3066
|
}));
|
|
908
|
-
const frontendDomain = defaults.frontendDomain ?? await unwrap2(await
|
|
3067
|
+
const frontendDomain = defaults.frontendDomain ?? await unwrap2(await text2({
|
|
909
3068
|
message: "Production frontend domain",
|
|
910
3069
|
placeholder: "app.example.com",
|
|
911
3070
|
validate: (value) => validateDomain(value ?? "")
|
|
912
3071
|
}));
|
|
913
|
-
const haEnabled = defaults.haEnabled ?? await unwrap2(await
|
|
3072
|
+
const haEnabled = defaults.haEnabled ?? await unwrap2(await confirm2({
|
|
914
3073
|
message: "Enable the higher-availability profile?",
|
|
915
3074
|
initialValue: false
|
|
916
3075
|
}));
|
|
@@ -1129,11 +3288,92 @@ async function applyDeploymentSelection2(repositoryRoot, projectName, selection)
|
|
|
1129
3288
|
// src/scaffold.ts
|
|
1130
3289
|
import { execFile } from "node:child_process";
|
|
1131
3290
|
import { createHash } from "node:crypto";
|
|
1132
|
-
import { cp, lstat, mkdir as mkdir4, mkdtemp, readFile as readFile5, readdir, rm as
|
|
3291
|
+
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
3292
|
import { tmpdir } from "node:os";
|
|
1134
|
-
import { basename, join as
|
|
3293
|
+
import { basename, join as join7, relative, resolve as resolve3 } from "node:path";
|
|
1135
3294
|
import { promisify } from "node:util";
|
|
1136
3295
|
|
|
3296
|
+
// src/delivery.ts
|
|
3297
|
+
import { createWriteStream } from "node:fs";
|
|
3298
|
+
import { rm as rm3 } from "node:fs/promises";
|
|
3299
|
+
import { join as join6 } from "node:path";
|
|
3300
|
+
import { Readable } from "node:stream";
|
|
3301
|
+
import { pipeline } from "node:stream/promises";
|
|
3302
|
+
var RELEASE_TAG_PATTERN2 = /^v\d+\.\d+\.\d+(?:-rc\.\d+)?$/;
|
|
3303
|
+
var INDEX_TIMEOUT_MS = 15000;
|
|
3304
|
+
var DOWNLOAD_TIMEOUT_MS = 300000;
|
|
3305
|
+
function deliveryBaseUrl(environment = process.env) {
|
|
3306
|
+
const configured = environment[DELIVERY_URL_VARIABLE]?.trim();
|
|
3307
|
+
return (configured || DELIVERY_BASE_URL).replace(/\/+$/, "");
|
|
3308
|
+
}
|
|
3309
|
+
function releaseAssetNames(releaseTag) {
|
|
3310
|
+
const artifact = `foundation-source-${releaseTag}.tar.gz`;
|
|
3311
|
+
return {
|
|
3312
|
+
artifact,
|
|
3313
|
+
checksum: `${artifact}.sha256`,
|
|
3314
|
+
manifest: `foundation-source-${releaseTag}.manifest.json`
|
|
3315
|
+
};
|
|
3316
|
+
}
|
|
3317
|
+
function describeFailure(status, subject) {
|
|
3318
|
+
if (status === 401) {
|
|
3319
|
+
return "That licence key was not accepted. Copy it exactly from your purchase receipt or the customer portal (polar.sh).";
|
|
3320
|
+
}
|
|
3321
|
+
if (status === 429) {
|
|
3322
|
+
return "Too many download requests for this licence key. Wait a minute and try again.";
|
|
3323
|
+
}
|
|
3324
|
+
if (status === 404)
|
|
3325
|
+
return `${subject} is not available for download.`;
|
|
3326
|
+
if (status >= 500) {
|
|
3327
|
+
return "Source delivery is temporarily unavailable. Wait a few minutes and try again.";
|
|
3328
|
+
}
|
|
3329
|
+
return `Source delivery refused the request (HTTP ${status}).`;
|
|
3330
|
+
}
|
|
3331
|
+
async function requestDelivery(url, init, subject) {
|
|
3332
|
+
let response;
|
|
3333
|
+
try {
|
|
3334
|
+
response = await fetch(url, init);
|
|
3335
|
+
} catch {
|
|
3336
|
+
throw new Error("Could not reach source delivery. Check your network connection and try again.");
|
|
3337
|
+
}
|
|
3338
|
+
if (!response.ok)
|
|
3339
|
+
throw new Error(describeFailure(response.status, subject));
|
|
3340
|
+
return response;
|
|
3341
|
+
}
|
|
3342
|
+
async function resolveRelease(licenseKey, baseUrl = deliveryBaseUrl()) {
|
|
3343
|
+
const response = await requestDelivery(`${baseUrl}/v1/releases`, {
|
|
3344
|
+
method: "POST",
|
|
3345
|
+
headers: { "content-type": "application/json" },
|
|
3346
|
+
body: JSON.stringify({ key: licenseKey }),
|
|
3347
|
+
signal: AbortSignal.timeout(INDEX_TIMEOUT_MS)
|
|
3348
|
+
}, "The release index");
|
|
3349
|
+
let index;
|
|
3350
|
+
try {
|
|
3351
|
+
index = await response.json();
|
|
3352
|
+
} catch {
|
|
3353
|
+
index = undefined;
|
|
3354
|
+
}
|
|
3355
|
+
if (!index || !RELEASE_TAG_PATTERN2.test(index.latest) || !Array.isArray(index.versions)) {
|
|
3356
|
+
throw new Error(`Source delivery returned an unreadable release index.`);
|
|
3357
|
+
}
|
|
3358
|
+
return index;
|
|
3359
|
+
}
|
|
3360
|
+
async function downloadAsset(licenseKey, releaseTag, assetName, directory, baseUrl = deliveryBaseUrl()) {
|
|
3361
|
+
const response = await requestDelivery(`${baseUrl}/v1/source/${encodeURIComponent(releaseTag)}/${encodeURIComponent(assetName)}`, {
|
|
3362
|
+
headers: { authorization: `Bearer ${licenseKey}` },
|
|
3363
|
+
signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS)
|
|
3364
|
+
}, releaseTag);
|
|
3365
|
+
if (!response.body)
|
|
3366
|
+
throw new Error(`Source delivery returned an empty ${assetName}.`);
|
|
3367
|
+
const path = join6(directory, assetName);
|
|
3368
|
+
try {
|
|
3369
|
+
await pipeline(Readable.fromWeb(response.body), createWriteStream(path));
|
|
3370
|
+
} catch {
|
|
3371
|
+
await rm3(path, { force: true });
|
|
3372
|
+
throw new Error(`Downloading ${assetName} was interrupted. Try again in a few minutes.`);
|
|
3373
|
+
}
|
|
3374
|
+
return path;
|
|
3375
|
+
}
|
|
3376
|
+
|
|
1137
3377
|
// src/core.ts
|
|
1138
3378
|
import { randomBytes } from "node:crypto";
|
|
1139
3379
|
import { extname } from "node:path";
|
|
@@ -1364,6 +3604,56 @@ into this repository.
|
|
|
1364
3604
|
}
|
|
1365
3605
|
return rewritten;
|
|
1366
3606
|
}
|
|
3607
|
+
var REQUIRED_BUYER_CLI_CONSTANTS = ["CLI_NAME", "CLI_PACKAGE_NAME", "DEFAULT_SCOPE"];
|
|
3608
|
+
function rewriteBuyerCliConstants(content, scope, brandName) {
|
|
3609
|
+
const buyerVariablePrefix = BUYER_CLI_NAME.toUpperCase().replaceAll("-", "_");
|
|
3610
|
+
const buyerConstants = [
|
|
3611
|
+
["CLI_NAME", BUYER_CLI_NAME],
|
|
3612
|
+
["CLI_PACKAGE_NAME", BUYER_CLI_PACKAGE_NAME],
|
|
3613
|
+
["DEFAULT_SCOPE", normalizeScope2(scope)],
|
|
3614
|
+
["SOURCE_BRAND_NAME", brandName],
|
|
3615
|
+
["TEMPLATE_REPOSITORY", "OWNER/REPOSITORY"],
|
|
3616
|
+
["DELIVERY_BASE_URL", "https://releases.example.com"],
|
|
3617
|
+
["DELIVERY_URL_VARIABLE", `${buyerVariablePrefix}_DELIVERY_URL`],
|
|
3618
|
+
["LICENSE_KEY_VARIABLE", `${buyerVariablePrefix}_LICENSE_KEY`],
|
|
3619
|
+
["LICENSE_KEY_PREFIX", "LICENSE-"]
|
|
3620
|
+
];
|
|
3621
|
+
let rewritten = content;
|
|
3622
|
+
for (const [name, value] of buyerConstants) {
|
|
3623
|
+
const declaration = new RegExp(`^export const ${name} = '[^']*'$`, "m");
|
|
3624
|
+
if (!declaration.test(rewritten)) {
|
|
3625
|
+
if (REQUIRED_BUYER_CLI_CONSTANTS.includes(name)) {
|
|
3626
|
+
throw new Error(`Source CLI constants are missing ${name}.`);
|
|
3627
|
+
}
|
|
3628
|
+
continue;
|
|
3629
|
+
}
|
|
3630
|
+
rewritten = rewritten.replace(declaration, `export const ${name} = '${value}'`);
|
|
3631
|
+
}
|
|
3632
|
+
const leaked = [
|
|
3633
|
+
CLI_PACKAGE_NAME,
|
|
3634
|
+
SOURCE_BRAND_NAME,
|
|
3635
|
+
DELIVERY_BASE_URL,
|
|
3636
|
+
DELIVERY_URL_VARIABLE,
|
|
3637
|
+
LICENSE_KEY_VARIABLE2,
|
|
3638
|
+
LICENSE_KEY_PREFIX
|
|
3639
|
+
].filter((identity) => rewritten.includes(identity));
|
|
3640
|
+
if (leaked.length > 0) {
|
|
3641
|
+
throw new Error(`Buyer CLI constants still name the source product: ${leaked.join(", ")}`);
|
|
3642
|
+
}
|
|
3643
|
+
return rewritten;
|
|
3644
|
+
}
|
|
3645
|
+
var SELLER_ONLY_ROOT_SCRIPTS = [
|
|
3646
|
+
"release:distribute",
|
|
3647
|
+
"release:publish-cli",
|
|
3648
|
+
"release:upload"
|
|
3649
|
+
];
|
|
3650
|
+
function stripSellerOnlyRootScripts(content) {
|
|
3651
|
+
const manifest = JSON.parse(content);
|
|
3652
|
+
for (const script of SELLER_ONLY_ROOT_SCRIPTS)
|
|
3653
|
+
delete manifest.scripts?.[script];
|
|
3654
|
+
return `${JSON.stringify(manifest, null, 2)}
|
|
3655
|
+
`;
|
|
3656
|
+
}
|
|
1367
3657
|
function rewriteBuyerClaudeInstructions(content) {
|
|
1368
3658
|
if (!/internal\/|landing\/|studio-owned/i.test(content))
|
|
1369
3659
|
return content;
|
|
@@ -1426,6 +3716,8 @@ function isTemplatePathExcluded(relativePath) {
|
|
|
1426
3716
|
return true;
|
|
1427
3717
|
if (normalized === "internal" || normalized.startsWith("internal/"))
|
|
1428
3718
|
return true;
|
|
3719
|
+
if (normalized === ".github/workflows/internal-commercial.yml")
|
|
3720
|
+
return true;
|
|
1429
3721
|
if (normalized === "apps/worker" || normalized.startsWith("apps/worker/"))
|
|
1430
3722
|
return true;
|
|
1431
3723
|
if (parts.includes("dist") || parts.includes("out"))
|
|
@@ -1491,7 +3783,7 @@ async function copyLocalTemplate(source, target) {
|
|
|
1491
3783
|
async function assertNoSymbolicLinks(directory, root = directory, skipExcludedPaths = false) {
|
|
1492
3784
|
const entries = await readdir(directory, { withFileTypes: true });
|
|
1493
3785
|
for (const entry of entries) {
|
|
1494
|
-
const path =
|
|
3786
|
+
const path = join7(directory, entry.name);
|
|
1495
3787
|
const relativePath = relative(root, path);
|
|
1496
3788
|
if (skipExcludedPaths && isTemplatePathExcluded(relativePath))
|
|
1497
3789
|
continue;
|
|
@@ -1514,57 +3806,33 @@ function verifyReleaseMetadata(checksum, manifest, artifactName, digest, templat
|
|
|
1514
3806
|
throw new Error(`${CLI_NAME2} release manifest does not match the downloaded source artifact.`);
|
|
1515
3807
|
}
|
|
1516
3808
|
}
|
|
1517
|
-
async function
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
"--repo",
|
|
1524
|
-
TEMPLATE_REPOSITORY,
|
|
1525
|
-
"--pattern",
|
|
1526
|
-
fileName,
|
|
1527
|
-
"--dir",
|
|
1528
|
-
directory
|
|
1529
|
-
]);
|
|
1530
|
-
} catch {
|
|
1531
|
-
throw new Error(`Unable to download ${templateRef}. Confirm that GitHub CLI is installed, run ` + `\`gh auth login\`, and accept your ${CLI_NAME2} repository invitation.`);
|
|
1532
|
-
}
|
|
1533
|
-
}
|
|
1534
|
-
async function downloadGitHubTemplate(target, templateRef) {
|
|
1535
|
-
if (!/^v\d+\.\d+\.\d+(?:-rc\.\d+)?$/.test(templateRef)) {
|
|
1536
|
-
throw new Error(`${CLI_NAME2} template reference must be an immutable release tag: ${templateRef}`);
|
|
1537
|
-
}
|
|
1538
|
-
const temporaryDirectory = await mkdtemp(join6(tmpdir(), `${CLI_NAME2}-`));
|
|
1539
|
-
const artifactName = `foundation-source-${templateRef}.tar.gz`;
|
|
1540
|
-
const checksumName = `${artifactName}.sha256`;
|
|
1541
|
-
const manifestName = `foundation-source-${templateRef}.manifest.json`;
|
|
1542
|
-
const archivePath = join6(temporaryDirectory, artifactName);
|
|
1543
|
-
const extractedPath = join6(temporaryDirectory, "template");
|
|
3809
|
+
async function downloadLicensedTemplate(target, licenseKey, sourceVersion) {
|
|
3810
|
+
const baseUrl = deliveryBaseUrl();
|
|
3811
|
+
const releaseTag = sourceVersion ?? (await resolveRelease(licenseKey, baseUrl)).latest;
|
|
3812
|
+
const { artifact, checksum: checksumName, manifest: manifestName } = releaseAssetNames(releaseTag);
|
|
3813
|
+
const temporaryDirectory = await mkdtemp(join7(tmpdir(), `${CLI_NAME2}-`));
|
|
3814
|
+
const extractedPath = join7(temporaryDirectory, "template");
|
|
1544
3815
|
try {
|
|
1545
|
-
await
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
await downloadReleaseAsset(templateRef, artifactName, temporaryDirectory);
|
|
1549
|
-
await downloadReleaseAsset(templateRef, checksumName, temporaryDirectory);
|
|
1550
|
-
await downloadReleaseAsset(templateRef, manifestName, temporaryDirectory);
|
|
3816
|
+
const archivePath = await downloadAsset(licenseKey, releaseTag, artifact, temporaryDirectory, baseUrl);
|
|
3817
|
+
await downloadAsset(licenseKey, releaseTag, checksumName, temporaryDirectory, baseUrl);
|
|
3818
|
+
await downloadAsset(licenseKey, releaseTag, manifestName, temporaryDirectory, baseUrl);
|
|
1551
3819
|
const archive = await readFile5(archivePath);
|
|
1552
3820
|
const digest = createHash("sha256").update(archive).digest("hex");
|
|
1553
|
-
const checksum = await readFile5(
|
|
1554
|
-
const manifest = JSON.parse(await readFile5(
|
|
1555
|
-
verifyReleaseMetadata(checksum, manifest,
|
|
3821
|
+
const checksum = await readFile5(join7(temporaryDirectory, checksumName), "utf8");
|
|
3822
|
+
const manifest = JSON.parse(await readFile5(join7(temporaryDirectory, manifestName), "utf8"));
|
|
3823
|
+
verifyReleaseMetadata(checksum, manifest, artifact, digest, releaseTag);
|
|
1556
3824
|
await mkdir4(extractedPath);
|
|
1557
3825
|
await execFileAsync("tar", ["-xzf", archivePath, "-C", extractedPath, "--strip-components=1"]);
|
|
1558
3826
|
await copyLocalTemplate(extractedPath, target);
|
|
1559
3827
|
} finally {
|
|
1560
|
-
await
|
|
3828
|
+
await rm4(temporaryDirectory, { recursive: true, force: true });
|
|
1561
3829
|
}
|
|
1562
3830
|
}
|
|
1563
3831
|
async function walk(directory) {
|
|
1564
3832
|
const entries = await readdir(directory, { withFileTypes: true });
|
|
1565
3833
|
const paths = [];
|
|
1566
3834
|
for (const entry of entries) {
|
|
1567
|
-
const path =
|
|
3835
|
+
const path = join7(directory, entry.name);
|
|
1568
3836
|
if (entry.isSymbolicLink()) {
|
|
1569
3837
|
throw new Error(`Generated template contains a symbolic link: ${path}`);
|
|
1570
3838
|
}
|
|
@@ -1606,7 +3874,7 @@ async function applyScopeRewrite(target, scope) {
|
|
|
1606
3874
|
async function applyBrandRewrite(target, brandName) {
|
|
1607
3875
|
const report = { files: 0, replacements: 0 };
|
|
1608
3876
|
for (const entry of BRAND_MANIFEST) {
|
|
1609
|
-
const path =
|
|
3877
|
+
const path = join7(target, entry.path);
|
|
1610
3878
|
const replacements = await rewriteFile(path, (content) => {
|
|
1611
3879
|
const result = rewriteBrandContent(content, brandName);
|
|
1612
3880
|
if (result.replacements > 0 && path.endsWith(".tsx")) {
|
|
@@ -1621,25 +3889,27 @@ async function applyBrandRewrite(target, brandName) {
|
|
|
1621
3889
|
return report;
|
|
1622
3890
|
}
|
|
1623
3891
|
async function generateEnvironmentFiles(target, databasePort = 5432) {
|
|
1624
|
-
const serverExample = await readFile5(
|
|
1625
|
-
await writeFile4(
|
|
1626
|
-
const webExample = await readFile5(
|
|
1627
|
-
await writeFile4(
|
|
1628
|
-
const docsExample = await readFile5(
|
|
1629
|
-
await writeFile4(
|
|
1630
|
-
await writeFile4(
|
|
3892
|
+
const serverExample = await readFile5(join7(target, "apps/server/.env.example"), "utf8");
|
|
3893
|
+
await writeFile4(join7(target, "apps/server/.env"), generateServerEnv(serverExample, undefined, databasePort));
|
|
3894
|
+
const webExample = await readFile5(join7(target, "apps/web/.env.example"), "utf8");
|
|
3895
|
+
await writeFile4(join7(target, "apps/web/.env"), webExample);
|
|
3896
|
+
const docsExample = await readFile5(join7(target, "apps/docs/.env.example"), "utf8");
|
|
3897
|
+
await writeFile4(join7(target, "apps/docs/.env"), docsExample);
|
|
3898
|
+
await writeFile4(join7(target, ".env"), `POSTGRES_PORT=${databasePort}
|
|
1631
3899
|
`);
|
|
1632
3900
|
}
|
|
1633
3901
|
async function neutralizeAgentInstructions(target) {
|
|
1634
|
-
const agentPath =
|
|
1635
|
-
const claudePath =
|
|
3902
|
+
const agentPath = join7(target, "AGENTS.md");
|
|
3903
|
+
const claudePath = join7(target, "CLAUDE.md");
|
|
1636
3904
|
await writeFile4(agentPath, rewriteBuyerAgentInstructions(await readFile5(agentPath, "utf8")));
|
|
1637
3905
|
await writeFile4(claudePath, rewriteBuyerClaudeInstructions(await readFile5(claudePath, "utf8")));
|
|
3906
|
+
const rootPackagePath = join7(target, "package.json");
|
|
3907
|
+
await writeFile4(rootPackagePath, stripSellerOnlyRootScripts(await readFile5(rootPackagePath, "utf8")));
|
|
1638
3908
|
}
|
|
1639
3909
|
async function neutralizeSourceCli(target, scope, brandName) {
|
|
1640
3910
|
if (String(CLI_NAME2) === BUYER_CLI_NAME && String(CLI_PACKAGE_NAME) === BUYER_CLI_PACKAGE_NAME)
|
|
1641
3911
|
return;
|
|
1642
|
-
const rootPackagePath =
|
|
3912
|
+
const rootPackagePath = join7(target, "package.json");
|
|
1643
3913
|
const rootPackage = JSON.parse(await readFile5(rootPackagePath, "utf8"));
|
|
1644
3914
|
const sourceScript = rootPackage.scripts?.[CLI_NAME2];
|
|
1645
3915
|
if (!sourceScript)
|
|
@@ -1648,7 +3918,7 @@ async function neutralizeSourceCli(target, scope, brandName) {
|
|
|
1648
3918
|
delete rootPackage.scripts[CLI_NAME2];
|
|
1649
3919
|
await writeFile4(rootPackagePath, `${JSON.stringify(rootPackage, null, 2)}
|
|
1650
3920
|
`);
|
|
1651
|
-
const cliPackagePath =
|
|
3921
|
+
const cliPackagePath = join7(target, "packages/create-app/package.json");
|
|
1652
3922
|
const cliPackage = JSON.parse(await readFile5(cliPackagePath, "utf8"));
|
|
1653
3923
|
if (cliPackage.name !== CLI_PACKAGE_NAME || !cliPackage.bin?.[CLI_NAME2]) {
|
|
1654
3924
|
throw new Error(`Source CLI package must expose ${CLI_PACKAGE_NAME} as ${CLI_NAME2}.`);
|
|
@@ -1656,6 +3926,8 @@ async function neutralizeSourceCli(target, scope, brandName) {
|
|
|
1656
3926
|
cliPackage.bin = { [BUYER_CLI_NAME]: "./src/cli.ts" };
|
|
1657
3927
|
delete cliPackage.description;
|
|
1658
3928
|
delete cliPackage.homepage;
|
|
3929
|
+
delete cliPackage.bugs;
|
|
3930
|
+
delete cliPackage.author;
|
|
1659
3931
|
delete cliPackage.repository;
|
|
1660
3932
|
delete cliPackage.keywords;
|
|
1661
3933
|
delete cliPackage.files;
|
|
@@ -1663,23 +3935,14 @@ async function neutralizeSourceCli(target, scope, brandName) {
|
|
|
1663
3935
|
const { name: _sourceName, version: cliVersion, ...cliPackageRemainder } = cliPackage;
|
|
1664
3936
|
await writeFile4(cliPackagePath, `${JSON.stringify({ name: BUYER_CLI_PACKAGE_NAME, version: cliVersion, private: true, ...cliPackageRemainder }, null, 2)}
|
|
1665
3937
|
`);
|
|
1666
|
-
const constantsPath =
|
|
1667
|
-
|
|
1668
|
-
const
|
|
1669
|
-
const packageDeclaration = `export const CLI_PACKAGE_NAME = '${CLI_PACKAGE_NAME}'`;
|
|
1670
|
-
const scopeDeclaration = `export const DEFAULT_SCOPE = '@app'`;
|
|
1671
|
-
const repositoryDeclaration = `export const TEMPLATE_REPOSITORY = '${TEMPLATE_REPOSITORY}'`;
|
|
1672
|
-
const brandDeclaration = `export const SOURCE_BRAND_NAME = '${SOURCE_BRAND_NAME}'`;
|
|
1673
|
-
if (!constants3.includes(cliDeclaration) || !constants3.includes(packageDeclaration) || !constants3.includes(scopeDeclaration) || !constants3.includes(repositoryDeclaration) || !constants3.includes(brandDeclaration)) {
|
|
1674
|
-
throw new Error("Source CLI constants do not match the package identity.");
|
|
1675
|
-
}
|
|
1676
|
-
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}'`));
|
|
1677
|
-
const brandingPath = join6(target, "docs/golden-paths/customize-branding-design-tokens.md");
|
|
3938
|
+
const constantsPath = join7(target, "packages/create-app/src/constants.ts");
|
|
3939
|
+
await writeFile4(constantsPath, rewriteBuyerCliConstants(await readFile5(constantsPath, "utf8"), scope, brandName));
|
|
3940
|
+
const brandingPath = join7(target, "docs/golden-paths/customize-branding-design-tokens.md");
|
|
1678
3941
|
const branding = await readFile5(brandingPath, "utf8");
|
|
1679
3942
|
await writeFile4(brandingPath, branding.replaceAll(`pnpm ${CLI_NAME2}`, `pnpm ${BUYER_CLI_NAME}`));
|
|
1680
|
-
const setupPath =
|
|
3943
|
+
const setupPath = join7(target, "docs/setup.md");
|
|
1681
3944
|
await writeFile4(setupPath, rewriteBuyerSetupInstructions(await readFile5(setupPath, "utf8")));
|
|
1682
|
-
const releasesPath =
|
|
3945
|
+
const releasesPath = join7(target, "docs/releases.md");
|
|
1683
3946
|
await writeFile4(releasesPath, rewriteBuyerReleaseInstructions(await readFile5(releasesPath, "utf8")));
|
|
1684
3947
|
}
|
|
1685
3948
|
async function initializeRepository(target) {
|
|
@@ -1701,12 +3964,12 @@ async function scaffold(options) {
|
|
|
1701
3964
|
try {
|
|
1702
3965
|
if (options.from)
|
|
1703
3966
|
await copyLocalTemplate(options.from, target);
|
|
1704
|
-
else if (options.
|
|
1705
|
-
await
|
|
1706
|
-
else {
|
|
1707
|
-
throw new Error(`A local source path or
|
|
3967
|
+
else if (options.licenseKey) {
|
|
3968
|
+
await downloadLicensedTemplate(target, options.licenseKey, options.sourceVersion);
|
|
3969
|
+
} else {
|
|
3970
|
+
throw new Error(`A local source path or a ${CLI_NAME2} licence key is required.`);
|
|
1708
3971
|
}
|
|
1709
|
-
const packagePath =
|
|
3972
|
+
const packagePath = join7(target, "package.json");
|
|
1710
3973
|
const packageReplacements = await rewriteFile(packagePath, (content) => rewriteRootPackageName(content, options.appName));
|
|
1711
3974
|
const scope = await applyScopeRewrite(target, options.scope);
|
|
1712
3975
|
await neutralizeAgentInstructions(target);
|
|
@@ -1727,7 +3990,7 @@ async function scaffold(options) {
|
|
|
1727
3990
|
}))?.isDirectory()) {
|
|
1728
3991
|
const entries = await readdir(target);
|
|
1729
3992
|
if (entries.length === 0)
|
|
1730
|
-
await
|
|
3993
|
+
await rm4(target, { recursive: true, force: true });
|
|
1731
3994
|
}
|
|
1732
3995
|
throw error;
|
|
1733
3996
|
}
|
|
@@ -1744,6 +4007,8 @@ function usage() {
|
|
|
1744
4007
|
Create a buyer-owned SaaS application from your licensed ${suggestBrandName(CLI_NAME)} release.
|
|
1745
4008
|
|
|
1746
4009
|
Options:
|
|
4010
|
+
--license-key <key> Licence key from your purchase (or set ${LICENSE_KEY_VARIABLE})
|
|
4011
|
+
--source-version <version> Pin an immutable release (default: the latest you are entitled to)
|
|
1747
4012
|
--from <path> Use a local source checkout (maintainer/testing)
|
|
1748
4013
|
--scope <namespace> Advanced workspace namespace override (default: derived from brand)
|
|
1749
4014
|
--brand <name> Display name (default: derived from app name)
|
|
@@ -1788,7 +4053,11 @@ function parseArguments(argv) {
|
|
|
1788
4053
|
const argument = argv[index];
|
|
1789
4054
|
if (argument === "--from")
|
|
1790
4055
|
parsed.from = takeValue3(argv, index++, argument);
|
|
1791
|
-
else if (argument === "--
|
|
4056
|
+
else if (argument === "--license-key")
|
|
4057
|
+
parsed.licenseKey = takeValue3(argv, index++, argument);
|
|
4058
|
+
else if (argument === "--source-version") {
|
|
4059
|
+
parsed.sourceVersion = normalizeSourceVersion(takeValue3(argv, index++, argument));
|
|
4060
|
+
} else if (argument === "--scope")
|
|
1792
4061
|
parsed.scope = takeValue3(argv, index++, argument);
|
|
1793
4062
|
else if (argument === "--brand")
|
|
1794
4063
|
parsed.brandName = takeValue3(argv, index++, argument);
|
|
@@ -1856,28 +4125,60 @@ function suggestScope(brandName, fallbackAppName) {
|
|
|
1856
4125
|
return namespace || fallbackAppName;
|
|
1857
4126
|
}
|
|
1858
4127
|
async function unwrapPrompt(value) {
|
|
1859
|
-
if (
|
|
1860
|
-
|
|
4128
|
+
if (isCancel(value)) {
|
|
4129
|
+
cancel("No project was created.");
|
|
1861
4130
|
throw new CliCancelled;
|
|
1862
4131
|
}
|
|
1863
4132
|
return value;
|
|
1864
4133
|
}
|
|
4134
|
+
function describeTargetConflict(appName) {
|
|
4135
|
+
const target = resolve4(process.cwd(), appName);
|
|
4136
|
+
if (!existsSync(target))
|
|
4137
|
+
return;
|
|
4138
|
+
if (!statSync(target).isDirectory())
|
|
4139
|
+
return `./${appName} already exists as a file.`;
|
|
4140
|
+
if (readdirSync(target).length > 0) {
|
|
4141
|
+
return `./${appName} already exists and is not empty. Pick another name, or remove it first.`;
|
|
4142
|
+
}
|
|
4143
|
+
return;
|
|
4144
|
+
}
|
|
4145
|
+
async function collectLicenseKey(parsed) {
|
|
4146
|
+
const supplied = parsed.licenseKey?.trim() ?? readLicenseKeyFromEnvironment();
|
|
4147
|
+
if (supplied) {
|
|
4148
|
+
const error = validateLicenseKey(supplied);
|
|
4149
|
+
if (error)
|
|
4150
|
+
throw new Error(error);
|
|
4151
|
+
return supplied.trim();
|
|
4152
|
+
}
|
|
4153
|
+
if (parsed.yes || !process.stdin.isTTY) {
|
|
4154
|
+
throw new Error(`A licence key is required. Pass --license-key or set ${LICENSE_KEY_VARIABLE}.`);
|
|
4155
|
+
}
|
|
4156
|
+
const entered = await unwrapPrompt(await password({
|
|
4157
|
+
message: "Licence key",
|
|
4158
|
+
validate: (value) => validateLicenseKey(value ?? "")
|
|
4159
|
+
}));
|
|
4160
|
+
return entered.trim();
|
|
4161
|
+
}
|
|
1865
4162
|
async function collectOptions(parsed) {
|
|
1866
4163
|
if (parsed.yes && !parsed.appName)
|
|
1867
4164
|
throw new Error("Pass an app name when using --yes.");
|
|
1868
4165
|
if (!parsed.yes && !process.stdin.isTTY && !parsed.appName) {
|
|
1869
4166
|
throw new Error("Interactive prompts need a terminal. Pass an app name and --yes instead.");
|
|
1870
4167
|
}
|
|
1871
|
-
const appName = parsed.appName ?? await unwrapPrompt(await
|
|
4168
|
+
const appName = parsed.appName ?? await unwrapPrompt(await text({
|
|
1872
4169
|
message: "App name",
|
|
1873
4170
|
placeholder: "my-saas",
|
|
1874
|
-
validate: (value) => validateAppName(value ?? "")
|
|
4171
|
+
validate: (value) => validateAppName(value ?? "") ?? describeTargetConflict(value ?? "")
|
|
1875
4172
|
}));
|
|
1876
4173
|
const appNameError = validateAppName(appName);
|
|
1877
4174
|
if (appNameError)
|
|
1878
4175
|
throw new Error(appNameError);
|
|
4176
|
+
const targetConflict = describeTargetConflict(appName);
|
|
4177
|
+
if (targetConflict)
|
|
4178
|
+
throw new Error(targetConflict);
|
|
4179
|
+
const licenseKey = parsed.from ? undefined : await collectLicenseKey(parsed);
|
|
1879
4180
|
const suggestedBrand = suggestBrandName(appName);
|
|
1880
|
-
const brandName = parsed.brandName ?? (parsed.yes ? suggestedBrand : await unwrapPrompt(await
|
|
4181
|
+
const brandName = parsed.brandName ?? (parsed.yes ? suggestedBrand : await unwrapPrompt(await text({
|
|
1881
4182
|
message: "Brand name",
|
|
1882
4183
|
placeholder: suggestedBrand,
|
|
1883
4184
|
defaultValue: suggestedBrand,
|
|
@@ -1887,22 +4188,22 @@ async function collectOptions(parsed) {
|
|
|
1887
4188
|
if (brandError)
|
|
1888
4189
|
throw new Error(brandError);
|
|
1889
4190
|
const scope = normalizeScope(parsed.scope ?? suggestScope(brandName, appName));
|
|
1890
|
-
const initializeGit = parsed.initializeGit ?? (parsed.yes ? true : await unwrapPrompt(await
|
|
4191
|
+
const initializeGit = parsed.initializeGit ?? (parsed.yes ? true : await unwrapPrompt(await confirm({
|
|
1891
4192
|
message: "Initialize a Git repository?",
|
|
1892
4193
|
initialValue: true
|
|
1893
4194
|
})));
|
|
1894
|
-
const installDependencies = parsed.installDependencies ?? (parsed.yes ? true : await unwrapPrompt(await
|
|
4195
|
+
const installDependencies = parsed.installDependencies ?? (parsed.yes ? true : await unwrapPrompt(await confirm({
|
|
1895
4196
|
message: "Install dependencies with pnpm?",
|
|
1896
4197
|
initialValue: true
|
|
1897
4198
|
})));
|
|
1898
4199
|
if (parsed.startDevelopment && !installDependencies) {
|
|
1899
4200
|
throw new Error("--start requires dependency installation. Remove --no-install.");
|
|
1900
4201
|
}
|
|
1901
|
-
const startDevelopment = parsed.startDevelopment ?? (parsed.yes || !installDependencies ? false : await unwrapPrompt(await
|
|
4202
|
+
const startDevelopment = parsed.startDevelopment ?? (parsed.yes || !installDependencies ? false : await unwrapPrompt(await confirm({
|
|
1902
4203
|
message: "Start local development now?",
|
|
1903
4204
|
initialValue: true
|
|
1904
4205
|
})));
|
|
1905
|
-
const setupDeployment = parsed.setupDeployment ?? (parsed.yes ? false : await unwrapPrompt(await
|
|
4206
|
+
const setupDeployment = parsed.setupDeployment ?? (parsed.yes ? false : await unwrapPrompt(await confirm({
|
|
1906
4207
|
message: "Set up cloud deployment now?",
|
|
1907
4208
|
initialValue: false
|
|
1908
4209
|
})));
|
|
@@ -1910,6 +4211,8 @@ async function collectOptions(parsed) {
|
|
|
1910
4211
|
return {
|
|
1911
4212
|
appName,
|
|
1912
4213
|
from: parsed.from ? resolve4(parsed.from) : undefined,
|
|
4214
|
+
licenseKey,
|
|
4215
|
+
sourceVersion: parsed.sourceVersion,
|
|
1913
4216
|
scope,
|
|
1914
4217
|
brandName,
|
|
1915
4218
|
initializeGit,
|
|
@@ -1924,15 +4227,6 @@ async function readCliVersion() {
|
|
|
1924
4227
|
throw new Error(`${CLI_NAME} package version is missing.`);
|
|
1925
4228
|
return packageJson.version;
|
|
1926
4229
|
}
|
|
1927
|
-
function templateRefForVersion(version) {
|
|
1928
|
-
if (!/^\d+\.\d+\.\d+(?:-rc\.\d+)?$/.test(version)) {
|
|
1929
|
-
throw new Error(`${CLI_NAME} package version is not release-compatible: ${version}`);
|
|
1930
|
-
}
|
|
1931
|
-
if (version === "0.0.0") {
|
|
1932
|
-
throw new Error(`This pre-release ${CLI_NAME} checkout requires --from <local-source-path>.`);
|
|
1933
|
-
}
|
|
1934
|
-
return `v${version}`;
|
|
1935
|
-
}
|
|
1936
4230
|
async function assertTargetAvailable(target) {
|
|
1937
4231
|
const targetStat = await stat5(target).catch(() => {
|
|
1938
4232
|
return;
|
|
@@ -1994,8 +4288,8 @@ function assertSiblingTarget(source, target) {
|
|
|
1994
4288
|
throw new Error(`Create the new app beside the ${CLI_NAME} source checkout, not inside it.`);
|
|
1995
4289
|
}
|
|
1996
4290
|
}
|
|
1997
|
-
function commandFailureOutput(
|
|
1998
|
-
const output = (stderr.trim() ||
|
|
4291
|
+
function commandFailureOutput(stdout2, stderr) {
|
|
4292
|
+
const output = (stderr.trim() || stdout2.trim()).split(`
|
|
1999
4293
|
`).slice(-12).join(`
|
|
2000
4294
|
`);
|
|
2001
4295
|
return output ? `
|
|
@@ -2003,39 +4297,36 @@ function commandFailureOutput(stdout, stderr) {
|
|
|
2003
4297
|
${output}` : "";
|
|
2004
4298
|
}
|
|
2005
4299
|
async function installDependencies(target) {
|
|
2006
|
-
const { stdout, stderr, exitCode } = await runCaptured2(["pnpm", "install", "--frozen-lockfile"], {
|
|
4300
|
+
const { stdout: stdout2, stderr, exitCode } = await runCaptured2(["pnpm", "install", "--frozen-lockfile"], {
|
|
2007
4301
|
cwd: target,
|
|
2008
4302
|
env: { ...process.env, CI: "1" }
|
|
2009
4303
|
});
|
|
2010
4304
|
if (exitCode !== 0) {
|
|
2011
|
-
throw new Error(`Dependency installation failed.${commandFailureOutput(
|
|
4305
|
+
throw new Error(`Dependency installation failed.${commandFailureOutput(stdout2, stderr)}`);
|
|
2012
4306
|
}
|
|
2013
4307
|
}
|
|
2014
4308
|
async function runCapturedCommand(command, target) {
|
|
2015
|
-
const { stdout, stderr, exitCode } = await runCaptured2(command, { cwd: target });
|
|
4309
|
+
const { stdout: stdout2, stderr, exitCode } = await runCaptured2(command, { cwd: target });
|
|
2016
4310
|
if (exitCode !== 0) {
|
|
2017
|
-
throw new Error(`${command.join(" ")} failed.${commandFailureOutput(
|
|
4311
|
+
throw new Error(`${command.join(" ")} failed.${commandFailureOutput(stdout2, stderr)}`);
|
|
2018
4312
|
}
|
|
2019
4313
|
}
|
|
4314
|
+
async function occupiedDevelopmentPorts() {
|
|
4315
|
+
const results = await Promise.all([5173, 8000].map(async (port) => ({ port, available: await isPortAvailable(port) })));
|
|
4316
|
+
return results.filter((result) => !result.available).map((result) => result.port);
|
|
4317
|
+
}
|
|
2020
4318
|
async function startDevelopment(target) {
|
|
2021
|
-
const occupiedPorts = (await Promise.all([5173, 8000].map(async (port) => ({
|
|
2022
|
-
port,
|
|
2023
|
-
available: await isPortAvailable(port)
|
|
2024
|
-
})))).filter((result) => !result.available).map((result) => result.port);
|
|
2025
|
-
if (occupiedPorts.length > 0) {
|
|
2026
|
-
throw new Error(`Cannot start development because port ${occupiedPorts.join(", ")} is in use.`);
|
|
2027
|
-
}
|
|
2028
4319
|
await runStep("Starting local Postgres", "Local Postgres is ready", () => runCapturedCommand(["docker", "compose", "up", "-d", "--wait", "postgres"], target));
|
|
2029
|
-
|
|
4320
|
+
log.info(`Web http://localhost:5173
|
|
2030
4321
|
API http://localhost:8000`);
|
|
2031
|
-
|
|
4322
|
+
outro("Development servers are starting. Ctrl+C stops app servers; Postgres stays running.");
|
|
2032
4323
|
const exitCode = await runInherited(["vp", "run", "-r", "--parallel", "dev"], { cwd: target });
|
|
2033
4324
|
if (exitCode !== 0 && exitCode !== 130) {
|
|
2034
4325
|
throw new Error(`Development servers exited with code ${exitCode}.`);
|
|
2035
4326
|
}
|
|
2036
4327
|
}
|
|
2037
4328
|
async function runStep(pending, complete, action, indicator = "dots") {
|
|
2038
|
-
const progress =
|
|
4329
|
+
const progress = spinner({ indicator });
|
|
2039
4330
|
progress.start(pending);
|
|
2040
4331
|
try {
|
|
2041
4332
|
const result = await action();
|
|
@@ -2046,22 +4337,22 @@ async function runStep(pending, complete, action, indicator = "dots") {
|
|
|
2046
4337
|
throw error;
|
|
2047
4338
|
}
|
|
2048
4339
|
}
|
|
2049
|
-
async function createApplication(options
|
|
4340
|
+
async function createApplication(options) {
|
|
2050
4341
|
const target = resolve4(process.cwd(), options.appName);
|
|
2051
4342
|
await assertTargetAvailable(target);
|
|
2052
4343
|
assertSiblingTarget(options.from, target);
|
|
2053
4344
|
const databasePort = await findAvailablePort();
|
|
2054
4345
|
await mkdir5(dirname2(target), { recursive: true });
|
|
2055
|
-
const staging = await mkdtemp2(
|
|
4346
|
+
const staging = await mkdtemp2(join8(dirname2(target), `.${options.appName}-${CLI_NAME}-`));
|
|
2056
4347
|
try {
|
|
2057
|
-
const templateRef = options.from ? undefined : templateRefForVersion(version);
|
|
2058
4348
|
await runStep("Preparing your application", "Application source prepared", () => scaffold({
|
|
2059
4349
|
appName: options.appName,
|
|
2060
4350
|
scope: options.scope,
|
|
2061
4351
|
brandName: options.brandName,
|
|
2062
4352
|
targetDirectory: staging,
|
|
2063
4353
|
from: options.from,
|
|
2064
|
-
|
|
4354
|
+
licenseKey: options.licenseKey,
|
|
4355
|
+
sourceVersion: options.sourceVersion,
|
|
2065
4356
|
initializeGit: options.initializeGit,
|
|
2066
4357
|
databasePort
|
|
2067
4358
|
}));
|
|
@@ -2078,7 +4369,7 @@ async function createApplication(options, version) {
|
|
|
2078
4369
|
await rename2(staging, target);
|
|
2079
4370
|
return { target, databasePort };
|
|
2080
4371
|
} catch (error) {
|
|
2081
|
-
await
|
|
4372
|
+
await rm5(staging, { recursive: true, force: true });
|
|
2082
4373
|
throw error;
|
|
2083
4374
|
}
|
|
2084
4375
|
}
|
|
@@ -2097,6 +4388,11 @@ function completionDetails(target, options, databasePort) {
|
|
|
2097
4388
|
database: `Postgres localhost:${databasePort}`
|
|
2098
4389
|
};
|
|
2099
4390
|
}
|
|
4391
|
+
function printRunnableCommands(commands) {
|
|
4392
|
+
console.log(`
|
|
4393
|
+
${commands}
|
|
4394
|
+
`);
|
|
4395
|
+
}
|
|
2100
4396
|
async function main() {
|
|
2101
4397
|
const argv = process.argv.slice(2);
|
|
2102
4398
|
if (argv[0] === "agent") {
|
|
@@ -2121,32 +4417,40 @@ async function main() {
|
|
|
2121
4417
|
console.log(version);
|
|
2122
4418
|
return;
|
|
2123
4419
|
}
|
|
2124
|
-
|
|
4420
|
+
intro(`${suggestBrandName(CLI_NAME)} ${version} \xB7 production SaaS foundation`);
|
|
2125
4421
|
const options = await collectOptions(parsed);
|
|
2126
|
-
const { target, databasePort } = await createApplication(options
|
|
4422
|
+
const { target, databasePort } = await createApplication(options);
|
|
2127
4423
|
const completion = completionDetails(target, options, databasePort);
|
|
2128
|
-
|
|
4424
|
+
log.success(`Created ${completion.directory}`);
|
|
2129
4425
|
if (!options.startDevelopment) {
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
prompts5.log.info(`Web http://localhost:5173
|
|
4426
|
+
log.step("Run locally");
|
|
4427
|
+
log.info(`Web http://localhost:5173
|
|
2133
4428
|
API http://localhost:8000
|
|
2134
4429
|
${completion.database}`);
|
|
2135
4430
|
if (options.deployment) {
|
|
2136
|
-
|
|
4431
|
+
log.info(`Deployment ${options.deployment.cloud.toUpperCase()} + ${options.deployment.storageProvider} + ${options.deployment.frontendTarget} locked. Review deployment/README.md.`);
|
|
2137
4432
|
} else {
|
|
2138
|
-
|
|
4433
|
+
log.info("Deployment deferred. Run `pnpm deploy:configure` when you are ready.");
|
|
2139
4434
|
}
|
|
2140
|
-
|
|
4435
|
+
outro(`${options.brandName} is ready.`);
|
|
4436
|
+
printRunnableCommands(completion.commands);
|
|
4437
|
+
return;
|
|
4438
|
+
}
|
|
4439
|
+
const occupiedPorts = await occupiedDevelopmentPorts();
|
|
4440
|
+
if (occupiedPorts.length > 0) {
|
|
4441
|
+
log.warn(`Port ${occupiedPorts.join(" and ")} already in use, so the development servers were not started.`);
|
|
4442
|
+
log.step("Free the port, then run");
|
|
4443
|
+
outro(`${options.brandName} is ready at ${completion.directory}.`);
|
|
4444
|
+
printRunnableCommands(completion.commands);
|
|
2141
4445
|
return;
|
|
2142
4446
|
}
|
|
2143
4447
|
try {
|
|
2144
4448
|
await startDevelopment(target);
|
|
2145
4449
|
} catch (error) {
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
4450
|
+
log.error(error instanceof Error ? error.message : String(error));
|
|
4451
|
+
log.step("Start it manually");
|
|
4452
|
+
outro(`${options.brandName} is ready at ${completion.directory}.`);
|
|
4453
|
+
printRunnableCommands(completion.commands);
|
|
2150
4454
|
process.exitCode = 1;
|
|
2151
4455
|
}
|
|
2152
4456
|
}
|
|
@@ -2154,16 +4458,19 @@ if (isEntrypoint(import.meta.url)) {
|
|
|
2154
4458
|
main().catch((error) => {
|
|
2155
4459
|
if (error instanceof CliCancelled)
|
|
2156
4460
|
return;
|
|
2157
|
-
|
|
2158
|
-
|
|
4461
|
+
log.error(error instanceof Error ? error.message : String(error));
|
|
4462
|
+
outro("No project was created.");
|
|
2159
4463
|
process.exitCode = 1;
|
|
2160
4464
|
});
|
|
2161
4465
|
}
|
|
2162
4466
|
export {
|
|
2163
4467
|
usage,
|
|
2164
|
-
templateRefForVersion,
|
|
2165
4468
|
suggestScope,
|
|
2166
4469
|
suggestBrandName,
|
|
4470
|
+
printRunnableCommands,
|
|
2167
4471
|
parseArguments,
|
|
2168
|
-
|
|
4472
|
+
occupiedDevelopmentPorts,
|
|
4473
|
+
findAvailablePort,
|
|
4474
|
+
describeTargetConflict,
|
|
4475
|
+
collectLicenseKey
|
|
2169
4476
|
};
|