superslate 0.2.1 → 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 +2477 -184
- 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,7 +3604,49 @@ into this repository.
|
|
|
1364
3604
|
}
|
|
1365
3605
|
return rewritten;
|
|
1366
3606
|
}
|
|
1367
|
-
var
|
|
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
|
+
];
|
|
1368
3650
|
function stripSellerOnlyRootScripts(content) {
|
|
1369
3651
|
const manifest = JSON.parse(content);
|
|
1370
3652
|
for (const script of SELLER_ONLY_ROOT_SCRIPTS)
|
|
@@ -1434,8 +3716,6 @@ function isTemplatePathExcluded(relativePath) {
|
|
|
1434
3716
|
return true;
|
|
1435
3717
|
if (normalized === "internal" || normalized.startsWith("internal/"))
|
|
1436
3718
|
return true;
|
|
1437
|
-
if (normalized === ".github/workflows/publish-npm.yml")
|
|
1438
|
-
return true;
|
|
1439
3719
|
if (normalized === ".github/workflows/internal-commercial.yml")
|
|
1440
3720
|
return true;
|
|
1441
3721
|
if (normalized === "apps/worker" || normalized.startsWith("apps/worker/"))
|
|
@@ -1503,7 +3783,7 @@ async function copyLocalTemplate(source, target) {
|
|
|
1503
3783
|
async function assertNoSymbolicLinks(directory, root = directory, skipExcludedPaths = false) {
|
|
1504
3784
|
const entries = await readdir(directory, { withFileTypes: true });
|
|
1505
3785
|
for (const entry of entries) {
|
|
1506
|
-
const path =
|
|
3786
|
+
const path = join7(directory, entry.name);
|
|
1507
3787
|
const relativePath = relative(root, path);
|
|
1508
3788
|
if (skipExcludedPaths && isTemplatePathExcluded(relativePath))
|
|
1509
3789
|
continue;
|
|
@@ -1526,57 +3806,33 @@ function verifyReleaseMetadata(checksum, manifest, artifactName, digest, templat
|
|
|
1526
3806
|
throw new Error(`${CLI_NAME2} release manifest does not match the downloaded source artifact.`);
|
|
1527
3807
|
}
|
|
1528
3808
|
}
|
|
1529
|
-
async function
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
"--repo",
|
|
1536
|
-
TEMPLATE_REPOSITORY,
|
|
1537
|
-
"--pattern",
|
|
1538
|
-
fileName,
|
|
1539
|
-
"--dir",
|
|
1540
|
-
directory
|
|
1541
|
-
]);
|
|
1542
|
-
} catch {
|
|
1543
|
-
throw new Error(`Unable to download ${templateRef}. Confirm that GitHub CLI is installed, run ` + `\`gh auth login\`, and accept your ${CLI_NAME2} repository invitation.`);
|
|
1544
|
-
}
|
|
1545
|
-
}
|
|
1546
|
-
async function downloadGitHubTemplate(target, templateRef) {
|
|
1547
|
-
if (!/^v\d+\.\d+\.\d+(?:-rc\.\d+)?$/.test(templateRef)) {
|
|
1548
|
-
throw new Error(`${CLI_NAME2} template reference must be an immutable release tag: ${templateRef}`);
|
|
1549
|
-
}
|
|
1550
|
-
const temporaryDirectory = await mkdtemp(join6(tmpdir(), `${CLI_NAME2}-`));
|
|
1551
|
-
const artifactName = `foundation-source-${templateRef}.tar.gz`;
|
|
1552
|
-
const checksumName = `${artifactName}.sha256`;
|
|
1553
|
-
const manifestName = `foundation-source-${templateRef}.manifest.json`;
|
|
1554
|
-
const archivePath = join6(temporaryDirectory, artifactName);
|
|
1555
|
-
const extractedPath = join6(temporaryDirectory, "template");
|
|
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");
|
|
1556
3815
|
try {
|
|
1557
|
-
await
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
await downloadReleaseAsset(templateRef, artifactName, temporaryDirectory);
|
|
1561
|
-
await downloadReleaseAsset(templateRef, checksumName, temporaryDirectory);
|
|
1562
|
-
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);
|
|
1563
3819
|
const archive = await readFile5(archivePath);
|
|
1564
3820
|
const digest = createHash("sha256").update(archive).digest("hex");
|
|
1565
|
-
const checksum = await readFile5(
|
|
1566
|
-
const manifest = JSON.parse(await readFile5(
|
|
1567
|
-
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);
|
|
1568
3824
|
await mkdir4(extractedPath);
|
|
1569
3825
|
await execFileAsync("tar", ["-xzf", archivePath, "-C", extractedPath, "--strip-components=1"]);
|
|
1570
3826
|
await copyLocalTemplate(extractedPath, target);
|
|
1571
3827
|
} finally {
|
|
1572
|
-
await
|
|
3828
|
+
await rm4(temporaryDirectory, { recursive: true, force: true });
|
|
1573
3829
|
}
|
|
1574
3830
|
}
|
|
1575
3831
|
async function walk(directory) {
|
|
1576
3832
|
const entries = await readdir(directory, { withFileTypes: true });
|
|
1577
3833
|
const paths = [];
|
|
1578
3834
|
for (const entry of entries) {
|
|
1579
|
-
const path =
|
|
3835
|
+
const path = join7(directory, entry.name);
|
|
1580
3836
|
if (entry.isSymbolicLink()) {
|
|
1581
3837
|
throw new Error(`Generated template contains a symbolic link: ${path}`);
|
|
1582
3838
|
}
|
|
@@ -1618,7 +3874,7 @@ async function applyScopeRewrite(target, scope) {
|
|
|
1618
3874
|
async function applyBrandRewrite(target, brandName) {
|
|
1619
3875
|
const report = { files: 0, replacements: 0 };
|
|
1620
3876
|
for (const entry of BRAND_MANIFEST) {
|
|
1621
|
-
const path =
|
|
3877
|
+
const path = join7(target, entry.path);
|
|
1622
3878
|
const replacements = await rewriteFile(path, (content) => {
|
|
1623
3879
|
const result = rewriteBrandContent(content, brandName);
|
|
1624
3880
|
if (result.replacements > 0 && path.endsWith(".tsx")) {
|
|
@@ -1633,27 +3889,27 @@ async function applyBrandRewrite(target, brandName) {
|
|
|
1633
3889
|
return report;
|
|
1634
3890
|
}
|
|
1635
3891
|
async function generateEnvironmentFiles(target, databasePort = 5432) {
|
|
1636
|
-
const serverExample = await readFile5(
|
|
1637
|
-
await writeFile4(
|
|
1638
|
-
const webExample = await readFile5(
|
|
1639
|
-
await writeFile4(
|
|
1640
|
-
const docsExample = await readFile5(
|
|
1641
|
-
await writeFile4(
|
|
1642
|
-
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}
|
|
1643
3899
|
`);
|
|
1644
3900
|
}
|
|
1645
3901
|
async function neutralizeAgentInstructions(target) {
|
|
1646
|
-
const agentPath =
|
|
1647
|
-
const claudePath =
|
|
3902
|
+
const agentPath = join7(target, "AGENTS.md");
|
|
3903
|
+
const claudePath = join7(target, "CLAUDE.md");
|
|
1648
3904
|
await writeFile4(agentPath, rewriteBuyerAgentInstructions(await readFile5(agentPath, "utf8")));
|
|
1649
3905
|
await writeFile4(claudePath, rewriteBuyerClaudeInstructions(await readFile5(claudePath, "utf8")));
|
|
1650
|
-
const rootPackagePath =
|
|
3906
|
+
const rootPackagePath = join7(target, "package.json");
|
|
1651
3907
|
await writeFile4(rootPackagePath, stripSellerOnlyRootScripts(await readFile5(rootPackagePath, "utf8")));
|
|
1652
3908
|
}
|
|
1653
3909
|
async function neutralizeSourceCli(target, scope, brandName) {
|
|
1654
3910
|
if (String(CLI_NAME2) === BUYER_CLI_NAME && String(CLI_PACKAGE_NAME) === BUYER_CLI_PACKAGE_NAME)
|
|
1655
3911
|
return;
|
|
1656
|
-
const rootPackagePath =
|
|
3912
|
+
const rootPackagePath = join7(target, "package.json");
|
|
1657
3913
|
const rootPackage = JSON.parse(await readFile5(rootPackagePath, "utf8"));
|
|
1658
3914
|
const sourceScript = rootPackage.scripts?.[CLI_NAME2];
|
|
1659
3915
|
if (!sourceScript)
|
|
@@ -1662,7 +3918,7 @@ async function neutralizeSourceCli(target, scope, brandName) {
|
|
|
1662
3918
|
delete rootPackage.scripts[CLI_NAME2];
|
|
1663
3919
|
await writeFile4(rootPackagePath, `${JSON.stringify(rootPackage, null, 2)}
|
|
1664
3920
|
`);
|
|
1665
|
-
const cliPackagePath =
|
|
3921
|
+
const cliPackagePath = join7(target, "packages/create-app/package.json");
|
|
1666
3922
|
const cliPackage = JSON.parse(await readFile5(cliPackagePath, "utf8"));
|
|
1667
3923
|
if (cliPackage.name !== CLI_PACKAGE_NAME || !cliPackage.bin?.[CLI_NAME2]) {
|
|
1668
3924
|
throw new Error(`Source CLI package must expose ${CLI_PACKAGE_NAME} as ${CLI_NAME2}.`);
|
|
@@ -1670,6 +3926,8 @@ async function neutralizeSourceCli(target, scope, brandName) {
|
|
|
1670
3926
|
cliPackage.bin = { [BUYER_CLI_NAME]: "./src/cli.ts" };
|
|
1671
3927
|
delete cliPackage.description;
|
|
1672
3928
|
delete cliPackage.homepage;
|
|
3929
|
+
delete cliPackage.bugs;
|
|
3930
|
+
delete cliPackage.author;
|
|
1673
3931
|
delete cliPackage.repository;
|
|
1674
3932
|
delete cliPackage.keywords;
|
|
1675
3933
|
delete cliPackage.files;
|
|
@@ -1677,23 +3935,14 @@ async function neutralizeSourceCli(target, scope, brandName) {
|
|
|
1677
3935
|
const { name: _sourceName, version: cliVersion, ...cliPackageRemainder } = cliPackage;
|
|
1678
3936
|
await writeFile4(cliPackagePath, `${JSON.stringify({ name: BUYER_CLI_PACKAGE_NAME, version: cliVersion, private: true, ...cliPackageRemainder }, null, 2)}
|
|
1679
3937
|
`);
|
|
1680
|
-
const constantsPath =
|
|
1681
|
-
|
|
1682
|
-
const
|
|
1683
|
-
const packageDeclaration = `export const CLI_PACKAGE_NAME = '${CLI_PACKAGE_NAME}'`;
|
|
1684
|
-
const scopeDeclaration = `export const DEFAULT_SCOPE = '@app'`;
|
|
1685
|
-
const repositoryDeclaration = `export const TEMPLATE_REPOSITORY = '${TEMPLATE_REPOSITORY}'`;
|
|
1686
|
-
const brandDeclaration = `export const SOURCE_BRAND_NAME = '${SOURCE_BRAND_NAME}'`;
|
|
1687
|
-
if (!constants3.includes(cliDeclaration) || !constants3.includes(packageDeclaration) || !constants3.includes(scopeDeclaration) || !constants3.includes(repositoryDeclaration) || !constants3.includes(brandDeclaration)) {
|
|
1688
|
-
throw new Error("Source CLI constants do not match the package identity.");
|
|
1689
|
-
}
|
|
1690
|
-
await writeFile4(constantsPath, constants3.replace(cliDeclaration, `export const CLI_NAME = '${BUYER_CLI_NAME}'`).replace(packageDeclaration, `export const CLI_PACKAGE_NAME = '${BUYER_CLI_PACKAGE_NAME}'`).replace(scopeDeclaration, `export const DEFAULT_SCOPE = '${normalizeScope2(scope)}'`).replace(repositoryDeclaration, "export const TEMPLATE_REPOSITORY = 'OWNER/REPOSITORY'").replace(brandDeclaration, `export const SOURCE_BRAND_NAME = '${brandName}'`));
|
|
1691
|
-
const brandingPath = join6(target, "docs/golden-paths/customize-branding-design-tokens.md");
|
|
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");
|
|
1692
3941
|
const branding = await readFile5(brandingPath, "utf8");
|
|
1693
3942
|
await writeFile4(brandingPath, branding.replaceAll(`pnpm ${CLI_NAME2}`, `pnpm ${BUYER_CLI_NAME}`));
|
|
1694
|
-
const setupPath =
|
|
3943
|
+
const setupPath = join7(target, "docs/setup.md");
|
|
1695
3944
|
await writeFile4(setupPath, rewriteBuyerSetupInstructions(await readFile5(setupPath, "utf8")));
|
|
1696
|
-
const releasesPath =
|
|
3945
|
+
const releasesPath = join7(target, "docs/releases.md");
|
|
1697
3946
|
await writeFile4(releasesPath, rewriteBuyerReleaseInstructions(await readFile5(releasesPath, "utf8")));
|
|
1698
3947
|
}
|
|
1699
3948
|
async function initializeRepository(target) {
|
|
@@ -1715,12 +3964,12 @@ async function scaffold(options) {
|
|
|
1715
3964
|
try {
|
|
1716
3965
|
if (options.from)
|
|
1717
3966
|
await copyLocalTemplate(options.from, target);
|
|
1718
|
-
else if (options.
|
|
1719
|
-
await
|
|
1720
|
-
else {
|
|
1721
|
-
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.`);
|
|
1722
3971
|
}
|
|
1723
|
-
const packagePath =
|
|
3972
|
+
const packagePath = join7(target, "package.json");
|
|
1724
3973
|
const packageReplacements = await rewriteFile(packagePath, (content) => rewriteRootPackageName(content, options.appName));
|
|
1725
3974
|
const scope = await applyScopeRewrite(target, options.scope);
|
|
1726
3975
|
await neutralizeAgentInstructions(target);
|
|
@@ -1741,7 +3990,7 @@ async function scaffold(options) {
|
|
|
1741
3990
|
}))?.isDirectory()) {
|
|
1742
3991
|
const entries = await readdir(target);
|
|
1743
3992
|
if (entries.length === 0)
|
|
1744
|
-
await
|
|
3993
|
+
await rm4(target, { recursive: true, force: true });
|
|
1745
3994
|
}
|
|
1746
3995
|
throw error;
|
|
1747
3996
|
}
|
|
@@ -1758,6 +4007,8 @@ function usage() {
|
|
|
1758
4007
|
Create a buyer-owned SaaS application from your licensed ${suggestBrandName(CLI_NAME)} release.
|
|
1759
4008
|
|
|
1760
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)
|
|
1761
4012
|
--from <path> Use a local source checkout (maintainer/testing)
|
|
1762
4013
|
--scope <namespace> Advanced workspace namespace override (default: derived from brand)
|
|
1763
4014
|
--brand <name> Display name (default: derived from app name)
|
|
@@ -1802,7 +4053,11 @@ function parseArguments(argv) {
|
|
|
1802
4053
|
const argument = argv[index];
|
|
1803
4054
|
if (argument === "--from")
|
|
1804
4055
|
parsed.from = takeValue3(argv, index++, argument);
|
|
1805
|
-
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")
|
|
1806
4061
|
parsed.scope = takeValue3(argv, index++, argument);
|
|
1807
4062
|
else if (argument === "--brand")
|
|
1808
4063
|
parsed.brandName = takeValue3(argv, index++, argument);
|
|
@@ -1870,28 +4125,60 @@ function suggestScope(brandName, fallbackAppName) {
|
|
|
1870
4125
|
return namespace || fallbackAppName;
|
|
1871
4126
|
}
|
|
1872
4127
|
async function unwrapPrompt(value) {
|
|
1873
|
-
if (
|
|
1874
|
-
|
|
4128
|
+
if (isCancel(value)) {
|
|
4129
|
+
cancel("No project was created.");
|
|
1875
4130
|
throw new CliCancelled;
|
|
1876
4131
|
}
|
|
1877
4132
|
return value;
|
|
1878
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
|
+
}
|
|
1879
4162
|
async function collectOptions(parsed) {
|
|
1880
4163
|
if (parsed.yes && !parsed.appName)
|
|
1881
4164
|
throw new Error("Pass an app name when using --yes.");
|
|
1882
4165
|
if (!parsed.yes && !process.stdin.isTTY && !parsed.appName) {
|
|
1883
4166
|
throw new Error("Interactive prompts need a terminal. Pass an app name and --yes instead.");
|
|
1884
4167
|
}
|
|
1885
|
-
const appName = parsed.appName ?? await unwrapPrompt(await
|
|
4168
|
+
const appName = parsed.appName ?? await unwrapPrompt(await text({
|
|
1886
4169
|
message: "App name",
|
|
1887
4170
|
placeholder: "my-saas",
|
|
1888
|
-
validate: (value) => validateAppName(value ?? "")
|
|
4171
|
+
validate: (value) => validateAppName(value ?? "") ?? describeTargetConflict(value ?? "")
|
|
1889
4172
|
}));
|
|
1890
4173
|
const appNameError = validateAppName(appName);
|
|
1891
4174
|
if (appNameError)
|
|
1892
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);
|
|
1893
4180
|
const suggestedBrand = suggestBrandName(appName);
|
|
1894
|
-
const brandName = parsed.brandName ?? (parsed.yes ? suggestedBrand : await unwrapPrompt(await
|
|
4181
|
+
const brandName = parsed.brandName ?? (parsed.yes ? suggestedBrand : await unwrapPrompt(await text({
|
|
1895
4182
|
message: "Brand name",
|
|
1896
4183
|
placeholder: suggestedBrand,
|
|
1897
4184
|
defaultValue: suggestedBrand,
|
|
@@ -1901,22 +4188,22 @@ async function collectOptions(parsed) {
|
|
|
1901
4188
|
if (brandError)
|
|
1902
4189
|
throw new Error(brandError);
|
|
1903
4190
|
const scope = normalizeScope(parsed.scope ?? suggestScope(brandName, appName));
|
|
1904
|
-
const initializeGit = parsed.initializeGit ?? (parsed.yes ? true : await unwrapPrompt(await
|
|
4191
|
+
const initializeGit = parsed.initializeGit ?? (parsed.yes ? true : await unwrapPrompt(await confirm({
|
|
1905
4192
|
message: "Initialize a Git repository?",
|
|
1906
4193
|
initialValue: true
|
|
1907
4194
|
})));
|
|
1908
|
-
const installDependencies = parsed.installDependencies ?? (parsed.yes ? true : await unwrapPrompt(await
|
|
4195
|
+
const installDependencies = parsed.installDependencies ?? (parsed.yes ? true : await unwrapPrompt(await confirm({
|
|
1909
4196
|
message: "Install dependencies with pnpm?",
|
|
1910
4197
|
initialValue: true
|
|
1911
4198
|
})));
|
|
1912
4199
|
if (parsed.startDevelopment && !installDependencies) {
|
|
1913
4200
|
throw new Error("--start requires dependency installation. Remove --no-install.");
|
|
1914
4201
|
}
|
|
1915
|
-
const startDevelopment = parsed.startDevelopment ?? (parsed.yes || !installDependencies ? false : await unwrapPrompt(await
|
|
4202
|
+
const startDevelopment = parsed.startDevelopment ?? (parsed.yes || !installDependencies ? false : await unwrapPrompt(await confirm({
|
|
1916
4203
|
message: "Start local development now?",
|
|
1917
4204
|
initialValue: true
|
|
1918
4205
|
})));
|
|
1919
|
-
const setupDeployment = parsed.setupDeployment ?? (parsed.yes ? false : await unwrapPrompt(await
|
|
4206
|
+
const setupDeployment = parsed.setupDeployment ?? (parsed.yes ? false : await unwrapPrompt(await confirm({
|
|
1920
4207
|
message: "Set up cloud deployment now?",
|
|
1921
4208
|
initialValue: false
|
|
1922
4209
|
})));
|
|
@@ -1924,6 +4211,8 @@ async function collectOptions(parsed) {
|
|
|
1924
4211
|
return {
|
|
1925
4212
|
appName,
|
|
1926
4213
|
from: parsed.from ? resolve4(parsed.from) : undefined,
|
|
4214
|
+
licenseKey,
|
|
4215
|
+
sourceVersion: parsed.sourceVersion,
|
|
1927
4216
|
scope,
|
|
1928
4217
|
brandName,
|
|
1929
4218
|
initializeGit,
|
|
@@ -1938,15 +4227,6 @@ async function readCliVersion() {
|
|
|
1938
4227
|
throw new Error(`${CLI_NAME} package version is missing.`);
|
|
1939
4228
|
return packageJson.version;
|
|
1940
4229
|
}
|
|
1941
|
-
function templateRefForVersion(version) {
|
|
1942
|
-
if (!/^\d+\.\d+\.\d+(?:-rc\.\d+)?$/.test(version)) {
|
|
1943
|
-
throw new Error(`${CLI_NAME} package version is not release-compatible: ${version}`);
|
|
1944
|
-
}
|
|
1945
|
-
if (version === "0.0.0") {
|
|
1946
|
-
throw new Error(`This pre-release ${CLI_NAME} checkout requires --from <local-source-path>.`);
|
|
1947
|
-
}
|
|
1948
|
-
return `v${version}`;
|
|
1949
|
-
}
|
|
1950
4230
|
async function assertTargetAvailable(target) {
|
|
1951
4231
|
const targetStat = await stat5(target).catch(() => {
|
|
1952
4232
|
return;
|
|
@@ -2008,8 +4288,8 @@ function assertSiblingTarget(source, target) {
|
|
|
2008
4288
|
throw new Error(`Create the new app beside the ${CLI_NAME} source checkout, not inside it.`);
|
|
2009
4289
|
}
|
|
2010
4290
|
}
|
|
2011
|
-
function commandFailureOutput(
|
|
2012
|
-
const output = (stderr.trim() ||
|
|
4291
|
+
function commandFailureOutput(stdout2, stderr) {
|
|
4292
|
+
const output = (stderr.trim() || stdout2.trim()).split(`
|
|
2013
4293
|
`).slice(-12).join(`
|
|
2014
4294
|
`);
|
|
2015
4295
|
return output ? `
|
|
@@ -2017,39 +4297,36 @@ function commandFailureOutput(stdout, stderr) {
|
|
|
2017
4297
|
${output}` : "";
|
|
2018
4298
|
}
|
|
2019
4299
|
async function installDependencies(target) {
|
|
2020
|
-
const { stdout, stderr, exitCode } = await runCaptured2(["pnpm", "install", "--frozen-lockfile"], {
|
|
4300
|
+
const { stdout: stdout2, stderr, exitCode } = await runCaptured2(["pnpm", "install", "--frozen-lockfile"], {
|
|
2021
4301
|
cwd: target,
|
|
2022
4302
|
env: { ...process.env, CI: "1" }
|
|
2023
4303
|
});
|
|
2024
4304
|
if (exitCode !== 0) {
|
|
2025
|
-
throw new Error(`Dependency installation failed.${commandFailureOutput(
|
|
4305
|
+
throw new Error(`Dependency installation failed.${commandFailureOutput(stdout2, stderr)}`);
|
|
2026
4306
|
}
|
|
2027
4307
|
}
|
|
2028
4308
|
async function runCapturedCommand(command, target) {
|
|
2029
|
-
const { stdout, stderr, exitCode } = await runCaptured2(command, { cwd: target });
|
|
4309
|
+
const { stdout: stdout2, stderr, exitCode } = await runCaptured2(command, { cwd: target });
|
|
2030
4310
|
if (exitCode !== 0) {
|
|
2031
|
-
throw new Error(`${command.join(" ")} failed.${commandFailureOutput(
|
|
4311
|
+
throw new Error(`${command.join(" ")} failed.${commandFailureOutput(stdout2, stderr)}`);
|
|
2032
4312
|
}
|
|
2033
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
|
+
}
|
|
2034
4318
|
async function startDevelopment(target) {
|
|
2035
|
-
const occupiedPorts = (await Promise.all([5173, 8000].map(async (port) => ({
|
|
2036
|
-
port,
|
|
2037
|
-
available: await isPortAvailable(port)
|
|
2038
|
-
})))).filter((result) => !result.available).map((result) => result.port);
|
|
2039
|
-
if (occupiedPorts.length > 0) {
|
|
2040
|
-
throw new Error(`Cannot start development because port ${occupiedPorts.join(", ")} is in use.`);
|
|
2041
|
-
}
|
|
2042
4319
|
await runStep("Starting local Postgres", "Local Postgres is ready", () => runCapturedCommand(["docker", "compose", "up", "-d", "--wait", "postgres"], target));
|
|
2043
|
-
|
|
4320
|
+
log.info(`Web http://localhost:5173
|
|
2044
4321
|
API http://localhost:8000`);
|
|
2045
|
-
|
|
4322
|
+
outro("Development servers are starting. Ctrl+C stops app servers; Postgres stays running.");
|
|
2046
4323
|
const exitCode = await runInherited(["vp", "run", "-r", "--parallel", "dev"], { cwd: target });
|
|
2047
4324
|
if (exitCode !== 0 && exitCode !== 130) {
|
|
2048
4325
|
throw new Error(`Development servers exited with code ${exitCode}.`);
|
|
2049
4326
|
}
|
|
2050
4327
|
}
|
|
2051
4328
|
async function runStep(pending, complete, action, indicator = "dots") {
|
|
2052
|
-
const progress =
|
|
4329
|
+
const progress = spinner({ indicator });
|
|
2053
4330
|
progress.start(pending);
|
|
2054
4331
|
try {
|
|
2055
4332
|
const result = await action();
|
|
@@ -2060,22 +4337,22 @@ async function runStep(pending, complete, action, indicator = "dots") {
|
|
|
2060
4337
|
throw error;
|
|
2061
4338
|
}
|
|
2062
4339
|
}
|
|
2063
|
-
async function createApplication(options
|
|
4340
|
+
async function createApplication(options) {
|
|
2064
4341
|
const target = resolve4(process.cwd(), options.appName);
|
|
2065
4342
|
await assertTargetAvailable(target);
|
|
2066
4343
|
assertSiblingTarget(options.from, target);
|
|
2067
4344
|
const databasePort = await findAvailablePort();
|
|
2068
4345
|
await mkdir5(dirname2(target), { recursive: true });
|
|
2069
|
-
const staging = await mkdtemp2(
|
|
4346
|
+
const staging = await mkdtemp2(join8(dirname2(target), `.${options.appName}-${CLI_NAME}-`));
|
|
2070
4347
|
try {
|
|
2071
|
-
const templateRef = options.from ? undefined : templateRefForVersion(version);
|
|
2072
4348
|
await runStep("Preparing your application", "Application source prepared", () => scaffold({
|
|
2073
4349
|
appName: options.appName,
|
|
2074
4350
|
scope: options.scope,
|
|
2075
4351
|
brandName: options.brandName,
|
|
2076
4352
|
targetDirectory: staging,
|
|
2077
4353
|
from: options.from,
|
|
2078
|
-
|
|
4354
|
+
licenseKey: options.licenseKey,
|
|
4355
|
+
sourceVersion: options.sourceVersion,
|
|
2079
4356
|
initializeGit: options.initializeGit,
|
|
2080
4357
|
databasePort
|
|
2081
4358
|
}));
|
|
@@ -2092,7 +4369,7 @@ async function createApplication(options, version) {
|
|
|
2092
4369
|
await rename2(staging, target);
|
|
2093
4370
|
return { target, databasePort };
|
|
2094
4371
|
} catch (error) {
|
|
2095
|
-
await
|
|
4372
|
+
await rm5(staging, { recursive: true, force: true });
|
|
2096
4373
|
throw error;
|
|
2097
4374
|
}
|
|
2098
4375
|
}
|
|
@@ -2111,6 +4388,11 @@ function completionDetails(target, options, databasePort) {
|
|
|
2111
4388
|
database: `Postgres localhost:${databasePort}`
|
|
2112
4389
|
};
|
|
2113
4390
|
}
|
|
4391
|
+
function printRunnableCommands(commands) {
|
|
4392
|
+
console.log(`
|
|
4393
|
+
${commands}
|
|
4394
|
+
`);
|
|
4395
|
+
}
|
|
2114
4396
|
async function main() {
|
|
2115
4397
|
const argv = process.argv.slice(2);
|
|
2116
4398
|
if (argv[0] === "agent") {
|
|
@@ -2135,32 +4417,40 @@ async function main() {
|
|
|
2135
4417
|
console.log(version);
|
|
2136
4418
|
return;
|
|
2137
4419
|
}
|
|
2138
|
-
|
|
4420
|
+
intro(`${suggestBrandName(CLI_NAME)} ${version} \xB7 production SaaS foundation`);
|
|
2139
4421
|
const options = await collectOptions(parsed);
|
|
2140
|
-
const { target, databasePort } = await createApplication(options
|
|
4422
|
+
const { target, databasePort } = await createApplication(options);
|
|
2141
4423
|
const completion = completionDetails(target, options, databasePort);
|
|
2142
|
-
|
|
4424
|
+
log.success(`Created ${completion.directory}`);
|
|
2143
4425
|
if (!options.startDevelopment) {
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
prompts5.log.info(`Web http://localhost:5173
|
|
4426
|
+
log.step("Run locally");
|
|
4427
|
+
log.info(`Web http://localhost:5173
|
|
2147
4428
|
API http://localhost:8000
|
|
2148
4429
|
${completion.database}`);
|
|
2149
4430
|
if (options.deployment) {
|
|
2150
|
-
|
|
4431
|
+
log.info(`Deployment ${options.deployment.cloud.toUpperCase()} + ${options.deployment.storageProvider} + ${options.deployment.frontendTarget} locked. Review deployment/README.md.`);
|
|
2151
4432
|
} else {
|
|
2152
|
-
|
|
4433
|
+
log.info("Deployment deferred. Run `pnpm deploy:configure` when you are ready.");
|
|
2153
4434
|
}
|
|
2154
|
-
|
|
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);
|
|
2155
4445
|
return;
|
|
2156
4446
|
}
|
|
2157
4447
|
try {
|
|
2158
4448
|
await startDevelopment(target);
|
|
2159
4449
|
} catch (error) {
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
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);
|
|
2164
4454
|
process.exitCode = 1;
|
|
2165
4455
|
}
|
|
2166
4456
|
}
|
|
@@ -2168,16 +4458,19 @@ if (isEntrypoint(import.meta.url)) {
|
|
|
2168
4458
|
main().catch((error) => {
|
|
2169
4459
|
if (error instanceof CliCancelled)
|
|
2170
4460
|
return;
|
|
2171
|
-
|
|
2172
|
-
|
|
4461
|
+
log.error(error instanceof Error ? error.message : String(error));
|
|
4462
|
+
outro("No project was created.");
|
|
2173
4463
|
process.exitCode = 1;
|
|
2174
4464
|
});
|
|
2175
4465
|
}
|
|
2176
4466
|
export {
|
|
2177
4467
|
usage,
|
|
2178
|
-
templateRefForVersion,
|
|
2179
4468
|
suggestScope,
|
|
2180
4469
|
suggestBrandName,
|
|
4470
|
+
printRunnableCommands,
|
|
2181
4471
|
parseArguments,
|
|
2182
|
-
|
|
4472
|
+
occupiedDevelopmentPorts,
|
|
4473
|
+
findAvailablePort,
|
|
4474
|
+
describeTargetConflict,
|
|
4475
|
+
collectLicenseKey
|
|
2183
4476
|
};
|