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.
Files changed (40) hide show
  1. package/LICENSE +12 -12
  2. package/README.md +63 -63
  3. package/dist/api/console.d.ts +28 -5
  4. package/dist/api/console.js +305 -137
  5. package/dist/api/native-server.js +25 -4
  6. package/dist/bin/vatts.js +192 -4
  7. package/dist/builder.js +70 -69
  8. package/dist/core-go/core-linux-arm64.node +0 -0
  9. package/dist/core-go/core-linux-x64.node +0 -0
  10. package/dist/core-go/core-win-x64.node +0 -0
  11. package/dist/global/global.d.ts +176 -176
  12. package/dist/helpers.d.ts +2 -2
  13. package/dist/helpers.js +20 -41
  14. package/dist/hotReload.js +205 -205
  15. package/dist/index.d.ts +2 -1
  16. package/dist/index.js +104 -19
  17. package/dist/loaders.js +15 -15
  18. package/dist/react/BuildingPage.js +202 -202
  19. package/dist/react/DefaultNotFound.js +16 -16
  20. package/dist/react/DevIndicator.js +101 -101
  21. package/dist/react/entry.client.js +7 -8
  22. package/dist/react/image/Image.js +1 -1
  23. package/dist/react/renderer-react.js +270 -33
  24. package/dist/react/server-error.d.ts +8 -0
  25. package/dist/react/server-error.js +346 -0
  26. package/dist/router.js +1 -65
  27. package/dist/types.d.ts +1 -5
  28. package/dist/utils/utils.d.ts +1 -0
  29. package/dist/utils/utils.js +68 -0
  30. package/dist/vue/App.vue +191 -191
  31. package/dist/vue/BuildingPage.vue +280 -280
  32. package/dist/vue/DefaultNotFound.vue +328 -328
  33. package/dist/vue/DevIndicator.vue +225 -225
  34. package/dist/vue/ErrorModal.vue +316 -316
  35. package/dist/vue/Link.vue +38 -38
  36. package/dist/vue/entry.client.js +7 -7
  37. package/dist/vue/image/Image.vue +106 -106
  38. package/dist/vue/renderer.vue.js +266 -46
  39. package/dist/vue/server-error.vue +351 -0
  40. package/package.json +1 -1
@@ -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['registerDynamicLine'](this._id, initialContent);
30
+ Console["registerDynamicLine"](this._id, initialContent);
31
31
  }
32
32
  update(newContent) {
33
- Console['updateDynamicLine'](this._id, newContent);
33
+ Console["updateDynamicLine"](this._id, newContent);
34
34
  }
