@tymber/create 0.0.1-alpha.0 → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +11 -0
  3. package/dist/index.js +747 -0
  4. package/package.json +23 -2
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2026-present Damien ARRACHEQUESNE
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,11 @@
1
+ <h1>Scaffold a new Tymber project</h1>
2
+
3
+ ## Usage
4
+
5
+ ```
6
+ npm create @tymber@latest
7
+ ```
8
+
9
+ ## License
10
+
11
+ [MIT](./LICENSE)
package/dist/index.js ADDED
@@ -0,0 +1,747 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { styleText } from 'node:util';
4
+ import V, { stdout, stdin } from 'node:process';
5
+ import * as b from 'node:readline';
6
+ import b__default from 'node:readline';
7
+ import { ReadStream } from 'node:tty';
8
+ import 'node:fs';
9
+ import * as path from 'node:path';
10
+ import * as fs from 'node:fs/promises';
11
+
12
+ /* MAIN */
13
+ const getCodePointsLength = (() => {
14
+ const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
15
+ return (input) => {
16
+ let surrogatePairsNr = 0;
17
+ SURROGATE_PAIR_RE.lastIndex = 0;
18
+ while (SURROGATE_PAIR_RE.test(input)) {
19
+ surrogatePairsNr += 1;
20
+ }
21
+ return input.length - surrogatePairsNr;
22
+ };
23
+ })();
24
+ const isFullWidth = (x) => {
25
+ return x === 0x3000 || x >= 0xFF01 && x <= 0xFF60 || x >= 0xFFE0 && x <= 0xFFE6;
26
+ };
27
+ const isWideNotCJKTNotEmoji = (x) => {
28
+ return x === 0x231B || x === 0x2329 || x >= 0x2FF0 && x <= 0x2FFF || x >= 0x3001 && x <= 0x303E || x >= 0x3099 && x <= 0x30FF || x >= 0x3105 && x <= 0x312F || x >= 0x3131 && x <= 0x318E || x >= 0x3190 && x <= 0x31E3 || x >= 0x31EF && x <= 0x321E || x >= 0x3220 && x <= 0x3247 || x >= 0x3250 && x <= 0x4DBF || x >= 0xFE10 && x <= 0xFE19 || x >= 0xFE30 && x <= 0xFE52 || x >= 0xFE54 && x <= 0xFE66 || x >= 0xFE68 && x <= 0xFE6B || x >= 0x1F200 && x <= 0x1F202 || x >= 0x1F210 && x <= 0x1F23B || x >= 0x1F240 && x <= 0x1F248 || x >= 0x20000 && x <= 0x2FFFD || x >= 0x30000 && x <= 0x3FFFD;
29
+ };
30
+
31
+ /* IMPORT */
32
+ /* HELPERS */
33
+ const ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
34
+ const CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
35
+ const 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;
36
+ const TAB_RE = /\t{1,1000}/y;
37
+ const 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;
38
+ const LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
39
+ const MODIFIER_RE = /\p{M}+/gu;
40
+ const NO_TRUNCATION$1 = { limit: Infinity, ellipsis: '' };
41
+ /* MAIN */
42
+ const getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
43
+ /* CONSTANTS */
44
+ const LIMIT = truncationOptions.limit ?? Infinity;
45
+ const ELLIPSIS = truncationOptions.ellipsis ?? '';
46
+ const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION$1, widthOptions).width : 0);
47
+ const ANSI_WIDTH = 0;
48
+ const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
49
+ const TAB_WIDTH = widthOptions.tabWidth ?? 8;
50
+ const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
51
+ const FULL_WIDTH_WIDTH = 2;
52
+ const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
53
+ const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
54
+ const PARSE_BLOCKS = [
55
+ [LATIN_RE, REGULAR_WIDTH],
56
+ [ANSI_RE, ANSI_WIDTH],
57
+ [CONTROL_RE, CONTROL_WIDTH],
58
+ [TAB_RE, TAB_WIDTH],
59
+ [EMOJI_RE, EMOJI_WIDTH],
60
+ [CJKT_WIDE_RE, WIDE_WIDTH],
61
+ ];
62
+ /* STATE */
63
+ let indexPrev = 0;
64
+ let index = 0;
65
+ let length = input.length;
66
+ let lengthExtra = 0;
67
+ let truncationEnabled = false;
68
+ let truncationIndex = length;
69
+ let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
70
+ let unmatchedStart = 0;
71
+ let unmatchedEnd = 0;
72
+ let width = 0;
73
+ let widthExtra = 0;
74
+ /* PARSE LOOP */
75
+ outer: while (true) {
76
+ /* UNMATCHED */
77
+ if ((unmatchedEnd > unmatchedStart) || (index >= length && index > indexPrev)) {
78
+ const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
79
+ lengthExtra = 0;
80
+ for (const char of unmatched.replaceAll(MODIFIER_RE, '')) {
81
+ const codePoint = char.codePointAt(0) || 0;
82
+ if (isFullWidth(codePoint)) {
83
+ widthExtra = FULL_WIDTH_WIDTH;
84
+ }
85
+ else if (isWideNotCJKTNotEmoji(codePoint)) {
86
+ widthExtra = WIDE_WIDTH;
87
+ }
88
+ else {
89
+ widthExtra = REGULAR_WIDTH;
90
+ }
91
+ if ((width + widthExtra) > truncationLimit) {
92
+ truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
93
+ }
94
+ if ((width + widthExtra) > LIMIT) {
95
+ truncationEnabled = true;
96
+ break outer;
97
+ }
98
+ lengthExtra += char.length;
99
+ width += widthExtra;
100
+ }
101
+ unmatchedStart = unmatchedEnd = 0;
102
+ }
103
+ /* EXITING */
104
+ if (index >= length) {
105
+ break outer;
106
+ }
107
+ /* PARSE BLOCKS */
108
+ for (let i = 0, l = PARSE_BLOCKS.length; i < l; i++) {
109
+ const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i];
110
+ BLOCK_RE.lastIndex = index;
111
+ if (BLOCK_RE.test(input)) {
112
+ lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
113
+ widthExtra = lengthExtra * BLOCK_WIDTH;
114
+ if ((width + widthExtra) > truncationLimit) {
115
+ truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
116
+ }
117
+ if ((width + widthExtra) > LIMIT) {
118
+ truncationEnabled = true;
119
+ break outer;
120
+ }
121
+ width += widthExtra;
122
+ unmatchedStart = indexPrev;
123
+ unmatchedEnd = index;
124
+ index = indexPrev = BLOCK_RE.lastIndex;
125
+ continue outer;
126
+ }
127
+ }
128
+ /* UNMATCHED INDEX */
129
+ index += 1;
130
+ }
131
+ /* RETURN */
132
+ return {
133
+ width: truncationEnabled ? truncationLimit : width,
134
+ index: truncationEnabled ? truncationIndex : length,
135
+ truncated: truncationEnabled,
136
+ ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
137
+ };
138
+ };
139
+
140
+ /* IMPORT */
141
+ /* HELPERS */
142
+ const NO_TRUNCATION = {
143
+ limit: Infinity,
144
+ ellipsis: '',
145
+ ellipsisWidth: 0,
146
+ };
147
+ /* MAIN */
148
+ const fastStringWidth = (input, options = {}) => {
149
+ return getStringTruncatedWidth(input, NO_TRUNCATION, options).width;
150
+ };
151
+
152
+ const ESC = '\x1B';
153
+ const CSI = '\x9B';
154
+ const END_CODE = 39;
155
+ const ANSI_ESCAPE_BELL = '\u0007';
156
+ const ANSI_CSI = '[';
157
+ const ANSI_OSC = ']';
158
+ const ANSI_SGR_TERMINATOR = 'm';
159
+ const ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
160
+ const GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, 'y');
161
+ const getClosingCode = (openingCode) => {
162
+ if (openingCode >= 30 && openingCode <= 37)
163
+ return 39;
164
+ if (openingCode >= 90 && openingCode <= 97)
165
+ return 39;
166
+ if (openingCode >= 40 && openingCode <= 47)
167
+ return 49;
168
+ if (openingCode >= 100 && openingCode <= 107)
169
+ return 49;
170
+ if (openingCode === 1 || openingCode === 2)
171
+ return 22;
172
+ if (openingCode === 3)
173
+ return 23;
174
+ if (openingCode === 4)
175
+ return 24;
176
+ if (openingCode === 7)
177
+ return 27;
178
+ if (openingCode === 8)
179
+ return 28;
180
+ if (openingCode === 9)
181
+ return 29;
182
+ if (openingCode === 0)
183
+ return 0;
184
+ return undefined;
185
+ };
186
+ const wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
187
+ const wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
188
+ const wrapWord = (rows, word, columns) => {
189
+ const characters = word[Symbol.iterator]();
190
+ let isInsideEscape = false;
191
+ let isInsideLinkEscape = false;
192
+ let lastRow = rows.at(-1);
193
+ let visible = lastRow === undefined ? 0 : fastStringWidth(lastRow);
194
+ let currentCharacter = characters.next();
195
+ let nextCharacter = characters.next();
196
+ let rawCharacterIndex = 0;
197
+ while (!currentCharacter.done) {
198
+ const character = currentCharacter.value;
199
+ const characterLength = fastStringWidth(character);
200
+ if (visible + characterLength <= columns) {
201
+ rows[rows.length - 1] += character;
202
+ }
203
+ else {
204
+ rows.push(character);
205
+ visible = 0;
206
+ }
207
+ if (character === ESC || character === CSI) {
208
+ isInsideEscape = true;
209
+ isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
210
+ }
211
+ if (isInsideEscape) {
212
+ if (isInsideLinkEscape) {
213
+ if (character === ANSI_ESCAPE_BELL) {
214
+ isInsideEscape = false;
215
+ isInsideLinkEscape = false;
216
+ }
217
+ }
218
+ else if (character === ANSI_SGR_TERMINATOR) {
219
+ isInsideEscape = false;
220
+ }
221
+ }
222
+ else {
223
+ visible += characterLength;
224
+ if (visible === columns && !nextCharacter.done) {
225
+ rows.push('');
226
+ visible = 0;
227
+ }
228
+ }
229
+ currentCharacter = nextCharacter;
230
+ nextCharacter = characters.next();
231
+ rawCharacterIndex += character.length;
232
+ }
233
+ lastRow = rows.at(-1);
234
+ if (!visible && lastRow !== undefined && lastRow.length && rows.length > 1) {
235
+ rows[rows.length - 2] += rows.pop();
236
+ }
237
+ };
238
+ const stringVisibleTrimSpacesRight = (string) => {
239
+ const words = string.split(' ');
240
+ let last = words.length;
241
+ while (last) {
242
+ if (fastStringWidth(words[last - 1])) {
243
+ break;
244
+ }
245
+ last--;
246
+ }
247
+ if (last === words.length) {
248
+ return string;
249
+ }
250
+ return words.slice(0, last).join(' ') + words.slice(last).join('');
251
+ };
252
+ const exec = (string, columns, options = {}) => {
253
+ if (options.trim !== false && string.trim() === '') {
254
+ return '';
255
+ }
256
+ let returnValue = '';
257
+ let escapeCode;
258
+ let escapeUrl;
259
+ const words = string.split(' ');
260
+ let rows = [''];
261
+ let rowLength = 0;
262
+ for (let index = 0; index < words.length; index++) {
263
+ const word = words[index];
264
+ if (options.trim !== false) {
265
+ const row = rows.at(-1) ?? '';
266
+ const trimmed = row.trimStart();
267
+ if (row.length !== trimmed.length) {
268
+ rows[rows.length - 1] = trimmed;
269
+ rowLength = fastStringWidth(trimmed);
270
+ }
271
+ }
272
+ if (index !== 0) {
273
+ if (rowLength >= columns &&
274
+ (options.wordWrap === false || options.trim === false)) {
275
+ rows.push('');
276
+ rowLength = 0;
277
+ }
278
+ if (rowLength || options.trim === false) {
279
+ rows[rows.length - 1] += ' ';
280
+ rowLength++;
281
+ }
282
+ }
283
+ const wordLength = fastStringWidth(word);
284
+ if (options.hard && wordLength > columns) {
285
+ const remainingColumns = columns - rowLength;
286
+ const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
287
+ const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);
288
+ if (breaksStartingNextLine < breaksStartingThisLine) {
289
+ rows.push('');
290
+ }
291
+ wrapWord(rows, word, columns);
292
+ rowLength = fastStringWidth(rows.at(-1) ?? '');
293
+ continue;
294
+ }
295
+ if (rowLength + wordLength > columns && rowLength && wordLength) {
296
+ if (options.wordWrap === false && rowLength < columns) {
297
+ wrapWord(rows, word, columns);
298
+ rowLength = fastStringWidth(rows.at(-1) ?? '');
299
+ continue;
300
+ }
301
+ rows.push('');
302
+ rowLength = 0;
303
+ }
304
+ if (rowLength + wordLength > columns && options.wordWrap === false) {
305
+ wrapWord(rows, word, columns);
306
+ rowLength = fastStringWidth(rows.at(-1) ?? '');
307
+ continue;
308
+ }
309
+ rows[rows.length - 1] += word;
310
+ rowLength += wordLength;
311
+ }
312
+ if (options.trim !== false) {
313
+ rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
314
+ }
315
+ const preString = rows.join('\n');
316
+ let inSurrogate = false;
317
+ for (let i = 0; i < preString.length; i++) {
318
+ const character = preString[i];
319
+ returnValue += character;
320
+ if (!inSurrogate) {
321
+ inSurrogate = character >= '\ud800' && character <= '\udbff';
322
+ if (inSurrogate) {
323
+ continue;
324
+ }
325
+ }
326
+ else {
327
+ inSurrogate = false;
328
+ }
329
+ if (character === ESC || character === CSI) {
330
+ GROUP_REGEX.lastIndex = i + 1;
331
+ const groupsResult = GROUP_REGEX.exec(preString);
332
+ const groups = groupsResult?.groups;
333
+ if (groups?.code !== undefined) {
334
+ const code = Number.parseFloat(groups.code);
335
+ escapeCode = code === END_CODE ? undefined : code;
336
+ }
337
+ else if (groups?.uri !== undefined) {
338
+ escapeUrl = groups.uri.length === 0 ? undefined : groups.uri;
339
+ }
340
+ }
341
+ if (preString[i + 1] === '\n') {
342
+ if (escapeUrl) {
343
+ returnValue += wrapAnsiHyperlink('');
344
+ }
345
+ const closingCode = escapeCode ? getClosingCode(escapeCode) : undefined;
346
+ if (escapeCode && closingCode) {
347
+ returnValue += wrapAnsiCode(closingCode);
348
+ }
349
+ }
350
+ else if (character === '\n') {
351
+ if (escapeCode && getClosingCode(escapeCode)) {
352
+ returnValue += wrapAnsiCode(escapeCode);
353
+ }
354
+ if (escapeUrl) {
355
+ returnValue += wrapAnsiHyperlink(escapeUrl);
356
+ }
357
+ }
358
+ }
359
+ return returnValue;
360
+ };
361
+ const CRLF_OR_LF = /\r?\n/;
362
+ function wrapAnsi(string, columns, options) {
363
+ return String(string)
364
+ .normalize()
365
+ .split(CRLF_OR_LF)
366
+ .map((line) => exec(line, columns, options))
367
+ .join('\n');
368
+ }
369
+
370
+ var src;
371
+ var hasRequiredSrc;
372
+
373
+ function requireSrc () {
374
+ if (hasRequiredSrc) return src;
375
+ hasRequiredSrc = 1;
376
+
377
+ const ESC = '\x1B';
378
+ const CSI = `${ESC}[`;
379
+ const beep = '\u0007';
380
+
381
+ const cursor = {
382
+ to(x, y) {
383
+ if (!y) return `${CSI}${x + 1}G`;
384
+ return `${CSI}${y + 1};${x + 1}H`;
385
+ },
386
+ move(x, y) {
387
+ let ret = '';
388
+
389
+ if (x < 0) ret += `${CSI}${-x}D`;
390
+ else if (x > 0) ret += `${CSI}${x}C`;
391
+
392
+ if (y < 0) ret += `${CSI}${-y}A`;
393
+ else if (y > 0) ret += `${CSI}${y}B`;
394
+
395
+ return ret;
396
+ },
397
+ up: (count = 1) => `${CSI}${count}A`,
398
+ down: (count = 1) => `${CSI}${count}B`,
399
+ forward: (count = 1) => `${CSI}${count}C`,
400
+ backward: (count = 1) => `${CSI}${count}D`,
401
+ nextLine: (count = 1) => `${CSI}E`.repeat(count),
402
+ prevLine: (count = 1) => `${CSI}F`.repeat(count),
403
+ left: `${CSI}G`,
404
+ hide: `${CSI}?25l`,
405
+ show: `${CSI}?25h`,
406
+ save: `${ESC}7`,
407
+ restore: `${ESC}8`
408
+ };
409
+
410
+ const scroll = {
411
+ up: (count = 1) => `${CSI}S`.repeat(count),
412
+ down: (count = 1) => `${CSI}T`.repeat(count)
413
+ };
414
+
415
+ const erase = {
416
+ screen: `${CSI}2J`,
417
+ up: (count = 1) => `${CSI}1J`.repeat(count),
418
+ down: (count = 1) => `${CSI}J`.repeat(count),
419
+ line: `${CSI}2K`,
420
+ lineEnd: `${CSI}K`,
421
+ lineStart: `${CSI}1K`,
422
+ lines(count) {
423
+ let clear = '';
424
+ for (let i = 0; i < count; i++)
425
+ clear += this.line + (i < count - 1 ? cursor.up() : '');
426
+ if (count)
427
+ clear += cursor.left;
428
+ return clear;
429
+ }
430
+ };
431
+
432
+ src = { cursor, scroll, erase, beep };
433
+ return src;
434
+ }
435
+
436
+ var srcExports = requireSrc();
437
+
438
+ function f(r,t,s){if(!s.some(o=>!o.disabled))return r;const e=r+t,i=Math.max(s.length-1,0),n=e<0?i:e>i?0:e;return s[n].disabled?f(n,t<0?-1:1,s):n}const G=["up","down","left","right","space","enter","cancel"],h={actions:new Set(G),aliases:new Map([["k","up"],["j","down"],["h","left"],["l","right"],["","cancel"],["escape","cancel"]]),messages:{cancel:"Canceled",error:"Something went wrong"},withGuide:true};function C(r,t){if(typeof r=="string")return h.aliases.get(r)===t;for(const s of r)if(s!==void 0&&C(s,t))return true;return false}function z$1(r,t){if(r===t)return;const s=r.split(`
439
+ `),e=t.split(`
440
+ `),i=Math.max(s.length,e.length),n=[];for(let o=0;o<i;o++)s[o]!==e[o]&&n.push(o);return {lines:n,numLinesBefore:s.length,numLinesAfter:e.length,numLines:i}}const Y$1=globalThis.process.platform.startsWith("win"),k=Symbol("clack:cancel");function q(r){return r===k}function w$1(r,t){const s=r;s.isTTY&&s.setRawMode(t);}function R$1({input:r=stdin,output:t=stdout,overwrite:s=true,hideCursor:e=true}={}){const i=b.createInterface({input:r,output:t,prompt:"",tabSize:1});b.emitKeypressEvents(r,i),r instanceof ReadStream&&r.isTTY&&r.setRawMode(true);const n=(o,{name:u,sequence:a})=>{const l=String(o);if(C([l,u,a],"cancel")){e&&t.write(srcExports.cursor.show),process.exit(0);return}if(!s)return;const c=u==="return"?0:-1,y=u==="return"?-1:0;b.moveCursor(t,c,y,()=>{b.clearLine(t,1,()=>{r.once("keypress",n);});});};return e&&t.write(srcExports.cursor.hide),r.once("keypress",n),()=>{r.off("keypress",n),e&&t.write(srcExports.cursor.show),r instanceof ReadStream&&r.isTTY&&!Y$1&&r.setRawMode(false),i.terminal=false,i.close();}}const A=r=>"columns"in r&&typeof r.columns=="number"?r.columns:80,L=r=>"rows"in r&&typeof r.rows=="number"?r.rows:20;function W(r,t,s,e=s,i=s,n){const o=A(r??stdout);return wrapAnsi(t,o-s.length,{hard:true,trim:false}).split(`
441
+ `).map((u,a,l)=>{const c=u;return a===0?`${e}${c}`:a===l.length-1?`${i}${c}`:`${s}${c}`}).join(`
442
+ `)}let m=class{input;output;_abortSignal;rl;opts;_render;_track=false;_prevFrame="";_subscribers=new Map;_cursor=0;state="initial";error="";value;userInput="";constructor(t,s=true){const{input:e=stdin,output:i=stdout,render:n,signal:o,...u}=t;this.opts=u,this.onKeypress=this.onKeypress.bind(this),this.close=this.close.bind(this),this.render=this.render.bind(this),this._render=n.bind(this),this._track=s,this._abortSignal=o,this.input=e,this.output=i;}unsubscribe(){this._subscribers.clear();}setSubscriber(t,s){const e=this._subscribers.get(t)??[];e.push(s),this._subscribers.set(t,e);}on(t,s){this.setSubscriber(t,{cb:s});}once(t,s){this.setSubscriber(t,{cb:s,once:true});}emit(t,...s){const e=this._subscribers.get(t)??[],i=[];for(const n of e)n.cb(...s),n.once&&i.push(()=>e.splice(e.indexOf(n),1));for(const n of i)n();}prompt(){return new Promise(t=>{if(this._abortSignal){if(this._abortSignal.aborted)return this.state="cancel",this.close(),t(k);this._abortSignal.addEventListener("abort",()=>{this.state="cancel",this.close();},{once:true});}this.rl=b__default.createInterface({input:this.input,tabSize:2,prompt:"",escapeCodeTimeout:50,terminal:true}),this.rl.prompt(),this.opts.initialUserInput!==void 0&&this._setUserInput(this.opts.initialUserInput,true),this.input.on("keypress",this.onKeypress),w$1(this.input,true),this.output.on("resize",this.render),this.render(),this.once("submit",()=>{this.output.write(srcExports.cursor.show),this.output.off("resize",this.render),w$1(this.input,false),t(this.value);}),this.once("cancel",()=>{this.output.write(srcExports.cursor.show),this.output.off("resize",this.render),w$1(this.input,false),t(k);});})}_isActionKey(t,s){return t===" "}_shouldSubmit(t,s){return true}_setValue(t){this.value=t,this.emit("value",this.value);}_setUserInput(t,s){this.userInput=t??"",this.emit("userInput",this.userInput),s&&this._track&&this.rl&&(this.rl.write(this.userInput),this._cursor=this.rl.cursor);}_clearUserInput(){this.rl?.write(null,{ctrl:true,name:"u"}),this._setUserInput("");}onKeypress(t,s){if(this._track&&s.name!=="return"&&(s.name&&this._isActionKey(t,s)&&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"),s?.name&&(!this._track&&h.aliases.has(s.name)&&this.emit("cursor",h.aliases.get(s.name)),h.actions.has(s.name)&&this.emit("cursor",s.name)),t&&(t.toLowerCase()==="y"||t.toLowerCase()==="n")&&this.emit("confirm",t.toLowerCase()==="y"),this.emit("key",t?.toLowerCase(),s),s?.name==="return"&&this._shouldSubmit(t,s)){if(this.opts.validate){const e=this.opts.validate(this.value);e&&(this.error=e instanceof Error?e.message:e,this.state="error",this.rl?.write(this.userInput));}this.state!=="error"&&(this.state="submit");}C([t,s?.name,s?.sequence],"cancel")&&(this.state="cancel"),(this.state==="submit"||this.state==="cancel")&&this.emit("finalize"),this.render(),(this.state==="submit"||this.state==="cancel")&&this.close();}close(){this.input.unpipe(),this.input.removeListener("keypress",this.onKeypress),this.output.write(`
443
+ `),w$1(this.input,false),this.rl?.close(),this.rl=void 0,this.emit(`${this.state}`,this.value),this.unsubscribe();}restoreCursor(){const t=wrapAnsi(this._prevFrame,process.stdout.columns,{hard:true,trim:false}).split(`
444
+ `).length-1;this.output.write(srcExports.cursor.move(-999,t*-1));}render(){const t=wrapAnsi(this._render(this)??"",process.stdout.columns,{hard:true,trim:false});if(t!==this._prevFrame){if(this.state==="initial")this.output.write(srcExports.cursor.hide);else {const s=z$1(this._prevFrame,t),e=L(this.output);if(this.restoreCursor(),s){const i=Math.max(0,s.numLinesAfter-e),n=Math.max(0,s.numLinesBefore-e);let o=s.lines.find(u=>u>=i);if(o===void 0){this._prevFrame=t;return}if(s.lines.length===1){this.output.write(srcExports.cursor.move(0,o-n)),this.output.write(srcExports.erase.lines(1));const u=t.split(`
445
+ `);this.output.write(u[o]),this._prevFrame=t,this.output.write(srcExports.cursor.move(0,u.length-o-1));return}else if(s.lines.length>1){if(i<n)o=i;else {const a=o-n;a>0&&this.output.write(srcExports.cursor.move(0,a));}this.output.write(srcExports.erase.down());const u=t.split(`
446
+ `).slice(o);this.output.write(u.join(`
447
+ `)),this._prevFrame=t;return}}this.output.write(srcExports.erase.down());}this.output.write(t),this.state==="initial"&&(this.state="active"),this._prevFrame=t;}}};let nt=class extends m{options;cursor=0;get _value(){return this.options[this.cursor].value}get _enabledOptions(){return this.options.filter(t=>t.disabled!==true)}toggleAll(){const t=this._enabledOptions,s=this.value!==void 0&&this.value.length===t.length;this.value=s?[]:t.map(e=>e.value);}toggleInvert(){const t=this.value;if(!t)return;const s=this._enabledOptions.filter(e=>!t.includes(e.value));this.value=s.map(e=>e.value);}toggleValue(){this.value===void 0&&(this.value=[]);const t=this.value.includes(this._value);this.value=t?this.value.filter(s=>s!==this._value):[...this.value,this._value];}constructor(t){super(t,false),this.options=t.options,this.value=[...t.initialValues??[]];const s=Math.max(this.options.findIndex(({value:e})=>e===t.cursorAt),0);this.cursor=this.options[s].disabled?f(s,1,this.options):s,this.on("key",e=>{e==="a"&&this.toggleAll(),e==="i"&&this.toggleInvert();}),this.on("cursor",e=>{switch(e){case "left":case "up":this.cursor=f(this.cursor,-1,this.options);break;case "down":case "right":this.cursor=f(this.cursor,1,this.options);break;case "space":this.toggleValue();break}});}};let ut$1 = class ut extends m{options;cursor=0;get _selectedValue(){return this.options[this.cursor]}changeValue(){this.value=this._selectedValue.value;}constructor(t){super(t,false),this.options=t.options;const s=this.options.findIndex(({value:i})=>i===t.initialValue),e=s===-1?0:s;this.cursor=this.options[e].disabled?f(e,1,this.options):e,this.changeValue(),this.on("cursor",i=>{switch(i){case "left":case "up":this.cursor=f(this.cursor,-1,this.options);break;case "down":case "right":this.cursor=f(this.cursor,1,this.options);break}this.changeValue();});}};let ht$1 = class ht extends m{get userInputWithCursor(){if(this.state==="submit")return this.userInput;const t=this.userInput;if(this.cursor>=t.length)return `${this.userInput}\u2588`;const s=t.slice(0,this.cursor),[e,...i]=t.slice(this.cursor);return `${s}${styleText("inverse",e)}${i.join("")}`}get cursor(){return this._cursor}constructor(t){super({...t,initialUserInput:t.initialUserInput??t.initialValue}),this.on("userInput",s=>{this._setValue(s);}),this.on("finalize",()=>{this.value||(this.value=t.defaultValue),this.value===void 0&&(this.value="");});}};
448
+
449
+ function ee(){return V.platform!=="win32"?V.env.TERM!=="linux":!!V.env.CI||!!V.env.WT_SESSION||!!V.env.TERMINUS_SUBLIME||V.env.ConEmuTask==="{cmd::Cmder}"||V.env.TERM_PROGRAM==="Terminus-Sublime"||V.env.TERM_PROGRAM==="vscode"||V.env.TERM==="xterm-256color"||V.env.TERM==="alacritty"||V.env.TERMINAL_EMULATOR==="JetBrains-JediTerm"}const tt=ee(),ot=()=>process.env.CI==="true",w=(t,i)=>tt?t:i,Tt=w("\u25C6","*"),at=w("\u25A0","x"),ut=w("\u25B2","x"),H=w("\u25C7","o"),lt=w("\u250C","T"),$=w("\u2502","|"),x=w("\u2514","\u2014"),z=w("\u25CF",">"),U=w("\u25CB"," "),et=w("\u25FB","[\u2022]"),K=w("\u25FC","[+]"),Y=w("\u25FB","[ ]"),st=w("\u2500","-"),ct=w("\u256E","+"),Gt=w("\u251C","+"),$t=w("\u256F","+"),ht=w("\u25CF","\u2022"),pt=w("\u25C6","*"),mt=w("\u25B2","!"),gt=w("\u25A0","x"),P=t=>{switch(t){case "initial":case "active":return styleText("cyan",Tt);case "cancel":return styleText("red",at);case "error":return styleText("yellow",ut);case "submit":return styleText("green",H)}},yt=t=>{switch(t){case "initial":case "active":return styleText("cyan",$);case "cancel":return styleText("red",$);case "error":return styleText("yellow",$);case "submit":return styleText("green",$)}},Ot=(t,i,s,r,u,n=false)=>{let a=i,c=0;if(n)for(let o=r-1;o>=s&&(a-=t[o].length,c++,!(a<=u));o--);else for(let o=s;o<r&&(a-=t[o].length,c++,!(a<=u));o++);return {lineCount:a,removals:c}},F=({cursor:t,options:i,style:s,output:r=process.stdout,maxItems:u=Number.POSITIVE_INFINITY,columnPadding:n=0,rowPadding:a=4})=>{const c=A(r)-n,o=L(r),l=styleText("dim","..."),d=Math.max(o-a,0),g=Math.max(Math.min(u,d),5);let p=0;t>=g-3&&(p=Math.max(Math.min(t-g+3,i.length-g),0));let f=g<i.length&&p>0,h=g<i.length&&p+g<i.length;const I=Math.min(p+g,i.length),m=[];let y=0;f&&y++,h&&y++;const v=p+(f?1:0),C=I-(h?1:0);for(let b=v;b<C;b++){const G=wrapAnsi(s(i[b],b===t),c,{hard:true,trim:false}).split(`
450
+ `);m.push(G),y+=G.length;}if(y>d){let b=0,G=0,M=y;const N=t-v;let O=d;const j=()=>Ot(m,M,0,N,O),k=()=>Ot(m,M,N+1,m.length,O,true);f?({lineCount:M,removals:b}=j(),M>O&&(h||(O-=1),{lineCount:M,removals:G}=k())):(h||(O-=1),{lineCount:M,removals:G}=k(),M>O&&(O-=1,{lineCount:M,removals:b}=j())),b>0&&(f=true,m.splice(0,b)),G>0&&(h=true,m.splice(m.length-G,G));}const S=[];f&&S.push(l);for(const b of m)for(const G of b)S.push(G);return h&&S.push(l),S};const he=async(t,i)=>{const s={},r=Object.keys(t);for(const u of r){const n=t[u],a=await n({results:s})?.catch(c=>{throw c});if(typeof i?.onCancel=="function"&&q(a)){s[u]="canceled",i.onCancel({results:s});continue}s[u]=a;}return s},R={message:(t=[],{symbol:i=styleText("gray",$),secondarySymbol:s=styleText("gray",$),output:r=process.stdout,spacing:u=1,withGuide:n}={})=>{const a=[],c=n??h.withGuide,o=c?s:"",l=c?`${i} `:"",d=c?`${s} `:"";for(let p=0;p<u;p++)a.push(o);const g=Array.isArray(t)?t:t.split(`
451
+ `);if(g.length>0){const[p,...f]=g;p.length>0?a.push(`${l}${p}`):a.push(c?i:"");for(const h of f)h.length>0?a.push(`${d}${h}`):a.push(c?s:"");}r.write(`${a.join(`
452
+ `)}
453
+ `);},info:(t,i)=>{R.message(t,{...i,symbol:styleText("blue",ht)});},success:(t,i)=>{R.message(t,{...i,symbol:styleText("green",pt)});},step:(t,i)=>{R.message(t,{...i,symbol:styleText("green",H)});},warn:(t,i)=>{R.message(t,{...i,symbol:styleText("yellow",mt)});},warning:(t,i)=>{R.warn(t,i);},error:(t,i)=>{R.message(t,{...i,symbol:styleText("red",gt)});}},me=(t="",i)=>{const s=process.stdout,r=`${styleText("gray",x)} `;s.write(`${r}${styleText("red",t)}
454
+
455
+ `);},ge=(t="",i)=>{const s=process.stdout,r=`${styleText("gray",lt)} `;s.write(`${r}${t}
456
+ `);},ye=(t="",i)=>{const s=process.stdout,r=`${styleText("gray",$)}
457
+ ${styleText("gray",x)} `;s.write(`${r}${t}
458
+
459
+ `);},Q=(t,i)=>t.split(`
460
+ `).map(s=>i(s)).join(`
461
+ `),ve=t=>{const i=(r,u)=>{const n=r.label??String(r.value);return u==="disabled"?`${styleText("gray",Y)} ${Q(n,a=>styleText(["strikethrough","gray"],a))}${r.hint?` ${styleText("dim",`(${r.hint??"disabled"})`)}`:""}`:u==="active"?`${styleText("cyan",et)} ${n}${r.hint?` ${styleText("dim",`(${r.hint})`)}`:""}`:u==="selected"?`${styleText("green",K)} ${Q(n,a=>styleText("dim",a))}${r.hint?` ${styleText("dim",`(${r.hint})`)}`:""}`:u==="cancelled"?`${Q(n,a=>styleText(["strikethrough","dim"],a))}`:u==="active-selected"?`${styleText("green",K)} ${n}${r.hint?` ${styleText("dim",`(${r.hint})`)}`:""}`:u==="submitted"?`${Q(n,a=>styleText("dim",a))}`:`${styleText("dim",Y)} ${Q(n,a=>styleText("dim",a))}`},s=t.required??true;return new nt({options:t.options,signal:t.signal,input:t.input,output:t.output,initialValues:t.initialValues,required:s,cursorAt:t.cursorAt,validate(r){if(s&&(r===void 0||r.length===0))return `Please select at least one option.
462
+ ${styleText("reset",styleText("dim",`Press ${styleText(["gray","bgWhite","inverse"]," space ")} to select, ${styleText("gray",styleText("bgWhite",styleText("inverse"," enter ")))} to submit`))}`},render(){const r=t.withGuide??h.withGuide,u=W(t.output,t.message,r?`${yt(this.state)} `:"",`${P(this.state)} `),n=`${r?`${styleText("gray",$)}
463
+ `:""}${u}
464
+ `,a=this.value??[],c=(o,l)=>{if(o.disabled)return i(o,"disabled");const d=a.includes(o.value);return l&&d?i(o,"active-selected"):d?i(o,"selected"):i(o,l?"active":"inactive")};switch(this.state){case "submit":{const o=this.options.filter(({value:d})=>a.includes(d)).map(d=>i(d,"submitted")).join(styleText("dim",", "))||styleText("dim","none"),l=W(t.output,o,r?`${styleText("gray",$)} `:"");return `${n}${l}`}case "cancel":{const o=this.options.filter(({value:d})=>a.includes(d)).map(d=>i(d,"cancelled")).join(styleText("dim",", "));if(o.trim()==="")return `${n}${styleText("gray",$)}`;const l=W(t.output,o,r?`${styleText("gray",$)} `:"");return `${n}${l}${r?`
465
+ ${styleText("gray",$)}`:""}`}case "error":{const o=r?`${styleText("yellow",$)} `:"",l=this.error.split(`
466
+ `).map((p,f)=>f===0?`${r?`${styleText("yellow",x)} `:""}${styleText("yellow",p)}`:` ${p}`).join(`
467
+ `),d=n.split(`
468
+ `).length,g=l.split(`
469
+ `).length+1;return `${n}${o}${F({output:t.output,options:this.options,cursor:this.cursor,maxItems:t.maxItems,columnPadding:o.length,rowPadding:d+g,style:c}).join(`
470
+ ${o}`)}
471
+ ${l}
472
+ `}default:{const o=r?`${styleText("cyan",$)} `:"",l=n.split(`
473
+ `).length,d=r?2:1;return `${n}${o}${F({output:t.output,options:this.options,cursor:this.cursor,maxItems:t.maxItems,columnPadding:o.length,rowPadding:l+d,style:c}).join(`
474
+ ${o}`)}
475
+ ${r?styleText("cyan",x):""}
476
+ `}}}}).prompt()},we=t=>styleText("dim",t),be=(t,i,s)=>{const r={hard:true,trim:false},u=wrapAnsi(t,i,r).split(`
477
+ `),n=u.reduce((o,l)=>Math.max(fastStringWidth(l),o),0),a=u.map(s).reduce((o,l)=>Math.max(fastStringWidth(l),o),0),c=i-(a-n);return wrapAnsi(t,c,r)},Se=(t="",i="",s)=>{const r=V.stdout,n=we,a=["",...be(t,A(r)-6,n).split(`
478
+ `).map(n),""],c=fastStringWidth(i),o=Math.max(a.reduce((p,f)=>{const h=fastStringWidth(f);return h>p?h:p},0),c)+2,l=a.map(p=>`${styleText("gray",$)} ${p}${" ".repeat(o-fastStringWidth(p))}${styleText("gray",$)}`).join(`
479
+ `),d=`${styleText("gray",$)}
480
+ `,g=Gt;r.write(`${d}${styleText("green",H)} ${styleText("reset",i)} ${styleText("gray",st.repeat(Math.max(o-c-1,1))+ct)}
481
+ ${l}
482
+ ${styleText("gray",g+st.repeat(o+2)+$t)}
483
+ `);},Te=t=>styleText("magenta",t),ft=({indicator:t="dots",onCancel:i,output:s=process.stdout,cancelMessage:r,errorMessage:u,frames:n=tt?["\u25D2","\u25D0","\u25D3","\u25D1"]:["\u2022","o","O","0"],delay:a=tt?80:120,signal:c,...o}={})=>{const l=ot();let d,g,p=false,f=false,h$1="",I,m=performance.now();const y=A(s),v=o?.styleFrame??Te,C=_=>{const A=_>1?u??h.messages.error:r??h.messages.cancel;f=_===1,p&&(W(A,_),f&&typeof i=="function"&&i());},S=()=>C(2),b=()=>C(1),G=()=>{process.on("uncaughtExceptionMonitor",S),process.on("unhandledRejection",S),process.on("SIGINT",b),process.on("SIGTERM",b),process.on("exit",C),c&&c.addEventListener("abort",b);},M=()=>{process.removeListener("uncaughtExceptionMonitor",S),process.removeListener("unhandledRejection",S),process.removeListener("SIGINT",b),process.removeListener("SIGTERM",b),process.removeListener("exit",C),c&&c.removeEventListener("abort",b);},N=()=>{if(I===void 0)return;l&&s.write(`
484
+ `);const _=wrapAnsi(I,y,{hard:true,trim:false}).split(`
485
+ `);_.length>1&&s.write(srcExports.cursor.up(_.length-1)),s.write(srcExports.cursor.to(0)),s.write(srcExports.erase.down());},O=_=>_.replace(/\.+$/,""),j=_=>{const A=(performance.now()-_)/1e3,L=Math.floor(A/60),D=Math.floor(A%60);return L>0?`[${L}m ${D}s]`:`[${D}s]`},k=o.withGuide??h.withGuide,rt=(_="")=>{p=true,d=R$1({output:s}),h$1=O(_),m=performance.now(),k&&s.write(`${styleText("gray",$)}
486
+ `);let A=0,L=0;G(),g=setInterval(()=>{if(l&&h$1===I)return;N(),I=h$1;const D=v(n[A]);let Z;if(l)Z=`${D} ${h$1}...`;else if(t==="timer")Z=`${D} ${h$1} ${j(m)}`;else {const kt=".".repeat(Math.floor(L)).slice(0,3);Z=`${D} ${h$1}${kt}`;}const Bt=wrapAnsi(Z,y,{hard:true,trim:false});s.write(Bt),A=A+1<n.length?A+1:0,L=L<4?L+.125:0;},a);},W=(_="",A=0,L=false)=>{if(!p)return;p=false,clearInterval(g),N();const D=A===0?styleText("green",H):A===1?styleText("red",at):styleText("red",ut);h$1=_??h$1,L||(t==="timer"?s.write(`${D} ${h$1} ${j(m)}
487
+ `):s.write(`${D} ${h$1}
488
+ `)),M(),d();};return {start:rt,stop:(_="")=>W(_,0),message:(_="")=>{h$1=O(_??h$1);},cancel:(_="")=>W(_,1),error:(_="")=>W(_,2),clear:()=>W("",0,true),get isCancelled(){return f}}};const it=(t,i)=>t.includes(`
489
+ `)?t.split(`
490
+ `).map(s=>i(s)).join(`
491
+ `):i(t),xe=t=>{const i=(s,r)=>{const u=s.label??String(s.value);switch(r){case "disabled":return `${styleText("gray",U)} ${it(u,n=>styleText("gray",n))}${s.hint?` ${styleText("dim",`(${s.hint??"disabled"})`)}`:""}`;case "selected":return `${it(u,n=>styleText("dim",n))}`;case "active":return `${styleText("green",z)} ${u}${s.hint?` ${styleText("dim",`(${s.hint})`)}`:""}`;case "cancelled":return `${it(u,n=>styleText(["strikethrough","dim"],n))}`;default:return `${styleText("dim",U)} ${it(u,n=>styleText("dim",n))}`}};return new ut$1({options:t.options,signal:t.signal,input:t.input,output:t.output,initialValue:t.initialValue,render(){const s=t.withGuide??h.withGuide,r=`${P(this.state)} `,u=`${yt(this.state)} `,n=W(t.output,t.message,u,r),a=`${s?`${styleText("gray",$)}
492
+ `:""}${n}
493
+ `;switch(this.state){case "submit":{const c=s?`${styleText("gray",$)} `:"",o=W(t.output,i(this.options[this.cursor],"selected"),c);return `${a}${o}`}case "cancel":{const c=s?`${styleText("gray",$)} `:"",o=W(t.output,i(this.options[this.cursor],"cancelled"),c);return `${a}${o}${s?`
494
+ ${styleText("gray",$)}`:""}`}default:{const c=s?`${styleText("cyan",$)} `:"",o=s?styleText("cyan",x):"",l=a.split(`
495
+ `).length,d=s?2:1;return `${a}${c}${F({output:t.output,cursor:this.cursor,options:this.options,maxItems:t.maxItems,columnPadding:c.length,rowPadding:l+d,style:(g,p)=>i(g,g.disabled?"disabled":p?"active":"inactive")}).join(`
496
+ ${c}`)}
497
+ ${o}
498
+ `}}}}).prompt()};`${styleText("gray",$)} `;const Pe=t=>new ht$1({validate:t.validate,placeholder:t.placeholder,defaultValue:t.defaultValue,initialValue:t.initialValue,output:t.output,signal:t.signal,input:t.input,render(){const i=t?.withGuide??h.withGuide,s=`${`${i?`${styleText("gray",$)}
499
+ `:""}${P(this.state)} `}${t.message}
500
+ `,r=t.placeholder?styleText("inverse",t.placeholder[0])+styleText("dim",t.placeholder.slice(1)):styleText(["inverse","hidden"],"_"),u=this.userInput?this.userInputWithCursor:r,n=this.value??"";switch(this.state){case "error":{const a=this.error?` ${styleText("yellow",this.error)}`:"",c=i?`${styleText("yellow",$)} `:"",o=i?styleText("yellow",x):"";return `${s.trim()}
501
+ ${c}${u}
502
+ ${o}${a}
503
+ `}case "submit":{const a=n?` ${styleText("dim",n)}`:"",c=i?styleText("gray",$):"";return `${s}${c}${a}`}case "cancel":{const a=n?` ${styleText(["strikethrough","dim"],n)}`:"",c=i?styleText("gray",$):"";return `${s}${c}${a}${n.trim()?`
504
+ ${c}`:""}`}default:{const a=i?`${styleText("cyan",$)} `:"",c=i?styleText("cyan",x):"";return `${s}${a}${u}
505
+ ${c}
506
+ `}}}}).prompt();
507
+
508
+ // from https://github.com/jashkenas/underscore/blob/master/modules/template.js
509
+ const escapeMap = {
510
+ "&": "&amp;",
511
+ "<": "&lt;",
512
+ ">": "&gt;",
513
+ '"': "&quot;",
514
+ };
515
+ const ESCAPE_REGEX = /[&<>"]/g;
516
+ const _ = {
517
+ escape(s) {
518
+ return s.replace(ESCAPE_REGEX, (match) => escapeMap[match]);
519
+ },
520
+ };
521
+ // When customizing `_.templateSettings`, if you don't want to define an
522
+ // interpolation, evaluation or escaping regex, we need one that is
523
+ // guaranteed not to match.
524
+ var noMatch = /(.)^/;
525
+ // Certain characters need to be escaped so that they can be put into a
526
+ // string literal.
527
+ var escapes = {
528
+ "'": "'",
529
+ "\\": "\\",
530
+ "\r": "r",
531
+ "\n": "n",
532
+ "\u2028": "u2028",
533
+ "\u2029": "u2029",
534
+ };
535
+ var escapeRegExp = /\\|'|\r|\n|\u2028|\u2029/g;
536
+ function escapeChar(match) {
537
+ return "\\" + escapes[match];
538
+ }
539
+ // In order to prevent third-party code injection through
540
+ // `_.templateSettings.variable`, we test it against the following regular
541
+ // expression. It is intentionally a bit more liberal than just matching valid
542
+ // identifiers, but still prevents possible loopholes through defaults or
543
+ // destructuring assignment.
544
+ var bareIdentifier = /^\s*(\w|\$)+\s*$/;
545
+ // JavaScript micro-templating, similar to John Resig's implementation.
546
+ // Underscore templating handles arbitrary delimiters, preserves whitespace,
547
+ // and correctly escapes quotes within interpolated code.
548
+ // NB: `oldSettings` only exists for backwards compatibility.
549
+ function compileTemplate(text) {
550
+ const settings = {
551
+ evaluate: /<%([\s\S]+?)%>/g,
552
+ interpolate: /<%=([\s\S]+?)%>/g,
553
+ escape: /<%-([\s\S]+?)%>/g,
554
+ };
555
+ // remove spaces before and newlines after delimiters
556
+ text = text.replace(/%>\r?\n/g, "%>").replace(/[ \t]+<%/g, "<%");
557
+ // Combine delimiters into one regular expression via alternation.
558
+ var matcher = RegExp([
559
+ (settings.escape || noMatch).source,
560
+ (settings.interpolate || noMatch).source,
561
+ (settings.evaluate || noMatch).source,
562
+ ].join("|") + "|$", "g");
563
+ // Compile the template source, escaping string literals appropriately.
564
+ var index = 0;
565
+ var source = "__p+='";
566
+ text.replace(matcher, function (match, escape, interpolate, evaluate, offset) {
567
+ source += text.slice(index, offset).replace(escapeRegExp, escapeChar);
568
+ index = offset + match.length;
569
+ if (escape) {
570
+ source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
571
+ }
572
+ else if (interpolate) {
573
+ source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
574
+ }
575
+ else if (evaluate) {
576
+ source += "';\n" + evaluate + "\n__p+='";
577
+ }
578
+ // Adobe VMs need the match returned to produce the correct offset.
579
+ return match;
580
+ });
581
+ source += "';\n";
582
+ // @ts-expect-error unknown property
583
+ var argument = settings.variable;
584
+ if (argument) {
585
+ // Insure against third-party code injection. (CVE-2021-23358)
586
+ if (!bareIdentifier.test(argument))
587
+ throw new Error("variable is not a bare identifier: " + argument);
588
+ }
589
+ else {
590
+ // If a variable is not specified, place data values in local scope.
591
+ source = "with(obj||{}){\n" + source + "}\n";
592
+ argument = "obj";
593
+ }
594
+ source =
595
+ "var __t,__p='',__j=Array.prototype.join," +
596
+ "print=function(){__p+=__j.call(arguments,'');};\n" +
597
+ source +
598
+ "return __p;\n";
599
+ var render;
600
+ try {
601
+ render = new Function(argument, "_", source);
602
+ }
603
+ catch (e) {
604
+ // @ts-expect-error unknown property
605
+ e.source = source;
606
+ throw e;
607
+ }
608
+ var template = function (data) {
609
+ // @ts-expect-error unknown this
610
+ return render.call(this, data, _);
611
+ };
612
+ // Provide the compiled source as a convenience for precompilation.
613
+ // @ts-expect-error unknown property
614
+ template.source = "function(" + argument + "){\n" + source + "}";
615
+ return template;
616
+ }
617
+
618
+ var nodeTsconfigTemplate = "{\n \"$schema\": \"https://json.schemastore.org/tsconfig\",\n \"extends\": \"@tsconfig/node24/tsconfig.json\",\n \"compilerOptions\": {\n \"types\": [\"node\"],\n \"verbatimModuleSyntax\": true\n },\n \"include\": [\n \"src/**/*.ts\",\n \"test/**/*.ts\"\n ]\n}\n";
619
+
620
+ var bunTsconfigTemplate = "{\n \"compilerOptions\": {\n // Environment setup & latest features\n \"lib\": [\"ESNext\"],\n \"target\": \"ESNext\",\n \"module\": \"Preserve\",\n \"moduleDetection\": \"force\",\n \"jsx\": \"react-jsx\",\n \"allowJs\": true,\n \"types\": [\"bun\"],\n\n // Bundler mode\n \"moduleResolution\": \"bundler\",\n \"allowImportingTsExtensions\": true,\n \"verbatimModuleSyntax\": true,\n \"noEmit\": true,\n\n // Best practices\n \"strict\": true,\n \"skipLibCheck\": true,\n \"noFallthroughCasesInSwitch\": true,\n \"noUncheckedIndexedAccess\": true,\n \"noImplicitOverride\": true,\n\n // Some stricter flags (disabled by default)\n \"noUnusedLocals\": false,\n \"noUnusedParameters\": false,\n \"noPropertyAccessFromIndexSignature\": false\n },\n \"include\": [\n \"src/**/*.ts\",\n \"test/**/*.ts\"\n ]\n}\n";
621
+
622
+ var moduleTemplate = "import { type Module } from \"@tymber/core\";\nimport { HelloWorld } from \"./endpoints/HelloWorld.js\";\n\nexport const MainModule: Module = {\n name: \"main\",\n version: \"0.1.0\",\n\n async init(app) {\n app.endpoint(\"GET\", \"/hello\", HelloWorld);\n },\n};\n";
623
+
624
+ var nodeEntrypointTemplate = "import { App, toNodeHandler } from \"@tymber/core\";\n<% if (db === \"postgres\") { %>\nimport { PostgresDB } from \"@tymber/postgres\";\nimport * as pg from \"pg\";\n<% } %>\n<% if (db === \"sqlite\") { %>\nimport { open } from \"sqlite\";\nimport sqlite3 from \"sqlite3\";\nimport { SQLiteDB } from \"@tymber/sqlite\";\n<% } %>\n<% if (modules.includes(\"admin\")) { %>\nimport { AdminModule } from \"@tymber/admin\";\n<% } %>\n<% if (modules.includes(\"config\")) { %>\nimport { ConfigModule } from \"@tymber/config\";\n<% } %>\n<% if (modules.includes(\"openapi\")) { %>\nimport { OpenApiModule } from \"@tymber/openapi\";\n<% } %>\n<% if (modules.includes(\"user\")) { %>\nimport { UserModule } from \"@tymber/user\";\n<% } %>\nimport { MainModule } from \"./module.js\";\nimport { createServer } from \"node:http\";\n\nasync function main() {\n <% if (db === \"postgres\") { %>\n const pgPool = new pg.Pool({\n user: \"postgres\",\n password: \"changeit\",\n });\n\n const db = new PostgresDB(pgPool);\n <% } %>\n <% if (db === \"sqlite\") { %>\n const dbFile = await open({\n filename: \"/tmp/<%= projectName %>.db\",\n driver: sqlite3.Database,\n });\n\n const db = new SQLiteDB(dbFile);\n <% } %>\n\n const app = await App.create({\n components: [db],\n modules: [\n <% if (modules.includes(\"admin\")) { %>\n AdminModule,\n <% } %>\n <% if (modules.includes(\"config\")) { %>\n ConfigModule,\n <% } %>\n <% if (modules.includes(\"openapi\")) { %>\n OpenApiModule,\n <% } %>\n <% if (modules.includes(\"user\")) { %>\n UserModule,\n <% } %>\n MainModule\n ],\n });\n\n const httpServer = createServer(toNodeHandler(app.fetch));\n\n httpServer.listen(8080, () => {\n console.log(\"Server listening on http://localhost:8080\");\n });\n}\n\nmain().catch(console.error);\n";
625
+
626
+ var bunEntrypointTemplate = "import { App } from \"@tymber/core\";\n<% if (db === \"postgres\") { %>\nimport { PostgresDB } from \"@tymber/postgres\";\nimport * as pg from \"pg\";\n<% } %>\n<% if (db === \"sqlite\") { %>\nimport { open } from \"sqlite\";\nimport sqlite3 from \"sqlite3\";\nimport { SQLiteDB } from \"@tymber/sqlite\";\n<% } %>\n<% if (modules.includes(\"admin\")) { %>\nimport { AdminModule } from \"@tymber/admin\";\n<% } %>\n<% if (modules.includes(\"config\")) { %>\nimport { ConfigModule } from \"@tymber/config\";\n<% } %>\n<% if (modules.includes(\"openapi\")) { %>\nimport { OpenApiModule } from \"@tymber/openapi\";\n<% } %>\n<% if (modules.includes(\"user\")) { %>\nimport { UserModule } from \"@tymber/user\";\n<% } %>\nimport { MainModule } from \"./module.js\";\n\n<% if (db === \"postgres\") { %>\nconst pgPool = new pg.Pool({\n user: \"postgres\",\n password: \"changeit\",\n});\n\nconst db = new PostgresDB(pgPool);\n<% } %>\n<% if (db === \"sqlite\") { %>\nconst dbFile = await open({\n filename: \"/tmp/<%= projectName %>.db\",\n driver: sqlite3.Database,\n});\n\nconst db = new SQLiteDB(dbFile);\n<% } %>\n\nconst app = await App.create({\n components: [db],\n modules: [\n <% if (modules.includes(\"admin\")) { %>\n AdminModule,\n <% } %>\n <% if (modules.includes(\"config\")) { %>\n ConfigModule,\n <% } %>\n <% if (modules.includes(\"openapi\")) { %>\n OpenApiModule,\n <% } %>\n <% if (modules.includes(\"user\")) { %>\n UserModule,\n <% } %>\n MainModule\n ],\n});\n\nexport default {\n port: 8080,\n fetch: app.fetch,\n};\n";
627
+
628
+ var helloWorldTemplate = "import { Endpoint, type HttpContext } from \"@tymber/core\";\n\nexport class HelloWorld extends Endpoint {\n async handle(ctx: HttpContext) {\n return Response.json({ message: \"Hello World\" });\n }\n}\n";
629
+
630
+ var setupTestTemplate = "import { createTestDB } from \"@tymber/<%= db %>\";\nimport { type BaseTestContext, createTestApp } from \"@tymber/core\";\n<% if (modules.includes(\"admin\")) { %>\nimport { AdminModule, initTestDB } from \"@tymber/admin\";\n<% } %>\n<% if (modules.includes(\"config\")) { %>\nimport { ConfigModule } from \"@tymber/config\";\n<% } %>\n<% if (modules.includes(\"openapi\")) { %>\nimport { OpenApiModule } from \"@tymber/openapi\";\n<% } %>\n<% if (modules.includes(\"user\")) { %>\nimport { UserModule } from \"@tymber/user\";\n<% } %>\nimport { MainModule } from \"../src/module.js\";\n\nexport interface TestContext extends BaseTestContext {}\n\nexport async function setup(): Promise<TestContext> {\n const ctx = await createTestApp(() => createTestDB(), [\n <% if (modules.includes(\"admin\")) { %>\n AdminModule,\n <% } %>\n <% if (modules.includes(\"config\")) { %>\n ConfigModule,\n <% } %>\n <% if (modules.includes(\"openapi\")) { %>\n OpenApiModule,\n <% } %>\n <% if (modules.includes(\"user\")) { %>\n UserModule,\n <% } %>\n MainModule\n ]);\n\n <% if (modules.includes(\"admin\")) { %>\n const { adminSessionId, adminUserId } = await initTestDB(ctx.db);\n <% } %>\n <% if (modules.includes(\"config\")) { %>\n process.env.CONFIG_SECRET_KEYS = \"S3cr3T\";\n <% } %>\n\n return {\n ...ctx,\n };\n}\n";
631
+
632
+ var helloWorldTestTemplate = "<% if (isBunRuntime) { %>\nimport { describe, it, beforeAll, afterAll } from \"bun:test\";\n<% } else { %>\nimport { describe, it, before, after } from \"node:test\";\n<% } %>\nimport * as assert from \"node:assert\";\nimport { setup, type TestContext } from \"../setup.js\";\n\ndescribe(\"HelloWorld\", () => {\n let ctx: TestContext;\n\n before<% if (isBunRuntime) { %>All<% } %>(async () => {\n ctx = await setup();\n });\n\n after<% if (isBunRuntime) { %>All<% } %>(() => ctx.close());\n\n it(\"should work\", async () => {\n const res = await fetch(`${ctx.baseUrl}/hello`);\n\n assert.equal(res.status, 200);\n });\n});\n";
633
+
634
+ // @ts-expect-error unknown global
635
+ const isBunRuntime = typeof Bun !== "undefined";
636
+ async function main() {
637
+ ge("Welcome to Tymber project generator!");
638
+ const { projectName, db, modules } = await he({
639
+ projectName: () => Pe({
640
+ message: "Project name",
641
+ placeholder: "tymber-app",
642
+ initialValue: "tymber-app",
643
+ }),
644
+ db: () => xe({
645
+ message: "Database to use",
646
+ options: [
647
+ { value: "postgres", label: "PostgreSQL" },
648
+ { value: "sqlite", label: "SQLite" },
649
+ ],
650
+ }),
651
+ modules: () => ve({
652
+ message: "Modules to include",
653
+ options: [
654
+ { value: "admin", label: "Admin dashboard" },
655
+ { value: "config", label: "Configuration management" },
656
+ { value: "openapi", label: "OpenAPI console" },
657
+ { value: "user", label: "User Management" },
658
+ ],
659
+ required: false,
660
+ }),
661
+ }, {
662
+ onCancel: () => {
663
+ me("Operation cancelled.");
664
+ process.exit(0);
665
+ },
666
+ });
667
+ const projectDir = path.resolve(projectName);
668
+ await fs.mkdir(projectDir, { recursive: true });
669
+ const s = ft();
670
+ s.start(`Creating project in ${projectDir}...`);
671
+ const templateData = {
672
+ projectName,
673
+ isBunRuntime,
674
+ db,
675
+ modules,
676
+ };
677
+ const dependencies = {
678
+ "@tymber/core": "latest",
679
+ [`@tymber/${db}`]: "latest",
680
+ };
681
+ for (const module of modules) {
682
+ dependencies[`@tymber/${module}`] = "latest";
683
+ }
684
+ const packageJsonContent = {
685
+ name: projectName,
686
+ version: "0.0.0",
687
+ type: "module",
688
+ scripts: isBunRuntime
689
+ ? {
690
+ start: "bun src/entrypoint.ts",
691
+ test: "bun test",
692
+ }
693
+ : {
694
+ start: "tsx src/entrypoint.ts",
695
+ test: "tsx --test test/**/*.test.ts",
696
+ },
697
+ dependencies,
698
+ devDependencies: isBunRuntime
699
+ ? {
700
+ "@types/bun": "latest",
701
+ typescript: "latest",
702
+ }
703
+ : {
704
+ "@tsconfig/node24": "latest",
705
+ "@types/node": "latest",
706
+ tsx: "latest",
707
+ typescript: "latest",
708
+ },
709
+ };
710
+ // package.json
711
+ await fs.writeFile(path.join(projectDir, "package.json"), JSON.stringify(packageJsonContent, null, 2));
712
+ // tsconfig.json
713
+ await fs.writeFile(path.join(projectDir, "tsconfig.json"), compileTemplate(isBunRuntime ? bunTsconfigTemplate : nodeTsconfigTemplate)(templateData));
714
+ // src directory
715
+ const srcDir = path.join(projectDir, "src");
716
+ await fs.mkdir(srcDir, { recursive: true });
717
+ // src/entrypoint.ts
718
+ await fs.writeFile(path.join(srcDir, "entrypoint.ts"), compileTemplate(isBunRuntime ? bunEntrypointTemplate : nodeEntrypointTemplate)(templateData));
719
+ // src/module.ts
720
+ await fs.writeFile(path.join(srcDir, "module.ts"), compileTemplate(moduleTemplate)(templateData));
721
+ // src/endpoints/HelloWorld.ts
722
+ const endpointsDir = path.join(srcDir, "endpoints");
723
+ await fs.mkdir(endpointsDir, { recursive: true });
724
+ await fs.writeFile(path.join(endpointsDir, "HelloWorld.ts"), compileTemplate(helloWorldTemplate)(templateData));
725
+ // tests
726
+ const testDir = path.join(projectDir, "test");
727
+ await fs.mkdir(path.join(testDir, "endpoints"), { recursive: true });
728
+ await fs.writeFile(path.join(testDir, "setup.ts"), compileTemplate(setupTestTemplate)(templateData));
729
+ await fs.writeFile(path.join(testDir, "endpoints", "HelloWorld.test.ts"), compileTemplate(helloWorldTestTemplate)(templateData));
730
+ // assets
731
+ const assetSubDirs = ["migrations", "static", "templates", "i18n"];
732
+ for (const subDir of assetSubDirs) {
733
+ const dirPath = path.join(projectDir, "assets", subDir);
734
+ await fs.mkdir(dirPath, { recursive: true });
735
+ await fs.writeFile(path.join(dirPath, ".gitkeep"), "");
736
+ }
737
+ s.stop("Project created successfully!");
738
+ Se(`Next steps:
739
+ cd ${projectName}
740
+ ${isBunRuntime ? "bun install" : "npm install"}
741
+ ${isBunRuntime ? "bun start" : "npm start"}`, "Done!");
742
+ ye("Happy coding!");
743
+ }
744
+ main().catch((err) => {
745
+ R.error(`Error creating project: ${err.message}`);
746
+ process.exit(1);
747
+ });
package/package.json CHANGED
@@ -1,7 +1,28 @@
1
1
  {
2
2
  "name": "@tymber/create",
3
- "version": "0.0.1-alpha.0",
3
+ "version": "0.0.1",
4
4
  "description": "Scaffold a new Tymber project",
5
5
  "license": "MIT",
6
- "author": "Damien ARRACHEQUESNE"
6
+ "author": "Damien ARRACHEQUESNE",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/tymber-framework/tymber.git"
10
+ },
11
+ "type": "module",
12
+ "bin": {
13
+ "create-tymber": "./dist/index.js"
14
+ },
15
+ "scripts": {
16
+ "compile": "rollup -c",
17
+ "format:check": "prettier -c src/",
18
+ "format:fix": "prettier -w src/"
19
+ },
20
+ "files": [
21
+ "dist/"
22
+ ],
23
+ "keywords": [
24
+ "tymber",
25
+ "typescript",
26
+ "framework"
27
+ ]
7
28
  }