najm-cli 0.1.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/dist/index.js +3624 -0
- package/package.json +54 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,3624 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
8
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
|
+
for (let key of __getOwnPropNames(mod))
|
|
11
|
+
if (!__hasOwnProp.call(to, key))
|
|
12
|
+
__defProp(to, key, {
|
|
13
|
+
get: () => mod[key],
|
|
14
|
+
enumerable: true
|
|
15
|
+
});
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
19
|
+
|
|
20
|
+
// ../../node_modules/sisteransi/src/index.js
|
|
21
|
+
var require_src = __commonJS((exports, module) => {
|
|
22
|
+
var ESC = "\x1B";
|
|
23
|
+
var CSI = `${ESC}[`;
|
|
24
|
+
var beep = "\x07";
|
|
25
|
+
var cursor = {
|
|
26
|
+
to(x, y) {
|
|
27
|
+
if (!y)
|
|
28
|
+
return `${CSI}${x + 1}G`;
|
|
29
|
+
return `${CSI}${y + 1};${x + 1}H`;
|
|
30
|
+
},
|
|
31
|
+
move(x, y) {
|
|
32
|
+
let ret = "";
|
|
33
|
+
if (x < 0)
|
|
34
|
+
ret += `${CSI}${-x}D`;
|
|
35
|
+
else if (x > 0)
|
|
36
|
+
ret += `${CSI}${x}C`;
|
|
37
|
+
if (y < 0)
|
|
38
|
+
ret += `${CSI}${-y}A`;
|
|
39
|
+
else if (y > 0)
|
|
40
|
+
ret += `${CSI}${y}B`;
|
|
41
|
+
return ret;
|
|
42
|
+
},
|
|
43
|
+
up: (count = 1) => `${CSI}${count}A`,
|
|
44
|
+
down: (count = 1) => `${CSI}${count}B`,
|
|
45
|
+
forward: (count = 1) => `${CSI}${count}C`,
|
|
46
|
+
backward: (count = 1) => `${CSI}${count}D`,
|
|
47
|
+
nextLine: (count = 1) => `${CSI}E`.repeat(count),
|
|
48
|
+
prevLine: (count = 1) => `${CSI}F`.repeat(count),
|
|
49
|
+
left: `${CSI}G`,
|
|
50
|
+
hide: `${CSI}?25l`,
|
|
51
|
+
show: `${CSI}?25h`,
|
|
52
|
+
save: `${ESC}7`,
|
|
53
|
+
restore: `${ESC}8`
|
|
54
|
+
};
|
|
55
|
+
var scroll = {
|
|
56
|
+
up: (count = 1) => `${CSI}S`.repeat(count),
|
|
57
|
+
down: (count = 1) => `${CSI}T`.repeat(count)
|
|
58
|
+
};
|
|
59
|
+
var erase = {
|
|
60
|
+
screen: `${CSI}2J`,
|
|
61
|
+
up: (count = 1) => `${CSI}1J`.repeat(count),
|
|
62
|
+
down: (count = 1) => `${CSI}J`.repeat(count),
|
|
63
|
+
line: `${CSI}2K`,
|
|
64
|
+
lineEnd: `${CSI}K`,
|
|
65
|
+
lineStart: `${CSI}1K`,
|
|
66
|
+
lines(count) {
|
|
67
|
+
let clear = "";
|
|
68
|
+
for (let i = 0;i < count; i++)
|
|
69
|
+
clear += this.line + (i < count - 1 ? cursor.up() : "");
|
|
70
|
+
if (count)
|
|
71
|
+
clear += cursor.left;
|
|
72
|
+
return clear;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
module.exports = { cursor, scroll, erase, beep };
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// ../../node_modules/picocolors/picocolors.js
|
|
79
|
+
var require_picocolors = __commonJS((exports, module) => {
|
|
80
|
+
var p = process || {};
|
|
81
|
+
var argv = p.argv || [];
|
|
82
|
+
var env = p.env || {};
|
|
83
|
+
var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
|
|
84
|
+
var formatter = (open, close, replace = open) => (input) => {
|
|
85
|
+
let string = "" + input, index = string.indexOf(close, open.length);
|
|
86
|
+
return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
|
|
87
|
+
};
|
|
88
|
+
var replaceClose = (string, close, replace, index) => {
|
|
89
|
+
let result = "", cursor = 0;
|
|
90
|
+
do {
|
|
91
|
+
result += string.substring(cursor, index) + replace;
|
|
92
|
+
cursor = index + close.length;
|
|
93
|
+
index = string.indexOf(close, cursor);
|
|
94
|
+
} while (~index);
|
|
95
|
+
return result + string.substring(cursor);
|
|
96
|
+
};
|
|
97
|
+
var createColors = (enabled = isColorSupported) => {
|
|
98
|
+
let f = enabled ? formatter : () => String;
|
|
99
|
+
return {
|
|
100
|
+
isColorSupported: enabled,
|
|
101
|
+
reset: f("\x1B[0m", "\x1B[0m"),
|
|
102
|
+
bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
|
|
103
|
+
dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
|
|
104
|
+
italic: f("\x1B[3m", "\x1B[23m"),
|
|
105
|
+
underline: f("\x1B[4m", "\x1B[24m"),
|
|
106
|
+
inverse: f("\x1B[7m", "\x1B[27m"),
|
|
107
|
+
hidden: f("\x1B[8m", "\x1B[28m"),
|
|
108
|
+
strikethrough: f("\x1B[9m", "\x1B[29m"),
|
|
109
|
+
black: f("\x1B[30m", "\x1B[39m"),
|
|
110
|
+
red: f("\x1B[31m", "\x1B[39m"),
|
|
111
|
+
green: f("\x1B[32m", "\x1B[39m"),
|
|
112
|
+
yellow: f("\x1B[33m", "\x1B[39m"),
|
|
113
|
+
blue: f("\x1B[34m", "\x1B[39m"),
|
|
114
|
+
magenta: f("\x1B[35m", "\x1B[39m"),
|
|
115
|
+
cyan: f("\x1B[36m", "\x1B[39m"),
|
|
116
|
+
white: f("\x1B[37m", "\x1B[39m"),
|
|
117
|
+
gray: f("\x1B[90m", "\x1B[39m"),
|
|
118
|
+
bgBlack: f("\x1B[40m", "\x1B[49m"),
|
|
119
|
+
bgRed: f("\x1B[41m", "\x1B[49m"),
|
|
120
|
+
bgGreen: f("\x1B[42m", "\x1B[49m"),
|
|
121
|
+
bgYellow: f("\x1B[43m", "\x1B[49m"),
|
|
122
|
+
bgBlue: f("\x1B[44m", "\x1B[49m"),
|
|
123
|
+
bgMagenta: f("\x1B[45m", "\x1B[49m"),
|
|
124
|
+
bgCyan: f("\x1B[46m", "\x1B[49m"),
|
|
125
|
+
bgWhite: f("\x1B[47m", "\x1B[49m"),
|
|
126
|
+
blackBright: f("\x1B[90m", "\x1B[39m"),
|
|
127
|
+
redBright: f("\x1B[91m", "\x1B[39m"),
|
|
128
|
+
greenBright: f("\x1B[92m", "\x1B[39m"),
|
|
129
|
+
yellowBright: f("\x1B[93m", "\x1B[39m"),
|
|
130
|
+
blueBright: f("\x1B[94m", "\x1B[39m"),
|
|
131
|
+
magentaBright: f("\x1B[95m", "\x1B[39m"),
|
|
132
|
+
cyanBright: f("\x1B[96m", "\x1B[39m"),
|
|
133
|
+
whiteBright: f("\x1B[97m", "\x1B[39m"),
|
|
134
|
+
bgBlackBright: f("\x1B[100m", "\x1B[49m"),
|
|
135
|
+
bgRedBright: f("\x1B[101m", "\x1B[49m"),
|
|
136
|
+
bgGreenBright: f("\x1B[102m", "\x1B[49m"),
|
|
137
|
+
bgYellowBright: f("\x1B[103m", "\x1B[49m"),
|
|
138
|
+
bgBlueBright: f("\x1B[104m", "\x1B[49m"),
|
|
139
|
+
bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
|
|
140
|
+
bgCyanBright: f("\x1B[106m", "\x1B[49m"),
|
|
141
|
+
bgWhiteBright: f("\x1B[107m", "\x1B[49m")
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
module.exports = createColors();
|
|
145
|
+
module.exports.createColors = createColors;
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// node_modules/@clack/prompts/node_modules/@clack/core/dist/index.mjs
|
|
149
|
+
var import_sisteransi = __toESM(require_src(), 1);
|
|
150
|
+
import { stdin as j, stdout as M } from "node:process";
|
|
151
|
+
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
152
|
+
import O from "node:readline";
|
|
153
|
+
import { Writable as X } from "node:stream";
|
|
154
|
+
function DD({ onlyFirst: e = false } = {}) {
|
|
155
|
+
const t = ["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))", "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"].join("|");
|
|
156
|
+
return new RegExp(t, e ? undefined : "g");
|
|
157
|
+
}
|
|
158
|
+
var uD = DD();
|
|
159
|
+
function P(e) {
|
|
160
|
+
if (typeof e != "string")
|
|
161
|
+
throw new TypeError(`Expected a \`string\`, got \`${typeof e}\``);
|
|
162
|
+
return e.replace(uD, "");
|
|
163
|
+
}
|
|
164
|
+
function L(e) {
|
|
165
|
+
return e && e.__esModule && Object.prototype.hasOwnProperty.call(e, "default") ? e.default : e;
|
|
166
|
+
}
|
|
167
|
+
var W = { exports: {} };
|
|
168
|
+
(function(e) {
|
|
169
|
+
var u = {};
|
|
170
|
+
e.exports = u, u.eastAsianWidth = function(F) {
|
|
171
|
+
var s = F.charCodeAt(0), i = F.length == 2 ? F.charCodeAt(1) : 0, D = s;
|
|
172
|
+
return 55296 <= s && s <= 56319 && 56320 <= i && i <= 57343 && (s &= 1023, i &= 1023, D = s << 10 | i, D += 65536), D == 12288 || 65281 <= D && D <= 65376 || 65504 <= D && D <= 65510 ? "F" : D == 8361 || 65377 <= D && D <= 65470 || 65474 <= D && D <= 65479 || 65482 <= D && D <= 65487 || 65490 <= D && D <= 65495 || 65498 <= D && D <= 65500 || 65512 <= D && D <= 65518 ? "H" : 4352 <= D && D <= 4447 || 4515 <= D && D <= 4519 || 4602 <= D && D <= 4607 || 9001 <= D && D <= 9002 || 11904 <= D && D <= 11929 || 11931 <= D && D <= 12019 || 12032 <= D && D <= 12245 || 12272 <= D && D <= 12283 || 12289 <= D && D <= 12350 || 12353 <= D && D <= 12438 || 12441 <= D && D <= 12543 || 12549 <= D && D <= 12589 || 12593 <= D && D <= 12686 || 12688 <= D && D <= 12730 || 12736 <= D && D <= 12771 || 12784 <= D && D <= 12830 || 12832 <= D && D <= 12871 || 12880 <= D && D <= 13054 || 13056 <= D && D <= 19903 || 19968 <= D && D <= 42124 || 42128 <= D && D <= 42182 || 43360 <= D && D <= 43388 || 44032 <= D && D <= 55203 || 55216 <= D && D <= 55238 || 55243 <= D && D <= 55291 || 63744 <= D && D <= 64255 || 65040 <= D && D <= 65049 || 65072 <= D && D <= 65106 || 65108 <= D && D <= 65126 || 65128 <= D && D <= 65131 || 110592 <= D && D <= 110593 || 127488 <= D && D <= 127490 || 127504 <= D && D <= 127546 || 127552 <= D && D <= 127560 || 127568 <= D && D <= 127569 || 131072 <= D && D <= 194367 || 177984 <= D && D <= 196605 || 196608 <= D && D <= 262141 ? "W" : 32 <= D && D <= 126 || 162 <= D && D <= 163 || 165 <= D && D <= 166 || D == 172 || D == 175 || 10214 <= D && D <= 10221 || 10629 <= D && D <= 10630 ? "Na" : D == 161 || D == 164 || 167 <= D && D <= 168 || D == 170 || 173 <= D && D <= 174 || 176 <= D && D <= 180 || 182 <= D && D <= 186 || 188 <= D && D <= 191 || D == 198 || D == 208 || 215 <= D && D <= 216 || 222 <= D && D <= 225 || D == 230 || 232 <= D && D <= 234 || 236 <= D && D <= 237 || D == 240 || 242 <= D && D <= 243 || 247 <= D && D <= 250 || D == 252 || D == 254 || D == 257 || D == 273 || D == 275 || D == 283 || 294 <= D && D <= 295 || D == 299 || 305 <= D && D <= 307 || D == 312 || 319 <= D && D <= 322 || D == 324 || 328 <= D && D <= 331 || D == 333 || 338 <= D && D <= 339 || 358 <= D && D <= 359 || D == 363 || D == 462 || D == 464 || D == 466 || D == 468 || D == 470 || D == 472 || D == 474 || D == 476 || D == 593 || D == 609 || D == 708 || D == 711 || 713 <= D && D <= 715 || D == 717 || D == 720 || 728 <= D && D <= 731 || D == 733 || D == 735 || 768 <= D && D <= 879 || 913 <= D && D <= 929 || 931 <= D && D <= 937 || 945 <= D && D <= 961 || 963 <= D && D <= 969 || D == 1025 || 1040 <= D && D <= 1103 || D == 1105 || D == 8208 || 8211 <= D && D <= 8214 || 8216 <= D && D <= 8217 || 8220 <= D && D <= 8221 || 8224 <= D && D <= 8226 || 8228 <= D && D <= 8231 || D == 8240 || 8242 <= D && D <= 8243 || D == 8245 || D == 8251 || D == 8254 || D == 8308 || D == 8319 || 8321 <= D && D <= 8324 || D == 8364 || D == 8451 || D == 8453 || D == 8457 || D == 8467 || D == 8470 || 8481 <= D && D <= 8482 || D == 8486 || D == 8491 || 8531 <= D && D <= 8532 || 8539 <= D && D <= 8542 || 8544 <= D && D <= 8555 || 8560 <= D && D <= 8569 || D == 8585 || 8592 <= D && D <= 8601 || 8632 <= D && D <= 8633 || D == 8658 || D == 8660 || D == 8679 || D == 8704 || 8706 <= D && D <= 8707 || 8711 <= D && D <= 8712 || D == 8715 || D == 8719 || D == 8721 || D == 8725 || D == 8730 || 8733 <= D && D <= 8736 || D == 8739 || D == 8741 || 8743 <= D && D <= 8748 || D == 8750 || 8756 <= D && D <= 8759 || 8764 <= D && D <= 8765 || D == 8776 || D == 8780 || D == 8786 || 8800 <= D && D <= 8801 || 8804 <= D && D <= 8807 || 8810 <= D && D <= 8811 || 8814 <= D && D <= 8815 || 8834 <= D && D <= 8835 || 8838 <= D && D <= 8839 || D == 8853 || D == 8857 || D == 8869 || D == 8895 || D == 8978 || 9312 <= D && D <= 9449 || 9451 <= D && D <= 9547 || 9552 <= D && D <= 9587 || 9600 <= D && D <= 9615 || 9618 <= D && D <= 9621 || 9632 <= D && D <= 9633 || 9635 <= D && D <= 9641 || 9650 <= D && D <= 9651 || 9654 <= D && D <= 9655 || 9660 <= D && D <= 9661 || 9664 <= D && D <= 9665 || 9670 <= D && D <= 9672 || D == 9675 || 9678 <= D && D <= 9681 || 9698 <= D && D <= 9701 || D == 9711 || 9733 <= D && D <= 9734 || D == 9737 || 9742 <= D && D <= 9743 || 9748 <= D && D <= 9749 || D == 9756 || D == 9758 || D == 9792 || D == 9794 || 9824 <= D && D <= 9825 || 9827 <= D && D <= 9829 || 9831 <= D && D <= 9834 || 9836 <= D && D <= 9837 || D == 9839 || 9886 <= D && D <= 9887 || 9918 <= D && D <= 9919 || 9924 <= D && D <= 9933 || 9935 <= D && D <= 9953 || D == 9955 || 9960 <= D && D <= 9983 || D == 10045 || D == 10071 || 10102 <= D && D <= 10111 || 11093 <= D && D <= 11097 || 12872 <= D && D <= 12879 || 57344 <= D && D <= 63743 || 65024 <= D && D <= 65039 || D == 65533 || 127232 <= D && D <= 127242 || 127248 <= D && D <= 127277 || 127280 <= D && D <= 127337 || 127344 <= D && D <= 127386 || 917760 <= D && D <= 917999 || 983040 <= D && D <= 1048573 || 1048576 <= D && D <= 1114109 ? "A" : "N";
|
|
173
|
+
}, u.characterLength = function(F) {
|
|
174
|
+
var s = this.eastAsianWidth(F);
|
|
175
|
+
return s == "F" || s == "W" || s == "A" ? 2 : 1;
|
|
176
|
+
};
|
|
177
|
+
function t(F) {
|
|
178
|
+
return F.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\uD800-\uDFFF]/g) || [];
|
|
179
|
+
}
|
|
180
|
+
u.length = function(F) {
|
|
181
|
+
for (var s = t(F), i = 0, D = 0;D < s.length; D++)
|
|
182
|
+
i = i + this.characterLength(s[D]);
|
|
183
|
+
return i;
|
|
184
|
+
}, u.slice = function(F, s, i) {
|
|
185
|
+
textLen = u.length(F), s = s || 0, i = i || 1, s < 0 && (s = textLen + s), i < 0 && (i = textLen + i);
|
|
186
|
+
for (var D = "", r = 0, n = t(F), E = 0;E < n.length; E++) {
|
|
187
|
+
var a = n[E], o = u.length(a);
|
|
188
|
+
if (r >= s - (o == 2 ? 1 : 0))
|
|
189
|
+
if (r + o <= i)
|
|
190
|
+
D += a;
|
|
191
|
+
else
|
|
192
|
+
break;
|
|
193
|
+
r += o;
|
|
194
|
+
}
|
|
195
|
+
return D;
|
|
196
|
+
};
|
|
197
|
+
})(W);
|
|
198
|
+
var tD = W.exports;
|
|
199
|
+
var eD = L(tD);
|
|
200
|
+
var FD = function() {
|
|
201
|
+
return /\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67)\uDB40\uDC7F|(?:\uD83E\uDDD1\uD83C\uDFFF\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFC-\uDFFF])|\uD83D\uDC68(?:\uD83C\uDFFB(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))?|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])\uFE0F|\u200D(?:(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D[\uDC66\uDC67])|\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC)?|(?:\uD83D\uDC69(?:\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69]))|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC69(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83E\uDDD1(?:\u200D(?:\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDE36\u200D\uD83C\uDF2B|\uD83C\uDFF3\uFE0F\u200D\u26A7|\uD83D\uDC3B\u200D\u2744|(?:(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\uD83C\uDFF4\u200D\u2620|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])\u200D[\u2640\u2642]|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u2600-\u2604\u260E\u2611\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26B0\u26B1\u26C8\u26CF\u26D1\u26D3\u26E9\u26F0\u26F1\u26F4\u26F7\u26F8\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u3030\u303D\u3297\u3299]|\uD83C[\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]|\uD83D[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3])\uFE0F|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDE35\u200D\uD83D\uDCAB|\uD83D\uDE2E\u200D\uD83D\uDCA8|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83E\uDDD1(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83D\uDC69(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF6\uD83C\uDDE6|\uD83C\uDDF4\uD83C\uDDF2|\uD83D\uDC08\u200D\u2B1B|\u2764\uFE0F\u200D(?:\uD83D\uDD25|\uD83E\uDE79)|\uD83D\uDC41\uFE0F|\uD83C\uDFF3\uFE0F|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|[#\*0-9]\uFE0F\u20E3|\u2764\uFE0F|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|\uD83C\uDFF4|(?:[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270C\u270D]|\uD83D[\uDD74\uDD90])(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC08\uDC15\uDC3B\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE2E\uDE35\uDE36\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5]|\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD]|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF]|[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0D\uDD0E\uDD10-\uDD17\uDD1D\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78\uDD7A-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCB\uDDD0\uDDE0-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6]|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26A7\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5-\uDED7\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDD77\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g;
|
|
202
|
+
};
|
|
203
|
+
var sD = L(FD);
|
|
204
|
+
function p(e, u = {}) {
|
|
205
|
+
if (typeof e != "string" || e.length === 0 || (u = { ambiguousIsNarrow: true, ...u }, e = P(e), e.length === 0))
|
|
206
|
+
return 0;
|
|
207
|
+
e = e.replace(sD(), " ");
|
|
208
|
+
const t = u.ambiguousIsNarrow ? 1 : 2;
|
|
209
|
+
let F = 0;
|
|
210
|
+
for (const s of e) {
|
|
211
|
+
const i = s.codePointAt(0);
|
|
212
|
+
if (i <= 31 || i >= 127 && i <= 159 || i >= 768 && i <= 879)
|
|
213
|
+
continue;
|
|
214
|
+
switch (eD.eastAsianWidth(s)) {
|
|
215
|
+
case "F":
|
|
216
|
+
case "W":
|
|
217
|
+
F += 2;
|
|
218
|
+
break;
|
|
219
|
+
case "A":
|
|
220
|
+
F += t;
|
|
221
|
+
break;
|
|
222
|
+
default:
|
|
223
|
+
F += 1;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return F;
|
|
227
|
+
}
|
|
228
|
+
var w = 10;
|
|
229
|
+
var N = (e = 0) => (u) => `\x1B[${u + e}m`;
|
|
230
|
+
var I = (e = 0) => (u) => `\x1B[${38 + e};5;${u}m`;
|
|
231
|
+
var R = (e = 0) => (u, t, F) => `\x1B[${38 + e};2;${u};${t};${F}m`;
|
|
232
|
+
var C = { modifier: { reset: [0, 0], bold: [1, 22], dim: [2, 22], italic: [3, 23], underline: [4, 24], overline: [53, 55], inverse: [7, 27], hidden: [8, 28], strikethrough: [9, 29] }, color: { black: [30, 39], red: [31, 39], green: [32, 39], yellow: [33, 39], blue: [34, 39], magenta: [35, 39], cyan: [36, 39], white: [37, 39], blackBright: [90, 39], gray: [90, 39], grey: [90, 39], redBright: [91, 39], greenBright: [92, 39], yellowBright: [93, 39], blueBright: [94, 39], magentaBright: [95, 39], cyanBright: [96, 39], whiteBright: [97, 39] }, bgColor: { bgBlack: [40, 49], bgRed: [41, 49], bgGreen: [42, 49], bgYellow: [43, 49], bgBlue: [44, 49], bgMagenta: [45, 49], bgCyan: [46, 49], bgWhite: [47, 49], bgBlackBright: [100, 49], bgGray: [100, 49], bgGrey: [100, 49], bgRedBright: [101, 49], bgGreenBright: [102, 49], bgYellowBright: [103, 49], bgBlueBright: [104, 49], bgMagentaBright: [105, 49], bgCyanBright: [106, 49], bgWhiteBright: [107, 49] } };
|
|
233
|
+
Object.keys(C.modifier);
|
|
234
|
+
var iD = Object.keys(C.color);
|
|
235
|
+
var rD = Object.keys(C.bgColor);
|
|
236
|
+
[...iD, ...rD];
|
|
237
|
+
function CD() {
|
|
238
|
+
const e = new Map;
|
|
239
|
+
for (const [u, t] of Object.entries(C)) {
|
|
240
|
+
for (const [F, s] of Object.entries(t))
|
|
241
|
+
C[F] = { open: `\x1B[${s[0]}m`, close: `\x1B[${s[1]}m` }, t[F] = C[F], e.set(s[0], s[1]);
|
|
242
|
+
Object.defineProperty(C, u, { value: t, enumerable: false });
|
|
243
|
+
}
|
|
244
|
+
return Object.defineProperty(C, "codes", { value: e, enumerable: false }), C.color.close = "\x1B[39m", C.bgColor.close = "\x1B[49m", C.color.ansi = N(), C.color.ansi256 = I(), C.color.ansi16m = R(), C.bgColor.ansi = N(w), C.bgColor.ansi256 = I(w), C.bgColor.ansi16m = R(w), Object.defineProperties(C, { rgbToAnsi256: { value: (u, t, F) => u === t && t === F ? u < 8 ? 16 : u > 248 ? 231 : Math.round((u - 8) / 247 * 24) + 232 : 16 + 36 * Math.round(u / 255 * 5) + 6 * Math.round(t / 255 * 5) + Math.round(F / 255 * 5), enumerable: false }, hexToRgb: { value: (u) => {
|
|
245
|
+
const t = /[a-f\d]{6}|[a-f\d]{3}/i.exec(u.toString(16));
|
|
246
|
+
if (!t)
|
|
247
|
+
return [0, 0, 0];
|
|
248
|
+
let [F] = t;
|
|
249
|
+
F.length === 3 && (F = [...F].map((i) => i + i).join(""));
|
|
250
|
+
const s = Number.parseInt(F, 16);
|
|
251
|
+
return [s >> 16 & 255, s >> 8 & 255, s & 255];
|
|
252
|
+
}, enumerable: false }, hexToAnsi256: { value: (u) => C.rgbToAnsi256(...C.hexToRgb(u)), enumerable: false }, ansi256ToAnsi: { value: (u) => {
|
|
253
|
+
if (u < 8)
|
|
254
|
+
return 30 + u;
|
|
255
|
+
if (u < 16)
|
|
256
|
+
return 90 + (u - 8);
|
|
257
|
+
let t, F, s;
|
|
258
|
+
if (u >= 232)
|
|
259
|
+
t = ((u - 232) * 10 + 8) / 255, F = t, s = t;
|
|
260
|
+
else {
|
|
261
|
+
u -= 16;
|
|
262
|
+
const r = u % 36;
|
|
263
|
+
t = Math.floor(u / 36) / 5, F = Math.floor(r / 6) / 5, s = r % 6 / 5;
|
|
264
|
+
}
|
|
265
|
+
const i = Math.max(t, F, s) * 2;
|
|
266
|
+
if (i === 0)
|
|
267
|
+
return 30;
|
|
268
|
+
let D = 30 + (Math.round(s) << 2 | Math.round(F) << 1 | Math.round(t));
|
|
269
|
+
return i === 2 && (D += 60), D;
|
|
270
|
+
}, enumerable: false }, rgbToAnsi: { value: (u, t, F) => C.ansi256ToAnsi(C.rgbToAnsi256(u, t, F)), enumerable: false }, hexToAnsi: { value: (u) => C.ansi256ToAnsi(C.hexToAnsi256(u)), enumerable: false } }), C;
|
|
271
|
+
}
|
|
272
|
+
var ED = CD();
|
|
273
|
+
var d = new Set(["\x1B", ""]);
|
|
274
|
+
var oD = 39;
|
|
275
|
+
var y = "\x07";
|
|
276
|
+
var V = "[";
|
|
277
|
+
var nD = "]";
|
|
278
|
+
var G = "m";
|
|
279
|
+
var _ = `${nD}8;;`;
|
|
280
|
+
var z = (e) => `${d.values().next().value}${V}${e}${G}`;
|
|
281
|
+
var K = (e) => `${d.values().next().value}${_}${e}${y}`;
|
|
282
|
+
var aD = (e) => e.split(" ").map((u) => p(u));
|
|
283
|
+
var k = (e, u, t) => {
|
|
284
|
+
const F = [...u];
|
|
285
|
+
let s = false, i = false, D = p(P(e[e.length - 1]));
|
|
286
|
+
for (const [r, n] of F.entries()) {
|
|
287
|
+
const E = p(n);
|
|
288
|
+
if (D + E <= t ? e[e.length - 1] += n : (e.push(n), D = 0), d.has(n) && (s = true, i = F.slice(r + 1).join("").startsWith(_)), s) {
|
|
289
|
+
i ? n === y && (s = false, i = false) : n === G && (s = false);
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
D += E, D === t && r < F.length - 1 && (e.push(""), D = 0);
|
|
293
|
+
}
|
|
294
|
+
!D && e[e.length - 1].length > 0 && e.length > 1 && (e[e.length - 2] += e.pop());
|
|
295
|
+
};
|
|
296
|
+
var hD = (e) => {
|
|
297
|
+
const u = e.split(" ");
|
|
298
|
+
let t = u.length;
|
|
299
|
+
for (;t > 0 && !(p(u[t - 1]) > 0); )
|
|
300
|
+
t--;
|
|
301
|
+
return t === u.length ? e : u.slice(0, t).join(" ") + u.slice(t).join("");
|
|
302
|
+
};
|
|
303
|
+
var lD = (e, u, t = {}) => {
|
|
304
|
+
if (t.trim !== false && e.trim() === "")
|
|
305
|
+
return "";
|
|
306
|
+
let F = "", s, i;
|
|
307
|
+
const D = aD(e);
|
|
308
|
+
let r = [""];
|
|
309
|
+
for (const [E, a] of e.split(" ").entries()) {
|
|
310
|
+
t.trim !== false && (r[r.length - 1] = r[r.length - 1].trimStart());
|
|
311
|
+
let o = p(r[r.length - 1]);
|
|
312
|
+
if (E !== 0 && (o >= u && (t.wordWrap === false || t.trim === false) && (r.push(""), o = 0), (o > 0 || t.trim === false) && (r[r.length - 1] += " ", o++)), t.hard && D[E] > u) {
|
|
313
|
+
const c = u - o, f = 1 + Math.floor((D[E] - c - 1) / u);
|
|
314
|
+
Math.floor((D[E] - 1) / u) < f && r.push(""), k(r, a, u);
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
if (o + D[E] > u && o > 0 && D[E] > 0) {
|
|
318
|
+
if (t.wordWrap === false && o < u) {
|
|
319
|
+
k(r, a, u);
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
r.push("");
|
|
323
|
+
}
|
|
324
|
+
if (o + D[E] > u && t.wordWrap === false) {
|
|
325
|
+
k(r, a, u);
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
r[r.length - 1] += a;
|
|
329
|
+
}
|
|
330
|
+
t.trim !== false && (r = r.map((E) => hD(E)));
|
|
331
|
+
const n = [...r.join(`
|
|
332
|
+
`)];
|
|
333
|
+
for (const [E, a] of n.entries()) {
|
|
334
|
+
if (F += a, d.has(a)) {
|
|
335
|
+
const { groups: c } = new RegExp(`(?:\\${V}(?<code>\\d+)m|\\${_}(?<uri>.*)${y})`).exec(n.slice(E).join("")) || { groups: {} };
|
|
336
|
+
if (c.code !== undefined) {
|
|
337
|
+
const f = Number.parseFloat(c.code);
|
|
338
|
+
s = f === oD ? undefined : f;
|
|
339
|
+
} else
|
|
340
|
+
c.uri !== undefined && (i = c.uri.length === 0 ? undefined : c.uri);
|
|
341
|
+
}
|
|
342
|
+
const o = ED.codes.get(Number(s));
|
|
343
|
+
n[E + 1] === `
|
|
344
|
+
` ? (i && (F += K("")), s && o && (F += z(o))) : a === `
|
|
345
|
+
` && (s && o && (F += z(s)), i && (F += K(i)));
|
|
346
|
+
}
|
|
347
|
+
return F;
|
|
348
|
+
};
|
|
349
|
+
function Y(e, u, t) {
|
|
350
|
+
return String(e).normalize().replace(/\r\n/g, `
|
|
351
|
+
`).split(`
|
|
352
|
+
`).map((F) => lD(F, u, t)).join(`
|
|
353
|
+
`);
|
|
354
|
+
}
|
|
355
|
+
var xD = ["up", "down", "left", "right", "space", "enter", "cancel"];
|
|
356
|
+
var B = { actions: new Set(xD), aliases: new Map([["k", "up"], ["j", "down"], ["h", "left"], ["l", "right"], ["\x03", "cancel"], ["escape", "cancel"]]) };
|
|
357
|
+
function $(e, u) {
|
|
358
|
+
if (typeof e == "string")
|
|
359
|
+
return B.aliases.get(e) === u;
|
|
360
|
+
for (const t of e)
|
|
361
|
+
if (t !== undefined && $(t, u))
|
|
362
|
+
return true;
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
function BD(e, u) {
|
|
366
|
+
if (e === u)
|
|
367
|
+
return;
|
|
368
|
+
const t = e.split(`
|
|
369
|
+
`), F = u.split(`
|
|
370
|
+
`), s = [];
|
|
371
|
+
for (let i = 0;i < Math.max(t.length, F.length); i++)
|
|
372
|
+
t[i] !== F[i] && s.push(i);
|
|
373
|
+
return s;
|
|
374
|
+
}
|
|
375
|
+
var AD = globalThis.process.platform.startsWith("win");
|
|
376
|
+
var S = Symbol("clack:cancel");
|
|
377
|
+
function pD(e) {
|
|
378
|
+
return e === S;
|
|
379
|
+
}
|
|
380
|
+
function m(e, u) {
|
|
381
|
+
const t = e;
|
|
382
|
+
t.isTTY && t.setRawMode(u);
|
|
383
|
+
}
|
|
384
|
+
var gD = Object.defineProperty;
|
|
385
|
+
var vD = (e, u, t) => (u in e) ? gD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t;
|
|
386
|
+
var h = (e, u, t) => (vD(e, typeof u != "symbol" ? u + "" : u, t), t);
|
|
387
|
+
|
|
388
|
+
class x {
|
|
389
|
+
constructor(u, t = true) {
|
|
390
|
+
h(this, "input"), h(this, "output"), h(this, "_abortSignal"), h(this, "rl"), h(this, "opts"), h(this, "_render"), h(this, "_track", false), h(this, "_prevFrame", ""), h(this, "_subscribers", new Map), h(this, "_cursor", 0), h(this, "state", "initial"), h(this, "error", ""), h(this, "value");
|
|
391
|
+
const { input: F = j, output: s = M, render: i, signal: D, ...r } = u;
|
|
392
|
+
this.opts = r, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = i.bind(this), this._track = t, this._abortSignal = D, this.input = F, this.output = s;
|
|
393
|
+
}
|
|
394
|
+
unsubscribe() {
|
|
395
|
+
this._subscribers.clear();
|
|
396
|
+
}
|
|
397
|
+
setSubscriber(u, t) {
|
|
398
|
+
const F = this._subscribers.get(u) ?? [];
|
|
399
|
+
F.push(t), this._subscribers.set(u, F);
|
|
400
|
+
}
|
|
401
|
+
on(u, t) {
|
|
402
|
+
this.setSubscriber(u, { cb: t });
|
|
403
|
+
}
|
|
404
|
+
once(u, t) {
|
|
405
|
+
this.setSubscriber(u, { cb: t, once: true });
|
|
406
|
+
}
|
|
407
|
+
emit(u, ...t) {
|
|
408
|
+
const F = this._subscribers.get(u) ?? [], s = [];
|
|
409
|
+
for (const i of F)
|
|
410
|
+
i.cb(...t), i.once && s.push(() => F.splice(F.indexOf(i), 1));
|
|
411
|
+
for (const i of s)
|
|
412
|
+
i();
|
|
413
|
+
}
|
|
414
|
+
prompt() {
|
|
415
|
+
return new Promise((u, t) => {
|
|
416
|
+
if (this._abortSignal) {
|
|
417
|
+
if (this._abortSignal.aborted)
|
|
418
|
+
return this.state = "cancel", this.close(), u(S);
|
|
419
|
+
this._abortSignal.addEventListener("abort", () => {
|
|
420
|
+
this.state = "cancel", this.close();
|
|
421
|
+
}, { once: true });
|
|
422
|
+
}
|
|
423
|
+
const F = new X;
|
|
424
|
+
F._write = (s, i, D) => {
|
|
425
|
+
this._track && (this.value = this.rl?.line.replace(/\t/g, ""), this._cursor = this.rl?.cursor ?? 0, this.emit("value", this.value)), D();
|
|
426
|
+
}, this.input.pipe(F), this.rl = O.createInterface({ input: this.input, output: F, tabSize: 2, prompt: "", escapeCodeTimeout: 50, terminal: true }), O.emitKeypressEvents(this.input, this.rl), this.rl.prompt(), this.opts.initialValue !== undefined && this._track && this.rl.write(this.opts.initialValue), this.input.on("keypress", this.onKeypress), m(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => {
|
|
427
|
+
this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), m(this.input, false), u(this.value);
|
|
428
|
+
}), this.once("cancel", () => {
|
|
429
|
+
this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), m(this.input, false), u(S);
|
|
430
|
+
});
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
onKeypress(u, t) {
|
|
434
|
+
if (this.state === "error" && (this.state = "active"), t?.name && (!this._track && B.aliases.has(t.name) && this.emit("cursor", B.aliases.get(t.name)), B.actions.has(t.name) && this.emit("cursor", t.name)), u && (u.toLowerCase() === "y" || u.toLowerCase() === "n") && this.emit("confirm", u.toLowerCase() === "y"), u === "\t" && this.opts.placeholder && (this.value || (this.rl?.write(this.opts.placeholder), this.emit("value", this.opts.placeholder))), u && this.emit("key", u.toLowerCase()), t?.name === "return") {
|
|
435
|
+
if (!this.value && this.opts.placeholder && (this.rl?.write(this.opts.placeholder), this.emit("value", this.opts.placeholder)), this.opts.validate) {
|
|
436
|
+
const F = this.opts.validate(this.value);
|
|
437
|
+
F && (this.error = F instanceof Error ? F.message : F, this.state = "error", this.rl?.write(this.value));
|
|
438
|
+
}
|
|
439
|
+
this.state !== "error" && (this.state = "submit");
|
|
440
|
+
}
|
|
441
|
+
$([u, t?.name, t?.sequence], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
|
|
442
|
+
}
|
|
443
|
+
close() {
|
|
444
|
+
this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
|
|
445
|
+
`), m(this.input, false), this.rl?.close(), this.rl = undefined, this.emit(`${this.state}`, this.value), this.unsubscribe();
|
|
446
|
+
}
|
|
447
|
+
restoreCursor() {
|
|
448
|
+
const u = Y(this._prevFrame, process.stdout.columns, { hard: true }).split(`
|
|
449
|
+
`).length - 1;
|
|
450
|
+
this.output.write(import_sisteransi.cursor.move(-999, u * -1));
|
|
451
|
+
}
|
|
452
|
+
render() {
|
|
453
|
+
const u = Y(this._render(this) ?? "", process.stdout.columns, { hard: true });
|
|
454
|
+
if (u !== this._prevFrame) {
|
|
455
|
+
if (this.state === "initial")
|
|
456
|
+
this.output.write(import_sisteransi.cursor.hide);
|
|
457
|
+
else {
|
|
458
|
+
const t = BD(this._prevFrame, u);
|
|
459
|
+
if (this.restoreCursor(), t && t?.length === 1) {
|
|
460
|
+
const F = t[0];
|
|
461
|
+
this.output.write(import_sisteransi.cursor.move(0, F)), this.output.write(import_sisteransi.erase.lines(1));
|
|
462
|
+
const s = u.split(`
|
|
463
|
+
`);
|
|
464
|
+
this.output.write(s[F]), this._prevFrame = u, this.output.write(import_sisteransi.cursor.move(0, s.length - F - 1));
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
if (t && t?.length > 1) {
|
|
468
|
+
const F = t[0];
|
|
469
|
+
this.output.write(import_sisteransi.cursor.move(0, F)), this.output.write(import_sisteransi.erase.down());
|
|
470
|
+
const s = u.split(`
|
|
471
|
+
`).slice(F);
|
|
472
|
+
this.output.write(s.join(`
|
|
473
|
+
`)), this._prevFrame = u;
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
this.output.write(import_sisteransi.erase.down());
|
|
477
|
+
}
|
|
478
|
+
this.output.write(u), this.state === "initial" && (this.state = "active"), this._prevFrame = u;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
class dD extends x {
|
|
484
|
+
get cursor() {
|
|
485
|
+
return this.value ? 0 : 1;
|
|
486
|
+
}
|
|
487
|
+
get _value() {
|
|
488
|
+
return this.cursor === 0;
|
|
489
|
+
}
|
|
490
|
+
constructor(u) {
|
|
491
|
+
super(u, false), this.value = !!u.initialValue, this.on("value", () => {
|
|
492
|
+
this.value = this._value;
|
|
493
|
+
}), this.on("confirm", (t) => {
|
|
494
|
+
this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = t, this.state = "submit", this.close();
|
|
495
|
+
}), this.on("cursor", () => {
|
|
496
|
+
this.value = !this.value;
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
var A;
|
|
501
|
+
A = new WeakMap;
|
|
502
|
+
var OD = Object.defineProperty;
|
|
503
|
+
var PD = (e, u, t) => (u in e) ? OD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t;
|
|
504
|
+
var J = (e, u, t) => (PD(e, typeof u != "symbol" ? u + "" : u, t), t);
|
|
505
|
+
|
|
506
|
+
class LD extends x {
|
|
507
|
+
constructor(u) {
|
|
508
|
+
super(u, false), J(this, "options"), J(this, "cursor", 0), this.options = u.options, this.cursor = this.options.findIndex(({ value: t }) => t === u.initialValue), this.cursor === -1 && (this.cursor = 0), this.changeValue(), this.on("cursor", (t) => {
|
|
509
|
+
switch (t) {
|
|
510
|
+
case "left":
|
|
511
|
+
case "up":
|
|
512
|
+
this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
|
|
513
|
+
break;
|
|
514
|
+
case "down":
|
|
515
|
+
case "right":
|
|
516
|
+
this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
|
|
517
|
+
break;
|
|
518
|
+
}
|
|
519
|
+
this.changeValue();
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
get _value() {
|
|
523
|
+
return this.options[this.cursor];
|
|
524
|
+
}
|
|
525
|
+
changeValue() {
|
|
526
|
+
this.value = this._value.value;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
class RD extends x {
|
|
530
|
+
get valueWithCursor() {
|
|
531
|
+
if (this.state === "submit")
|
|
532
|
+
return this.value;
|
|
533
|
+
if (this.cursor >= this.value.length)
|
|
534
|
+
return `${this.value}█`;
|
|
535
|
+
const u = this.value.slice(0, this.cursor), [t, ...F] = this.value.slice(this.cursor);
|
|
536
|
+
return `${u}${import_picocolors.default.inverse(t)}${F.join("")}`;
|
|
537
|
+
}
|
|
538
|
+
get cursor() {
|
|
539
|
+
return this._cursor;
|
|
540
|
+
}
|
|
541
|
+
constructor(u) {
|
|
542
|
+
super(u), this.on("finalize", () => {
|
|
543
|
+
this.value || (this.value = u.defaultValue);
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// node_modules/@clack/prompts/dist/index.mjs
|
|
549
|
+
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
550
|
+
var import_sisteransi2 = __toESM(require_src(), 1);
|
|
551
|
+
import y2 from "node:process";
|
|
552
|
+
function ce() {
|
|
553
|
+
return y2.platform !== "win32" ? y2.env.TERM !== "linux" : !!y2.env.CI || !!y2.env.WT_SESSION || !!y2.env.TERMINUS_SUBLIME || y2.env.ConEmuTask === "{cmd::Cmder}" || y2.env.TERM_PROGRAM === "Terminus-Sublime" || y2.env.TERM_PROGRAM === "vscode" || y2.env.TERM === "xterm-256color" || y2.env.TERM === "alacritty" || y2.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
554
|
+
}
|
|
555
|
+
var V2 = ce();
|
|
556
|
+
var u = (t, n) => V2 ? t : n;
|
|
557
|
+
var le = u("◆", "*");
|
|
558
|
+
var L2 = u("■", "x");
|
|
559
|
+
var W2 = u("▲", "x");
|
|
560
|
+
var C2 = u("◇", "o");
|
|
561
|
+
var ue = u("┌", "T");
|
|
562
|
+
var o = u("│", "|");
|
|
563
|
+
var d2 = u("└", "—");
|
|
564
|
+
var k2 = u("●", ">");
|
|
565
|
+
var P2 = u("○", " ");
|
|
566
|
+
var A2 = u("◻", "[•]");
|
|
567
|
+
var T = u("◼", "[+]");
|
|
568
|
+
var F = u("◻", "[ ]");
|
|
569
|
+
var $e = u("▪", "•");
|
|
570
|
+
var _2 = u("─", "-");
|
|
571
|
+
var me = u("╮", "+");
|
|
572
|
+
var de = u("├", "+");
|
|
573
|
+
var pe = u("╯", "+");
|
|
574
|
+
var q = u("●", "•");
|
|
575
|
+
var D = u("◆", "*");
|
|
576
|
+
var U = u("▲", "!");
|
|
577
|
+
var K2 = u("■", "x");
|
|
578
|
+
var b2 = (t) => {
|
|
579
|
+
switch (t) {
|
|
580
|
+
case "initial":
|
|
581
|
+
case "active":
|
|
582
|
+
return import_picocolors2.default.cyan(le);
|
|
583
|
+
case "cancel":
|
|
584
|
+
return import_picocolors2.default.red(L2);
|
|
585
|
+
case "error":
|
|
586
|
+
return import_picocolors2.default.yellow(W2);
|
|
587
|
+
case "submit":
|
|
588
|
+
return import_picocolors2.default.green(C2);
|
|
589
|
+
}
|
|
590
|
+
};
|
|
591
|
+
var G2 = (t) => {
|
|
592
|
+
const { cursor: n, options: r, style: i } = t, s = t.maxItems ?? Number.POSITIVE_INFINITY, c = Math.max(process.stdout.rows - 4, 0), a = Math.min(c, Math.max(s, 5));
|
|
593
|
+
let l2 = 0;
|
|
594
|
+
n >= l2 + a - 3 ? l2 = Math.max(Math.min(n - a + 3, r.length - a), 0) : n < l2 + 2 && (l2 = Math.max(n - 2, 0));
|
|
595
|
+
const $2 = a < r.length && l2 > 0, g = a < r.length && l2 + a < r.length;
|
|
596
|
+
return r.slice(l2, l2 + a).map((p2, v2, f) => {
|
|
597
|
+
const j2 = v2 === 0 && $2, E = v2 === f.length - 1 && g;
|
|
598
|
+
return j2 || E ? import_picocolors2.default.dim("...") : i(p2, v2 + l2 === n);
|
|
599
|
+
});
|
|
600
|
+
};
|
|
601
|
+
var he = (t) => new RD({ validate: t.validate, placeholder: t.placeholder, defaultValue: t.defaultValue, initialValue: t.initialValue, render() {
|
|
602
|
+
const n = `${import_picocolors2.default.gray(o)}
|
|
603
|
+
${b2(this.state)} ${t.message}
|
|
604
|
+
`, r = t.placeholder ? import_picocolors2.default.inverse(t.placeholder[0]) + import_picocolors2.default.dim(t.placeholder.slice(1)) : import_picocolors2.default.inverse(import_picocolors2.default.hidden("_")), i = this.value ? this.valueWithCursor : r;
|
|
605
|
+
switch (this.state) {
|
|
606
|
+
case "error":
|
|
607
|
+
return `${n.trim()}
|
|
608
|
+
${import_picocolors2.default.yellow(o)} ${i}
|
|
609
|
+
${import_picocolors2.default.yellow(d2)} ${import_picocolors2.default.yellow(this.error)}
|
|
610
|
+
`;
|
|
611
|
+
case "submit":
|
|
612
|
+
return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.dim(this.value || t.placeholder)}`;
|
|
613
|
+
case "cancel":
|
|
614
|
+
return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(this.value ?? ""))}${this.value?.trim() ? `
|
|
615
|
+
${import_picocolors2.default.gray(o)}` : ""}`;
|
|
616
|
+
default:
|
|
617
|
+
return `${n}${import_picocolors2.default.cyan(o)} ${i}
|
|
618
|
+
${import_picocolors2.default.cyan(d2)}
|
|
619
|
+
`;
|
|
620
|
+
}
|
|
621
|
+
} }).prompt();
|
|
622
|
+
var ye = (t) => {
|
|
623
|
+
const n = t.active ?? "Yes", r = t.inactive ?? "No";
|
|
624
|
+
return new dD({ active: n, inactive: r, initialValue: t.initialValue ?? true, render() {
|
|
625
|
+
const i = `${import_picocolors2.default.gray(o)}
|
|
626
|
+
${b2(this.state)} ${t.message}
|
|
627
|
+
`, s = this.value ? n : r;
|
|
628
|
+
switch (this.state) {
|
|
629
|
+
case "submit":
|
|
630
|
+
return `${i}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.dim(s)}`;
|
|
631
|
+
case "cancel":
|
|
632
|
+
return `${i}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}
|
|
633
|
+
${import_picocolors2.default.gray(o)}`;
|
|
634
|
+
default:
|
|
635
|
+
return `${i}${import_picocolors2.default.cyan(o)} ${this.value ? `${import_picocolors2.default.green(k2)} ${n}` : `${import_picocolors2.default.dim(P2)} ${import_picocolors2.default.dim(n)}`} ${import_picocolors2.default.dim("/")} ${this.value ? `${import_picocolors2.default.dim(P2)} ${import_picocolors2.default.dim(r)}` : `${import_picocolors2.default.green(k2)} ${r}`}
|
|
636
|
+
${import_picocolors2.default.cyan(d2)}
|
|
637
|
+
`;
|
|
638
|
+
}
|
|
639
|
+
} }).prompt();
|
|
640
|
+
};
|
|
641
|
+
var ve = (t) => {
|
|
642
|
+
const n = (r, i) => {
|
|
643
|
+
const s = r.label ?? String(r.value);
|
|
644
|
+
switch (i) {
|
|
645
|
+
case "selected":
|
|
646
|
+
return `${import_picocolors2.default.dim(s)}`;
|
|
647
|
+
case "active":
|
|
648
|
+
return `${import_picocolors2.default.green(k2)} ${s} ${r.hint ? import_picocolors2.default.dim(`(${r.hint})`) : ""}`;
|
|
649
|
+
case "cancelled":
|
|
650
|
+
return `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}`;
|
|
651
|
+
default:
|
|
652
|
+
return `${import_picocolors2.default.dim(P2)} ${import_picocolors2.default.dim(s)}`;
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
return new LD({ options: t.options, initialValue: t.initialValue, render() {
|
|
656
|
+
const r = `${import_picocolors2.default.gray(o)}
|
|
657
|
+
${b2(this.state)} ${t.message}
|
|
658
|
+
`;
|
|
659
|
+
switch (this.state) {
|
|
660
|
+
case "submit":
|
|
661
|
+
return `${r}${import_picocolors2.default.gray(o)} ${n(this.options[this.cursor], "selected")}`;
|
|
662
|
+
case "cancel":
|
|
663
|
+
return `${r}${import_picocolors2.default.gray(o)} ${n(this.options[this.cursor], "cancelled")}
|
|
664
|
+
${import_picocolors2.default.gray(o)}`;
|
|
665
|
+
default:
|
|
666
|
+
return `${r}${import_picocolors2.default.cyan(o)} ${G2({ cursor: this.cursor, options: this.options, maxItems: t.maxItems, style: (i, s) => n(i, s ? "active" : "inactive") }).join(`
|
|
667
|
+
${import_picocolors2.default.cyan(o)} `)}
|
|
668
|
+
${import_picocolors2.default.cyan(d2)}
|
|
669
|
+
`;
|
|
670
|
+
}
|
|
671
|
+
} }).prompt();
|
|
672
|
+
};
|
|
673
|
+
var Ie = (t = "") => {
|
|
674
|
+
process.stdout.write(`${import_picocolors2.default.gray(ue)} ${t}
|
|
675
|
+
`);
|
|
676
|
+
};
|
|
677
|
+
var Se = (t = "") => {
|
|
678
|
+
process.stdout.write(`${import_picocolors2.default.gray(o)}
|
|
679
|
+
${import_picocolors2.default.gray(d2)} ${t}
|
|
680
|
+
|
|
681
|
+
`);
|
|
682
|
+
};
|
|
683
|
+
var M2 = { message: (t = "", { symbol: n = import_picocolors2.default.gray(o) } = {}) => {
|
|
684
|
+
const r = [`${import_picocolors2.default.gray(o)}`];
|
|
685
|
+
if (t) {
|
|
686
|
+
const [i, ...s] = t.split(`
|
|
687
|
+
`);
|
|
688
|
+
r.push(`${n} ${i}`, ...s.map((c) => `${import_picocolors2.default.gray(o)} ${c}`));
|
|
689
|
+
}
|
|
690
|
+
process.stdout.write(`${r.join(`
|
|
691
|
+
`)}
|
|
692
|
+
`);
|
|
693
|
+
}, info: (t) => {
|
|
694
|
+
M2.message(t, { symbol: import_picocolors2.default.blue(q) });
|
|
695
|
+
}, success: (t) => {
|
|
696
|
+
M2.message(t, { symbol: import_picocolors2.default.green(D) });
|
|
697
|
+
}, step: (t) => {
|
|
698
|
+
M2.message(t, { symbol: import_picocolors2.default.green(C2) });
|
|
699
|
+
}, warn: (t) => {
|
|
700
|
+
M2.message(t, { symbol: import_picocolors2.default.yellow(U) });
|
|
701
|
+
}, warning: (t) => {
|
|
702
|
+
M2.warn(t);
|
|
703
|
+
}, error: (t) => {
|
|
704
|
+
M2.message(t, { symbol: import_picocolors2.default.red(K2) });
|
|
705
|
+
} };
|
|
706
|
+
var J2 = `${import_picocolors2.default.gray(o)} `;
|
|
707
|
+
var Ce = async (t, n) => {
|
|
708
|
+
const r = {}, i = Object.keys(t);
|
|
709
|
+
for (const s of i) {
|
|
710
|
+
const c = t[s], a = await c({ results: r })?.catch((l2) => {
|
|
711
|
+
throw l2;
|
|
712
|
+
});
|
|
713
|
+
if (typeof n?.onCancel == "function" && pD(a)) {
|
|
714
|
+
r[s] = "canceled", n.onCancel({ results: r });
|
|
715
|
+
continue;
|
|
716
|
+
}
|
|
717
|
+
r[s] = a;
|
|
718
|
+
}
|
|
719
|
+
return r;
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
// src/help.ts
|
|
723
|
+
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
724
|
+
async function showHelp() {
|
|
725
|
+
console.log(`
|
|
726
|
+
${import_picocolors3.default.blue("NajmApi Backend CLI")} ${import_picocolors3.default.green("v0.1.0")}
|
|
727
|
+
|
|
728
|
+
${import_picocolors3.default.yellow("USAGE:")}
|
|
729
|
+
najm-api <command>
|
|
730
|
+
|
|
731
|
+
${import_picocolors3.default.yellow("COMMANDS:")}
|
|
732
|
+
${import_picocolors3.default.green("init")} Initialize a new NajmApi project with optional database setup
|
|
733
|
+
${import_picocolors3.default.green("create")} Create a new project from scratch
|
|
734
|
+
${import_picocolors3.default.green("new")} Create a specific component (controller, service, repository, or module)
|
|
735
|
+
${import_picocolors3.default.green("database")} Add database support to an existing project
|
|
736
|
+
${import_picocolors3.default.green("help")} Show this help message
|
|
737
|
+
|
|
738
|
+
${import_picocolors3.default.yellow("NEW COMMAND USAGE:")}
|
|
739
|
+
najm-api new controller UserController Create a new controller
|
|
740
|
+
najm-api new service AuthService Create a new service
|
|
741
|
+
najm-api new repository ProductRepository Create a new repository
|
|
742
|
+
najm-api new module blog Create a complete module
|
|
743
|
+
|
|
744
|
+
${import_picocolors3.default.yellow("DATABASE COMMANDS:")}
|
|
745
|
+
${import_picocolors3.default.green("db:generate")} Generate migrations based on your schema changes
|
|
746
|
+
${import_picocolors3.default.green("db:push")} Push schema changes to your database
|
|
747
|
+
${import_picocolors3.default.green("db:drop")} Drop all database tables
|
|
748
|
+
${import_picocolors3.default.green("db:check")} Check migration status
|
|
749
|
+
|
|
750
|
+
${import_picocolors3.default.yellow("EXAMPLES:")}
|
|
751
|
+
najm-api init Start interactive project creation with optional DB setup
|
|
752
|
+
najm-api generate Start interactive component generation
|
|
753
|
+
najm-api new controller UserController Create a new controller
|
|
754
|
+
najm-api new module blog Create a complete blog module
|
|
755
|
+
najm-api db:setup Add database support to your project
|
|
756
|
+
najm-api help Show this help message
|
|
757
|
+
`);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
// src/templates/index.ts
|
|
761
|
+
var TS_CONFIG = `
|
|
762
|
+
{
|
|
763
|
+
"compilerOptions": {
|
|
764
|
+
"target": "ES2020",
|
|
765
|
+
"module": "ESNext",
|
|
766
|
+
"lib": ["ES2020"],
|
|
767
|
+
"moduleResolution": "bundler",
|
|
768
|
+
"outDir": "./dist",
|
|
769
|
+
"strict": false,
|
|
770
|
+
"declaration": true,
|
|
771
|
+
"declarationMap": false,
|
|
772
|
+
"skipLibCheck": true,
|
|
773
|
+
"emitDeclarationOnly": true,
|
|
774
|
+
"esModuleInterop": true,
|
|
775
|
+
"experimentalDecorators": true,
|
|
776
|
+
"emitDecoratorMetadata": true
|
|
777
|
+
},
|
|
778
|
+
"include": ["src/**/*.ts"],
|
|
779
|
+
"exclude": ["node_modules", "dist", "test"]
|
|
780
|
+
}
|
|
781
|
+
`;
|
|
782
|
+
var BUN_MAIN_CONTENT = `
|
|
783
|
+
import { Server } from 'najm-api';
|
|
784
|
+
import './modules';
|
|
785
|
+
await Server({ port: {{port}} });
|
|
786
|
+
`;
|
|
787
|
+
var NODE_MAIN_CONTENT = `
|
|
788
|
+
import { Server } from 'najm-api';
|
|
789
|
+
import { {{moduleName}}Controller } from './modules/{{moduleName}}s/{{moduleName}}Controller';
|
|
790
|
+
|
|
791
|
+
await Server({
|
|
792
|
+
port: {{port}},
|
|
793
|
+
controllers:[
|
|
794
|
+
{{moduleName}}Controller,
|
|
795
|
+
]
|
|
796
|
+
});
|
|
797
|
+
|
|
798
|
+
`;
|
|
799
|
+
var SERVICE_CONTENT = `
|
|
800
|
+
import { Injectable } from 'najm-api';
|
|
801
|
+
import { {{moduleName}}Repository } from './{{moduleName}}Repository';
|
|
802
|
+
|
|
803
|
+
@Service()
|
|
804
|
+
export class {{moduleName}}Service {
|
|
805
|
+
constructor(private {{moduleName}}Repository: {{moduleName}}Repository) {}
|
|
806
|
+
|
|
807
|
+
async getAll() {
|
|
808
|
+
return await this.{{moduleName}}Repository.getAll();
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
async getById(id) {
|
|
812
|
+
return await this.{{moduleName}}Repository.getById(id);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
async create(data) {
|
|
816
|
+
return await this.{{moduleName}}Repository.create(data);
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
async update(id, data) {
|
|
820
|
+
return await this.{{moduleName}}Repository.update(id, data);
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
async delete(id) {
|
|
824
|
+
return await this.{{moduleName}}Repository.delete(id);
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
`;
|
|
828
|
+
var CONTROLLER_CONTENT = `
|
|
829
|
+
import { Controller, Get, Post, Put, Delete } from 'najm-api';
|
|
830
|
+
import { {{moduleName}}Service } from './{{moduleName}}Service';
|
|
831
|
+
|
|
832
|
+
@Controller('/{{moduleName}}s')
|
|
833
|
+
export class {{moduleName}}Controller {
|
|
834
|
+
constructor(private {{moduleName}}Service: {{moduleName}}Service) {}
|
|
835
|
+
|
|
836
|
+
@Get()
|
|
837
|
+
async get{{moduleNameUpper}}s() {
|
|
838
|
+
return await this.{{moduleName}}Service.getAll();
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
@Get('/:id')
|
|
842
|
+
async get{{moduleNameUpper}}(params) {
|
|
843
|
+
return await this.{{moduleName}}Service.getById(params.id);
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
@Post()
|
|
847
|
+
async create{{moduleNameUpper}}(body) {
|
|
848
|
+
return await this.{{moduleName}}Service.create(body);
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
@Put('/:id')
|
|
852
|
+
async update{{moduleNameUpper}}(params, body) {
|
|
853
|
+
return await this.{{moduleName}}Service.update(params.id, body);
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
@Delete('/:id')
|
|
857
|
+
async delete{{moduleNameUpper}}(params) {
|
|
858
|
+
return await this.{{moduleName}}Service.delete(params.id);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
`;
|
|
862
|
+
var REPOSITORY_CONTENT = `
|
|
863
|
+
import { Repository } from '../../shared/decorators';
|
|
864
|
+
import { DB } from '../../database/db'
|
|
865
|
+
import { {{moduleName}}s } from '../../database/schema';
|
|
866
|
+
import { eq } from 'drizzle-orm';
|
|
867
|
+
|
|
868
|
+
@Repository()
|
|
869
|
+
export class {{moduleName}}Repository {
|
|
870
|
+
|
|
871
|
+
declare db: DB;
|
|
872
|
+
|
|
873
|
+
async getAll() {
|
|
874
|
+
return await this.db.select().from({{moduleName}}s);
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
async getById(id) {
|
|
878
|
+
const results = await this.db.select().from({{moduleName}}s)
|
|
879
|
+
.where(eq({{moduleName}}s.id, id))
|
|
880
|
+
.limit(1);
|
|
881
|
+
return results[0] || null;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
async create(data) {
|
|
885
|
+
return await this.db.insert({{moduleName}}s).values(data).returning();
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
async update(id, data) {
|
|
889
|
+
return await this.db.update({{moduleName}}s)
|
|
890
|
+
.set(data)
|
|
891
|
+
.where(eq({{moduleName}}s.id, id))
|
|
892
|
+
.returning();
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
async delete(id) {
|
|
896
|
+
return await this.db.delete({{moduleName}}s)
|
|
897
|
+
.where(eq({{moduleName}}s.id, id))
|
|
898
|
+
.returning();
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
`;
|
|
902
|
+
var PACKAGE_JSON_TEMPLATE = `{
|
|
903
|
+
"name": "{{projectName}}",
|
|
904
|
+
"version": "{{version}}",
|
|
905
|
+
"description": "{{description}}",
|
|
906
|
+
"author": "{{author}}",
|
|
907
|
+
"license": "MIT",
|
|
908
|
+
"type": "module",
|
|
909
|
+
"main": "src/index.js",
|
|
910
|
+
"scripts": {
|
|
911
|
+
"start": "{{runtime}} src/index.ts",
|
|
912
|
+
"dev": "{{runtime}} --watch src/index.ts",
|
|
913
|
+
"build": "tsc",
|
|
914
|
+
"test": "echo \\"Error: no test specified\\" && exit 1"
|
|
915
|
+
},
|
|
916
|
+
"keywords": [
|
|
917
|
+
"najm-api",
|
|
918
|
+
"hono",
|
|
919
|
+
"api"
|
|
920
|
+
]
|
|
921
|
+
}`;
|
|
922
|
+
var DRIZZLE_CONFIG_TEMPLATE = {
|
|
923
|
+
pg: `import type { Config } from 'drizzle-kit';
|
|
924
|
+
|
|
925
|
+
export default {
|
|
926
|
+
schema: './{{basePath}}/database/schema/*.ts',
|
|
927
|
+
out: './{{basePath}}/database/migrations',
|
|
928
|
+
dialect: 'postgresql',
|
|
929
|
+
dbCredentials: {
|
|
930
|
+
url: process.env.DB_URL!,
|
|
931
|
+
},
|
|
932
|
+
} satisfies Config;`,
|
|
933
|
+
mysql: `import type { Config } from 'drizzle-kit';
|
|
934
|
+
|
|
935
|
+
export default {
|
|
936
|
+
schema: './{{basePath}}/database/schema/*.ts',
|
|
937
|
+
out: './{{basePath}}/database/migrations',
|
|
938
|
+
dialect: 'mysql',
|
|
939
|
+
dbCredentials: {
|
|
940
|
+
url: process.env.DB_URL!,
|
|
941
|
+
},
|
|
942
|
+
} satisfies Config;`,
|
|
943
|
+
sqlite: `import type { Config } from 'drizzle-kit';
|
|
944
|
+
|
|
945
|
+
export default {
|
|
946
|
+
schema: './{{basePath}}/database/schema/*.ts',
|
|
947
|
+
out: './{{basePath}}/database/migrations',
|
|
948
|
+
dialect: 'sqlite',
|
|
949
|
+
dbCredentials: {
|
|
950
|
+
url: process.env.DB_URL!.replace('file:', ''),
|
|
951
|
+
},
|
|
952
|
+
} satisfies Config;`
|
|
953
|
+
};
|
|
954
|
+
var DB_TEMPLATES = {
|
|
955
|
+
pg: `import { drizzle, PostgresJsDatabase } from 'drizzle-orm/postgres-js';
|
|
956
|
+
import * as schema from './schema';
|
|
957
|
+
|
|
958
|
+
export type DB = PostgresJsDatabase<typeof schema>;
|
|
959
|
+
export const db: DB = drizzle(process.env.DB_URL);`,
|
|
960
|
+
mysql: `import { drizzle, MySql2Database } from 'drizzle-orm/mysql2';
|
|
961
|
+
import * as schema from './schema';
|
|
962
|
+
|
|
963
|
+
export type DB = MySql2Database<typeof schema>;
|
|
964
|
+
export const db: DB = drizzle(process.env.DB_URL);`,
|
|
965
|
+
sqlite: `import { drizzle, BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
|
|
966
|
+
import * as schema from './schema';
|
|
967
|
+
|
|
968
|
+
export type DB = BetterSQLite3Database<typeof schema>;
|
|
969
|
+
export const db: DB = drizzle(process.env.DB_URL);`
|
|
970
|
+
};
|
|
971
|
+
var DB_TEST_TEMPLATES = {
|
|
972
|
+
pg: `import { db } from '../db';
|
|
973
|
+
|
|
974
|
+
async function testConnection() {
|
|
975
|
+
try {
|
|
976
|
+
console.log('Testing PostgreSQL connection...');
|
|
977
|
+
const result = await db.execute('select 1');
|
|
978
|
+
console.log('✅ Successfully connected to PostgreSQL database');
|
|
979
|
+
process.exit(0);
|
|
980
|
+
} catch (error) {
|
|
981
|
+
console.error('❌ Failed to connect to PostgreSQL database:', error);
|
|
982
|
+
process.exit(1);
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
testConnection();`,
|
|
987
|
+
mysql: `import { db } from '../db';
|
|
988
|
+
import { sql } from 'drizzle-orm';
|
|
989
|
+
|
|
990
|
+
async function testConnection() {
|
|
991
|
+
try {
|
|
992
|
+
console.log('Testing MySQL connection...');
|
|
993
|
+
const response = await db.select().from(sql\`DUAL\`);
|
|
994
|
+
console.log('✅ Successfully connected to MySQL database');
|
|
995
|
+
process.exit(0);
|
|
996
|
+
} catch (error) {
|
|
997
|
+
console.error('❌ Failed to connect to MySQL database:', error);
|
|
998
|
+
process.exit(1);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
testConnection();`,
|
|
1003
|
+
sqlite: `import { db } from '../db';
|
|
1004
|
+
|
|
1005
|
+
function testConnection() {
|
|
1006
|
+
try {
|
|
1007
|
+
console.log('Testing SQLite connection...');
|
|
1008
|
+
const result = await db.execute('select 1');
|
|
1009
|
+
console.log('✅ Successfully connected to SQLite database');
|
|
1010
|
+
process.exit(0);
|
|
1011
|
+
} catch (error) {
|
|
1012
|
+
console.error('❌ Failed to connect to SQLite database:', error);
|
|
1013
|
+
process.exit(1);
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
testConnection();`
|
|
1018
|
+
};
|
|
1019
|
+
var SCHEMA_TEMPLATES = {
|
|
1020
|
+
pg: `import { pgTable, serial, text, timestamp, boolean, integer, numeric, uniqueIndex } from 'drizzle-orm/pg-core';
|
|
1021
|
+
|
|
1022
|
+
import { nanoid } from 'nanoid';
|
|
1023
|
+
// Users table with common fields
|
|
1024
|
+
export const users = pgTable('users', {
|
|
1025
|
+
id: text('id').primaryKey().notNull().$defaultFn(() => nanoid()),
|
|
1026
|
+
name: text('name').notNull(),
|
|
1027
|
+
email: text('email').notNull().unique(),
|
|
1028
|
+
emailVerified: boolean('emailVerified').default(false),
|
|
1029
|
+
password: text('password').notNull(),
|
|
1030
|
+
image: text('image'),
|
|
1031
|
+
status: text('status').default('pending'),
|
|
1032
|
+
roleId: text('roleId').references(() => roles.id),
|
|
1033
|
+
createdAt: timestamp('createdAt', { mode: 'string' }).defaultNow(),
|
|
1034
|
+
updatedAt: timestamp('updatedAt', { mode: 'string' }).defaultNow(),
|
|
1035
|
+
});
|
|
1036
|
+
|
|
1037
|
+
export const roles = pgTable('roles', {
|
|
1038
|
+
id: text('id').primaryKey().notNull(),
|
|
1039
|
+
name: text('name').notNull(),
|
|
1040
|
+
description: text('description'),
|
|
1041
|
+
});
|
|
1042
|
+
`,
|
|
1043
|
+
mysql: `import { mysqlTable, serial, varchar, timestamp, boolean, int, decimal, uniqueIndex } from 'drizzle-orm/mysql-core';
|
|
1044
|
+
import { nanoid } from 'nanoid';
|
|
1045
|
+
// Users table with common fields
|
|
1046
|
+
export const roles = mysqlTable('roles', {
|
|
1047
|
+
id: varchar('id', { length: 255 }).primaryKey().notNull(),
|
|
1048
|
+
name: varchar('name', { length: 255 }).notNull(),
|
|
1049
|
+
description: text('description'),
|
|
1050
|
+
});
|
|
1051
|
+
|
|
1052
|
+
export const users = mysqlTable('users', {
|
|
1053
|
+
id: varchar('id', { length: 255 }).primaryKey().notNull().$defaultFn(() => nanoid()),
|
|
1054
|
+
name: varchar('name', { length: 255 }).notNull(),
|
|
1055
|
+
email: varchar('email', { length: 255 }).notNull().unique(),
|
|
1056
|
+
emailVerified: boolean('emailVerified').default(false),
|
|
1057
|
+
password: varchar('password', { length: 255 }).notNull(),
|
|
1058
|
+
image: varchar('image', { length: 255 }),
|
|
1059
|
+
status: varchar('status', { length: 255 }).default('pending'),
|
|
1060
|
+
roleId: varchar('roleId', { length: 255 }).references(() => roles.id),
|
|
1061
|
+
createdAt: timestamp('createdAt').defaultNow(),
|
|
1062
|
+
updatedAt: timestamp('updatedAt').defaultNow(),
|
|
1063
|
+
});
|
|
1064
|
+
`,
|
|
1065
|
+
sqlite: `import { sqliteTable, integer, text, blob, uniqueIndex } from 'drizzle-orm/sqlite-core';
|
|
1066
|
+
import { nanoid } from 'nanoid';
|
|
1067
|
+
// Users table with common fields
|
|
1068
|
+
export const users = sqliteTable('users', {
|
|
1069
|
+
id: text('id').primaryKey().notNull().$defaultFn(() => nanoid()),
|
|
1070
|
+
name: text('name').notNull(),
|
|
1071
|
+
email: text('email').notNull().unique(),
|
|
1072
|
+
emailVerified: integer('emailVerified', { mode: 'boolean' }).default(false),
|
|
1073
|
+
password: text('password').notNull(),
|
|
1074
|
+
image: text('image'),
|
|
1075
|
+
status: text('status').default('pending'),
|
|
1076
|
+
roleId: text('roleId').references(() => roles.id),
|
|
1077
|
+
createdAt: timestamp('createdAt').defaultNow(sql'CURRENT_TIMESTAMP'),
|
|
1078
|
+
updatedAt: timestamp('updatedAt').defaultNow(sql'CURRENT_TIMESTAMP'),
|
|
1079
|
+
});
|
|
1080
|
+
|
|
1081
|
+
export const roles = sqliteTable('roles', {
|
|
1082
|
+
id: text('id').primaryKey().notNull(),
|
|
1083
|
+
name: text('name').notNull(),
|
|
1084
|
+
description: text('description'),
|
|
1085
|
+
});
|
|
1086
|
+
`
|
|
1087
|
+
};
|
|
1088
|
+
var DB_DECORATORS_TEMPLATE = `
|
|
1089
|
+
import { Injectable } from 'najm-api';
|
|
1090
|
+
import { db } from '../../database/db';
|
|
1091
|
+
|
|
1092
|
+
/**
|
|
1093
|
+
* Repository decorator for database-backed services
|
|
1094
|
+
* Automatically injects the database instance and applies Injectable
|
|
1095
|
+
*/
|
|
1096
|
+
export function Repository() {
|
|
1097
|
+
return function <T extends new (...args: any[]) => any>(target: T): T {
|
|
1098
|
+
Injectable()(target);
|
|
1099
|
+
|
|
1100
|
+
Object.defineProperty(target.prototype, 'db', {
|
|
1101
|
+
get: function () {
|
|
1102
|
+
return db;
|
|
1103
|
+
},
|
|
1104
|
+
configurable: true
|
|
1105
|
+
});
|
|
1106
|
+
|
|
1107
|
+
return target as T & { prototype: any };
|
|
1108
|
+
};
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
/**
|
|
1112
|
+
* DB property decorator for injecting the database instance
|
|
1113
|
+
* Usage: @DB() private database: DB;
|
|
1114
|
+
*/
|
|
1115
|
+
export function DB() {
|
|
1116
|
+
return function(target: any, propertyKey: string) {
|
|
1117
|
+
const descriptor = {
|
|
1118
|
+
get: function() {
|
|
1119
|
+
return db;
|
|
1120
|
+
},
|
|
1121
|
+
enumerable: true,
|
|
1122
|
+
configurable: true
|
|
1123
|
+
};
|
|
1124
|
+
|
|
1125
|
+
Object.defineProperty(target, propertyKey, descriptor);
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
1128
|
+
`;
|
|
1129
|
+
var NEXT_TEMPLATE = `
|
|
1130
|
+
import { Server } from 'najm-api';
|
|
1131
|
+
import './modules'
|
|
1132
|
+
|
|
1133
|
+
const app = await Server({
|
|
1134
|
+
serverless: true,
|
|
1135
|
+
basePath: '/api',
|
|
1136
|
+
});
|
|
1137
|
+
|
|
1138
|
+
export default app
|
|
1139
|
+
`;
|
|
1140
|
+
|
|
1141
|
+
// src/Commands/InitCommand.ts
|
|
1142
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
1143
|
+
|
|
1144
|
+
// ../../node_modules/strip-json-comments/index.js
|
|
1145
|
+
var singleComment = Symbol("singleComment");
|
|
1146
|
+
var multiComment = Symbol("multiComment");
|
|
1147
|
+
var stripWithoutWhitespace = () => "";
|
|
1148
|
+
var stripWithWhitespace = (string, start, end) => string.slice(start, end).replace(/[^ \t\r\n]/g, " ");
|
|
1149
|
+
var isEscaped = (jsonString, quotePosition) => {
|
|
1150
|
+
let index = quotePosition - 1;
|
|
1151
|
+
let backslashCount = 0;
|
|
1152
|
+
while (jsonString[index] === "\\") {
|
|
1153
|
+
index -= 1;
|
|
1154
|
+
backslashCount += 1;
|
|
1155
|
+
}
|
|
1156
|
+
return Boolean(backslashCount % 2);
|
|
1157
|
+
};
|
|
1158
|
+
function stripJsonComments(jsonString, { whitespace = true, trailingCommas = false } = {}) {
|
|
1159
|
+
if (typeof jsonString !== "string") {
|
|
1160
|
+
throw new TypeError(`Expected argument \`jsonString\` to be a \`string\`, got \`${typeof jsonString}\``);
|
|
1161
|
+
}
|
|
1162
|
+
const strip = whitespace ? stripWithWhitespace : stripWithoutWhitespace;
|
|
1163
|
+
let isInsideString = false;
|
|
1164
|
+
let isInsideComment = false;
|
|
1165
|
+
let offset = 0;
|
|
1166
|
+
let buffer = "";
|
|
1167
|
+
let result = "";
|
|
1168
|
+
let commaIndex = -1;
|
|
1169
|
+
for (let index = 0;index < jsonString.length; index++) {
|
|
1170
|
+
const currentCharacter = jsonString[index];
|
|
1171
|
+
const nextCharacter = jsonString[index + 1];
|
|
1172
|
+
if (!isInsideComment && currentCharacter === '"') {
|
|
1173
|
+
const escaped = isEscaped(jsonString, index);
|
|
1174
|
+
if (!escaped) {
|
|
1175
|
+
isInsideString = !isInsideString;
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
if (isInsideString) {
|
|
1179
|
+
continue;
|
|
1180
|
+
}
|
|
1181
|
+
if (!isInsideComment && currentCharacter + nextCharacter === "//") {
|
|
1182
|
+
buffer += jsonString.slice(offset, index);
|
|
1183
|
+
offset = index;
|
|
1184
|
+
isInsideComment = singleComment;
|
|
1185
|
+
index++;
|
|
1186
|
+
} else if (isInsideComment === singleComment && currentCharacter + nextCharacter === `\r
|
|
1187
|
+
`) {
|
|
1188
|
+
index++;
|
|
1189
|
+
isInsideComment = false;
|
|
1190
|
+
buffer += strip(jsonString, offset, index);
|
|
1191
|
+
offset = index;
|
|
1192
|
+
continue;
|
|
1193
|
+
} else if (isInsideComment === singleComment && currentCharacter === `
|
|
1194
|
+
`) {
|
|
1195
|
+
isInsideComment = false;
|
|
1196
|
+
buffer += strip(jsonString, offset, index);
|
|
1197
|
+
offset = index;
|
|
1198
|
+
} else if (!isInsideComment && currentCharacter + nextCharacter === "/*") {
|
|
1199
|
+
buffer += jsonString.slice(offset, index);
|
|
1200
|
+
offset = index;
|
|
1201
|
+
isInsideComment = multiComment;
|
|
1202
|
+
index++;
|
|
1203
|
+
continue;
|
|
1204
|
+
} else if (isInsideComment === multiComment && currentCharacter + nextCharacter === "*/") {
|
|
1205
|
+
index++;
|
|
1206
|
+
isInsideComment = false;
|
|
1207
|
+
buffer += strip(jsonString, offset, index + 1);
|
|
1208
|
+
offset = index + 1;
|
|
1209
|
+
continue;
|
|
1210
|
+
} else if (trailingCommas && !isInsideComment) {
|
|
1211
|
+
if (commaIndex !== -1) {
|
|
1212
|
+
if (currentCharacter === "}" || currentCharacter === "]") {
|
|
1213
|
+
buffer += jsonString.slice(offset, index);
|
|
1214
|
+
result += strip(buffer, 0, 1) + buffer.slice(1);
|
|
1215
|
+
buffer = "";
|
|
1216
|
+
offset = index;
|
|
1217
|
+
commaIndex = -1;
|
|
1218
|
+
} else if (currentCharacter !== " " && currentCharacter !== "\t" && currentCharacter !== "\r" && currentCharacter !== `
|
|
1219
|
+
`) {
|
|
1220
|
+
buffer += jsonString.slice(offset, index);
|
|
1221
|
+
offset = index;
|
|
1222
|
+
commaIndex = -1;
|
|
1223
|
+
}
|
|
1224
|
+
} else if (currentCharacter === ",") {
|
|
1225
|
+
result += buffer + jsonString.slice(offset, index);
|
|
1226
|
+
buffer = "";
|
|
1227
|
+
offset = index;
|
|
1228
|
+
commaIndex = index;
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
const remaining = isInsideComment === singleComment ? strip(jsonString, offset) : jsonString.slice(offset);
|
|
1233
|
+
return result + buffer + remaining;
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
// src/utils.ts
|
|
1237
|
+
function cleanJsonString(str) {
|
|
1238
|
+
let cleaned = stripJsonComments(str).trim();
|
|
1239
|
+
cleaned = cleaned.replace(/,(\s*[}\]])/g, "$1");
|
|
1240
|
+
cleaned = cleaned.replace(/,(\s*})/g, "$1");
|
|
1241
|
+
cleaned = cleaned.replace(/,(\s*\])/g, "$1");
|
|
1242
|
+
return cleaned;
|
|
1243
|
+
}
|
|
1244
|
+
function isValidProjectName(name) {
|
|
1245
|
+
if (!name)
|
|
1246
|
+
return false;
|
|
1247
|
+
return /^[a-z0-9-_]+$/i.test(name) && name.toLowerCase() === name && name.length <= 214 && !name.startsWith(".");
|
|
1248
|
+
}
|
|
1249
|
+
function isNumber(value) {
|
|
1250
|
+
if (value === null || value === undefined)
|
|
1251
|
+
return false;
|
|
1252
|
+
if (typeof value === "number")
|
|
1253
|
+
return !isNaN(value);
|
|
1254
|
+
if (typeof value === "string") {
|
|
1255
|
+
const trimmed = value.trim();
|
|
1256
|
+
if (trimmed === "")
|
|
1257
|
+
return false;
|
|
1258
|
+
return !isNaN(Number(trimmed)) && isFinite(Number(trimmed));
|
|
1259
|
+
}
|
|
1260
|
+
return false;
|
|
1261
|
+
}
|
|
1262
|
+
function validatePort(value) {
|
|
1263
|
+
if (!value.trim())
|
|
1264
|
+
return;
|
|
1265
|
+
if (!isNumber(value))
|
|
1266
|
+
return "Port must be a valid number";
|
|
1267
|
+
const port = Number(value);
|
|
1268
|
+
if (port < 1 || port > 65535)
|
|
1269
|
+
return "Port must be between 1 and 65535";
|
|
1270
|
+
return;
|
|
1271
|
+
}
|
|
1272
|
+
function validateHostname(value) {
|
|
1273
|
+
if (!value.trim())
|
|
1274
|
+
return;
|
|
1275
|
+
const hostnameRegex = /^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
1276
|
+
if (!["localhost", "127.0.0.1"].includes(value) && !hostnameRegex.test(value)) {
|
|
1277
|
+
return "Invalid hostname format";
|
|
1278
|
+
}
|
|
1279
|
+
return;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
// ../../node_modules/pm-ninja/dist/index.js
|
|
1283
|
+
import * as fs from "fs/promises";
|
|
1284
|
+
import path, { resolve } from "path";
|
|
1285
|
+
import { exec } from "child_process";
|
|
1286
|
+
import { promisify } from "util";
|
|
1287
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
1288
|
+
import { stdout } from "process";
|
|
1289
|
+
var __create2 = Object.create;
|
|
1290
|
+
var __getProtoOf2 = Object.getPrototypeOf;
|
|
1291
|
+
var __defProp2 = Object.defineProperty;
|
|
1292
|
+
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
1293
|
+
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
1294
|
+
var __toESM2 = (mod, isNodeMode, target) => {
|
|
1295
|
+
target = mod != null ? __create2(__getProtoOf2(mod)) : {};
|
|
1296
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp2(target, "default", { value: mod, enumerable: true }) : target;
|
|
1297
|
+
for (let key of __getOwnPropNames2(mod))
|
|
1298
|
+
if (!__hasOwnProp2.call(to, key))
|
|
1299
|
+
__defProp2(to, key, {
|
|
1300
|
+
get: () => mod[key],
|
|
1301
|
+
enumerable: true
|
|
1302
|
+
});
|
|
1303
|
+
return to;
|
|
1304
|
+
};
|
|
1305
|
+
var __commonJS2 = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
1306
|
+
var require_picocolors2 = __commonJS2((exports, module) => {
|
|
1307
|
+
var p2 = process || {};
|
|
1308
|
+
var argv = p2.argv || [];
|
|
1309
|
+
var env = p2.env || {};
|
|
1310
|
+
var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p2.platform === "win32" || (p2.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
|
|
1311
|
+
var formatter = (open, close, replace = open) => (input) => {
|
|
1312
|
+
let string = "" + input, index = string.indexOf(close, open.length);
|
|
1313
|
+
return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
|
|
1314
|
+
};
|
|
1315
|
+
var replaceClose = (string, close, replace, index) => {
|
|
1316
|
+
let result = "", cursor = 0;
|
|
1317
|
+
do {
|
|
1318
|
+
result += string.substring(cursor, index) + replace;
|
|
1319
|
+
cursor = index + close.length;
|
|
1320
|
+
index = string.indexOf(close, cursor);
|
|
1321
|
+
} while (~index);
|
|
1322
|
+
return result + string.substring(cursor);
|
|
1323
|
+
};
|
|
1324
|
+
var createColors = (enabled = isColorSupported) => {
|
|
1325
|
+
let f = enabled ? formatter : () => String;
|
|
1326
|
+
return {
|
|
1327
|
+
isColorSupported: enabled,
|
|
1328
|
+
reset: f("\x1B[0m", "\x1B[0m"),
|
|
1329
|
+
bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
|
|
1330
|
+
dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
|
|
1331
|
+
italic: f("\x1B[3m", "\x1B[23m"),
|
|
1332
|
+
underline: f("\x1B[4m", "\x1B[24m"),
|
|
1333
|
+
inverse: f("\x1B[7m", "\x1B[27m"),
|
|
1334
|
+
hidden: f("\x1B[8m", "\x1B[28m"),
|
|
1335
|
+
strikethrough: f("\x1B[9m", "\x1B[29m"),
|
|
1336
|
+
black: f("\x1B[30m", "\x1B[39m"),
|
|
1337
|
+
red: f("\x1B[31m", "\x1B[39m"),
|
|
1338
|
+
green: f("\x1B[32m", "\x1B[39m"),
|
|
1339
|
+
yellow: f("\x1B[33m", "\x1B[39m"),
|
|
1340
|
+
blue: f("\x1B[34m", "\x1B[39m"),
|
|
1341
|
+
magenta: f("\x1B[35m", "\x1B[39m"),
|
|
1342
|
+
cyan: f("\x1B[36m", "\x1B[39m"),
|
|
1343
|
+
white: f("\x1B[37m", "\x1B[39m"),
|
|
1344
|
+
gray: f("\x1B[90m", "\x1B[39m"),
|
|
1345
|
+
bgBlack: f("\x1B[40m", "\x1B[49m"),
|
|
1346
|
+
bgRed: f("\x1B[41m", "\x1B[49m"),
|
|
1347
|
+
bgGreen: f("\x1B[42m", "\x1B[49m"),
|
|
1348
|
+
bgYellow: f("\x1B[43m", "\x1B[49m"),
|
|
1349
|
+
bgBlue: f("\x1B[44m", "\x1B[49m"),
|
|
1350
|
+
bgMagenta: f("\x1B[45m", "\x1B[49m"),
|
|
1351
|
+
bgCyan: f("\x1B[46m", "\x1B[49m"),
|
|
1352
|
+
bgWhite: f("\x1B[47m", "\x1B[49m"),
|
|
1353
|
+
blackBright: f("\x1B[90m", "\x1B[39m"),
|
|
1354
|
+
redBright: f("\x1B[91m", "\x1B[39m"),
|
|
1355
|
+
greenBright: f("\x1B[92m", "\x1B[39m"),
|
|
1356
|
+
yellowBright: f("\x1B[93m", "\x1B[39m"),
|
|
1357
|
+
blueBright: f("\x1B[94m", "\x1B[39m"),
|
|
1358
|
+
magentaBright: f("\x1B[95m", "\x1B[39m"),
|
|
1359
|
+
cyanBright: f("\x1B[96m", "\x1B[39m"),
|
|
1360
|
+
whiteBright: f("\x1B[97m", "\x1B[39m"),
|
|
1361
|
+
bgBlackBright: f("\x1B[100m", "\x1B[49m"),
|
|
1362
|
+
bgRedBright: f("\x1B[101m", "\x1B[49m"),
|
|
1363
|
+
bgGreenBright: f("\x1B[102m", "\x1B[49m"),
|
|
1364
|
+
bgYellowBright: f("\x1B[103m", "\x1B[49m"),
|
|
1365
|
+
bgBlueBright: f("\x1B[104m", "\x1B[49m"),
|
|
1366
|
+
bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
|
|
1367
|
+
bgCyanBright: f("\x1B[106m", "\x1B[49m"),
|
|
1368
|
+
bgWhiteBright: f("\x1B[107m", "\x1B[49m")
|
|
1369
|
+
};
|
|
1370
|
+
};
|
|
1371
|
+
module.exports = createColors();
|
|
1372
|
+
module.exports.createColors = createColors;
|
|
1373
|
+
});
|
|
1374
|
+
var import_picocolors22 = __toESM2(require_picocolors2(), 1);
|
|
1375
|
+
var import_picocolors4 = __toESM2(require_picocolors2(), 1);
|
|
1376
|
+
var spinners = {
|
|
1377
|
+
dots: ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"],
|
|
1378
|
+
line: ["|", "/", "-", "\\"],
|
|
1379
|
+
arrow: ["←", "↖", "↑", "↗", "→", "↘", "↓", "↙"],
|
|
1380
|
+
bouncingBar: ["[ ]", "[= ]", "[== ]", "[=== ]", "[ ===]", "[ ==]", "[ =]", "[ ]", "[ =]", "[ ==]", "[ ===]", "[====]", "[=== ]", "[== ]", "[= ]"],
|
|
1381
|
+
dots2: [". ", ".. ", "...", " ..", " .", " "],
|
|
1382
|
+
moon: ["\uD83C\uDF11", "\uD83C\uDF12", "\uD83C\uDF13", "\uD83C\uDF14", "\uD83C\uDF15", "\uD83C\uDF16", "\uD83C\uDF17", "\uD83C\uDF18"],
|
|
1383
|
+
clock: ["\uD83D\uDD5B", "\uD83D\uDD50", "\uD83D\uDD51", "\uD83D\uDD52", "\uD83D\uDD53", "\uD83D\uDD54", "\uD83D\uDD55", "\uD83D\uDD56", "\uD83D\uDD57", "\uD83D\uDD58", "\uD83D\uDD59", "\uD83D\uDD5A"],
|
|
1384
|
+
aesthetic: ["◜", "◠", "◝", "◞", "◡", "◟"],
|
|
1385
|
+
squares: ["◰", "◳", "◲", "◱"],
|
|
1386
|
+
dots3: ["⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"],
|
|
1387
|
+
dots4: ["⣷", "⣯", "⣟", "⡿", "⢿", "⣻", "⣽", "⣾"]
|
|
1388
|
+
};
|
|
1389
|
+
|
|
1390
|
+
class Spinner {
|
|
1391
|
+
frames;
|
|
1392
|
+
text;
|
|
1393
|
+
interval;
|
|
1394
|
+
color;
|
|
1395
|
+
currentFrame;
|
|
1396
|
+
timer;
|
|
1397
|
+
active;
|
|
1398
|
+
cleanupListenerAdded;
|
|
1399
|
+
constructor(options = {}) {
|
|
1400
|
+
this.frames = options.frames || spinners.bouncingBar;
|
|
1401
|
+
this.text = options.text || "";
|
|
1402
|
+
this.interval = options.interval || 80;
|
|
1403
|
+
this.color = options.color || null;
|
|
1404
|
+
this.currentFrame = 0;
|
|
1405
|
+
this.timer = null;
|
|
1406
|
+
this.active = false;
|
|
1407
|
+
this.cleanupListenerAdded = false;
|
|
1408
|
+
}
|
|
1409
|
+
start(text) {
|
|
1410
|
+
if (text) {
|
|
1411
|
+
this.text = text;
|
|
1412
|
+
}
|
|
1413
|
+
if (!this.active) {
|
|
1414
|
+
this.active = true;
|
|
1415
|
+
this.hideCursor();
|
|
1416
|
+
this.render();
|
|
1417
|
+
this.timer = setInterval(() => this.render(), this.interval);
|
|
1418
|
+
if (!this.cleanupListenerAdded) {
|
|
1419
|
+
process.on("SIGINT", () => {
|
|
1420
|
+
this.stop();
|
|
1421
|
+
process.exit(0);
|
|
1422
|
+
});
|
|
1423
|
+
process.on("exit", () => {
|
|
1424
|
+
this.stop();
|
|
1425
|
+
});
|
|
1426
|
+
this.cleanupListenerAdded = true;
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
return this;
|
|
1430
|
+
}
|
|
1431
|
+
stop(text) {
|
|
1432
|
+
if (!this.active) {
|
|
1433
|
+
return this;
|
|
1434
|
+
}
|
|
1435
|
+
clearInterval(this.timer);
|
|
1436
|
+
this.timer = null;
|
|
1437
|
+
this.active = false;
|
|
1438
|
+
this.clearLine();
|
|
1439
|
+
if (text) {
|
|
1440
|
+
stdout.write(text + `
|
|
1441
|
+
`);
|
|
1442
|
+
}
|
|
1443
|
+
this.showCursor();
|
|
1444
|
+
return this;
|
|
1445
|
+
}
|
|
1446
|
+
update(text) {
|
|
1447
|
+
this.text = text;
|
|
1448
|
+
return this;
|
|
1449
|
+
}
|
|
1450
|
+
setColor(color) {
|
|
1451
|
+
this.color = color;
|
|
1452
|
+
return this;
|
|
1453
|
+
}
|
|
1454
|
+
isSpinning() {
|
|
1455
|
+
return this.active;
|
|
1456
|
+
}
|
|
1457
|
+
render() {
|
|
1458
|
+
this.clearLine();
|
|
1459
|
+
const frame = this.frames[this.currentFrame];
|
|
1460
|
+
const coloredFrame = this.color ? this.colorize(frame, this.color) : frame;
|
|
1461
|
+
stdout.write(`${coloredFrame} ${this.text}`);
|
|
1462
|
+
this.currentFrame = (this.currentFrame + 1) % this.frames.length;
|
|
1463
|
+
}
|
|
1464
|
+
succeed(text) {
|
|
1465
|
+
this.stop();
|
|
1466
|
+
console.log(`${import_picocolors4.default.green("✓")} ${text || this.text}`);
|
|
1467
|
+
}
|
|
1468
|
+
fail(text) {
|
|
1469
|
+
this.stop();
|
|
1470
|
+
console.log(`${import_picocolors4.default.red("✗")} ${text || this.text}`);
|
|
1471
|
+
}
|
|
1472
|
+
info(text) {
|
|
1473
|
+
this.stop();
|
|
1474
|
+
console.log(`${import_picocolors4.default.blue("ℹ")} ${text || this.text}`);
|
|
1475
|
+
}
|
|
1476
|
+
warn(text) {
|
|
1477
|
+
this.stop();
|
|
1478
|
+
console.log(`${import_picocolors4.default.yellow("⚠")} ${text || this.text}`);
|
|
1479
|
+
}
|
|
1480
|
+
clearLine() {
|
|
1481
|
+
stdout.write("\r\x1B[K");
|
|
1482
|
+
}
|
|
1483
|
+
hideCursor() {
|
|
1484
|
+
stdout.write("\x1B[?25l");
|
|
1485
|
+
}
|
|
1486
|
+
showCursor() {
|
|
1487
|
+
stdout.write("\x1B[?25h");
|
|
1488
|
+
}
|
|
1489
|
+
colorize(text, color) {
|
|
1490
|
+
switch (color) {
|
|
1491
|
+
case "black":
|
|
1492
|
+
return import_picocolors4.default.black(text);
|
|
1493
|
+
case "red":
|
|
1494
|
+
return import_picocolors4.default.red(text);
|
|
1495
|
+
case "green":
|
|
1496
|
+
return import_picocolors4.default.green(text);
|
|
1497
|
+
case "yellow":
|
|
1498
|
+
return import_picocolors4.default.yellow(text);
|
|
1499
|
+
case "blue":
|
|
1500
|
+
return import_picocolors4.default.blue(text);
|
|
1501
|
+
case "magenta":
|
|
1502
|
+
return import_picocolors4.default.magenta(text);
|
|
1503
|
+
case "cyan":
|
|
1504
|
+
return import_picocolors4.default.cyan(text);
|
|
1505
|
+
case "white":
|
|
1506
|
+
return import_picocolors4.default.white(text);
|
|
1507
|
+
case "gray":
|
|
1508
|
+
return import_picocolors4.default.gray(text);
|
|
1509
|
+
default:
|
|
1510
|
+
return text;
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
var cache = new Map;
|
|
1515
|
+
var execAsync = promisify(exec);
|
|
1516
|
+
var INSTALL_COMMANDS = {
|
|
1517
|
+
npm: {
|
|
1518
|
+
dep: "install",
|
|
1519
|
+
devDep: "install -D"
|
|
1520
|
+
},
|
|
1521
|
+
yarn: {
|
|
1522
|
+
dep: "add",
|
|
1523
|
+
devDep: "add -D"
|
|
1524
|
+
},
|
|
1525
|
+
pnpm: {
|
|
1526
|
+
dep: "add",
|
|
1527
|
+
devDep: "add -D"
|
|
1528
|
+
},
|
|
1529
|
+
bun: {
|
|
1530
|
+
dep: "add",
|
|
1531
|
+
devDep: "add -D"
|
|
1532
|
+
}
|
|
1533
|
+
};
|
|
1534
|
+
async function pathExists(p2) {
|
|
1535
|
+
try {
|
|
1536
|
+
await fs.access(p2);
|
|
1537
|
+
return true;
|
|
1538
|
+
} catch {
|
|
1539
|
+
return false;
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
async function getPackageManager(cwd = ".") {
|
|
1543
|
+
const key = `lockfile_${cwd}`;
|
|
1544
|
+
if (cache.has(key)) {
|
|
1545
|
+
return Promise.resolve(cache.get(key));
|
|
1546
|
+
}
|
|
1547
|
+
const [isYarn, isNpm, isPnpm, isBunLock, isBunLockb] = await Promise.all([
|
|
1548
|
+
pathExists(resolve(cwd, "yarn.lock")),
|
|
1549
|
+
pathExists(resolve(cwd, "package-lock.json")),
|
|
1550
|
+
pathExists(resolve(cwd, "pnpm-lock.yaml")),
|
|
1551
|
+
pathExists(resolve(cwd, "bun.lock")),
|
|
1552
|
+
pathExists(resolve(cwd, "bun.lockb"))
|
|
1553
|
+
]);
|
|
1554
|
+
let value = null;
|
|
1555
|
+
if (isYarn) {
|
|
1556
|
+
value = "yarn";
|
|
1557
|
+
} else if (isPnpm) {
|
|
1558
|
+
value = "pnpm";
|
|
1559
|
+
} else if (isBunLock || isBunLockb) {
|
|
1560
|
+
value = "bun";
|
|
1561
|
+
} else if (isNpm) {
|
|
1562
|
+
value = "npm";
|
|
1563
|
+
}
|
|
1564
|
+
cache.set(key, value);
|
|
1565
|
+
return value;
|
|
1566
|
+
}
|
|
1567
|
+
async function readPackageJson() {
|
|
1568
|
+
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
1569
|
+
const content = await readFile2(packageJsonPath, "utf-8");
|
|
1570
|
+
return JSON.parse(content);
|
|
1571
|
+
}
|
|
1572
|
+
async function installPackages(packages, options = {}) {
|
|
1573
|
+
const workingDir = options.cwd || process.cwd();
|
|
1574
|
+
const packageManager = options.pm || await getPackageManager(workingDir);
|
|
1575
|
+
if (!packageManager) {
|
|
1576
|
+
throw new Error("No package manager detected");
|
|
1577
|
+
}
|
|
1578
|
+
const commands = INSTALL_COMMANDS[packageManager];
|
|
1579
|
+
if (!commands) {
|
|
1580
|
+
throw new Error(`Unsupported package manager: ${packageManager}`);
|
|
1581
|
+
}
|
|
1582
|
+
console.log(import_picocolors22.default.cyan(`\uD83D\uDD0D Installing packages in ${import_picocolors22.default.bold(workingDir)} using ${import_picocolors22.default.bold(packageManager)}...`));
|
|
1583
|
+
if (packages.dependencies && packages.dependencies.length > 0) {
|
|
1584
|
+
const depsText = `Installing dependencies: ${import_picocolors22.default.bold(packages.dependencies.join(", "))}`;
|
|
1585
|
+
const spinner = new Spinner({ text: depsText, color: "blue" }).start();
|
|
1586
|
+
const depCommand = `${packageManager} ${commands.dep} ${packages.dependencies.join(" ")}`;
|
|
1587
|
+
try {
|
|
1588
|
+
await execAsync(depCommand, { cwd: workingDir });
|
|
1589
|
+
spinner.stop();
|
|
1590
|
+
} catch (error) {
|
|
1591
|
+
spinner.fail(import_picocolors22.default.red(`Failed to install dependencies: ${error.message}`));
|
|
1592
|
+
throw error;
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
if (packages.devDependencies && packages.devDependencies.length > 0) {
|
|
1596
|
+
const devDepsText = `Installing dev dependencies: ${import_picocolors22.default.bold(packages.devDependencies.join(", "))}`;
|
|
1597
|
+
const spinner = new Spinner({ text: devDepsText, color: "magenta" }).start();
|
|
1598
|
+
const devDepCommand = `${packageManager} ${commands.devDep} ${packages.devDependencies.join(" ")}`;
|
|
1599
|
+
try {
|
|
1600
|
+
await execAsync(devDepCommand, { cwd: workingDir });
|
|
1601
|
+
spinner.stop();
|
|
1602
|
+
} catch (error) {
|
|
1603
|
+
spinner.fail(import_picocolors22.default.red(`Failed to install dev dependencies: ${error.message}`));
|
|
1604
|
+
throw error;
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
console.log(import_picocolors22.default.green("✅ All packages installed successfully \uD83C\uDF89"));
|
|
1608
|
+
}
|
|
1609
|
+
async function runScript(script, args = [], options = {}) {
|
|
1610
|
+
const { cwd = ".", pm: specifiedPM = null, silent = false } = options;
|
|
1611
|
+
const packageManager = specifiedPM || await getPackageManager(cwd);
|
|
1612
|
+
if (!packageManager) {
|
|
1613
|
+
throw new Error("No package manager detected");
|
|
1614
|
+
}
|
|
1615
|
+
const scriptArgs = args.length > 0 ? ` -- ${args.join(" ")}` : "";
|
|
1616
|
+
const fullCommand = `${packageManager} run ${script}${scriptArgs}`;
|
|
1617
|
+
if (!silent)
|
|
1618
|
+
console.log(import_picocolors22.default.cyan(`\uD83D\uDE80 Running script: ${import_picocolors22.default.bold(fullCommand)}`));
|
|
1619
|
+
return await execAsync(fullCommand, { cwd });
|
|
1620
|
+
}
|
|
1621
|
+
async function writePackageJson(packageJson) {
|
|
1622
|
+
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
1623
|
+
await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2) + `
|
|
1624
|
+
`, "utf-8");
|
|
1625
|
+
}
|
|
1626
|
+
async function addScripts(scripts) {
|
|
1627
|
+
const packageJson = await readPackageJson();
|
|
1628
|
+
if (!packageJson.scripts) {
|
|
1629
|
+
packageJson.scripts = {};
|
|
1630
|
+
}
|
|
1631
|
+
packageJson.scripts = {
|
|
1632
|
+
...packageJson.scripts,
|
|
1633
|
+
...scripts
|
|
1634
|
+
};
|
|
1635
|
+
await writePackageJson(packageJson);
|
|
1636
|
+
console.log(import_picocolors22.default.green(`✅ Successfully added/updated scripts: ${import_picocolors22.default.bold(Object.keys(scripts).join(", "))} \uD83D\uDCDD`));
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
// ../../node_modules/forji/dist/index.js
|
|
1640
|
+
import { mkdir, writeFile as writeFile2 } from "fs/promises";
|
|
1641
|
+
import { posix } from "path";
|
|
1642
|
+
function normalizeFileName(name) {
|
|
1643
|
+
if (name.startsWith("'") || name.startsWith('"')) {
|
|
1644
|
+
return name.slice(1, -1);
|
|
1645
|
+
}
|
|
1646
|
+
if (name.includes("$")) {
|
|
1647
|
+
const [baseName, ext] = name.split("$");
|
|
1648
|
+
return `${baseName}.${ext}`;
|
|
1649
|
+
}
|
|
1650
|
+
return name;
|
|
1651
|
+
}
|
|
1652
|
+
var FOLDER_MARKER = Symbol("FOLDER");
|
|
1653
|
+
|
|
1654
|
+
class ProjectBuilder {
|
|
1655
|
+
static instance;
|
|
1656
|
+
pathContentMap;
|
|
1657
|
+
rootPath;
|
|
1658
|
+
files;
|
|
1659
|
+
folders;
|
|
1660
|
+
isBuilt;
|
|
1661
|
+
constructor() {
|
|
1662
|
+
this.pathContentMap = new Map;
|
|
1663
|
+
this.rootPath = "";
|
|
1664
|
+
this.files = {};
|
|
1665
|
+
this.folders = {};
|
|
1666
|
+
this.isBuilt = false;
|
|
1667
|
+
}
|
|
1668
|
+
async build(structure, rootPath, variables = {}) {
|
|
1669
|
+
this.pathContentMap.clear();
|
|
1670
|
+
this.rootPath = rootPath;
|
|
1671
|
+
this.isBuilt = false;
|
|
1672
|
+
await this.analyzeStructure(structure, rootPath, variables);
|
|
1673
|
+
this.folders = await this.createFolders();
|
|
1674
|
+
this.files = await this.createFiles();
|
|
1675
|
+
this.isBuilt = true;
|
|
1676
|
+
}
|
|
1677
|
+
isFolder(content, name) {
|
|
1678
|
+
if (name.includes("$")) {
|
|
1679
|
+
return false;
|
|
1680
|
+
}
|
|
1681
|
+
return typeof content === "object" && content !== null && !Array.isArray(content);
|
|
1682
|
+
}
|
|
1683
|
+
async analyzeStructure(structure, currentPath, variables) {
|
|
1684
|
+
for (const [name, content] of Object.entries(structure)) {
|
|
1685
|
+
const processedName = normalizeFileName(this.processVariables(name, variables));
|
|
1686
|
+
if (this.isFolder(content, name)) {
|
|
1687
|
+
const folderPath = posix.join(currentPath, processedName);
|
|
1688
|
+
this.pathContentMap.set(folderPath, FOLDER_MARKER);
|
|
1689
|
+
await this.analyzeStructure(content, folderPath, variables);
|
|
1690
|
+
} else {
|
|
1691
|
+
if (content === null || content === undefined) {
|
|
1692
|
+
continue;
|
|
1693
|
+
}
|
|
1694
|
+
const filePath = posix.join(currentPath, processedName);
|
|
1695
|
+
const fileContent = this.processVariables(content, variables);
|
|
1696
|
+
this.pathContentMap.set(filePath, fileContent);
|
|
1697
|
+
const parentDir = posix.dirname(filePath);
|
|
1698
|
+
if (!this.pathContentMap.has(parentDir)) {
|
|
1699
|
+
this.pathContentMap.set(parentDir, FOLDER_MARKER);
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
async createFolders() {
|
|
1705
|
+
const folders = Array.from(this.pathContentMap.entries()).filter(([_3, content]) => content === FOLDER_MARKER).map(([path2]) => path2).sort((a, b3) => a.split("/").length - b3.split("/").length);
|
|
1706
|
+
for (const dir of folders) {
|
|
1707
|
+
await mkdir(dir, { recursive: true });
|
|
1708
|
+
}
|
|
1709
|
+
return folders.reduce((acc, path2) => {
|
|
1710
|
+
const name = path2.split("/").pop();
|
|
1711
|
+
acc[name] = path2;
|
|
1712
|
+
return acc;
|
|
1713
|
+
}, {});
|
|
1714
|
+
}
|
|
1715
|
+
async createFiles() {
|
|
1716
|
+
const files = Array.from(this.pathContentMap.entries()).filter(([_3, content]) => content !== FOLDER_MARKER);
|
|
1717
|
+
await Promise.all(files.map(async ([path2, content]) => {
|
|
1718
|
+
try {
|
|
1719
|
+
await writeFile2(path2, content, { flag: "w" });
|
|
1720
|
+
} catch {}
|
|
1721
|
+
}));
|
|
1722
|
+
return files.reduce((acc, [path2]) => {
|
|
1723
|
+
const name = path2.split("/").pop();
|
|
1724
|
+
acc[name] = path2;
|
|
1725
|
+
return acc;
|
|
1726
|
+
}, {});
|
|
1727
|
+
}
|
|
1728
|
+
getFilesByExtension(extension) {
|
|
1729
|
+
const normalizedExt = extension.startsWith(".") ? extension : `.${extension}`;
|
|
1730
|
+
return Object.entries(this.files).filter(([filename, _3]) => filename.endsWith(normalizedExt)).map(([_3, path2]) => path2);
|
|
1731
|
+
}
|
|
1732
|
+
getFilesInFolder(folderName) {
|
|
1733
|
+
const folderPath = this.folders[folderName];
|
|
1734
|
+
if (!folderPath) {
|
|
1735
|
+
throw new Error(`Folder "${folderName}" not found.`);
|
|
1736
|
+
}
|
|
1737
|
+
return Object.entries(this.files).filter(([_3, path2]) => posix.dirname(path2) === folderPath).map(([_3, path2]) => path2);
|
|
1738
|
+
}
|
|
1739
|
+
static getInstance() {
|
|
1740
|
+
if (!ProjectBuilder.instance) {
|
|
1741
|
+
ProjectBuilder.instance = new ProjectBuilder;
|
|
1742
|
+
}
|
|
1743
|
+
return ProjectBuilder.instance;
|
|
1744
|
+
}
|
|
1745
|
+
processVariables(content, variables) {
|
|
1746
|
+
if (typeof content !== "string") {
|
|
1747
|
+
return content;
|
|
1748
|
+
}
|
|
1749
|
+
return content.replace(/\{\{([^}]+)\}\}/g, (match, variableName) => {
|
|
1750
|
+
if (variableName in variables) {
|
|
1751
|
+
return String(variables[variableName]);
|
|
1752
|
+
}
|
|
1753
|
+
return match;
|
|
1754
|
+
});
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
function getFile(fileName) {
|
|
1758
|
+
const builder = ProjectBuilder.getInstance();
|
|
1759
|
+
if (!builder.isBuilt) {
|
|
1760
|
+
throw new Error("Project has not been built yet. Call projectBuild() first.");
|
|
1761
|
+
}
|
|
1762
|
+
return builder.files[fileName];
|
|
1763
|
+
}
|
|
1764
|
+
async function Build(structure, rootPath = process.cwd(), variables = {}) {
|
|
1765
|
+
const builder = ProjectBuilder.getInstance();
|
|
1766
|
+
await builder.build(structure, rootPath, variables);
|
|
1767
|
+
return builder;
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
// src/Commands/InitCommand.ts
|
|
1771
|
+
var import_picocolors5 = __toESM(require_picocolors(), 1);
|
|
1772
|
+
import path2 from "path/posix";
|
|
1773
|
+
|
|
1774
|
+
// ../../node_modules/dotenv-pro/dist/index.js
|
|
1775
|
+
import { join } from "path";
|
|
1776
|
+
import fs2, { existsSync, readFileSync, writeFileSync } from "fs";
|
|
1777
|
+
|
|
1778
|
+
class ProcessSync {
|
|
1779
|
+
static instance = null;
|
|
1780
|
+
autoSync;
|
|
1781
|
+
constructor(autoSync = true) {
|
|
1782
|
+
this.autoSync = autoSync;
|
|
1783
|
+
}
|
|
1784
|
+
static getInstance(autoSync = true) {
|
|
1785
|
+
if (!ProcessSync.instance) {
|
|
1786
|
+
ProcessSync.instance = new ProcessSync(autoSync);
|
|
1787
|
+
}
|
|
1788
|
+
return ProcessSync.instance;
|
|
1789
|
+
}
|
|
1790
|
+
syncToProcess(envVars) {
|
|
1791
|
+
if (!this.autoSync)
|
|
1792
|
+
return;
|
|
1793
|
+
for (const [key, value] of envVars.entries()) {
|
|
1794
|
+
process.env[key] = String(value);
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
removeFromProcess(key) {
|
|
1798
|
+
if (!this.autoSync)
|
|
1799
|
+
return;
|
|
1800
|
+
delete process.env[key];
|
|
1801
|
+
}
|
|
1802
|
+
setAutoSync(value) {
|
|
1803
|
+
this.autoSync = value;
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
var REGEXES = {
|
|
1807
|
+
VARIABLE: /^\s*([A-Za-z_]\w*)\s*=\s*(.*)$/,
|
|
1808
|
+
COMMENT: /#\s*(.+)$/,
|
|
1809
|
+
UNQUOTED_HASH: /(?<!['"`])(?<!^)\s*#/,
|
|
1810
|
+
VAR_REFERENCE: /\${([^}]+)}/g,
|
|
1811
|
+
QUOTED_VALUE: /^(['"`])([\s\S]*)\1$/mg
|
|
1812
|
+
};
|
|
1813
|
+
function removeQuotes(value) {
|
|
1814
|
+
return value.replace(REGEXES.QUOTED_VALUE, "$2");
|
|
1815
|
+
}
|
|
1816
|
+
function handleEscChars(value) {
|
|
1817
|
+
return value.replace(/\\n/g, `
|
|
1818
|
+
`).replace(/\\r/g, "\r").replace(/\\t/g, "\t").replace(/\\\\/g, "\\").replace(/\\"/g, '"').replace(/\\'/g, "'");
|
|
1819
|
+
}
|
|
1820
|
+
function escapeString(value) {
|
|
1821
|
+
return value.replace(/\\/g, "\\\\").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
|
|
1822
|
+
}
|
|
1823
|
+
function findCommentStart(str, char) {
|
|
1824
|
+
let inQuotes = false;
|
|
1825
|
+
let quoteChar = "";
|
|
1826
|
+
let escape = false;
|
|
1827
|
+
for (let i = 0;i < str.length; i++) {
|
|
1828
|
+
const currentChar = str[i];
|
|
1829
|
+
if (escape) {
|
|
1830
|
+
escape = false;
|
|
1831
|
+
continue;
|
|
1832
|
+
}
|
|
1833
|
+
if (currentChar === "\\") {
|
|
1834
|
+
escape = true;
|
|
1835
|
+
continue;
|
|
1836
|
+
}
|
|
1837
|
+
if ((currentChar === '"' || currentChar === "'" || currentChar === "`") && (!inQuotes || currentChar === quoteChar)) {
|
|
1838
|
+
if (!inQuotes)
|
|
1839
|
+
quoteChar = currentChar;
|
|
1840
|
+
inQuotes = !inQuotes;
|
|
1841
|
+
continue;
|
|
1842
|
+
}
|
|
1843
|
+
if (currentChar === char && char === "#") {
|
|
1844
|
+
const isLikelyHexColor = (i === 0 || str[i - 1] === " " || str[i - 1] === "(") && /[A-Fa-f0-9]/.test(str[i + 1] || "");
|
|
1845
|
+
if (!isLikelyHexColor && !inQuotes) {
|
|
1846
|
+
return i;
|
|
1847
|
+
}
|
|
1848
|
+
continue;
|
|
1849
|
+
}
|
|
1850
|
+
if (currentChar === char && !inQuotes) {
|
|
1851
|
+
return i;
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
return -1;
|
|
1855
|
+
}
|
|
1856
|
+
function cleanValue(value) {
|
|
1857
|
+
const unquoted = removeQuotes(value);
|
|
1858
|
+
return handleEscChars(unquoted);
|
|
1859
|
+
}
|
|
1860
|
+
function isEmpty(line) {
|
|
1861
|
+
return line.trim().length === 0;
|
|
1862
|
+
}
|
|
1863
|
+
function isSimpleComment(line) {
|
|
1864
|
+
if (isEmpty(line))
|
|
1865
|
+
return false;
|
|
1866
|
+
return line.trim().startsWith("#");
|
|
1867
|
+
}
|
|
1868
|
+
function isVariable(line) {
|
|
1869
|
+
if (isEmpty(line))
|
|
1870
|
+
return false;
|
|
1871
|
+
if (isSimpleComment(line))
|
|
1872
|
+
return false;
|
|
1873
|
+
const trimmed = line.trim();
|
|
1874
|
+
const match = trimmed.match(REGEXES.VARIABLE);
|
|
1875
|
+
if (!match)
|
|
1876
|
+
return false;
|
|
1877
|
+
const hashIndex = findCommentStart(match[2], "#");
|
|
1878
|
+
return hashIndex === -1;
|
|
1879
|
+
}
|
|
1880
|
+
function isVariableComment(line) {
|
|
1881
|
+
if (isEmpty(line))
|
|
1882
|
+
return false;
|
|
1883
|
+
if (isSimpleComment(line))
|
|
1884
|
+
return false;
|
|
1885
|
+
const trimmed = line.trim();
|
|
1886
|
+
const match = trimmed.match(REGEXES.VARIABLE);
|
|
1887
|
+
if (!match)
|
|
1888
|
+
return false;
|
|
1889
|
+
const hashIndex = findCommentStart(match[2], "#");
|
|
1890
|
+
return hashIndex !== -1;
|
|
1891
|
+
}
|
|
1892
|
+
function getSimpleComment(line) {
|
|
1893
|
+
if (!isSimpleComment(line))
|
|
1894
|
+
return null;
|
|
1895
|
+
const match = line.trim().match(REGEXES.COMMENT);
|
|
1896
|
+
return match ? match[1].trim() : null;
|
|
1897
|
+
}
|
|
1898
|
+
function getVariable(line) {
|
|
1899
|
+
if (!isVariable(line))
|
|
1900
|
+
return null;
|
|
1901
|
+
const match = line.trim().match(REGEXES.VARIABLE);
|
|
1902
|
+
const [_3, name, value] = match;
|
|
1903
|
+
const hashIndex = findCommentStart(value, "#");
|
|
1904
|
+
const valueWithQuotes = hashIndex !== -1 ? value.slice(0, hashIndex).trim() : value.trim();
|
|
1905
|
+
return {
|
|
1906
|
+
name,
|
|
1907
|
+
value: cleanValue(valueWithQuotes)
|
|
1908
|
+
};
|
|
1909
|
+
}
|
|
1910
|
+
function getVariableComment(line) {
|
|
1911
|
+
if (!isVariableComment(line))
|
|
1912
|
+
return null;
|
|
1913
|
+
const trimmed = line.trim();
|
|
1914
|
+
const match = trimmed.match(REGEXES.VARIABLE);
|
|
1915
|
+
if (!match)
|
|
1916
|
+
return null;
|
|
1917
|
+
const [_3, name, valueWithComment] = match;
|
|
1918
|
+
const hashIndex = findCommentStart(valueWithComment, "#");
|
|
1919
|
+
if (hashIndex === -1)
|
|
1920
|
+
return null;
|
|
1921
|
+
const valueWithQuotes = valueWithComment.slice(0, hashIndex).trim();
|
|
1922
|
+
const comment = valueWithComment.slice(hashIndex + 1).trim();
|
|
1923
|
+
return {
|
|
1924
|
+
name,
|
|
1925
|
+
value: cleanValue(valueWithQuotes),
|
|
1926
|
+
comment
|
|
1927
|
+
};
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1930
|
+
class BaseEnvManager {
|
|
1931
|
+
options;
|
|
1932
|
+
processSync;
|
|
1933
|
+
variableManager;
|
|
1934
|
+
commentManager;
|
|
1935
|
+
emptyManager;
|
|
1936
|
+
constructor(options) {
|
|
1937
|
+
this.options = this.normalizeOptions(options);
|
|
1938
|
+
}
|
|
1939
|
+
inputToLine(nameOrInput, value, comment) {
|
|
1940
|
+
if (typeof nameOrInput === "string" && value !== undefined) {
|
|
1941
|
+
return comment ? `${nameOrInput}=${value} # ${comment}` : `${nameOrInput}=${value}`;
|
|
1942
|
+
}
|
|
1943
|
+
if (nameOrInput === null || nameOrInput === undefined || nameOrInput === "") {
|
|
1944
|
+
return "";
|
|
1945
|
+
}
|
|
1946
|
+
if (Array.isArray(nameOrInput)) {
|
|
1947
|
+
const [name, value2, comment2] = nameOrInput;
|
|
1948
|
+
return comment2 ? `${name}=${value2} # ${comment2}` : `${name}=${value2}`;
|
|
1949
|
+
}
|
|
1950
|
+
if (typeof nameOrInput === "object") {
|
|
1951
|
+
const { name, value: value2, comment: comment2 } = nameOrInput;
|
|
1952
|
+
return comment2 ? `${name}=${value2} # ${comment2}` : `${name}=${value2}`;
|
|
1953
|
+
}
|
|
1954
|
+
return nameOrInput;
|
|
1955
|
+
}
|
|
1956
|
+
add(input, value, comment) {
|
|
1957
|
+
const line = this.inputToLine(input, value, comment);
|
|
1958
|
+
if (isEmpty(line)) {
|
|
1959
|
+
this.emptyManager.add();
|
|
1960
|
+
this.saveIfNeeded();
|
|
1961
|
+
return;
|
|
1962
|
+
}
|
|
1963
|
+
if (isSimpleComment(line)) {
|
|
1964
|
+
const comment2 = getSimpleComment(line);
|
|
1965
|
+
if (comment2) {
|
|
1966
|
+
this.commentManager.add(comment2);
|
|
1967
|
+
this.saveIfNeeded();
|
|
1968
|
+
return;
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
if (isVariableComment(line)) {
|
|
1972
|
+
const variable = getVariableComment(line);
|
|
1973
|
+
if (variable) {
|
|
1974
|
+
const nextLine = this.nextLineNum();
|
|
1975
|
+
this.variableManager.add(variable.name, variable.value, nextLine);
|
|
1976
|
+
this.commentManager.add(variable.comment, variable.name, nextLine);
|
|
1977
|
+
this.saveIfNeeded();
|
|
1978
|
+
return;
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
if (isVariable(line)) {
|
|
1982
|
+
const variable = getVariable(line);
|
|
1983
|
+
if (variable) {
|
|
1984
|
+
this.variableManager.add(variable.name, variable.value);
|
|
1985
|
+
this.saveIfNeeded();
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
nextLineNum() {
|
|
1990
|
+
const allItems = this.getAll();
|
|
1991
|
+
return allItems.length > 0 ? Math.max(...allItems.map((item) => item.lineNum)) + 1 : 1;
|
|
1992
|
+
}
|
|
1993
|
+
update(name, value, comment) {
|
|
1994
|
+
if (comment !== undefined) {
|
|
1995
|
+
const variable = this.variableManager.get(name);
|
|
1996
|
+
if (variable) {
|
|
1997
|
+
this.commentManager.add(comment, name, variable.lineNum);
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
2000
|
+
this.variableManager.update(name, value);
|
|
2001
|
+
this.saveIfNeeded();
|
|
2002
|
+
}
|
|
2003
|
+
get(name) {
|
|
2004
|
+
return this.variableManager.getValue(name);
|
|
2005
|
+
}
|
|
2006
|
+
delete(name) {
|
|
2007
|
+
const variable = this.variableManager.get(name);
|
|
2008
|
+
if (variable) {
|
|
2009
|
+
this.commentManager.delete(name);
|
|
2010
|
+
this.variableManager.delete(name);
|
|
2011
|
+
this.saveIfNeeded();
|
|
2012
|
+
return true;
|
|
2013
|
+
}
|
|
2014
|
+
return false;
|
|
2015
|
+
}
|
|
2016
|
+
has(name) {
|
|
2017
|
+
return this.variableManager.has(name);
|
|
2018
|
+
}
|
|
2019
|
+
getAll() {
|
|
2020
|
+
const items = [
|
|
2021
|
+
...this.variableManager.getAll(),
|
|
2022
|
+
...this.commentManager.getAll().filter((item) => item.type === "simpleComment"),
|
|
2023
|
+
...this.emptyManager.getAll()
|
|
2024
|
+
].sort((a, b3) => a.lineNum - b3.lineNum);
|
|
2025
|
+
items.forEach((item, index) => {
|
|
2026
|
+
item.lineNum = index + 1;
|
|
2027
|
+
});
|
|
2028
|
+
return items;
|
|
2029
|
+
}
|
|
2030
|
+
addComment(comment) {
|
|
2031
|
+
const result = this.commentManager.add(comment);
|
|
2032
|
+
this.saveIfNeeded();
|
|
2033
|
+
return result;
|
|
2034
|
+
}
|
|
2035
|
+
updateComment(lineNum, comment) {
|
|
2036
|
+
const result = this.commentManager.update(lineNum, comment);
|
|
2037
|
+
this.saveIfNeeded();
|
|
2038
|
+
return result;
|
|
2039
|
+
}
|
|
2040
|
+
getComment(name) {
|
|
2041
|
+
return this.commentManager.get(name);
|
|
2042
|
+
}
|
|
2043
|
+
hasComment(lineNum) {
|
|
2044
|
+
return this.commentManager.has(lineNum);
|
|
2045
|
+
}
|
|
2046
|
+
deleteComment(query) {
|
|
2047
|
+
const result = this.commentManager.delete(query);
|
|
2048
|
+
this.saveIfNeeded();
|
|
2049
|
+
return result;
|
|
2050
|
+
}
|
|
2051
|
+
getAllComments() {
|
|
2052
|
+
return this.commentManager.getAll();
|
|
2053
|
+
}
|
|
2054
|
+
addEmpty() {
|
|
2055
|
+
this.emptyManager.add();
|
|
2056
|
+
this.saveIfNeeded();
|
|
2057
|
+
}
|
|
2058
|
+
hasEmpty(lineNum) {
|
|
2059
|
+
return this.emptyManager.has(lineNum);
|
|
2060
|
+
}
|
|
2061
|
+
deleteEmpty(lineNum) {
|
|
2062
|
+
this.emptyManager.delete(lineNum);
|
|
2063
|
+
this.saveIfNeeded();
|
|
2064
|
+
}
|
|
2065
|
+
getAllEmpty() {
|
|
2066
|
+
return this.emptyManager.getAll();
|
|
2067
|
+
}
|
|
2068
|
+
reindex() {
|
|
2069
|
+
const allItems = this.getAll().sort((a, b3) => a.lineNum - b3.lineNum);
|
|
2070
|
+
allItems.forEach((item, index) => {
|
|
2071
|
+
const newLineNum = index + 1;
|
|
2072
|
+
if (item.type === "variable") {
|
|
2073
|
+
this.variableManager.updateLineNumber(item.name, newLineNum);
|
|
2074
|
+
} else if (item.type === "empty") {
|
|
2075
|
+
this.emptyManager.updateLineNumber(item.lineNum, newLineNum);
|
|
2076
|
+
} else if (item.type === "simpleComment" || item.type === "inlineComment") {
|
|
2077
|
+
this.commentManager.updateLineNumber(item.lineNum, newLineNum);
|
|
2078
|
+
}
|
|
2079
|
+
});
|
|
2080
|
+
this.saveIfNeeded();
|
|
2081
|
+
}
|
|
2082
|
+
normalizeOptions(options) {
|
|
2083
|
+
return {
|
|
2084
|
+
path: options.path ?? join(process.cwd(), ".env"),
|
|
2085
|
+
defaults: options.defaults ?? {},
|
|
2086
|
+
autoSync: options.autoSync ?? false,
|
|
2087
|
+
createIfNotExist: options.createIfNotExist ?? true,
|
|
2088
|
+
autoSave: options.autoSave ?? true
|
|
2089
|
+
};
|
|
2090
|
+
}
|
|
2091
|
+
saveIfNeeded() {
|
|
2092
|
+
if (this instanceof EnvManager) {
|
|
2093
|
+
this.save();
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
clear() {
|
|
2097
|
+
const variables = this.variableManager.getAll();
|
|
2098
|
+
for (const variable of variables) {
|
|
2099
|
+
this.variableManager.delete(variable.name);
|
|
2100
|
+
}
|
|
2101
|
+
const comments = this.commentManager.getAll();
|
|
2102
|
+
for (const comment of comments) {
|
|
2103
|
+
this.commentManager.delete(comment.lineNum);
|
|
2104
|
+
}
|
|
2105
|
+
const emptyLines = this.emptyManager.getAll();
|
|
2106
|
+
for (const emptyLine of emptyLines) {
|
|
2107
|
+
this.emptyManager.delete(emptyLine.lineNum);
|
|
2108
|
+
}
|
|
2109
|
+
this.saveIfNeeded();
|
|
2110
|
+
}
|
|
2111
|
+
get path() {
|
|
2112
|
+
return this.options.path;
|
|
2113
|
+
}
|
|
2114
|
+
get defaults() {
|
|
2115
|
+
return this.options.defaults;
|
|
2116
|
+
}
|
|
2117
|
+
get autoSync() {
|
|
2118
|
+
return this.options.autoSync;
|
|
2119
|
+
}
|
|
2120
|
+
get createIfNotExist() {
|
|
2121
|
+
return this.options.createIfNotExist;
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2125
|
+
class EmptyManager {
|
|
2126
|
+
emptyLines;
|
|
2127
|
+
envManager;
|
|
2128
|
+
constructor(envManager) {
|
|
2129
|
+
this.emptyLines = new Map;
|
|
2130
|
+
this.envManager = envManager;
|
|
2131
|
+
}
|
|
2132
|
+
add() {
|
|
2133
|
+
const lineNum = this.getNextLineNum();
|
|
2134
|
+
this.emptyLines.set(lineNum, { type: "empty", lineNum });
|
|
2135
|
+
return this;
|
|
2136
|
+
}
|
|
2137
|
+
has(lineNum) {
|
|
2138
|
+
return this.emptyLines.has(lineNum);
|
|
2139
|
+
}
|
|
2140
|
+
delete(lineNum) {
|
|
2141
|
+
const deleted = this.emptyLines.delete(lineNum);
|
|
2142
|
+
if (deleted) {
|
|
2143
|
+
this.envManager.reindex();
|
|
2144
|
+
}
|
|
2145
|
+
return deleted;
|
|
2146
|
+
}
|
|
2147
|
+
getAll() {
|
|
2148
|
+
return Array.from(this.emptyLines.values());
|
|
2149
|
+
}
|
|
2150
|
+
getNextLineNum() {
|
|
2151
|
+
return this.envManager.nextLineNum();
|
|
2152
|
+
}
|
|
2153
|
+
updateLineNumber(oldLineNum, newLineNum) {
|
|
2154
|
+
const empty = this.emptyLines.get(oldLineNum);
|
|
2155
|
+
if (!empty)
|
|
2156
|
+
return false;
|
|
2157
|
+
this.emptyLines.delete(oldLineNum);
|
|
2158
|
+
this.emptyLines.set(newLineNum, {
|
|
2159
|
+
...empty,
|
|
2160
|
+
lineNum: newLineNum
|
|
2161
|
+
});
|
|
2162
|
+
return true;
|
|
2163
|
+
}
|
|
2164
|
+
clearLineNumbers() {
|
|
2165
|
+
for (const [name, variable] of this.emptyLines.entries()) {
|
|
2166
|
+
this.emptyLines.set(name, { ...variable, lineNum: -1 });
|
|
2167
|
+
}
|
|
2168
|
+
return this;
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
var EMPTY_VALUES = ["", "EMPTY_VALUE"];
|
|
2172
|
+
var NULL_VALUES = ["null", "NULL_VALUE"];
|
|
2173
|
+
var UNDEFINED_VALUES = ["undefined", "UNDEFINED_VALUE"];
|
|
2174
|
+
var isStringNumber = (value) => {
|
|
2175
|
+
if (!isString(value))
|
|
2176
|
+
return false;
|
|
2177
|
+
return /^-?\d*\.?\d+$/.test(value.trim());
|
|
2178
|
+
};
|
|
2179
|
+
var isUrl = (value) => {
|
|
2180
|
+
if (!isString(value))
|
|
2181
|
+
return false;
|
|
2182
|
+
try {
|
|
2183
|
+
new URL(value.trim());
|
|
2184
|
+
return true;
|
|
2185
|
+
} catch {
|
|
2186
|
+
return false;
|
|
2187
|
+
}
|
|
2188
|
+
};
|
|
2189
|
+
var isStringBoolean = (value) => {
|
|
2190
|
+
if (!isString(value))
|
|
2191
|
+
return false;
|
|
2192
|
+
const lowered = value.trim().toLowerCase();
|
|
2193
|
+
return ["true", "false", "on", "off", "yes", "no"].includes(lowered);
|
|
2194
|
+
};
|
|
2195
|
+
var isCommaSeparatedArray = (value) => {
|
|
2196
|
+
if (!isString(value))
|
|
2197
|
+
return false;
|
|
2198
|
+
const trimmed = value.trim();
|
|
2199
|
+
if (!trimmed)
|
|
2200
|
+
return false;
|
|
2201
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
2202
|
+
return false;
|
|
2203
|
+
}
|
|
2204
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]") || trimmed.startsWith("{") && trimmed.endsWith("}")) {
|
|
2205
|
+
try {
|
|
2206
|
+
JSON.parse(trimmed);
|
|
2207
|
+
return false;
|
|
2208
|
+
} catch {}
|
|
2209
|
+
}
|
|
2210
|
+
const nonArrayPatterns = [
|
|
2211
|
+
/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,
|
|
2212
|
+
/^\d{4}-\d{2}-\d{2}$/,
|
|
2213
|
+
/^rgba?\(\d{1,3},\s*\d{1,3},\s*\d{1,3}(?:,\s*(?:0|1|0?\.\d+))?\)$/,
|
|
2214
|
+
/^#[0-9a-fA-F]{3,8}$/
|
|
2215
|
+
];
|
|
2216
|
+
if (nonArrayPatterns.some((pattern) => pattern.test(trimmed))) {
|
|
2217
|
+
return false;
|
|
2218
|
+
}
|
|
2219
|
+
if (!trimmed.includes(",")) {
|
|
2220
|
+
return false;
|
|
2221
|
+
}
|
|
2222
|
+
if (/,\s[a-z]/.test(trimmed.toLowerCase())) {
|
|
2223
|
+
return false;
|
|
2224
|
+
}
|
|
2225
|
+
const parts = trimmed.split(",").map((p2) => p2.trim());
|
|
2226
|
+
return parts.length >= 2 && parts.every((p2) => p2.length > 0);
|
|
2227
|
+
};
|
|
2228
|
+
var isJsonArray = (value) => {
|
|
2229
|
+
if (!isString(value))
|
|
2230
|
+
return false;
|
|
2231
|
+
const trimmed = value.trim();
|
|
2232
|
+
if (!trimmed.startsWith("[") || !trimmed.endsWith("]"))
|
|
2233
|
+
return false;
|
|
2234
|
+
try {
|
|
2235
|
+
const parsed = JSON.parse(trimmed);
|
|
2236
|
+
return isArray(parsed);
|
|
2237
|
+
} catch {
|
|
2238
|
+
return false;
|
|
2239
|
+
}
|
|
2240
|
+
};
|
|
2241
|
+
var isJsonObject = (value) => {
|
|
2242
|
+
if (!isString(value))
|
|
2243
|
+
return false;
|
|
2244
|
+
const trimmed = value.trim();
|
|
2245
|
+
if (!trimmed.startsWith("{") || !trimmed.endsWith("}"))
|
|
2246
|
+
return false;
|
|
2247
|
+
try {
|
|
2248
|
+
const parsed = JSON.parse(trimmed);
|
|
2249
|
+
return isObject(parsed);
|
|
2250
|
+
} catch {
|
|
2251
|
+
return false;
|
|
2252
|
+
}
|
|
2253
|
+
};
|
|
2254
|
+
var isString = (value) => typeof value === "string";
|
|
2255
|
+
var isNumber2 = (value) => typeof value === "number" && !isNaN(value);
|
|
2256
|
+
var isBoolean = (value) => typeof value === "boolean";
|
|
2257
|
+
var isObject = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2258
|
+
var isArray = (value) => Array.isArray(value);
|
|
2259
|
+
var isNull = (value) => value === null;
|
|
2260
|
+
var isUndefined = (value) => value === undefined;
|
|
2261
|
+
var parseString = (value) => {
|
|
2262
|
+
if (isString(value)) {
|
|
2263
|
+
const trimmed = value.trim();
|
|
2264
|
+
if (EMPTY_VALUES.includes(trimmed))
|
|
2265
|
+
return "";
|
|
2266
|
+
if (NULL_VALUES.includes(trimmed))
|
|
2267
|
+
return null;
|
|
2268
|
+
if (UNDEFINED_VALUES.includes(trimmed))
|
|
2269
|
+
return;
|
|
2270
|
+
return trimmed;
|
|
2271
|
+
}
|
|
2272
|
+
if (isNull(value))
|
|
2273
|
+
return "";
|
|
2274
|
+
if (isUndefined(value))
|
|
2275
|
+
return;
|
|
2276
|
+
return String(value);
|
|
2277
|
+
};
|
|
2278
|
+
var parseNumber = (value) => {
|
|
2279
|
+
if (isNumber2(value))
|
|
2280
|
+
return value;
|
|
2281
|
+
if (isString(value)) {
|
|
2282
|
+
const trimmed = value.trim();
|
|
2283
|
+
if (EMPTY_VALUES.includes(trimmed) || NULL_VALUES.includes(trimmed) || UNDEFINED_VALUES.includes(trimmed))
|
|
2284
|
+
return 0;
|
|
2285
|
+
const parsed = parseFloat(trimmed);
|
|
2286
|
+
return isNaN(parsed) ? 0 : parsed;
|
|
2287
|
+
}
|
|
2288
|
+
if (isBoolean(value))
|
|
2289
|
+
return value ? 1 : 0;
|
|
2290
|
+
return 0;
|
|
2291
|
+
};
|
|
2292
|
+
var parseBoolean = (value) => {
|
|
2293
|
+
if (isBoolean(value))
|
|
2294
|
+
return value;
|
|
2295
|
+
if (isString(value)) {
|
|
2296
|
+
const trimmed = value.trim();
|
|
2297
|
+
if (EMPTY_VALUES.includes(trimmed) || NULL_VALUES.includes(trimmed) || UNDEFINED_VALUES.includes(trimmed))
|
|
2298
|
+
return false;
|
|
2299
|
+
const lowered = trimmed.toLowerCase();
|
|
2300
|
+
return lowered === "true" || lowered === "1" || lowered === "yes" || lowered === "on";
|
|
2301
|
+
}
|
|
2302
|
+
if (isNumber2(value))
|
|
2303
|
+
return value !== 0;
|
|
2304
|
+
return false;
|
|
2305
|
+
};
|
|
2306
|
+
var parseArray = (value) => {
|
|
2307
|
+
if (isArray(value))
|
|
2308
|
+
return value;
|
|
2309
|
+
if (isString(value)) {
|
|
2310
|
+
const trimmed = value.trim();
|
|
2311
|
+
if (EMPTY_VALUES.includes(trimmed) || NULL_VALUES.includes(trimmed) || UNDEFINED_VALUES.includes(trimmed))
|
|
2312
|
+
return [];
|
|
2313
|
+
if (isCommaSeparatedArray(trimmed)) {
|
|
2314
|
+
return trimmed.split(",").map((item) => {
|
|
2315
|
+
const trimmedItem = item.trim();
|
|
2316
|
+
if (EMPTY_VALUES.includes(trimmedItem) || NULL_VALUES.includes(trimmedItem) || UNDEFINED_VALUES.includes(trimmedItem))
|
|
2317
|
+
return null;
|
|
2318
|
+
if (isStringNumber(trimmedItem))
|
|
2319
|
+
return parseFloat(trimmedItem);
|
|
2320
|
+
if (isStringBoolean(trimmedItem))
|
|
2321
|
+
return parseBoolean(trimmedItem);
|
|
2322
|
+
return trimmedItem;
|
|
2323
|
+
}).filter((item) => item !== null);
|
|
2324
|
+
}
|
|
2325
|
+
try {
|
|
2326
|
+
const parsed = JSON.parse(trimmed);
|
|
2327
|
+
return isArray(parsed) ? parsed : [trimmed];
|
|
2328
|
+
} catch {
|
|
2329
|
+
return [trimmed];
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
if (isNull(value) || isUndefined(value))
|
|
2333
|
+
return [];
|
|
2334
|
+
return [value];
|
|
2335
|
+
};
|
|
2336
|
+
var parseObjectValues = (obj) => {
|
|
2337
|
+
if (!isObject(obj) && !isArray(obj))
|
|
2338
|
+
return obj;
|
|
2339
|
+
if (isArray(obj)) {
|
|
2340
|
+
return obj.map((item) => parseObjectValues(item));
|
|
2341
|
+
}
|
|
2342
|
+
const result = {};
|
|
2343
|
+
for (const [key, val] of Object.entries(obj)) {
|
|
2344
|
+
if (isObject(val) || isArray(val)) {
|
|
2345
|
+
result[key] = parseObjectValues(val);
|
|
2346
|
+
} else {
|
|
2347
|
+
result[key] = parseValue(val);
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
return result;
|
|
2351
|
+
};
|
|
2352
|
+
var parseObject = (value) => {
|
|
2353
|
+
if (isObject(value))
|
|
2354
|
+
return parseObjectValues(value);
|
|
2355
|
+
if (isString(value)) {
|
|
2356
|
+
const trimmed = value.trim();
|
|
2357
|
+
if (EMPTY_VALUES.includes(trimmed) || NULL_VALUES.includes(trimmed) || UNDEFINED_VALUES.includes(trimmed))
|
|
2358
|
+
return {};
|
|
2359
|
+
try {
|
|
2360
|
+
const parsed = JSON.parse(trimmed);
|
|
2361
|
+
return isObject(parsed) ? parseObjectValues(parsed) : {};
|
|
2362
|
+
} catch {
|
|
2363
|
+
return {};
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
return {};
|
|
2367
|
+
};
|
|
2368
|
+
var getType = (value) => {
|
|
2369
|
+
if (isString(value)) {
|
|
2370
|
+
const trimmed = value.trim();
|
|
2371
|
+
if (EMPTY_VALUES.includes(trimmed))
|
|
2372
|
+
return "empty";
|
|
2373
|
+
if (NULL_VALUES.includes(trimmed))
|
|
2374
|
+
return "null";
|
|
2375
|
+
if (UNDEFINED_VALUES.includes(trimmed))
|
|
2376
|
+
return "undefined";
|
|
2377
|
+
switch (true) {
|
|
2378
|
+
case isUrl(trimmed):
|
|
2379
|
+
return "url";
|
|
2380
|
+
case isStringNumber(trimmed):
|
|
2381
|
+
return "stringNumber";
|
|
2382
|
+
case isStringBoolean(trimmed):
|
|
2383
|
+
return "stringBoolean";
|
|
2384
|
+
case isCommaSeparatedArray(trimmed):
|
|
2385
|
+
return "csvArray";
|
|
2386
|
+
case isJsonArray(trimmed):
|
|
2387
|
+
return "jsonArray";
|
|
2388
|
+
case isJsonObject(trimmed):
|
|
2389
|
+
return "jsonObject";
|
|
2390
|
+
default:
|
|
2391
|
+
return "string";
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
switch (true) {
|
|
2395
|
+
case isNull(value):
|
|
2396
|
+
return "null";
|
|
2397
|
+
case isUndefined(value):
|
|
2398
|
+
return "undefined";
|
|
2399
|
+
case isNumber2(value):
|
|
2400
|
+
return "number";
|
|
2401
|
+
case isBoolean(value):
|
|
2402
|
+
return "boolean";
|
|
2403
|
+
case isArray(value):
|
|
2404
|
+
return "array";
|
|
2405
|
+
case isObject(value):
|
|
2406
|
+
return "object";
|
|
2407
|
+
default:
|
|
2408
|
+
return "unknown";
|
|
2409
|
+
}
|
|
2410
|
+
};
|
|
2411
|
+
var parseValue = (value, type = null) => {
|
|
2412
|
+
if (type) {
|
|
2413
|
+
return parseValueByType(value, type.toLowerCase());
|
|
2414
|
+
}
|
|
2415
|
+
const valueType = getType(value);
|
|
2416
|
+
switch (valueType) {
|
|
2417
|
+
case "empty":
|
|
2418
|
+
case "null":
|
|
2419
|
+
return "";
|
|
2420
|
+
case "undefined":
|
|
2421
|
+
return "";
|
|
2422
|
+
case "stringNumber":
|
|
2423
|
+
return parseFloat(value.trim());
|
|
2424
|
+
case "stringBoolean":
|
|
2425
|
+
return parseBoolean(value);
|
|
2426
|
+
case "csvArray":
|
|
2427
|
+
case "jsonArray":
|
|
2428
|
+
return parseArray(value);
|
|
2429
|
+
case "jsonObject":
|
|
2430
|
+
return parseObject(value);
|
|
2431
|
+
case "string":
|
|
2432
|
+
return parseString(value);
|
|
2433
|
+
case "number":
|
|
2434
|
+
case "boolean":
|
|
2435
|
+
case "array":
|
|
2436
|
+
case "object":
|
|
2437
|
+
return value;
|
|
2438
|
+
default:
|
|
2439
|
+
return value;
|
|
2440
|
+
}
|
|
2441
|
+
};
|
|
2442
|
+
var parseValueByType = (value, type) => {
|
|
2443
|
+
switch (type) {
|
|
2444
|
+
case "string":
|
|
2445
|
+
return parseString(value);
|
|
2446
|
+
case "number":
|
|
2447
|
+
return parseNumber(value);
|
|
2448
|
+
case "boolean":
|
|
2449
|
+
return parseBoolean(value);
|
|
2450
|
+
case "array":
|
|
2451
|
+
return parseArray(value);
|
|
2452
|
+
case "object":
|
|
2453
|
+
return parseObject(value);
|
|
2454
|
+
default:
|
|
2455
|
+
return value;
|
|
2456
|
+
}
|
|
2457
|
+
};
|
|
2458
|
+
|
|
2459
|
+
class VariableManager {
|
|
2460
|
+
variables;
|
|
2461
|
+
envManager;
|
|
2462
|
+
constructor(envManager) {
|
|
2463
|
+
this.variables = new Map;
|
|
2464
|
+
this.envManager = envManager;
|
|
2465
|
+
}
|
|
2466
|
+
add(name, value, index) {
|
|
2467
|
+
if (this.has(name)) {
|
|
2468
|
+
this.update(name, value);
|
|
2469
|
+
return this;
|
|
2470
|
+
}
|
|
2471
|
+
const lineNum = index ?? this.envManager.nextLineNum();
|
|
2472
|
+
const parsedValue = parseValue(value);
|
|
2473
|
+
const item = { type: "variable", lineNum, name, value: parsedValue };
|
|
2474
|
+
this.variables.set(name, item);
|
|
2475
|
+
return this;
|
|
2476
|
+
}
|
|
2477
|
+
update(name, value) {
|
|
2478
|
+
const item = this.variables.get(name);
|
|
2479
|
+
if (!item)
|
|
2480
|
+
return;
|
|
2481
|
+
const parsedValue = value !== undefined ? parseValue(value) : item.value;
|
|
2482
|
+
const updatedItem = {
|
|
2483
|
+
type: "variable",
|
|
2484
|
+
lineNum: item.lineNum,
|
|
2485
|
+
name,
|
|
2486
|
+
value: parsedValue
|
|
2487
|
+
};
|
|
2488
|
+
this.variables.set(name, updatedItem);
|
|
2489
|
+
return true;
|
|
2490
|
+
}
|
|
2491
|
+
get(name) {
|
|
2492
|
+
return this.variables.get(name) ?? null;
|
|
2493
|
+
}
|
|
2494
|
+
expandValue(value, visited = new Set) {
|
|
2495
|
+
if (typeof value === "string") {
|
|
2496
|
+
return value.replace(/\${([^}]+)}/g, (match, varName) => {
|
|
2497
|
+
if (visited.has(varName)) {
|
|
2498
|
+
return match;
|
|
2499
|
+
}
|
|
2500
|
+
const newVisited = new Set(visited);
|
|
2501
|
+
newVisited.add(varName);
|
|
2502
|
+
const expandedValue = this.getValue(varName, newVisited);
|
|
2503
|
+
return expandedValue !== null ? expandedValue : match;
|
|
2504
|
+
});
|
|
2505
|
+
}
|
|
2506
|
+
if (Array.isArray(value)) {
|
|
2507
|
+
return value.map((item) => this.expandValue(item, visited));
|
|
2508
|
+
}
|
|
2509
|
+
if (typeof value === "object" && value !== null) {
|
|
2510
|
+
const result = {};
|
|
2511
|
+
for (const [key, val] of Object.entries(value)) {
|
|
2512
|
+
result[key] = this.expandValue(val, visited);
|
|
2513
|
+
}
|
|
2514
|
+
return result;
|
|
2515
|
+
}
|
|
2516
|
+
return value;
|
|
2517
|
+
}
|
|
2518
|
+
getValue(name, visited = new Set) {
|
|
2519
|
+
const variable = this.variables.get(name);
|
|
2520
|
+
if (!variable)
|
|
2521
|
+
return null;
|
|
2522
|
+
const rawValue = variable.value;
|
|
2523
|
+
let parsedValue = rawValue;
|
|
2524
|
+
if (typeof rawValue === "string") {
|
|
2525
|
+
if (rawValue.startsWith("{") && rawValue.endsWith("}") || rawValue.startsWith("[") && rawValue.endsWith("]")) {
|
|
2526
|
+
try {
|
|
2527
|
+
parsedValue = JSON.parse(rawValue);
|
|
2528
|
+
} catch (e2) {}
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
visited.add(name);
|
|
2532
|
+
return this.expandValue(parsedValue, visited);
|
|
2533
|
+
}
|
|
2534
|
+
delete(name) {
|
|
2535
|
+
const deleted = this.variables.delete(name);
|
|
2536
|
+
if (deleted) {
|
|
2537
|
+
this.envManager.reindex();
|
|
2538
|
+
}
|
|
2539
|
+
return deleted ? true : false;
|
|
2540
|
+
}
|
|
2541
|
+
has(name) {
|
|
2542
|
+
return this.variables.has(name);
|
|
2543
|
+
}
|
|
2544
|
+
getAll() {
|
|
2545
|
+
return Array.from(this.variables.values());
|
|
2546
|
+
}
|
|
2547
|
+
updateLineNumber(name, newLineNum) {
|
|
2548
|
+
const item = this.variables.get(name);
|
|
2549
|
+
if (!item)
|
|
2550
|
+
return;
|
|
2551
|
+
this.variables.set(name, {
|
|
2552
|
+
...item,
|
|
2553
|
+
lineNum: newLineNum
|
|
2554
|
+
});
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
|
|
2558
|
+
class CommentManager {
|
|
2559
|
+
comments;
|
|
2560
|
+
envManager;
|
|
2561
|
+
constructor(envManager) {
|
|
2562
|
+
this.comments = new Map;
|
|
2563
|
+
this.envManager = envManager;
|
|
2564
|
+
}
|
|
2565
|
+
getLine(comment) {
|
|
2566
|
+
const existingComment = this.getAll().find((c) => c.comment === comment);
|
|
2567
|
+
return existingComment ? existingComment.lineNum : null;
|
|
2568
|
+
}
|
|
2569
|
+
add(comment, variable, index) {
|
|
2570
|
+
if (this.hasSimpleComment(comment)) {
|
|
2571
|
+
return this;
|
|
2572
|
+
}
|
|
2573
|
+
if (variable && this.hasInlineComment(variable)) {
|
|
2574
|
+
const lineNum = this.getLine(variable);
|
|
2575
|
+
if (lineNum !== null) {
|
|
2576
|
+
this.update(lineNum, comment);
|
|
2577
|
+
return this;
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
const line = index ?? this.envManager.nextLineNum();
|
|
2581
|
+
const content = variable ? {
|
|
2582
|
+
type: "inlineComment",
|
|
2583
|
+
lineNum: line,
|
|
2584
|
+
comment,
|
|
2585
|
+
variable
|
|
2586
|
+
} : {
|
|
2587
|
+
type: "simpleComment",
|
|
2588
|
+
lineNum: line,
|
|
2589
|
+
comment
|
|
2590
|
+
};
|
|
2591
|
+
this.comments.set(line, content);
|
|
2592
|
+
return this;
|
|
2593
|
+
}
|
|
2594
|
+
update(lineNum, newComment) {
|
|
2595
|
+
const existingComment = this.comments.get(lineNum);
|
|
2596
|
+
if (!existingComment)
|
|
2597
|
+
return false;
|
|
2598
|
+
const updatedComment = {
|
|
2599
|
+
...existingComment,
|
|
2600
|
+
comment: newComment
|
|
2601
|
+
};
|
|
2602
|
+
this.comments.set(lineNum, updatedComment);
|
|
2603
|
+
return true;
|
|
2604
|
+
}
|
|
2605
|
+
get(query) {
|
|
2606
|
+
if (typeof query === "number") {
|
|
2607
|
+
return this.getByLine(query);
|
|
2608
|
+
}
|
|
2609
|
+
const byVariable = this.getByVariable(query);
|
|
2610
|
+
if (byVariable)
|
|
2611
|
+
return byVariable;
|
|
2612
|
+
return this.getByContent(query);
|
|
2613
|
+
}
|
|
2614
|
+
getByVariable(variableName) {
|
|
2615
|
+
const inlineComment = this.getAll().find((c) => c.type === "inlineComment" && c.variable === variableName);
|
|
2616
|
+
return inlineComment ? inlineComment.comment : null;
|
|
2617
|
+
}
|
|
2618
|
+
getByLine(lineNum) {
|
|
2619
|
+
return this.comments.get(lineNum)?.comment ?? null;
|
|
2620
|
+
}
|
|
2621
|
+
getByContent(comment) {
|
|
2622
|
+
const foundComment = this.getAll().find((c) => c.comment === comment);
|
|
2623
|
+
return foundComment ? foundComment.comment : null;
|
|
2624
|
+
}
|
|
2625
|
+
delete(query) {
|
|
2626
|
+
if (!this.has(query)) {
|
|
2627
|
+
return false;
|
|
2628
|
+
}
|
|
2629
|
+
if (isNumber2(query)) {
|
|
2630
|
+
this.comments.delete(query);
|
|
2631
|
+
this.envManager.reindex();
|
|
2632
|
+
return true;
|
|
2633
|
+
}
|
|
2634
|
+
const comment = this.getByVariable(query);
|
|
2635
|
+
if (comment) {
|
|
2636
|
+
const lineNum = this.getLine(comment);
|
|
2637
|
+
if (lineNum !== null) {
|
|
2638
|
+
this.comments.delete(lineNum);
|
|
2639
|
+
this.envManager.reindex();
|
|
2640
|
+
return true;
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
const allComments = this.getAll();
|
|
2644
|
+
const simpleComment = allComments.find((c) => c.type === "simpleComment" && c.comment === query);
|
|
2645
|
+
if (simpleComment) {
|
|
2646
|
+
this.comments.delete(simpleComment.lineNum);
|
|
2647
|
+
this.envManager.reindex();
|
|
2648
|
+
return true;
|
|
2649
|
+
}
|
|
2650
|
+
return false;
|
|
2651
|
+
}
|
|
2652
|
+
getAll() {
|
|
2653
|
+
return Array.from(this.comments.values());
|
|
2654
|
+
}
|
|
2655
|
+
has(query) {
|
|
2656
|
+
if (isNumber2(query)) {
|
|
2657
|
+
return this.comments.has(query);
|
|
2658
|
+
}
|
|
2659
|
+
const commentByVariable = this.getByVariable(query);
|
|
2660
|
+
if (commentByVariable) {
|
|
2661
|
+
return true;
|
|
2662
|
+
}
|
|
2663
|
+
return this.getAll().some((comment) => comment.type === "simpleComment" ? comment.comment === query : comment.type === "inlineComment" ? comment.variable === query : false);
|
|
2664
|
+
}
|
|
2665
|
+
hasInlineComment(variable) {
|
|
2666
|
+
return this.getAll().some((c) => c.type === "inlineComment" && c.variable === variable);
|
|
2667
|
+
}
|
|
2668
|
+
hasSimpleComment(comment) {
|
|
2669
|
+
return this.getAll().some((c) => c.type === "simpleComment" && c.comment === comment);
|
|
2670
|
+
}
|
|
2671
|
+
updateLineNumber(oldLineNum, newLineNum) {
|
|
2672
|
+
const comment = this.comments.get(oldLineNum);
|
|
2673
|
+
if (!comment)
|
|
2674
|
+
return;
|
|
2675
|
+
this.comments.delete(oldLineNum);
|
|
2676
|
+
this.comments.set(newLineNum, {
|
|
2677
|
+
...comment,
|
|
2678
|
+
lineNum: newLineNum
|
|
2679
|
+
});
|
|
2680
|
+
return this;
|
|
2681
|
+
}
|
|
2682
|
+
clearLineNumbers() {
|
|
2683
|
+
for (const [name, variable] of this.comments.entries()) {
|
|
2684
|
+
this.comments.set(name, { ...variable, lineNum: -1 });
|
|
2685
|
+
}
|
|
2686
|
+
return this;
|
|
2687
|
+
}
|
|
2688
|
+
}
|
|
2689
|
+
|
|
2690
|
+
class EnvManager extends BaseEnvManager {
|
|
2691
|
+
static instance = null;
|
|
2692
|
+
constructor(options) {
|
|
2693
|
+
super(options);
|
|
2694
|
+
this.processSync = new ProcessSync(this.autoSync);
|
|
2695
|
+
this.variableManager = new VariableManager(this);
|
|
2696
|
+
this.commentManager = new CommentManager(this);
|
|
2697
|
+
this.emptyManager = new EmptyManager(this);
|
|
2698
|
+
}
|
|
2699
|
+
parse() {
|
|
2700
|
+
this.ensureEnvFileExists();
|
|
2701
|
+
const content = readFileSync(this.path, "utf-8");
|
|
2702
|
+
if (!content)
|
|
2703
|
+
return;
|
|
2704
|
+
const lines = content.split(`
|
|
2705
|
+
`);
|
|
2706
|
+
lines.forEach((line) => {
|
|
2707
|
+
this.add(line.trim());
|
|
2708
|
+
});
|
|
2709
|
+
}
|
|
2710
|
+
serializeItem(item) {
|
|
2711
|
+
switch (item.type) {
|
|
2712
|
+
case "empty":
|
|
2713
|
+
return "";
|
|
2714
|
+
case "simpleComment":
|
|
2715
|
+
return `# ${item.comment}`;
|
|
2716
|
+
case "variable":
|
|
2717
|
+
const [serializedValue, shouldQuote] = this.getValueWithType(item.value);
|
|
2718
|
+
const baseStr = shouldQuote ? `${item.name}="${serializedValue}"` : `${item.name}=${serializedValue}`;
|
|
2719
|
+
const comment = this.commentManager.getByLine(item.lineNum);
|
|
2720
|
+
return comment ? `${baseStr} # ${comment}` : baseStr;
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
save() {
|
|
2724
|
+
const lines = [];
|
|
2725
|
+
this.getAll().forEach((item) => {
|
|
2726
|
+
lines[item.lineNum - 1] = this.serializeItem(item);
|
|
2727
|
+
});
|
|
2728
|
+
const content = lines.join(`
|
|
2729
|
+
`);
|
|
2730
|
+
fs2.writeFileSync(this.path, content, "utf-8");
|
|
2731
|
+
}
|
|
2732
|
+
getValueWithType(value) {
|
|
2733
|
+
const type = getType(value);
|
|
2734
|
+
const typeHandlers = {
|
|
2735
|
+
number: () => [String(value), false],
|
|
2736
|
+
stringNumber: () => [String(value), false],
|
|
2737
|
+
boolean: () => [String(value), false],
|
|
2738
|
+
stringBoolean: () => [String(value), false],
|
|
2739
|
+
array: () => [JSON.stringify(value).replace(/\\n/g, "\\\\n"), false],
|
|
2740
|
+
object: () => [JSON.stringify(value), false],
|
|
2741
|
+
string: () => [value, false],
|
|
2742
|
+
url: () => [escapeString(value), true],
|
|
2743
|
+
null: () => ["NULL_VALUE", false],
|
|
2744
|
+
undefined: () => ["UNDEFINED_VALUE", false],
|
|
2745
|
+
empty: () => ["EMPTY_VALUE", false]
|
|
2746
|
+
};
|
|
2747
|
+
return typeHandlers[type]?.() || [String(value), true];
|
|
2748
|
+
}
|
|
2749
|
+
ensureEnvFileExists() {
|
|
2750
|
+
if (!existsSync(this.options.path)) {
|
|
2751
|
+
writeFileSync(this.options.path, "", "utf-8");
|
|
2752
|
+
}
|
|
2753
|
+
}
|
|
2754
|
+
static getInstance(options) {
|
|
2755
|
+
if (!EnvManager.instance) {
|
|
2756
|
+
EnvManager.instance = new EnvManager(options);
|
|
2757
|
+
}
|
|
2758
|
+
return EnvManager.instance;
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
function Env(options = {}) {
|
|
2762
|
+
const env = EnvManager.getInstance(options);
|
|
2763
|
+
env.parse();
|
|
2764
|
+
return env;
|
|
2765
|
+
}
|
|
2766
|
+
|
|
2767
|
+
// src/Commands/InitCommand.ts
|
|
2768
|
+
class InitCommand {
|
|
2769
|
+
basePath;
|
|
2770
|
+
port;
|
|
2771
|
+
packageManager;
|
|
2772
|
+
runtime;
|
|
2773
|
+
constructor() {
|
|
2774
|
+
this.basePath = "src";
|
|
2775
|
+
this.port = 3000;
|
|
2776
|
+
}
|
|
2777
|
+
async initialize() {
|
|
2778
|
+
try {
|
|
2779
|
+
Ie(import_picocolors5.default.blue("\uD83C\uDFD7️ NajmApi Project Initialization"));
|
|
2780
|
+
await this.promptBasePath();
|
|
2781
|
+
await this.promptPKManager();
|
|
2782
|
+
await this.buildProject();
|
|
2783
|
+
await this.addPackages();
|
|
2784
|
+
Se(import_picocolors5.default.green("\uD83C\uDFAF NajmApi initialized in existing project, Happy coding!! \uD83D\uDE80"));
|
|
2785
|
+
} catch (error) {
|
|
2786
|
+
console.error("An error occurred:", error);
|
|
2787
|
+
process.exit(1);
|
|
2788
|
+
}
|
|
2789
|
+
}
|
|
2790
|
+
async promptPKManager() {
|
|
2791
|
+
const packageManagerOptions = [
|
|
2792
|
+
{ value: "bun", label: "bun" },
|
|
2793
|
+
{ value: "npm", label: "npm" },
|
|
2794
|
+
{ value: "yarn", label: "yarn" },
|
|
2795
|
+
{ value: "pnpm", label: "pnpm" }
|
|
2796
|
+
];
|
|
2797
|
+
this.packageManager = await ve({
|
|
2798
|
+
message: "Which Package Manager would you like to use?",
|
|
2799
|
+
options: packageManagerOptions
|
|
2800
|
+
});
|
|
2801
|
+
this.runtime = this.packageManager === "bun" ? "bun" : "node";
|
|
2802
|
+
}
|
|
2803
|
+
async promptBasePath() {
|
|
2804
|
+
this.basePath = await he({
|
|
2805
|
+
message: "Enter base path (e.g., src, src/server):",
|
|
2806
|
+
placeholder: "src",
|
|
2807
|
+
initialValue: "src"
|
|
2808
|
+
});
|
|
2809
|
+
const env = Env();
|
|
2810
|
+
env.add("BASE_PATH", this.basePath, "Base path for modules");
|
|
2811
|
+
M2.info(`Base path saved to environment: ${this.basePath}`);
|
|
2812
|
+
}
|
|
2813
|
+
async getTSDefaultConfig() {
|
|
2814
|
+
const tsconfigPath = path2.join(process.cwd(), "tsconfig.json");
|
|
2815
|
+
const exists = await pathExists(tsconfigPath);
|
|
2816
|
+
if (exists) {
|
|
2817
|
+
const existingConfig = await readFile3(tsconfigPath, "utf-8");
|
|
2818
|
+
const cleanConfig = cleanJsonString(existingConfig).trim();
|
|
2819
|
+
const config = JSON.parse(cleanConfig);
|
|
2820
|
+
const needsUpdate = !config.compilerOptions?.experimentalDecorators || !config.compilerOptions?.emitDecoratorMetadata;
|
|
2821
|
+
if (needsUpdate) {
|
|
2822
|
+
config.compilerOptions = config.compilerOptions || {};
|
|
2823
|
+
config.compilerOptions.experimentalDecorators = true;
|
|
2824
|
+
config.compilerOptions.emitDecoratorMetadata = true;
|
|
2825
|
+
}
|
|
2826
|
+
return JSON.stringify(config, null, 2);
|
|
2827
|
+
} else {
|
|
2828
|
+
return TS_CONFIG;
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2831
|
+
async buildProject() {
|
|
2832
|
+
const MAIN_CONTENT = this.runtime === "bun" ? BUN_MAIN_CONTENT : NODE_MAIN_CONTENT;
|
|
2833
|
+
const structure = {
|
|
2834
|
+
"{{basePath}}": {
|
|
2835
|
+
modules: {
|
|
2836
|
+
index$ts: ""
|
|
2837
|
+
},
|
|
2838
|
+
shared: {
|
|
2839
|
+
decorators: {
|
|
2840
|
+
index$ts: DB_DECORATORS_TEMPLATE
|
|
2841
|
+
},
|
|
2842
|
+
guards: {},
|
|
2843
|
+
services: {},
|
|
2844
|
+
utils: {}
|
|
2845
|
+
},
|
|
2846
|
+
index$ts: MAIN_CONTENT
|
|
2847
|
+
},
|
|
2848
|
+
tsconfig$json: await this.getTSDefaultConfig()
|
|
2849
|
+
};
|
|
2850
|
+
const result = await Build(structure, process.cwd(), {
|
|
2851
|
+
basePath: this.basePath,
|
|
2852
|
+
port: this.port,
|
|
2853
|
+
runtime: this.runtime
|
|
2854
|
+
});
|
|
2855
|
+
M2.success(`NajmApi Project initialized successfully with the following structure:`);
|
|
2856
|
+
M2.info(`- Created files:`);
|
|
2857
|
+
Object.entries(result.files).forEach(([name, filePath]) => {
|
|
2858
|
+
M2.info(` - ${name}: ${filePath}`);
|
|
2859
|
+
});
|
|
2860
|
+
return result;
|
|
2861
|
+
}
|
|
2862
|
+
async addPackages() {
|
|
2863
|
+
const packages = {
|
|
2864
|
+
dependencies: ["hono", "najm-api", "reflect-metadata"],
|
|
2865
|
+
devDependencies: ["typescript", "@types/node"]
|
|
2866
|
+
};
|
|
2867
|
+
await installPackages(packages, {
|
|
2868
|
+
cwd: process.cwd(),
|
|
2869
|
+
pm: this.packageManager
|
|
2870
|
+
});
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
|
|
2874
|
+
// src/constants.ts
|
|
2875
|
+
var DATABASE_PACKAGES = {
|
|
2876
|
+
pg: {
|
|
2877
|
+
dependencies: ["postgres", "drizzle-orm"],
|
|
2878
|
+
devDependencies: ["drizzle-kit", "@types/pg"]
|
|
2879
|
+
},
|
|
2880
|
+
mysql: {
|
|
2881
|
+
dependencies: ["mysql2", "drizzle-orm"],
|
|
2882
|
+
devDependencies: ["drizzle-kit", "@types/mysql"]
|
|
2883
|
+
},
|
|
2884
|
+
sqlite: {
|
|
2885
|
+
dependencies: ["better-sqlite3", "drizzle-orm"],
|
|
2886
|
+
devDependencies: ["drizzle-kit", "@types/better-sqlite3"]
|
|
2887
|
+
}
|
|
2888
|
+
};
|
|
2889
|
+
var DATABASE_SCRIPTS = {
|
|
2890
|
+
"db:generate": "drizzle-kit generate --config=drizzle.config.ts",
|
|
2891
|
+
"db:push": "drizzle-kit push --config=drizzle.config.ts",
|
|
2892
|
+
"db:drop": "drizzle-kit drop --config=drizzle.config.ts",
|
|
2893
|
+
"db:check": "drizzle-kit check --config=drizzle.config.ts"
|
|
2894
|
+
};
|
|
2895
|
+
var DEFAULT_CONFIG = {
|
|
2896
|
+
host: "localhost",
|
|
2897
|
+
port: 5432,
|
|
2898
|
+
username: "postgres",
|
|
2899
|
+
password: "postgres",
|
|
2900
|
+
database: "postgres"
|
|
2901
|
+
};
|
|
2902
|
+
|
|
2903
|
+
// src/Commands/DBCommand.ts
|
|
2904
|
+
var import_picocolors6 = __toESM(require_picocolors(), 1);
|
|
2905
|
+
|
|
2906
|
+
class DBCommand {
|
|
2907
|
+
env;
|
|
2908
|
+
dbType = "pg";
|
|
2909
|
+
basePath;
|
|
2910
|
+
dbHost = DEFAULT_CONFIG.host;
|
|
2911
|
+
dbPort = DEFAULT_CONFIG.port;
|
|
2912
|
+
dbName = DEFAULT_CONFIG.database;
|
|
2913
|
+
dbUsername = DEFAULT_CONFIG.username;
|
|
2914
|
+
dbPassword = DEFAULT_CONFIG.password;
|
|
2915
|
+
dbFilePath = "./data.db";
|
|
2916
|
+
dbUrl = "";
|
|
2917
|
+
connectionSuccess = false;
|
|
2918
|
+
constructor() {
|
|
2919
|
+
this.basePath = "src";
|
|
2920
|
+
this.env = Env();
|
|
2921
|
+
}
|
|
2922
|
+
async initialize() {
|
|
2923
|
+
try {
|
|
2924
|
+
Ie(import_picocolors6.default.blue("\uD83C\uDFD7️ NajmApi Database Setup"));
|
|
2925
|
+
await this.loadEnvironment();
|
|
2926
|
+
await this.promptDBtype();
|
|
2927
|
+
await this.setupDBEnv();
|
|
2928
|
+
await this.buildProject();
|
|
2929
|
+
await this.addMigrationScripts();
|
|
2930
|
+
await this.addPackages();
|
|
2931
|
+
await this.testDBConnection();
|
|
2932
|
+
M2.success(`✅ Selected database: ${import_picocolors6.default.green(this.dbType)}`);
|
|
2933
|
+
M2.success(`✅ Database url: ${import_picocolors6.default.green(this.dbUrl)}`);
|
|
2934
|
+
M2.success(`✅ Generated ${import_picocolors6.default.green("drizzle.config.ts")}`);
|
|
2935
|
+
M2.success(`✅ Generated database files in ${import_picocolors6.default.green("db.ts")}`);
|
|
2936
|
+
M2.success(`✅ Generated schema files in ${import_picocolors6.default.green("exampleSchema.ts")}`);
|
|
2937
|
+
M2.success(`✅ Added migration scripts to package.json for ${import_picocolors6.default.green(this.dbType)}`);
|
|
2938
|
+
if (!this.connectionSuccess) {
|
|
2939
|
+
M2.warn(import_picocolors6.default.yellow("⚠️ Database connection failed. Please verify:"));
|
|
2940
|
+
M2.warn(import_picocolors6.default.yellow(" • Database name is correct"));
|
|
2941
|
+
M2.warn(import_picocolors6.default.yellow(" • Username and password are valid"));
|
|
2942
|
+
M2.warn(import_picocolors6.default.yellow(" • Database server is running"));
|
|
2943
|
+
M2.warn(import_picocolors6.default.yellow(" • Host and port are accessible"));
|
|
2944
|
+
M2.warn(import_picocolors6.default.yellow(" • Check your .env file configuration"));
|
|
2945
|
+
Se(import_picocolors6.default.yellow("⚠️ Please fix database connection issues before proceeding."));
|
|
2946
|
+
} else {
|
|
2947
|
+
Se(import_picocolors6.default.green("✅ Database setup completed successfully! ✨"));
|
|
2948
|
+
}
|
|
2949
|
+
} catch (error) {
|
|
2950
|
+
M2.error(import_picocolors6.default.red("An error occurred during setup:"));
|
|
2951
|
+
M2.error(error instanceof Error ? error.message : String(error));
|
|
2952
|
+
process.exit(1);
|
|
2953
|
+
}
|
|
2954
|
+
}
|
|
2955
|
+
async buildProject() {
|
|
2956
|
+
const structure = {
|
|
2957
|
+
"{{basePath}}": {
|
|
2958
|
+
database: {
|
|
2959
|
+
db$ts: DB_TEMPLATES[this.dbType],
|
|
2960
|
+
schema: {
|
|
2961
|
+
exampleSchema$ts: SCHEMA_TEMPLATES[this.dbType],
|
|
2962
|
+
index$ts: `// Export your schemas here
|
|
2963
|
+
export * from "./exampleSchema";`
|
|
2964
|
+
},
|
|
2965
|
+
tests: {
|
|
2966
|
+
connectionTest$ts: DB_TEST_TEMPLATES[this.dbType]
|
|
2967
|
+
},
|
|
2968
|
+
migrations: {}
|
|
2969
|
+
}
|
|
2970
|
+
},
|
|
2971
|
+
"drizzle.config$ts": DRIZZLE_CONFIG_TEMPLATE[this.dbType]
|
|
2972
|
+
};
|
|
2973
|
+
return await Build(structure, process.cwd(), {
|
|
2974
|
+
basePath: this.basePath,
|
|
2975
|
+
dbType: this.dbType
|
|
2976
|
+
});
|
|
2977
|
+
}
|
|
2978
|
+
async testDBConnection() {
|
|
2979
|
+
M2.info(`Testing ${this.dbType} database connection...`);
|
|
2980
|
+
const testFilePath = getFile("connectionTest.ts");
|
|
2981
|
+
const result = await runScript(testFilePath);
|
|
2982
|
+
if (result) {
|
|
2983
|
+
M2.success("✅ Database connection test successful");
|
|
2984
|
+
this.connectionSuccess = true;
|
|
2985
|
+
return;
|
|
2986
|
+
}
|
|
2987
|
+
this.connectionSuccess = false;
|
|
2988
|
+
}
|
|
2989
|
+
async addMigrationScripts() {
|
|
2990
|
+
await addScripts(DATABASE_SCRIPTS);
|
|
2991
|
+
}
|
|
2992
|
+
async addPackages() {
|
|
2993
|
+
return await installPackages(DATABASE_PACKAGES[this.dbType]);
|
|
2994
|
+
}
|
|
2995
|
+
async promptPg() {
|
|
2996
|
+
const config = await Ce({
|
|
2997
|
+
host: () => he({
|
|
2998
|
+
message: `Enter database host:`,
|
|
2999
|
+
placeholder: DEFAULT_CONFIG.host,
|
|
3000
|
+
validate: validateHostname
|
|
3001
|
+
}),
|
|
3002
|
+
port: () => he({
|
|
3003
|
+
message: `Enter database port:`,
|
|
3004
|
+
placeholder: String(DEFAULT_CONFIG.port),
|
|
3005
|
+
validate: validatePort
|
|
3006
|
+
}),
|
|
3007
|
+
database: () => he({
|
|
3008
|
+
message: `Enter database name:`,
|
|
3009
|
+
placeholder: DEFAULT_CONFIG.database
|
|
3010
|
+
}),
|
|
3011
|
+
username: () => he({
|
|
3012
|
+
message: `Enter database username:`,
|
|
3013
|
+
placeholder: DEFAULT_CONFIG.username
|
|
3014
|
+
}),
|
|
3015
|
+
password: () => he({
|
|
3016
|
+
message: `Enter database password:`,
|
|
3017
|
+
placeholder: DEFAULT_CONFIG.password
|
|
3018
|
+
})
|
|
3019
|
+
});
|
|
3020
|
+
this.dbType = "pg";
|
|
3021
|
+
this.dbHost = config.host?.trim() || DEFAULT_CONFIG.host;
|
|
3022
|
+
this.dbPort = config.port?.trim() ? Number(config.port) : DEFAULT_CONFIG.port;
|
|
3023
|
+
this.dbName = config.database?.trim() || DEFAULT_CONFIG.database;
|
|
3024
|
+
this.dbUsername = config.username?.trim() || DEFAULT_CONFIG.username;
|
|
3025
|
+
this.dbPassword = config.password?.trim() || DEFAULT_CONFIG.password;
|
|
3026
|
+
this.dbUrl = `postgres://${this.dbUsername}:${this.dbPassword}@${this.dbHost}:${this.dbPort}/${this.dbName}`;
|
|
3027
|
+
}
|
|
3028
|
+
async promptMySql() {
|
|
3029
|
+
const config = await Ce({
|
|
3030
|
+
host: () => he({
|
|
3031
|
+
message: `Enter database host:`,
|
|
3032
|
+
placeholder: DEFAULT_CONFIG.host,
|
|
3033
|
+
validate: validateHostname
|
|
3034
|
+
}),
|
|
3035
|
+
port: () => he({
|
|
3036
|
+
message: `Enter database port:`,
|
|
3037
|
+
placeholder: "3306",
|
|
3038
|
+
validate: validatePort
|
|
3039
|
+
}),
|
|
3040
|
+
database: () => he({
|
|
3041
|
+
message: `Enter database name:`,
|
|
3042
|
+
placeholder: "mysql"
|
|
3043
|
+
}),
|
|
3044
|
+
username: () => he({
|
|
3045
|
+
message: `Enter database username:`,
|
|
3046
|
+
placeholder: "root"
|
|
3047
|
+
}),
|
|
3048
|
+
password: () => he({
|
|
3049
|
+
message: `Enter database password:`,
|
|
3050
|
+
placeholder: ""
|
|
3051
|
+
})
|
|
3052
|
+
});
|
|
3053
|
+
this.dbType = "mysql";
|
|
3054
|
+
this.dbHost = config.host?.trim() || DEFAULT_CONFIG.host;
|
|
3055
|
+
this.dbPort = config.port?.trim() ? Number(config.port) : 3306;
|
|
3056
|
+
this.dbName = config.database?.trim() || "mysql";
|
|
3057
|
+
this.dbUsername = config.username?.trim() || "root";
|
|
3058
|
+
this.dbPassword = config.password?.trim() || "";
|
|
3059
|
+
this.dbUrl = `mysql://${this.dbUsername}:${this.dbPassword}@${this.dbHost}:${this.dbPort}/${this.dbName}`;
|
|
3060
|
+
}
|
|
3061
|
+
async promptSqlite() {
|
|
3062
|
+
const config = await Ce({
|
|
3063
|
+
database: () => he({
|
|
3064
|
+
message: `Enter database file path:`,
|
|
3065
|
+
placeholder: "./data.db"
|
|
3066
|
+
})
|
|
3067
|
+
});
|
|
3068
|
+
this.dbType = "sqlite";
|
|
3069
|
+
this.dbFilePath = config.database?.trim() || "./data.db";
|
|
3070
|
+
this.dbUrl = `file:${this.dbFilePath}`;
|
|
3071
|
+
}
|
|
3072
|
+
async promptDBtype() {
|
|
3073
|
+
this.dbType = await ve({
|
|
3074
|
+
message: "Select your database type:",
|
|
3075
|
+
options: [
|
|
3076
|
+
{ value: "pg", label: "PostgreSQL" },
|
|
3077
|
+
{ value: "mysql", label: "MySQL" },
|
|
3078
|
+
{ value: "sqlite", label: "SQLite (Better-Sqlite3)" }
|
|
3079
|
+
]
|
|
3080
|
+
});
|
|
3081
|
+
}
|
|
3082
|
+
async setupDB() {
|
|
3083
|
+
switch (this.dbType) {
|
|
3084
|
+
case "pg":
|
|
3085
|
+
await this.promptPg();
|
|
3086
|
+
break;
|
|
3087
|
+
case "mysql":
|
|
3088
|
+
await this.promptMySql();
|
|
3089
|
+
break;
|
|
3090
|
+
case "sqlite":
|
|
3091
|
+
await this.promptSqlite();
|
|
3092
|
+
break;
|
|
3093
|
+
default:
|
|
3094
|
+
throw new Error(`Unsupported database type: ${this.dbType}`);
|
|
3095
|
+
}
|
|
3096
|
+
}
|
|
3097
|
+
async createNewConfig() {
|
|
3098
|
+
await this.setupDB();
|
|
3099
|
+
this.env.addComment("# Database Configuration");
|
|
3100
|
+
this.env.add("DB_TYPE", this.dbType, "Database type");
|
|
3101
|
+
this.env.add("DB_URL", this.dbUrl, "Database connection URL");
|
|
3102
|
+
this.env.addEmpty();
|
|
3103
|
+
if (this.dbType === "pg") {
|
|
3104
|
+
this.env.addComment("# PostgreSQL Configuration Details");
|
|
3105
|
+
this.env.add("PG_HOST", this.dbHost, "PostgreSQL host");
|
|
3106
|
+
this.env.add("PG_PORT", String(this.dbPort), "PostgreSQL port");
|
|
3107
|
+
this.env.add("PG_DATABASE", this.dbName, "PostgreSQL database name");
|
|
3108
|
+
this.env.add("PG_USER", this.dbUsername, "PostgreSQL username");
|
|
3109
|
+
this.env.add("PG_PASSWORD", this.dbPassword, "PostgreSQL password");
|
|
3110
|
+
} else if (this.dbType === "mysql") {
|
|
3111
|
+
this.env.addComment("# MySQL Configuration Details");
|
|
3112
|
+
this.env.add("MYSQL_HOST", this.dbHost, "MySQL host");
|
|
3113
|
+
this.env.add("MYSQL_PORT", String(this.dbPort), "MySQL port");
|
|
3114
|
+
this.env.add("MYSQL_DATABASE", this.dbName, "MySQL database name");
|
|
3115
|
+
this.env.add("MYSQL_USER", this.dbUsername, "MySQL username");
|
|
3116
|
+
this.env.add("MYSQL_PASSWORD", this.dbPassword, "MySQL password");
|
|
3117
|
+
} else if (this.dbType === "sqlite") {
|
|
3118
|
+
this.env.addComment("# SQLite Configuration Details");
|
|
3119
|
+
this.env.add("SQLITE_FILE", this.dbFilePath, "SQLite database file path");
|
|
3120
|
+
}
|
|
3121
|
+
}
|
|
3122
|
+
async setupDBEnv() {
|
|
3123
|
+
let configCreated = false;
|
|
3124
|
+
const existingDbType = this.env.get("DB_TYPE");
|
|
3125
|
+
const existingDbUrl = this.env.get("DB_URL");
|
|
3126
|
+
if (!this.env.has("DB_TYPE") || !this.env.has("DB_URL")) {
|
|
3127
|
+
M2.info("Incomplete database configuration found. Creating new configuration...");
|
|
3128
|
+
await this.createNewConfig();
|
|
3129
|
+
configCreated = true;
|
|
3130
|
+
} else if (existingDbType !== this.dbType) {
|
|
3131
|
+
M2.info(`Different database type found (${existingDbType} vs ${this.dbType}). Creating new configuration...`);
|
|
3132
|
+
await this.createNewConfig();
|
|
3133
|
+
configCreated = true;
|
|
3134
|
+
} else if (existingDbUrl) {
|
|
3135
|
+
M2.info(`Existing ${this.dbType} configuration found:`);
|
|
3136
|
+
M2.info(`DB_TYPE=${existingDbType}`);
|
|
3137
|
+
M2.info(`DB_URL=${existingDbUrl}`);
|
|
3138
|
+
const shouldOverride = await ye({
|
|
3139
|
+
message: "Would you like to override the existing database configuration?",
|
|
3140
|
+
initialValue: false
|
|
3141
|
+
});
|
|
3142
|
+
if (shouldOverride) {
|
|
3143
|
+
await this.createNewConfig();
|
|
3144
|
+
configCreated = true;
|
|
3145
|
+
} else {
|
|
3146
|
+
this.dbUrl = existingDbUrl;
|
|
3147
|
+
}
|
|
3148
|
+
}
|
|
3149
|
+
if (!configCreated && existingDbUrl) {
|
|
3150
|
+
this.dbUrl = existingDbUrl;
|
|
3151
|
+
}
|
|
3152
|
+
}
|
|
3153
|
+
async promptBasePath() {
|
|
3154
|
+
this.basePath = await he({
|
|
3155
|
+
message: "Enter base path (e.g., src, src/server):",
|
|
3156
|
+
placeholder: "src",
|
|
3157
|
+
initialValue: "src"
|
|
3158
|
+
});
|
|
3159
|
+
}
|
|
3160
|
+
async loadEnvironment() {
|
|
3161
|
+
const env = Env();
|
|
3162
|
+
if (env.has("BASE_PATH")) {
|
|
3163
|
+
this.basePath = env.get("BASE_PATH");
|
|
3164
|
+
M2.info(`Using base path from environment: ${this.basePath}`);
|
|
3165
|
+
} else {
|
|
3166
|
+
await this.promptBasePath();
|
|
3167
|
+
env.add("BASE_PATH", this.basePath, "Base path for modules");
|
|
3168
|
+
M2.info(`Base path saved to environment: ${this.basePath}`);
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
3171
|
+
}
|
|
3172
|
+
|
|
3173
|
+
// src/Commands/CreateCommand.ts
|
|
3174
|
+
var import_picocolors7 = __toESM(require_picocolors(), 1);
|
|
3175
|
+
import path3 from "path/posix";
|
|
3176
|
+
|
|
3177
|
+
class CreateCommand {
|
|
3178
|
+
basePath;
|
|
3179
|
+
port;
|
|
3180
|
+
projectName;
|
|
3181
|
+
version;
|
|
3182
|
+
description;
|
|
3183
|
+
author;
|
|
3184
|
+
packageManager;
|
|
3185
|
+
buildPath;
|
|
3186
|
+
runtime;
|
|
3187
|
+
constructor() {
|
|
3188
|
+
this.basePath = "src";
|
|
3189
|
+
this.port = 3000;
|
|
3190
|
+
this.projectName = "";
|
|
3191
|
+
this.version = "1.0.0";
|
|
3192
|
+
this.description = "A Backend API project";
|
|
3193
|
+
this.author = "";
|
|
3194
|
+
this.buildPath = "";
|
|
3195
|
+
}
|
|
3196
|
+
async initialize() {
|
|
3197
|
+
try {
|
|
3198
|
+
Ie(import_picocolors7.default.blue("\uD83C\uDFD7️ NajmApi Project Creation"));
|
|
3199
|
+
await this.promptProjectInfo();
|
|
3200
|
+
await this.promptPKManager();
|
|
3201
|
+
await this.buildProject();
|
|
3202
|
+
await this.addPackages();
|
|
3203
|
+
Se(import_picocolors7.default.green("\uD83C\uDFAF Project created successfully! Happy coding!! \uD83D\uDE80"));
|
|
3204
|
+
} catch (error) {
|
|
3205
|
+
console.error("An error occurred:", error);
|
|
3206
|
+
process.exit(1);
|
|
3207
|
+
}
|
|
3208
|
+
}
|
|
3209
|
+
async promptPKManager() {
|
|
3210
|
+
const packageManagerOptions = [
|
|
3211
|
+
{ value: "bun", label: "bun" },
|
|
3212
|
+
{ value: "npm", label: "npm" },
|
|
3213
|
+
{ value: "yarn", label: "yarn" },
|
|
3214
|
+
{ value: "pnpm", label: "pnpm" }
|
|
3215
|
+
];
|
|
3216
|
+
this.packageManager = await ve({
|
|
3217
|
+
message: "Which Package Manager would you like to use?",
|
|
3218
|
+
options: packageManagerOptions
|
|
3219
|
+
});
|
|
3220
|
+
this.runtime = this.packageManager === "bun" ? "bun" : "node";
|
|
3221
|
+
}
|
|
3222
|
+
async promptProjectInfo() {
|
|
3223
|
+
this.projectName = await he({
|
|
3224
|
+
message: "Enter project name:",
|
|
3225
|
+
placeholder: "api-project",
|
|
3226
|
+
initialValue: "api-project",
|
|
3227
|
+
validate: (value) => {
|
|
3228
|
+
if (value.trim() === "") {
|
|
3229
|
+
return "Project name cannot be empty";
|
|
3230
|
+
}
|
|
3231
|
+
if (!isValidProjectName(value)) {
|
|
3232
|
+
return "Please enter a valid project name (lowercase letters, numbers, hyphens, underscores)";
|
|
3233
|
+
}
|
|
3234
|
+
}
|
|
3235
|
+
});
|
|
3236
|
+
this.buildPath = path3.join(process.cwd(), this.projectName);
|
|
3237
|
+
}
|
|
3238
|
+
async buildProject() {
|
|
3239
|
+
const MAIN_CONTENT = this.runtime === "bun" ? BUN_MAIN_CONTENT : NODE_MAIN_CONTENT;
|
|
3240
|
+
const structure = {
|
|
3241
|
+
"{{basePath}}": {
|
|
3242
|
+
modules: {
|
|
3243
|
+
index$ts: ""
|
|
3244
|
+
},
|
|
3245
|
+
shared: {
|
|
3246
|
+
decorators: {
|
|
3247
|
+
index$ts: DB_DECORATORS_TEMPLATE
|
|
3248
|
+
},
|
|
3249
|
+
guards: {},
|
|
3250
|
+
services: {},
|
|
3251
|
+
utils: {}
|
|
3252
|
+
},
|
|
3253
|
+
index$ts: MAIN_CONTENT
|
|
3254
|
+
},
|
|
3255
|
+
tsconfig$json: TS_CONFIG,
|
|
3256
|
+
package$json: PACKAGE_JSON_TEMPLATE,
|
|
3257
|
+
$env: `BASE_PATH={{basePath}} # Base path for modules`
|
|
3258
|
+
};
|
|
3259
|
+
const result = await Build(structure, this.buildPath, {
|
|
3260
|
+
basePath: this.basePath,
|
|
3261
|
+
port: this.port,
|
|
3262
|
+
projectName: this.projectName,
|
|
3263
|
+
version: this.version,
|
|
3264
|
+
description: this.description,
|
|
3265
|
+
author: this.author,
|
|
3266
|
+
runtime: this.runtime
|
|
3267
|
+
});
|
|
3268
|
+
M2.success(`NajmApi Project created successfully with the following structure:`);
|
|
3269
|
+
M2.info(`- Root path: ${result.rootPath}`);
|
|
3270
|
+
M2.info(`- Created files:`);
|
|
3271
|
+
Object.entries(result.files).forEach(([name, filePath]) => {
|
|
3272
|
+
M2.info(` - ${name}: ${filePath}`);
|
|
3273
|
+
});
|
|
3274
|
+
return result;
|
|
3275
|
+
}
|
|
3276
|
+
async addPackages() {
|
|
3277
|
+
const packages = {
|
|
3278
|
+
dependencies: ["hono", "najm-api", "reflect-metadata"],
|
|
3279
|
+
devDependencies: ["typescript", "@types/node"]
|
|
3280
|
+
};
|
|
3281
|
+
await installPackages(packages, {
|
|
3282
|
+
cwd: this.buildPath,
|
|
3283
|
+
pm: this.packageManager
|
|
3284
|
+
});
|
|
3285
|
+
}
|
|
3286
|
+
}
|
|
3287
|
+
|
|
3288
|
+
// src/Commands/NextCommand.ts
|
|
3289
|
+
import { readFile as readFile5 } from "fs/promises";
|
|
3290
|
+
var import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
3291
|
+
import path4 from "path/posix";
|
|
3292
|
+
class NextCommand {
|
|
3293
|
+
basePath;
|
|
3294
|
+
port;
|
|
3295
|
+
packageManager;
|
|
3296
|
+
runtime;
|
|
3297
|
+
constructor() {
|
|
3298
|
+
this.basePath = "src";
|
|
3299
|
+
this.port = 3000;
|
|
3300
|
+
}
|
|
3301
|
+
async initialize() {
|
|
3302
|
+
try {
|
|
3303
|
+
Ie(import_picocolors8.default.blue("\uD83C\uDFD7️ NajmApi Project NetxtJs Initialization"));
|
|
3304
|
+
await this.promptBasePath();
|
|
3305
|
+
await this.promptPKManager();
|
|
3306
|
+
await this.buildProject();
|
|
3307
|
+
await this.addPackages();
|
|
3308
|
+
Se(import_picocolors8.default.green("\uD83C\uDFAF NajmApi initialized in existing project, Happy coding!! \uD83D\uDE80"));
|
|
3309
|
+
} catch (error) {
|
|
3310
|
+
console.error("An error occurred:", error);
|
|
3311
|
+
process.exit(1);
|
|
3312
|
+
}
|
|
3313
|
+
}
|
|
3314
|
+
async promptPKManager() {
|
|
3315
|
+
const packageManagerOptions = [
|
|
3316
|
+
{ value: "bun", label: "bun" },
|
|
3317
|
+
{ value: "npm", label: "npm" },
|
|
3318
|
+
{ value: "yarn", label: "yarn" },
|
|
3319
|
+
{ value: "pnpm", label: "pnpm" }
|
|
3320
|
+
];
|
|
3321
|
+
this.packageManager = await ve({
|
|
3322
|
+
message: "Which Package Manager would you like to use?",
|
|
3323
|
+
options: packageManagerOptions
|
|
3324
|
+
});
|
|
3325
|
+
this.runtime = this.packageManager === "bun" ? "bun" : "node";
|
|
3326
|
+
}
|
|
3327
|
+
async promptBasePath() {
|
|
3328
|
+
this.basePath = await he({
|
|
3329
|
+
message: "Enter server path (default: src/server):",
|
|
3330
|
+
placeholder: "src/server",
|
|
3331
|
+
initialValue: "src/server"
|
|
3332
|
+
});
|
|
3333
|
+
const env = Env();
|
|
3334
|
+
env.add("BASE_PATH", this.basePath, "Base path for modules");
|
|
3335
|
+
M2.info(`Base path saved to environment: ${this.basePath}`);
|
|
3336
|
+
}
|
|
3337
|
+
async getTSDefaultConfig() {
|
|
3338
|
+
const tsconfigPath = path4.join(process.cwd(), "tsconfig.json");
|
|
3339
|
+
const exists = await pathExists(tsconfigPath);
|
|
3340
|
+
if (exists) {
|
|
3341
|
+
const existingConfig = await readFile5(tsconfigPath, "utf-8");
|
|
3342
|
+
const cleanConfig = cleanJsonString(existingConfig).trim();
|
|
3343
|
+
const config = JSON.parse(cleanConfig);
|
|
3344
|
+
const needsUpdate = !config.compilerOptions?.experimentalDecorators || !config.compilerOptions?.emitDecoratorMetadata;
|
|
3345
|
+
if (needsUpdate) {
|
|
3346
|
+
config.compilerOptions = config.compilerOptions || {};
|
|
3347
|
+
config.compilerOptions.experimentalDecorators = true;
|
|
3348
|
+
config.compilerOptions.emitDecoratorMetadata = true;
|
|
3349
|
+
}
|
|
3350
|
+
return JSON.stringify(config, null, 2);
|
|
3351
|
+
} else {
|
|
3352
|
+
return TS_CONFIG;
|
|
3353
|
+
}
|
|
3354
|
+
}
|
|
3355
|
+
async buildProject() {
|
|
3356
|
+
const pathParts = this.basePath.split("/");
|
|
3357
|
+
const baseDir = pathParts[0];
|
|
3358
|
+
const serverDir = pathParts.slice(1).join("/");
|
|
3359
|
+
const structure = {
|
|
3360
|
+
[baseDir]: {
|
|
3361
|
+
[serverDir]: {
|
|
3362
|
+
modules: {
|
|
3363
|
+
index$ts: ""
|
|
3364
|
+
},
|
|
3365
|
+
shared: {
|
|
3366
|
+
decorators: {
|
|
3367
|
+
index$ts: DB_DECORATORS_TEMPLATE
|
|
3368
|
+
},
|
|
3369
|
+
guards: {},
|
|
3370
|
+
services: {},
|
|
3371
|
+
utils: {}
|
|
3372
|
+
},
|
|
3373
|
+
index$ts: NEXT_TEMPLATE
|
|
3374
|
+
}
|
|
3375
|
+
},
|
|
3376
|
+
tsconfig$json: await this.getTSDefaultConfig()
|
|
3377
|
+
};
|
|
3378
|
+
const result = await Build(structure, process.cwd(), {
|
|
3379
|
+
basePath: this.basePath,
|
|
3380
|
+
port: this.port,
|
|
3381
|
+
runtime: this.runtime
|
|
3382
|
+
});
|
|
3383
|
+
M2.success(`NajmApi Project initialized successfully with the following structure:`);
|
|
3384
|
+
M2.info(`- Created files:`);
|
|
3385
|
+
Object.entries(result.files).forEach(([name, filePath]) => {
|
|
3386
|
+
M2.info(` - ${name}: ${filePath}`);
|
|
3387
|
+
});
|
|
3388
|
+
return result;
|
|
3389
|
+
}
|
|
3390
|
+
async addPackages() {
|
|
3391
|
+
const packages = {
|
|
3392
|
+
dependencies: ["hono", "najm-api", "reflect-metadata"],
|
|
3393
|
+
devDependencies: ["typescript", "@types/node"]
|
|
3394
|
+
};
|
|
3395
|
+
await installPackages(packages, {
|
|
3396
|
+
cwd: process.cwd(),
|
|
3397
|
+
pm: this.packageManager
|
|
3398
|
+
});
|
|
3399
|
+
}
|
|
3400
|
+
}
|
|
3401
|
+
|
|
3402
|
+
// src/Commands/NewCommand.ts
|
|
3403
|
+
var import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
3404
|
+
import path5 from "path/posix";
|
|
3405
|
+
import fs3 from "fs/promises";
|
|
3406
|
+
class NewCommand {
|
|
3407
|
+
basePath;
|
|
3408
|
+
componentName;
|
|
3409
|
+
componentType;
|
|
3410
|
+
moduleName;
|
|
3411
|
+
moduleNameUpper;
|
|
3412
|
+
constructor(type, name) {
|
|
3413
|
+
this.basePath = "src";
|
|
3414
|
+
this.componentName = name || "";
|
|
3415
|
+
this.componentType = type || "controller";
|
|
3416
|
+
this.moduleName = "";
|
|
3417
|
+
this.moduleNameUpper = "";
|
|
3418
|
+
}
|
|
3419
|
+
async initialize() {
|
|
3420
|
+
try {
|
|
3421
|
+
Ie(import_picocolors9.default.blue("\uD83C\uDFD7️ NajmApi Component Generator"));
|
|
3422
|
+
await this.loadEnvironment();
|
|
3423
|
+
if (!this.componentName) {
|
|
3424
|
+
await this.promptComponentType();
|
|
3425
|
+
await this.promptComponentName();
|
|
3426
|
+
}
|
|
3427
|
+
await this.processModuleName();
|
|
3428
|
+
await this.generateComponent();
|
|
3429
|
+
Se(import_picocolors9.default.green(`✅ ${this.componentType} generated successfully!`));
|
|
3430
|
+
} catch (error) {
|
|
3431
|
+
console.error("An error occurred:", error);
|
|
3432
|
+
process.exit(1);
|
|
3433
|
+
}
|
|
3434
|
+
}
|
|
3435
|
+
async promptComponentType() {
|
|
3436
|
+
this.componentType = await ve({
|
|
3437
|
+
message: "What type of component do you want to create?",
|
|
3438
|
+
options: [
|
|
3439
|
+
{ value: "controller", label: "Controller" },
|
|
3440
|
+
{ value: "service", label: "Service" },
|
|
3441
|
+
{ value: "repository", label: "Repository" },
|
|
3442
|
+
{ value: "module", label: "Full Module (Controller+Service+Repository)" }
|
|
3443
|
+
]
|
|
3444
|
+
});
|
|
3445
|
+
}
|
|
3446
|
+
async promptComponentName() {
|
|
3447
|
+
this.componentName = await he({
|
|
3448
|
+
message: `Enter ${this.componentType} name:`,
|
|
3449
|
+
placeholder: "user",
|
|
3450
|
+
initialValue: ""
|
|
3451
|
+
});
|
|
3452
|
+
if (!this.componentName) {
|
|
3453
|
+
M2.error("Component name cannot be empty");
|
|
3454
|
+
process.exit(1);
|
|
3455
|
+
}
|
|
3456
|
+
}
|
|
3457
|
+
async processModuleName() {
|
|
3458
|
+
if (this.componentType !== "module") {
|
|
3459
|
+
const suffixes = ["Controller", "Service", "Repository"];
|
|
3460
|
+
for (const suffix of suffixes) {
|
|
3461
|
+
if (this.componentName.endsWith(suffix)) {
|
|
3462
|
+
this.moduleName = this.componentName.substring(0, this.componentName.length - suffix.length).toLowerCase();
|
|
3463
|
+
return;
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
}
|
|
3467
|
+
this.moduleName = this.componentName.toLowerCase();
|
|
3468
|
+
this.moduleNameUpper = this.moduleName.charAt(0).toUpperCase() + this.moduleName.slice(1);
|
|
3469
|
+
}
|
|
3470
|
+
async generateComponent() {
|
|
3471
|
+
const structure = {
|
|
3472
|
+
"{{basePath}}": {
|
|
3473
|
+
modules: {
|
|
3474
|
+
"{{moduleName}}s": {}
|
|
3475
|
+
}
|
|
3476
|
+
}
|
|
3477
|
+
};
|
|
3478
|
+
if (this.componentType === "controller" || this.componentType === "module") {
|
|
3479
|
+
structure["{{basePath}}"].modules["{{moduleName}}s"]["{{moduleName}}Controller$ts"] = CONTROLLER_CONTENT;
|
|
3480
|
+
}
|
|
3481
|
+
if (this.componentType === "service" || this.componentType === "module") {
|
|
3482
|
+
structure["{{basePath}}"].modules["{{moduleName}}s"]["{{moduleName}}Service$ts"] = SERVICE_CONTENT;
|
|
3483
|
+
}
|
|
3484
|
+
if (this.componentType === "repository" || this.componentType === "module") {
|
|
3485
|
+
structure["{{basePath}}"].modules["{{moduleName}}s"]["{{moduleName}}Repository$ts"] = REPOSITORY_CONTENT;
|
|
3486
|
+
}
|
|
3487
|
+
if (this.componentType === "module") {
|
|
3488
|
+
structure["{{basePath}}"].modules["{{moduleName}}s"]["index$ts"] = `export * from './{{moduleName}}Controller';
|
|
3489
|
+
` + `export * from './{{moduleName}}Service';
|
|
3490
|
+
` + `export * from './{{moduleName}}Repository';
|
|
3491
|
+
`;
|
|
3492
|
+
}
|
|
3493
|
+
const result = await Build(structure, process.cwd(), {
|
|
3494
|
+
basePath: this.basePath,
|
|
3495
|
+
moduleName: this.moduleName,
|
|
3496
|
+
moduleNameUpper: this.moduleNameUpper
|
|
3497
|
+
});
|
|
3498
|
+
M2.success(`Generated the following files:`);
|
|
3499
|
+
Object.entries(result.files).forEach(([name, filePath]) => {
|
|
3500
|
+
M2.info(` - ${name}: ${filePath}`);
|
|
3501
|
+
});
|
|
3502
|
+
if (this.componentType === "module") {
|
|
3503
|
+
await this.updateModulesIndex();
|
|
3504
|
+
}
|
|
3505
|
+
}
|
|
3506
|
+
async updateModulesIndex() {
|
|
3507
|
+
const indexPath = path5.join(process.cwd(), this.basePath, "modules", "index.ts");
|
|
3508
|
+
try {
|
|
3509
|
+
const indexExists = await pathExists(indexPath);
|
|
3510
|
+
if (!indexExists) {
|
|
3511
|
+
await fs3.writeFile(indexPath, `export * from './${this.moduleName}s';
|
|
3512
|
+
`, "utf-8");
|
|
3513
|
+
M2.success(`Created modules/index.ts with export for '${this.moduleName}'.`);
|
|
3514
|
+
return;
|
|
3515
|
+
}
|
|
3516
|
+
const content = await fs3.readFile(indexPath, "utf-8");
|
|
3517
|
+
const exportLine = `export * from './${this.moduleName}s';`;
|
|
3518
|
+
if (content.includes(exportLine)) {
|
|
3519
|
+
M2.info(`Export for '${this.moduleName}' already exists in modules/index.ts.`);
|
|
3520
|
+
return;
|
|
3521
|
+
}
|
|
3522
|
+
let newContent = content;
|
|
3523
|
+
if (!content.endsWith(`
|
|
3524
|
+
`)) {
|
|
3525
|
+
newContent += `
|
|
3526
|
+
`;
|
|
3527
|
+
}
|
|
3528
|
+
newContent += `${exportLine}
|
|
3529
|
+
`;
|
|
3530
|
+
await fs3.writeFile(indexPath, newContent, "utf-8");
|
|
3531
|
+
M2.success(`Updated modules/index.ts to include export for '${this.moduleName}'.`);
|
|
3532
|
+
} catch (error) {
|
|
3533
|
+
M2.error(`Failed to update modules/index.ts: ${error.message}`);
|
|
3534
|
+
}
|
|
3535
|
+
}
|
|
3536
|
+
async loadEnvironment() {
|
|
3537
|
+
const env = Env();
|
|
3538
|
+
if (env.has("BASE_PATH")) {
|
|
3539
|
+
this.basePath = env.get("BASE_PATH");
|
|
3540
|
+
M2.info(`Using base path from environment: ${this.basePath}`);
|
|
3541
|
+
} else {
|
|
3542
|
+
await this.promptBasePath();
|
|
3543
|
+
env.add("BASE_PATH", this.basePath, "Base path for modules");
|
|
3544
|
+
M2.info(`Base path saved to environment: ${this.basePath}`);
|
|
3545
|
+
}
|
|
3546
|
+
}
|
|
3547
|
+
async promptBasePath() {
|
|
3548
|
+
this.basePath = await he({
|
|
3549
|
+
message: "Enter base path (e.g., src, src/server):",
|
|
3550
|
+
placeholder: "src",
|
|
3551
|
+
initialValue: "src"
|
|
3552
|
+
});
|
|
3553
|
+
}
|
|
3554
|
+
}
|
|
3555
|
+
|
|
3556
|
+
// src/index.ts
|
|
3557
|
+
async function main() {
|
|
3558
|
+
try {
|
|
3559
|
+
const args = process.argv.slice(2);
|
|
3560
|
+
const command = args[0];
|
|
3561
|
+
const subCommand = args[1];
|
|
3562
|
+
const componentName = args[2];
|
|
3563
|
+
switch (command) {
|
|
3564
|
+
case "create":
|
|
3565
|
+
const createCmd = new CreateCommand;
|
|
3566
|
+
await createCmd.initialize();
|
|
3567
|
+
break;
|
|
3568
|
+
case "init":
|
|
3569
|
+
if (subCommand === "next" || subCommand === "nextjs") {
|
|
3570
|
+
const nextCmd = new NextCommand;
|
|
3571
|
+
await nextCmd.initialize();
|
|
3572
|
+
} else {
|
|
3573
|
+
const initCmd = new InitCommand;
|
|
3574
|
+
await initCmd.initialize();
|
|
3575
|
+
}
|
|
3576
|
+
break;
|
|
3577
|
+
case "new":
|
|
3578
|
+
case "generate":
|
|
3579
|
+
let componentType = undefined;
|
|
3580
|
+
if (subCommand) {
|
|
3581
|
+
switch (subCommand.toLowerCase()) {
|
|
3582
|
+
case "controller":
|
|
3583
|
+
case "service":
|
|
3584
|
+
case "repository":
|
|
3585
|
+
case "module":
|
|
3586
|
+
componentType = subCommand.toLowerCase();
|
|
3587
|
+
break;
|
|
3588
|
+
default:
|
|
3589
|
+
M2.error(`Unknown component type: ${subCommand}`);
|
|
3590
|
+
M2.info("Supported types: controller, service, repository, module");
|
|
3591
|
+
process.exit(1);
|
|
3592
|
+
}
|
|
3593
|
+
}
|
|
3594
|
+
const newCmd = new NewCommand(componentType, componentName);
|
|
3595
|
+
await newCmd.initialize();
|
|
3596
|
+
break;
|
|
3597
|
+
case "database":
|
|
3598
|
+
const dbCommand = new DBCommand;
|
|
3599
|
+
await dbCommand.initialize();
|
|
3600
|
+
break;
|
|
3601
|
+
case "help":
|
|
3602
|
+
case "--help":
|
|
3603
|
+
case "-h":
|
|
3604
|
+
await showHelp();
|
|
3605
|
+
break;
|
|
3606
|
+
default:
|
|
3607
|
+
if (!command) {
|
|
3608
|
+
M2.warn('No command specified. Use "najm-api init" to create a new project.');
|
|
3609
|
+
await showHelp();
|
|
3610
|
+
} else {
|
|
3611
|
+
M2.error(`Unknown command: ${command}`);
|
|
3612
|
+
await showHelp();
|
|
3613
|
+
}
|
|
3614
|
+
break;
|
|
3615
|
+
}
|
|
3616
|
+
setTimeout(() => {
|
|
3617
|
+
process.exit(0);
|
|
3618
|
+
}, 100);
|
|
3619
|
+
} catch (error) {
|
|
3620
|
+
console.error("An error occurred:", error);
|
|
3621
|
+
process.exit(1);
|
|
3622
|
+
}
|
|
3623
|
+
}
|
|
3624
|
+
main();
|