vatts 2.0.2 → 2.1.0-canary.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +12 -12
- package/README.md +63 -63
- package/dist/api/console.d.ts +28 -5
- package/dist/api/console.js +305 -137
- package/dist/api/native-server.js +25 -4
- package/dist/bin/vatts.js +192 -4
- package/dist/builder.js +70 -69
- package/dist/core-go/core-linux-arm64.node +0 -0
- package/dist/core-go/core-linux-x64.node +0 -0
- package/dist/core-go/core-win-x64.node +0 -0
- package/dist/global/global.d.ts +176 -176
- package/dist/helpers.d.ts +2 -2
- package/dist/helpers.js +20 -41
- package/dist/hotReload.js +205 -205
- package/dist/index.d.ts +2 -1
- package/dist/index.js +104 -19
- package/dist/loaders.js +15 -15
- package/dist/react/BuildingPage.js +202 -202
- package/dist/react/DefaultNotFound.js +16 -16
- package/dist/react/DevIndicator.js +101 -101
- package/dist/react/entry.client.js +7 -8
- package/dist/react/image/Image.js +1 -1
- package/dist/react/renderer-react.js +270 -33
- package/dist/react/server-error.d.ts +8 -0
- package/dist/react/server-error.js +346 -0
- package/dist/router.js +1 -65
- package/dist/types.d.ts +1 -5
- package/dist/utils/utils.d.ts +1 -0
- package/dist/utils/utils.js +68 -0
- package/dist/vue/App.vue +191 -191
- package/dist/vue/BuildingPage.vue +280 -280
- package/dist/vue/DefaultNotFound.vue +328 -328
- package/dist/vue/DevIndicator.vue +225 -225
- package/dist/vue/ErrorModal.vue +316 -316
- package/dist/vue/Link.vue +38 -38
- package/dist/vue/entry.client.js +7 -7
- package/dist/vue/image/Image.vue +106 -106
- package/dist/vue/renderer.vue.js +266 -46
- package/dist/vue/server-error.vue +351 -0
- package/package.json +1 -1
package/dist/api/console.js
CHANGED
|
@@ -27,13 +27,13 @@ const node_readline_1 = __importDefault(require("node:readline"));
|
|
|
27
27
|
class DynamicLine {
|
|
28
28
|
_id = Symbol();
|
|
29
29
|
constructor(initialContent) {
|
|
30
|
-
Console[
|
|
30
|
+
Console["registerDynamicLine"](this._id, initialContent);
|
|
31
31
|
}
|
|
32
32
|
update(newContent) {
|
|
33
|
-
Console[
|
|
33
|
+
Console["updateDynamicLine"](this._id, newContent);
|
|
34
34
|
}
|
|
35
35
|
end(finalContent) {
|
|
36
|
-
Console[
|
|
36
|
+
Console["endDynamicLine"](this._id, finalContent);
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
exports.DynamicLine = DynamicLine;
|
|
@@ -75,113 +75,240 @@ var Levels;
|
|
|
75
75
|
Levels["SUCCESS"] = "SUCCESS";
|
|
76
76
|
})(Levels || (exports.Levels = Levels = {}));
|
|
77
77
|
class Console {
|
|
78
|
-
|
|
79
|
-
static
|
|
80
|
-
//
|
|
81
|
-
static
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
node_readline_1.default.cursorTo(stream, 0);
|
|
90
|
-
node_readline_1.default.clearScreenDown(stream);
|
|
91
|
-
if (this.activeLines.length > 0) {
|
|
92
|
-
stream.write(this.activeLines.map(l => this.formatLog('WAIT', l.content)).join('\n') + '\n');
|
|
93
|
-
}
|
|
94
|
-
this.lastRenderedLines = this.activeLines.length;
|
|
78
|
+
// Map storing active lines and their offset from the current cursor position (rows up)
|
|
79
|
+
static activeLines = new Map();
|
|
80
|
+
// Hook para interceptar stdout
|
|
81
|
+
static originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
82
|
+
static isHooked = false;
|
|
83
|
+
static isWriting = false;
|
|
84
|
+
// --- THEME / HELPERS VISUAIS ---
|
|
85
|
+
static ANSI_REGEX = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
|
|
86
|
+
static stripAnsi(text) {
|
|
87
|
+
return text.replace(this.ANSI_REGEX, "");
|
|
95
88
|
}
|
|
96
|
-
static
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
89
|
+
static fg(r, g, b) {
|
|
90
|
+
return `\x1b[38;2;${r};${g};${b}m`;
|
|
91
|
+
}
|
|
92
|
+
static bg(r, g, b) {
|
|
93
|
+
return `\x1b[48;2;${r};${g};${b}m`;
|
|
94
|
+
}
|
|
95
|
+
static padCenter(text, width) {
|
|
96
|
+
const cleanLen = this.stripAnsi(text).length;
|
|
97
|
+
if (cleanLen >= width)
|
|
98
|
+
return text;
|
|
99
|
+
const total = width - cleanLen;
|
|
100
|
+
const left = Math.floor(total / 2);
|
|
101
|
+
const right = total - left;
|
|
102
|
+
return " ".repeat(left) + text + " ".repeat(right);
|
|
103
|
+
}
|
|
104
|
+
static padRight(text, width) {
|
|
105
|
+
const cleanLen = this.stripAnsi(text).length;
|
|
106
|
+
if (cleanLen >= width)
|
|
107
|
+
return text;
|
|
108
|
+
return text + " ".repeat(width - cleanLen);
|
|
109
|
+
}
|
|
110
|
+
static getTime() {
|
|
111
|
+
return new Date().toLocaleTimeString("pt-BR", { hour12: false });
|
|
112
|
+
}
|
|
113
|
+
static normalizeLevelName(level) {
|
|
114
|
+
if (level === null || level === undefined)
|
|
115
|
+
return "";
|
|
116
|
+
return String(level).trim();
|
|
117
|
+
}
|
|
118
|
+
static isKnownLevel(level) {
|
|
119
|
+
const normalized = this.normalizeLevelName(level);
|
|
120
|
+
if (!normalized)
|
|
121
|
+
return false;
|
|
122
|
+
const upper = normalized.toUpperCase();
|
|
123
|
+
return (upper === Levels.ERROR ||
|
|
124
|
+
upper === Levels.WARN ||
|
|
125
|
+
upper === Levels.INFO ||
|
|
126
|
+
upper === Levels.DEBUG ||
|
|
127
|
+
upper === Levels.SUCCESS ||
|
|
128
|
+
upper === "WAIT");
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Converte uma cor ANSI (Colors.FgX) em um background 24-bit escuro combinando.
|
|
132
|
+
* Isso faz teu methodColor virar um badge bonitinho (fg + bg).
|
|
133
|
+
*/
|
|
134
|
+
static bgForFgColor(fgColor) {
|
|
135
|
+
switch (fgColor) {
|
|
136
|
+
case Colors.FgRed:
|
|
137
|
+
return this.bg(86, 24, 24);
|
|
138
|
+
case Colors.FgGreen:
|
|
139
|
+
return this.bg(18, 64, 34);
|
|
140
|
+
case Colors.FgYellow:
|
|
141
|
+
return this.bg(72, 58, 20);
|
|
142
|
+
case Colors.FgBlue:
|
|
143
|
+
return this.bg(18, 38, 70);
|
|
144
|
+
case Colors.FgMagenta:
|
|
145
|
+
return this.bg(46, 28, 66);
|
|
146
|
+
case Colors.FgCyan:
|
|
147
|
+
return this.bg(18, 56, 64);
|
|
148
|
+
case Colors.FgGray:
|
|
149
|
+
return this.bg(48, 48, 48);
|
|
150
|
+
case Colors.FgWhite:
|
|
151
|
+
case Colors.FgAlmostWhite:
|
|
152
|
+
return this.bg(64, 64, 64);
|
|
153
|
+
case Colors.FgBlack:
|
|
154
|
+
return this.bg(20, 20, 20);
|
|
155
|
+
default:
|
|
156
|
+
return this.bg(64, 64, 64);
|
|
113
157
|
}
|
|
114
158
|
}
|
|
115
|
-
static
|
|
116
|
-
|
|
117
|
-
|
|
159
|
+
static levelStyle(level) {
|
|
160
|
+
const C = {
|
|
161
|
+
red: { fg: this.fg(255, 95, 95), bg: this.bg(86, 24, 24) },
|
|
162
|
+
yellow: { fg: this.fg(255, 210, 90), bg: this.bg(72, 58, 20) },
|
|
163
|
+
cyan: { fg: this.fg(120, 230, 255), bg: this.bg(18, 56, 64) },
|
|
164
|
+
green: { fg: this.fg(120, 255, 165), bg: this.bg(18, 64, 34) },
|
|
165
|
+
gray: { fg: this.fg(170, 170, 170), bg: this.bg(48, 48, 48) },
|
|
166
|
+
white: { fg: this.fg(230, 230, 230), bg: this.bg(64, 64, 64) },
|
|
167
|
+
purple: { fg: this.fg(200, 160, 255), bg: this.bg(46, 28, 66) },
|
|
168
|
+
};
|
|
118
169
|
switch (level) {
|
|
119
170
|
case Levels.ERROR:
|
|
120
|
-
icon
|
|
121
|
-
baseColor = Colors.FgRed;
|
|
122
|
-
break;
|
|
171
|
+
return { icon: "✖", badgeFg: C.red.fg, badgeBg: C.red.bg, msgFg: Colors.FgAlmostWhite };
|
|
123
172
|
case Levels.WARN:
|
|
124
|
-
icon
|
|
125
|
-
baseColor = Colors.FgYellow;
|
|
126
|
-
break;
|
|
173
|
+
return { icon: "▲", badgeFg: C.yellow.fg, badgeBg: C.yellow.bg, msgFg: Colors.FgAlmostWhite };
|
|
127
174
|
case Levels.INFO:
|
|
128
|
-
icon
|
|
129
|
-
baseColor = Colors.FgCyan;
|
|
130
|
-
break;
|
|
175
|
+
return { icon: "ℹ", badgeFg: C.cyan.fg, badgeBg: C.cyan.bg, msgFg: Colors.FgAlmostWhite };
|
|
131
176
|
case Levels.SUCCESS:
|
|
132
|
-
icon
|
|
133
|
-
baseColor = Colors.FgGreen;
|
|
134
|
-
break;
|
|
177
|
+
return { icon: "✓", badgeFg: C.green.fg, badgeBg: C.green.bg, msgFg: Colors.FgAlmostWhite };
|
|
135
178
|
case Levels.DEBUG:
|
|
136
|
-
icon
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
case 'WAIT':
|
|
140
|
-
icon = '○';
|
|
141
|
-
baseColor = Colors.FgCyan;
|
|
142
|
-
break;
|
|
179
|
+
return { icon: "›", badgeFg: C.gray.fg, badgeBg: C.gray.bg, msgFg: Colors.FgGray };
|
|
180
|
+
case "WAIT":
|
|
181
|
+
return { icon: "", badgeFg: C.purple.fg, badgeBg: C.purple.bg, msgFg: Colors.FgAlmostWhite };
|
|
143
182
|
default:
|
|
144
|
-
icon
|
|
145
|
-
baseColor = color || Colors.FgWhite;
|
|
146
|
-
break;
|
|
183
|
+
return { icon: "", badgeFg: C.white.fg, badgeBg: C.white.bg, msgFg: Colors.FgAlmostWhite };
|
|
147
184
|
}
|
|
148
|
-
|
|
149
|
-
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Agora aceita override de cor pro badge (pra custom levels tipo GET/POST).
|
|
188
|
+
*/
|
|
189
|
+
static renderBadge(level, badgeFgOverride) {
|
|
150
190
|
const reset = Colors.Reset;
|
|
151
|
-
const
|
|
152
|
-
const
|
|
153
|
-
|
|
191
|
+
const bold = Colors.Bright;
|
|
192
|
+
const normalized = this.normalizeLevelName(level);
|
|
193
|
+
if (normalized === "")
|
|
194
|
+
return "";
|
|
195
|
+
const name = normalized.toUpperCase();
|
|
196
|
+
const trimmed = name.length > 7 ? name.slice(0, 7) : name;
|
|
197
|
+
// centraliza dentro do badge
|
|
198
|
+
const padded = this.padCenter(trimmed, 7);
|
|
199
|
+
const base = this.levelStyle(level);
|
|
200
|
+
const fg = badgeFgOverride ?? base.badgeFg;
|
|
201
|
+
const bg = badgeFgOverride ? this.bgForFgColor(badgeFgOverride) : base.badgeBg;
|
|
202
|
+
return `${bg}${fg}${bold} ${padded} ${reset}`;
|
|
203
|
+
}
|
|
204
|
+
static indentMultiline(msg, indent) {
|
|
205
|
+
return msg
|
|
206
|
+
.split("\n")
|
|
207
|
+
.map((line, i) => (i === 0 ? line : indent + line))
|
|
208
|
+
.join("\n");
|
|
209
|
+
}
|
|
210
|
+
// --- HELPER PARA CALCULAR ALTURA ADICIONADA ---
|
|
211
|
+
static countRowsAdded(text) {
|
|
212
|
+
const columns = process.stdout.columns || 80;
|
|
213
|
+
const clean = text.replace(this.ANSI_REGEX, "");
|
|
214
|
+
let rowsAdded = 0;
|
|
215
|
+
const lines = clean.split("\n");
|
|
216
|
+
for (let i = 0; i < lines.length; i++) {
|
|
217
|
+
const width = lines[i].length;
|
|
218
|
+
if (width > 0) {
|
|
219
|
+
rowsAdded += Math.floor((width - 1) / columns);
|
|
220
|
+
}
|
|
221
|
+
if (i < lines.length - 1) {
|
|
222
|
+
rowsAdded++;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return rowsAdded;
|
|
226
|
+
}
|
|
227
|
+
// --- HOOK SYSTEM ---
|
|
228
|
+
static hook() {
|
|
229
|
+
if (this.isHooked)
|
|
230
|
+
return;
|
|
231
|
+
this.isHooked = true;
|
|
232
|
+
process.stdout.write = (chunk, encoding, callback) => {
|
|
233
|
+
if (this.isWriting) {
|
|
234
|
+
return this.originalStdoutWrite(chunk, encoding, callback);
|
|
235
|
+
}
|
|
236
|
+
const text = chunk.toString();
|
|
237
|
+
const rowsAdded = this.countRowsAdded(text);
|
|
238
|
+
if (rowsAdded > 0) {
|
|
239
|
+
for (const line of this.activeLines.values()) {
|
|
240
|
+
line.offset += rowsAdded;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return this.originalStdoutWrite(chunk, encoding, callback);
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
// --- HELPER WRITER ---
|
|
247
|
+
static writeStatic(content) {
|
|
248
|
+
console.log(content.replace(/\n$/, ""));
|
|
154
249
|
}
|
|
155
|
-
// --- INTERATIVIDADE (SELECTION) ---
|
|
156
250
|
/**
|
|
157
|
-
*
|
|
158
|
-
* @param options Objeto no formato { "valor_retornado": "Label Exibida" }
|
|
251
|
+
* IMPORTANT: o `color` aqui (quando custom level) agora pinta o BADGE também.
|
|
159
252
|
*/
|
|
253
|
+
static formatLog(level, message, color) {
|
|
254
|
+
if (message === "end_clear")
|
|
255
|
+
return "";
|
|
256
|
+
const reset = Colors.Reset;
|
|
257
|
+
const dim = Colors.Dim;
|
|
258
|
+
const time = this.getTime();
|
|
259
|
+
const timePart = `${dim}${Colors.FgGray}${time}${reset}`;
|
|
260
|
+
const normalizedLevel = this.normalizeLevelName(level);
|
|
261
|
+
const isEmptyLevel = normalizedLevel === "";
|
|
262
|
+
const known = this.isKnownLevel(level);
|
|
263
|
+
const st = this.levelStyle(level);
|
|
264
|
+
// Se for custom (não-known) e tiver color, usa ele no badge
|
|
265
|
+
const shouldOverrideBadge = !known && !!color && !isEmptyLevel;
|
|
266
|
+
const badge = isEmptyLevel ? "" : this.renderBadge(level, shouldOverrideBadge ? color : null);
|
|
267
|
+
const gapAfterTime = " ";
|
|
268
|
+
const gapAfterBadge = badge ? " " : " ";
|
|
269
|
+
// Icon também acompanha cor do custom
|
|
270
|
+
const iconFg = shouldOverrideBadge ? color : st.badgeFg;
|
|
271
|
+
const iconSymbol = isEmptyLevel ? "" : st.icon || "";
|
|
272
|
+
const iconPart = `${iconFg}${iconSymbol}${reset}`;
|
|
273
|
+
const prefix = badge
|
|
274
|
+
? ` ${timePart}${gapAfterTime}${badge}${gapAfterBadge}${iconPart} `
|
|
275
|
+
: ` ${timePart}${gapAfterTime}${iconPart} `;
|
|
276
|
+
// Mensagem: mantém msgFg padrão, mas tu pode também colorir o texto todo se quiser.
|
|
277
|
+
const msgColor = st.msgFg;
|
|
278
|
+
const indent = " ".repeat(this.stripAnsi(prefix).length);
|
|
279
|
+
const prettyMsg = this.indentMultiline(message, indent);
|
|
280
|
+
return `${prefix}${msgColor}${prettyMsg}${reset}`;
|
|
281
|
+
}
|
|
282
|
+
// --- INTERATIVIDADE (SELECTION) ---
|
|
160
283
|
static async selection(question, options) {
|
|
161
284
|
const entries = Object.entries(options);
|
|
162
285
|
let currentIndex = 0;
|
|
163
286
|
const stream = process.stdout;
|
|
164
287
|
let firstRender = true;
|
|
165
|
-
|
|
166
|
-
node_readline_1.default.moveCursor(stream, 0, -this.lastRenderedLines);
|
|
167
|
-
node_readline_1.default.cursorTo(stream, 0);
|
|
168
|
-
node_readline_1.default.clearScreenDown(stream);
|
|
169
|
-
}
|
|
170
|
-
stream.write('\x1b[?25l'); // Hide cursor
|
|
288
|
+
stream.write("\x1b[?25l");
|
|
171
289
|
const render = () => {
|
|
172
|
-
// Se não for a primeira vez, sobe as linhas do menu anterior para sobrescrever
|
|
173
290
|
if (!firstRender) {
|
|
174
|
-
|
|
291
|
+
// FIXED: Changed from +3 to +2 so it doesn't eat the previous logs
|
|
292
|
+
node_readline_1.default.moveCursor(stream, 0, -(entries.length + 2));
|
|
175
293
|
}
|
|
176
294
|
node_readline_1.default.cursorTo(stream, 0);
|
|
177
295
|
node_readline_1.default.clearScreenDown(stream);
|
|
178
|
-
|
|
179
|
-
|
|
296
|
+
const title = ` ${Colors.FgCyan}${Colors.Bright}◆${Colors.Reset} ${Colors.Bright}${question}${Colors.Reset}`;
|
|
297
|
+
let output = `${title}\n ${Colors.Dim}${Colors.FgGray}Use ↑/↓ e Enter${Colors.Reset}\n`;
|
|
298
|
+
entries.forEach(([_key, label], i) => {
|
|
180
299
|
const isSelected = i === currentIndex;
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
300
|
+
const bullet = isSelected
|
|
301
|
+
? `${this.bg(18, 56, 64)}${this.fg(120, 230, 255)} ${Colors.Bright}❯${Colors.Reset}${this.bg(18, 56, 64)}${this.fg(120, 230, 255)} `
|
|
302
|
+
: ` `;
|
|
303
|
+
const text = isSelected
|
|
304
|
+
? `${this.bg(18, 56, 64)}${this.fg(220, 245, 255)}${Colors.Bright}${String(label)}${Colors.Reset}`
|
|
305
|
+
: `${Colors.FgGray}${String(label)}${Colors.Reset}`;
|
|
306
|
+
const suffix = isSelected ? `${this.bg(18, 56, 64)}${Colors.Reset}` : "";
|
|
307
|
+
output += ` ${bullet}${text}${suffix}\n`;
|
|
184
308
|
});
|
|
309
|
+
this.isWriting = true;
|
|
310
|
+
this.originalStdoutWrite(output);
|
|
311
|
+
this.isWriting = false;
|
|
185
312
|
firstRender = false;
|
|
186
313
|
};
|
|
187
314
|
render();
|
|
@@ -189,30 +316,30 @@ class Console {
|
|
|
189
316
|
const handleKey = (_chunk, key) => {
|
|
190
317
|
if (!key)
|
|
191
318
|
return;
|
|
192
|
-
if (key.name ===
|
|
319
|
+
if (key.name === "up") {
|
|
193
320
|
currentIndex = (currentIndex - 1 + entries.length) % entries.length;
|
|
194
321
|
render();
|
|
195
322
|
}
|
|
196
|
-
else if (key.name ===
|
|
323
|
+
else if (key.name === "down") {
|
|
197
324
|
currentIndex = (currentIndex + 1) % entries.length;
|
|
198
325
|
render();
|
|
199
326
|
}
|
|
200
|
-
else if (key.name ===
|
|
201
|
-
process.stdin.removeListener(
|
|
327
|
+
else if (key.name === "return") {
|
|
328
|
+
process.stdin.removeListener("keypress", handleKey);
|
|
202
329
|
if (process.stdin.isTTY)
|
|
203
330
|
process.stdin.setRawMode(false);
|
|
204
331
|
process.stdin.pause();
|
|
205
|
-
stream.write(
|
|
206
|
-
//
|
|
207
|
-
node_readline_1.default.moveCursor(stream, 0, -(entries.length +
|
|
332
|
+
stream.write("\x1b[?25h");
|
|
333
|
+
// FIXED: Changed from +3 to +2 here as well for proper cleanup
|
|
334
|
+
node_readline_1.default.moveCursor(stream, 0, -(entries.length + 2));
|
|
208
335
|
node_readline_1.default.cursorTo(stream, 0);
|
|
209
336
|
node_readline_1.default.clearScreenDown(stream);
|
|
210
|
-
const [
|
|
211
|
-
this.writeStatic(
|
|
212
|
-
resolve(
|
|
337
|
+
const [_selectedKey, selectedLabel] = entries[currentIndex];
|
|
338
|
+
this.writeStatic(this.formatLog(Levels.SUCCESS, `${question} ${Colors.FgGray}›${Colors.Reset} ${String(selectedLabel)}`));
|
|
339
|
+
resolve(_selectedKey);
|
|
213
340
|
}
|
|
214
|
-
else if (key.ctrl && key.name ===
|
|
215
|
-
stream.write(
|
|
341
|
+
else if (key.ctrl && key.name === "c") {
|
|
342
|
+
stream.write("\x1b[?25h");
|
|
216
343
|
process.exit();
|
|
217
344
|
}
|
|
218
345
|
};
|
|
@@ -220,22 +347,36 @@ class Console {
|
|
|
220
347
|
if (process.stdin.isTTY)
|
|
221
348
|
process.stdin.setRawMode(true);
|
|
222
349
|
process.stdin.resume();
|
|
223
|
-
process.stdin.on(
|
|
350
|
+
process.stdin.on("keypress", handleKey);
|
|
224
351
|
});
|
|
225
352
|
}
|
|
226
353
|
// --- MÉTODOS PÚBLICOS ---
|
|
227
|
-
static error(...args) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
static
|
|
231
|
-
|
|
232
|
-
|
|
354
|
+
static error(...args) {
|
|
355
|
+
this.log(Levels.ERROR, null, ...args);
|
|
356
|
+
}
|
|
357
|
+
static warn(...args) {
|
|
358
|
+
this.log(Levels.WARN, null, ...args);
|
|
359
|
+
}
|
|
360
|
+
static info(...args) {
|
|
361
|
+
this.log(Levels.INFO, null, ...args);
|
|
362
|
+
}
|
|
363
|
+
static success(...args) {
|
|
364
|
+
this.log(Levels.SUCCESS, null, ...args);
|
|
365
|
+
}
|
|
366
|
+
static default_log(...args) {
|
|
367
|
+
this.log(Levels.INFO, null, ...args);
|
|
368
|
+
}
|
|
369
|
+
static debug(...args) {
|
|
370
|
+
this.log(Levels.DEBUG, null, ...args);
|
|
371
|
+
}
|
|
233
372
|
static logCustomLevel(levelName, without = true, color, ...args) {
|
|
373
|
+
const normalized = this.normalizeLevelName(levelName);
|
|
374
|
+
const lvl = normalized;
|
|
234
375
|
if (without) {
|
|
235
|
-
this.logWithout(
|
|
376
|
+
this.logWithout(lvl, color, ...args);
|
|
236
377
|
}
|
|
237
378
|
else {
|
|
238
|
-
this.log(
|
|
379
|
+
this.log(lvl, color, ...args);
|
|
239
380
|
}
|
|
240
381
|
}
|
|
241
382
|
static logWithout(level, colors, ...args) {
|
|
@@ -244,75 +385,102 @@ class Console {
|
|
|
244
385
|
static log(level, colors, ...args) {
|
|
245
386
|
let output = "";
|
|
246
387
|
for (const arg of args) {
|
|
247
|
-
|
|
388
|
+
const msg = arg instanceof Error ? arg.stack : typeof arg === "string" ? arg : JSON.stringify(arg, null, 2);
|
|
248
389
|
if (msg)
|
|
249
|
-
output += this.formatLog(level, msg, colors) +
|
|
390
|
+
output += this.formatLog(level, msg, colors) + "\n";
|
|
250
391
|
}
|
|
251
|
-
this.writeStatic(output
|
|
392
|
+
this.writeStatic(output);
|
|
252
393
|
}
|
|
253
394
|
static async ask(question, defaultValue) {
|
|
254
395
|
const rl = node_readline_1.default.createInterface({ input: process.stdin, output: process.stdout });
|
|
255
|
-
const defaultPart = defaultValue ? ` ${Colors.FgGray}(${defaultValue})${Colors.Reset}` :
|
|
256
|
-
const prompt = ` ${Colors.FgCyan}
|
|
257
|
-
|
|
258
|
-
|
|
396
|
+
const defaultPart = defaultValue ? ` ${Colors.Dim}${Colors.FgGray}(${defaultValue})${Colors.Reset}` : "";
|
|
397
|
+
const prompt = ` ${Colors.FgCyan}${Colors.Bright}◆${Colors.Reset} ${Colors.Bright}${question}${Colors.Reset}${defaultPart}\n` +
|
|
398
|
+
` ${Colors.FgCyan}❯${Colors.Reset} `;
|
|
399
|
+
return new Promise((resolve) => {
|
|
400
|
+
rl.question(prompt, (ans) => {
|
|
259
401
|
rl.close();
|
|
260
402
|
const value = ans.trim();
|
|
261
|
-
resolve(value ===
|
|
403
|
+
resolve(value === "" && defaultValue !== undefined ? defaultValue : value);
|
|
262
404
|
});
|
|
263
405
|
});
|
|
264
406
|
}
|
|
265
407
|
static async confirm(message, defaultYes = false) {
|
|
266
|
-
const suffix = defaultYes ?
|
|
267
|
-
const ans = (await this.ask(`${message} ${Colors.FgGray}[${suffix}]${Colors.Reset}`)).toLowerCase();
|
|
268
|
-
if (ans ===
|
|
408
|
+
const suffix = defaultYes ? "Y/n" : "y/N";
|
|
409
|
+
const ans = (await this.ask(`${message} ${Colors.Dim}${Colors.FgGray}[${suffix}]${Colors.Reset}`)).toLowerCase();
|
|
410
|
+
if (ans === "")
|
|
269
411
|
return defaultYes;
|
|
270
|
-
return [
|
|
412
|
+
return ["y", "yes", "s", "sim"].includes(ans);
|
|
271
413
|
}
|
|
272
414
|
static table(data) {
|
|
273
415
|
let rows;
|
|
274
416
|
if (Array.isArray(data)) {
|
|
275
|
-
rows = data.map(row => ({ Field: String(row.Field), Value: String(row.Value) }));
|
|
417
|
+
rows = data.map((row) => ({ Field: String(row.Field), Value: String(row.Value) }));
|
|
276
418
|
}
|
|
277
419
|
else {
|
|
278
420
|
rows = Object.entries(data).map(([Field, Value]) => ({ Field, Value: String(Value) }));
|
|
279
421
|
}
|
|
280
|
-
const fieldLen = Math.max(...rows.map(r => r.Field.length),
|
|
281
|
-
const valueLen = Math.max(...rows.map(r => r.Value.length),
|
|
282
|
-
const h_line =
|
|
283
|
-
const v_line =
|
|
422
|
+
const fieldLen = Math.max(...rows.map((r) => r.Field.length), "Field".length);
|
|
423
|
+
const valueLen = Math.max(...rows.map((r) => r.Value.length), "Value".length);
|
|
424
|
+
const h_line = "─".repeat(fieldLen + 2);
|
|
425
|
+
const v_line = "─".repeat(valueLen + 2);
|
|
284
426
|
const top = `┌${h_line}┬${v_line}┐`;
|
|
285
427
|
const mid = `├${h_line}┼${v_line}┤`;
|
|
286
428
|
const bottom = `└${h_line}┴${v_line}┘`;
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
output
|
|
429
|
+
const headFg = this.fg(120, 230, 255);
|
|
430
|
+
const headBg = this.bg(18, 56, 64);
|
|
431
|
+
let output = `${Colors.Dim}${Colors.FgGray}${top}${Colors.Reset}\n`;
|
|
432
|
+
output += `${Colors.Dim}${Colors.FgGray}│${Colors.Reset} ${headBg}${headFg}${Colors.Bright}${"Field".padEnd(fieldLen)}${Colors.Reset} ${Colors.Dim}${Colors.FgGray}│${Colors.Reset} ${headBg}${headFg}${Colors.Bright}${"Value".padEnd(valueLen)}${Colors.Reset} ${Colors.Dim}${Colors.FgGray}│${Colors.Reset}\n`;
|
|
433
|
+
output += `${Colors.Dim}${Colors.FgGray}${mid}${Colors.Reset}\n`;
|
|
290
434
|
for (const row of rows) {
|
|
291
|
-
output +=
|
|
435
|
+
output += `${Colors.Dim}${Colors.FgGray}│${Colors.Reset} ${Colors.FgAlmostWhite}${row.Field.padEnd(fieldLen)}${Colors.Reset} ${Colors.Dim}${Colors.FgGray}│${Colors.Reset} ${Colors.FgAlmostWhite}${row.Value.padEnd(valueLen)}${Colors.Reset} ${Colors.Dim}${Colors.FgGray}│${Colors.Reset}\n`;
|
|
292
436
|
}
|
|
293
|
-
output += bottom
|
|
437
|
+
output += `${Colors.Dim}${Colors.FgGray}${bottom}${Colors.Reset}\n`;
|
|
294
438
|
this.writeStatic(output);
|
|
295
439
|
}
|
|
296
440
|
static dynamicLine(initialContent) {
|
|
297
441
|
return new DynamicLine(initialContent);
|
|
298
442
|
}
|
|
299
443
|
static registerDynamicLine(id, content) {
|
|
300
|
-
this.
|
|
301
|
-
this.
|
|
444
|
+
this.hook();
|
|
445
|
+
const formatted = this.formatLog("WAIT", content);
|
|
446
|
+
const rows = this.countRowsAdded(formatted + "\n");
|
|
447
|
+
this.writeStatic(formatted);
|
|
448
|
+
this.activeLines.set(id, { offset: rows });
|
|
302
449
|
}
|
|
303
450
|
static updateDynamicLine(id, newContent) {
|
|
304
|
-
|
|
305
|
-
if (line) {
|
|
306
|
-
line.content = newContent;
|
|
307
|
-
this.redrawDynamicLines();
|
|
308
|
-
}
|
|
451
|
+
this.editLine(id, newContent, "WAIT");
|
|
309
452
|
}
|
|
310
453
|
static endDynamicLine(id, finalContent) {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
this.activeLines.
|
|
314
|
-
|
|
454
|
+
if (this.activeLines.has(id)) {
|
|
455
|
+
this.editLine(id, finalContent, Levels.SUCCESS);
|
|
456
|
+
this.activeLines.delete(id);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
static editLine(id, content, level) {
|
|
460
|
+
const line = this.activeLines.get(id);
|
|
461
|
+
if (!line)
|
|
462
|
+
return;
|
|
463
|
+
const stream = process.stdout;
|
|
464
|
+
const formatted = this.formatLog(level, content);
|
|
465
|
+
this.isWriting = true;
|
|
466
|
+
try {
|
|
467
|
+
node_readline_1.default.moveCursor(stream, 0, -line.offset);
|
|
468
|
+
node_readline_1.default.clearLine(stream, 0);
|
|
469
|
+
node_readline_1.default.cursorTo(stream, 0);
|
|
470
|
+
stream.write(formatted + "\n");
|
|
471
|
+
const newRows = this.countRowsAdded(formatted + "\n");
|
|
472
|
+
const rowsToMoveDown = line.offset - newRows;
|
|
473
|
+
if (rowsToMoveDown > 0) {
|
|
474
|
+
node_readline_1.default.moveCursor(stream, 0, rowsToMoveDown);
|
|
475
|
+
}
|
|
476
|
+
else if (rowsToMoveDown < 0) {
|
|
477
|
+
node_readline_1.default.moveCursor(stream, 0, rowsToMoveDown);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
catch (e) {
|
|
481
|
+
// ignore
|
|
315
482
|
}
|
|
483
|
+
this.isWriting = false;
|
|
316
484
|
}
|
|
317
485
|
}
|
|
318
486
|
exports.default = Console;
|
|
@@ -24,7 +24,7 @@ class NativeServer {
|
|
|
24
24
|
const platform = os_1.default.platform();
|
|
25
25
|
const arch = os_1.default.arch();
|
|
26
26
|
let osName = '';
|
|
27
|
-
let ext = '.node';
|
|
27
|
+
let ext = '.node'; // Mantido .node conforme solicitado
|
|
28
28
|
switch (platform) {
|
|
29
29
|
case 'win32':
|
|
30
30
|
osName = 'win';
|
|
@@ -55,15 +55,26 @@ class NativeServer {
|
|
|
55
55
|
static loadLibrary(customPath) {
|
|
56
56
|
if (this.lib)
|
|
57
57
|
return;
|
|
58
|
-
const
|
|
58
|
+
// Alterado de const para let para permitir reatribuição se cair no fallback
|
|
59
|
+
let libPath = customPath || this.getLibPath();
|
|
59
60
|
if (!fs_1.default.existsSync(libPath)) {
|
|
61
|
+
// Tenta resolver relativo ao CWD se não achar no __dirname
|
|
60
62
|
const altPath = path_1.default.resolve(process.cwd(), libPath);
|
|
61
|
-
|
|
63
|
+
// Ou tenta buscar direto pelo nome do arquivo no CWD caso o path relativo esteja errado
|
|
64
|
+
const altPathSimple = path_1.default.resolve(process.cwd(), path_1.default.basename(libPath));
|
|
65
|
+
if (fs_1.default.existsSync(altPath)) {
|
|
66
|
+
libPath = altPath; // <--- AQUI ESTAVA O ERRO: Atualiza libPath para o caminho que existe
|
|
67
|
+
}
|
|
68
|
+
else if (fs_1.default.existsSync(altPathSimple)) {
|
|
69
|
+
libPath = altPathSimple; // <--- Fallback extra de segurança
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
62
72
|
console.warn(`Native Server Library not found at: ${libPath}`);
|
|
63
73
|
return;
|
|
64
74
|
}
|
|
65
75
|
}
|
|
66
76
|
try {
|
|
77
|
+
// Agora o koffi carrega o caminho correto (libPath atualizado)
|
|
67
78
|
this.lib = koffi_1.default.load(libPath);
|
|
68
79
|
// func StartServer(..., onData, onClose)
|
|
69
80
|
this.startFunc = this.lib.func('StartServer', 'str', [
|
|
@@ -79,7 +90,7 @@ class NativeServer {
|
|
|
79
90
|
this.closeConnFunc = this.lib.func('CloseConn', 'void', ['int']);
|
|
80
91
|
}
|
|
81
92
|
catch (error) {
|
|
82
|
-
throw new Error(`Failed to load native library: ${error}`);
|
|
93
|
+
throw new Error(`Failed to load native library at ${libPath}: ${error}`);
|
|
83
94
|
}
|
|
84
95
|
}
|
|
85
96
|
static start(options) {
|
|
@@ -87,6 +98,16 @@ class NativeServer {
|
|
|
87
98
|
this.loadLibrary(customLibPath);
|
|
88
99
|
if (!this.startFunc)
|
|
89
100
|
return;
|
|
101
|
+
// Validação de certificados SSL ANTES de iniciar
|
|
102
|
+
const useSSL = certPath && keyPath;
|
|
103
|
+
if (useSSL) {
|
|
104
|
+
if (!fs_1.default.existsSync(certPath)) {
|
|
105
|
+
throw new Error(`SSL Certificate file not found at: ${certPath}`);
|
|
106
|
+
}
|
|
107
|
+
if (!fs_1.default.existsSync(keyPath)) {
|
|
108
|
+
throw new Error(`SSL Key file not found at: ${keyPath}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
90
111
|
// Callback de DADOS: Agora recebe pointer e length
|
|
91
112
|
const onDataPtr = koffi_1.default.register((connId, ptr, len) => {
|
|
92
113
|
try {
|