35
35
  end(finalContent) {
36
- Console['endDynamicLine'](this._id, finalContent);
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
- static activeLines = [];
79
- static lastRenderedLines = 0;
80
- // --- RENDERIZAÇÃO ---
81
- static redrawDynamicLines() {
82
- const stream = process.stdout;
83
- if (this.lastRenderedLines > 0) {
84
- try {
85
- node_readline_1.default.moveCursor(stream, 0, -this.lastRenderedLines);
86
- }
87
- catch { }
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 writeStatic(content) {
97
- const stream = process.stdout;
98
- if (this.lastRenderedLines > 0) {
99
- try {
100
- node_readline_1.default.moveCursor(stream, 0, -this.lastRenderedLines);
101
- }
102
- catch { }
103
- node_readline_1.default.cursorTo(stream, 0);
104
- node_readline_1.default.clearScreenDown(stream);
105
- }
106
- console.log(content.replace(/\n$/, ''));
107
- if (this.activeLines.length > 0) {
108
- stream.write(this.activeLines.map(l => this.formatLog('WAIT', l.content)).join('\n') + '\n');
109
- this.lastRenderedLines = this.activeLines.length;
110
- }
111
- else {
112
- this.lastRenderedLines = 0;
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 formatLog(level, message, color) {
116
- let icon = '•';
117
- let baseColor = Colors.FgWhite;
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
- baseColor = Colors.FgGray;
138
- break;
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
- const gray = Colors.FgGray;
149
- const bold = Colors.Bright;
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 time = new Date().toLocaleTimeString('pt-BR', { hour12: false });
152
- const levelStr = level === 'WAIT' ? '' : ` ${bold}${level}${reset}`;
153
- return ` ${gray}${time}${reset} ${baseColor}${icon}${levelStr}${reset} ${message}`;
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
- * Menu de seleção interativo usando setas do teclado.
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
- if (this.lastRenderedLines > 0) {
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
- node_readline_1.default.moveCursor(stream, 0, -(entries.length + 1));
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
- stream.write(` ${Colors.FgCyan}?${Colors.Reset} ${Colors.Bright}${question}${Colors.Reset}\n`);
179
- entries.forEach(([key, label], i) => {
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 prefix = isSelected ? `${Colors.FgCyan}❯${Colors.Reset}` : ' ';
182
- const text = isSelected ? `${Colors.FgCyan}${Colors.Bright}${label}${Colors.Reset}` : `${Colors.FgGray}${label}${Colors.Reset}`;
183
- stream.write(` ${prefix} ${text}\n`);
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 === 'up') {
319
+ if (key.name === "up") {
193
320
  currentIndex = (currentIndex - 1 + entries.length) % entries.length;
194
321
  render();
195
322
  }
196
- else if (key.name === 'down') {
323
+ else if (key.name === "down") {
197
324
  currentIndex = (currentIndex + 1) % entries.length;
198
325
  render();
199
326
  }
200
- else if (key.name === 'return') {
201
- process.stdin.removeListener('keypress', handleKey);
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('\x1b[?25h'); // Show cursor
206
- // Limpa o menu final antes de escrever o log estático
207
- node_readline_1.default.moveCursor(stream, 0, -(entries.length + 1));
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 [selectedKey, selectedLabel] = entries[currentIndex];
211
- this.writeStatic(` ${Colors.FgCyan}✓${Colors.Reset} ${Colors.Bright}${question}${Colors.Reset} ${Colors.FgGray}›${Colors.Reset} ${selectedLabel}`);
212
- resolve(selectedKey);
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 === 'c') {
215
- stream.write('\x1b[?25h');
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('keypress', handleKey);
350
+ process.stdin.on("keypress", handleKey);
224
351
  });
225
352
  }
226
353
  // --- MÉTODOS PÚBLICOS ---
227
- static error(...args) { this.log(Levels.ERROR, null, ...args); }
228
- static warn(...args) { this.log(Levels.WARN, null, ...args); }
229
- static info(...args) { this.log(Levels.INFO, null, ...args); }
230
- static success(...args) { this.log(Levels.SUCCESS, null, ...args); }
231
- static default_log(...args) { this.log(Levels.INFO, null, ...args); }
232
- static debug(...args) { this.log(Levels.DEBUG, null, ...args); }
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(levelName, color, ...args);
376
+ this.logWithout(lvl, color, ...args);
236
377
  }
237
378
  else {
238
- this.log(levelName, color, ...args);
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
- let msg = (arg instanceof Error) ? arg.stack : (typeof arg === 'string') ? arg : JSON.stringify(arg, null, 2);
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) + '\n';
390
+ output += this.formatLog(level, msg, colors) + "\n";
250
391
  }
251
- this.writeStatic(output.replace(/\n$/, ''));
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}?${Colors.Reset} ${Colors.Bright}${question}${Colors.Reset}${defaultPart}\n ${Colors.FgCyan}❯${Colors.Reset} `;
257
- return new Promise(resolve => {
258
- rl.question(prompt, ans => {
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 === '' && defaultValue !== undefined ? defaultValue : 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 ? 'Y/n' : 'y/N';
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 ['y', 'yes', 's', 'sim'].includes(ans);
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), 'Field'.length);
281
- const valueLen = Math.max(...rows.map(r => r.Value.length), 'Value'.length);
282
- const h_line = ''.repeat(fieldLen + 2);
283
- const v_line = ''.repeat(valueLen + 2);
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
- let output = top + '\n';
288
- output += `│ ${Colors.Bright}${Colors.FgCyan}${'Field'.padEnd(fieldLen)}${Colors.Reset} ${Colors.Bright}${Colors.FgCyan}${'Value'.padEnd(valueLen)}${Colors.Reset} │\n`;
289
- output += mid + '\n';
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 += `│ ${row.Field.padEnd(fieldLen)} ${row.Value.padEnd(valueLen)} │\n`;
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 + '\n';
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.activeLines.push({ id, content });
301
- this.redrawDynamicLines();
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
- const line = this.activeLines.find(l => l.id === id);
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
- const index = this.activeLines.findIndex(l => l.id === id);
312
- if (index > -1) {
313
- this.activeLines.splice(index, 1);
314
- this.writeStatic(this.formatLog(Levels.SUCCESS, finalContent));
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 libPath = customPath || this.getLibPath();
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
- if (!fs_1.default.existsSync(altPath)) {
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 {