nyte 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +13 -0
- package/README.md +59 -0
- package/dist/adapters/express.d.ts +7 -0
- package/dist/adapters/express.js +63 -0
- package/dist/adapters/factory.d.ts +23 -0
- package/dist/adapters/factory.js +121 -0
- package/dist/adapters/fastify.d.ts +25 -0
- package/dist/adapters/fastify.js +61 -0
- package/dist/adapters/native.d.ts +8 -0
- package/dist/adapters/native.js +200 -0
- package/dist/api/console.d.ts +81 -0
- package/dist/api/console.js +318 -0
- package/dist/api/http.d.ts +180 -0
- package/dist/api/http.js +469 -0
- package/dist/bin/nytejs.d.ts +2 -0
- package/dist/bin/nytejs.js +277 -0
- package/dist/builder.d.ts +32 -0
- package/dist/builder.js +634 -0
- package/dist/client/DefaultNotFound.d.ts +1 -0
- package/dist/client/DefaultNotFound.js +79 -0
- package/dist/client/client.d.ts +4 -0
- package/dist/client/client.js +27 -0
- package/dist/client/clientRouter.d.ts +58 -0
- package/dist/client/clientRouter.js +132 -0
- package/dist/client/entry.client.d.ts +1 -0
- package/dist/client/entry.client.js +455 -0
- package/dist/client/rpc.d.ts +8 -0
- package/dist/client/rpc.js +97 -0
- package/dist/components/Link.d.ts +7 -0
- package/dist/components/Link.js +13 -0
- package/dist/global/global.d.ts +117 -0
- package/dist/global/global.js +17 -0
- package/dist/helpers.d.ts +20 -0
- package/dist/helpers.js +604 -0
- package/dist/hotReload.d.ts +32 -0
- package/dist/hotReload.js +545 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +515 -0
- package/dist/loaders.d.ts +1 -0
- package/dist/loaders.js +138 -0
- package/dist/renderer.d.ts +14 -0
- package/dist/renderer.js +380 -0
- package/dist/router.d.ts +101 -0
- package/dist/router.js +659 -0
- package/dist/rpc/server.d.ts +11 -0
- package/dist/rpc/server.js +166 -0
- package/dist/rpc/types.d.ts +22 -0
- package/dist/rpc/types.js +20 -0
- package/dist/types/framework.d.ts +37 -0
- package/dist/types/framework.js +2 -0
- package/dist/types.d.ts +218 -0
- package/dist/types.js +2 -0
- package/package.json +87 -0
- package/src/adapters/express.ts +87 -0
- package/src/adapters/factory.ts +112 -0
- package/src/adapters/fastify.ts +104 -0
- package/src/adapters/native.ts +245 -0
- package/src/api/console.ts +348 -0
- package/src/api/http.ts +535 -0
- package/src/bin/nytejs.js +331 -0
- package/src/builder.js +690 -0
- package/src/client/DefaultNotFound.tsx +119 -0
- package/src/client/client.ts +24 -0
- package/src/client/clientRouter.ts +153 -0
- package/src/client/entry.client.tsx +529 -0
- package/src/client/rpc.ts +101 -0
- package/src/components/Link.tsx +38 -0
- package/src/global/global.ts +171 -0
- package/src/helpers.ts +657 -0
- package/src/hotReload.ts +566 -0
- package/src/index.ts +582 -0
- package/src/loaders.js +160 -0
- package/src/renderer.tsx +421 -0
- package/src/router.ts +732 -0
- package/src/rpc/server.ts +190 -0
- package/src/rpc/types.ts +45 -0
- package/src/types/framework.ts +58 -0
- package/src/types.ts +288 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Nyte.js Project.
|
|
3
|
+
* Copyright (c) 2026 itsmuzin
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import boxen, { Options as BoxenOptions } from 'boxen';
|
|
18
|
+
import readline from 'node:readline';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Um "handle" para uma linha dinâmica. As instâncias desta classe
|
|
22
|
+
* são retornadas por `Console.dynamicLine()` e usadas para controlar
|
|
23
|
+
* o conteúdo da linha.
|
|
24
|
+
*/
|
|
25
|
+
export class DynamicLine {
|
|
26
|
+
// A ID é usada internamente pela classe Console para rastrear esta linha.
|
|
27
|
+
private readonly _id = Symbol();
|
|
28
|
+
|
|
29
|
+
constructor(initialContent: string) {
|
|
30
|
+
// Registra esta nova linha na classe Console para que ela seja renderizada.
|
|
31
|
+
Console['registerDynamicLine'](this._id, initialContent);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Atualiza o conteúdo da linha no console.
|
|
36
|
+
* @param newContent O novo texto a ser exibido.
|
|
37
|
+
*/
|
|
38
|
+
update(newContent: string): void {
|
|
39
|
+
Console['updateDynamicLine'](this._id, newContent);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Finaliza a linha, opcionalmente com um texto final, e a torna estática.
|
|
44
|
+
* @param finalContent O texto final a ser exibido.
|
|
45
|
+
*/
|
|
46
|
+
end(finalContent: string): void {
|
|
47
|
+
Console['endDynamicLine'](this._id, finalContent);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export enum Colors {
|
|
52
|
+
Reset = "\x1b[0m",
|
|
53
|
+
Bright = "\x1b[1m",
|
|
54
|
+
Dim = "\x1b[2m",
|
|
55
|
+
Underscore = "\x1b[4m",
|
|
56
|
+
Blink = "\x1b[5m",
|
|
57
|
+
Reverse = "\x1b[7m",
|
|
58
|
+
Hidden = "\x1b[8m",
|
|
59
|
+
|
|
60
|
+
FgBlack = "\x1b[30m",
|
|
61
|
+
FgRed = "\x1b[31m",
|
|
62
|
+
FgGreen = "\x1b[32m",
|
|
63
|
+
FgYellow = "\x1b[33m",
|
|
64
|
+
FgBlue = "\x1b[34m",
|
|
65
|
+
FgMagenta = "\x1b[35m",
|
|
66
|
+
FgCyan = "\x1b[36m",
|
|
67
|
+
FgWhite = "\x1b[37m",
|
|
68
|
+
FgGray = "\x1b[90m",
|
|
69
|
+
FgAlmostWhite = "\x1b[38;2;220;220;220m",
|
|
70
|
+
BgBlack = "\x1b[40m",
|
|
71
|
+
BgRed = "\x1b[41m",
|
|
72
|
+
BgGreen = "\x1b[42m",
|
|
73
|
+
BgYellow = "\x1b[43m",
|
|
74
|
+
BgBlue = "\x1b[44m",
|
|
75
|
+
BgMagenta = "\x1b[45m",
|
|
76
|
+
BgCyan = "\x1b[46m",
|
|
77
|
+
BgWhite = "\x1b[47m",
|
|
78
|
+
BgGray = "\x1b[100m",
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
export enum Levels {
|
|
83
|
+
ERROR = "ERROR",
|
|
84
|
+
WARN = "WARN",
|
|
85
|
+
INFO = "INFO",
|
|
86
|
+
DEBUG = "DEBUG",
|
|
87
|
+
SUCCESS = "SUCCESS"
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export default class Console {
|
|
91
|
+
// Armazena o estado de todas as linhas dinâmicas ativas
|
|
92
|
+
private static activeLines: { id: symbol; content: string }[] = [];
|
|
93
|
+
|
|
94
|
+
// Quantas linhas foram efetivamente renderizadas na última operação.
|
|
95
|
+
private static lastRenderedLines = 0;
|
|
96
|
+
|
|
97
|
+
// --- MÉTODOS PRIVADOS PARA GERENCIAR A RENDERIZAÇÃO ---
|
|
98
|
+
|
|
99
|
+
private static redrawDynamicLines(): void {
|
|
100
|
+
const stream = process.stdout;
|
|
101
|
+
|
|
102
|
+
if (this.lastRenderedLines > 0) {
|
|
103
|
+
try {
|
|
104
|
+
readline.moveCursor(stream, 0, -this.lastRenderedLines);
|
|
105
|
+
} catch (_e) {
|
|
106
|
+
// Em terminais estranhos a movimentação pode falhar — ignoramos.
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
readline.cursorTo(stream, 0);
|
|
111
|
+
readline.clearScreenDown(stream);
|
|
112
|
+
|
|
113
|
+
if (this.activeLines.length > 0) {
|
|
114
|
+
// ATUALIZADO: Aplica o formato de log (Timestamp + Style) nas linhas dinâmicas
|
|
115
|
+
// Usamos um nível pseudo 'WAIT' para indicar processo em andamento
|
|
116
|
+
stream.write(this.activeLines.map(l => this.formatLog('WAIT', l.content, Colors.FgCyan)).join('\n') + '\n');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
this.lastRenderedLines = this.activeLines.length;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
private static writeStatic(content: string): void {
|
|
123
|
+
const stream = process.stdout;
|
|
124
|
+
|
|
125
|
+
if (this.lastRenderedLines > 0) {
|
|
126
|
+
try {
|
|
127
|
+
readline.moveCursor(stream, 0, -this.lastRenderedLines);
|
|
128
|
+
} catch (_e) {}
|
|
129
|
+
readline.cursorTo(stream, 0);
|
|
130
|
+
readline.clearScreenDown(stream);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (!content.endsWith('\n')) content += '\n';
|
|
134
|
+
stream.write(content);
|
|
135
|
+
|
|
136
|
+
if (this.activeLines.length > 0) {
|
|
137
|
+
// ATUALIZADO: Garante que ao redesenhar após um log estático, o formato se mantém
|
|
138
|
+
stream.write(this.activeLines.map(l => this.formatLog('WAIT', l.content, Colors.FgCyan)).join('\n') + '\n');
|
|
139
|
+
this.lastRenderedLines = this.activeLines.length;
|
|
140
|
+
} else {
|
|
141
|
+
this.lastRenderedLines = 0;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// --- HELPER DE FORMATAÇÃO CENTRALIZADO ---
|
|
146
|
+
private static formatLog(level: Levels | string, message: string, color?: Colors | null): string {
|
|
147
|
+
let icon = '•';
|
|
148
|
+
let baseColor = Colors.FgWhite;
|
|
149
|
+
|
|
150
|
+
switch (level) {
|
|
151
|
+
// ✕ : Multiplication X (Matemático, sempre texto)
|
|
152
|
+
case Levels.ERROR:
|
|
153
|
+
icon = '✕';
|
|
154
|
+
baseColor = Colors.FgRed;
|
|
155
|
+
break;
|
|
156
|
+
|
|
157
|
+
// ⚠ : Muitas vezes vira emoji. O triângulo ▲ é mais seguro e fica bonito colorido
|
|
158
|
+
// Alternativa: '‼'
|
|
159
|
+
case Levels.WARN:
|
|
160
|
+
icon = '▲';
|
|
161
|
+
baseColor = Colors.FgYellow;
|
|
162
|
+
break;
|
|
163
|
+
|
|
164
|
+
// ℹ : Vira emoji. O '𝐢' é um "i" matemático em negrito (Math Bold Small I)
|
|
165
|
+
// Ele mantém a cor que você definir e parece muito um ícone.
|
|
166
|
+
case Levels.INFO:
|
|
167
|
+
icon = '𝐢';
|
|
168
|
+
baseColor = Colors.FgCyan;
|
|
169
|
+
break;
|
|
170
|
+
|
|
171
|
+
// ✔ : Às vezes vira emoji verde. O '✓' simples costuma obedecer a cor.
|
|
172
|
+
// Se der erro, use '√' (raiz quadrada)
|
|
173
|
+
case Levels.SUCCESS:
|
|
174
|
+
icon = '✓';
|
|
175
|
+
baseColor = Colors.FgGreen;
|
|
176
|
+
break;
|
|
177
|
+
|
|
178
|
+
// ⚙ : Vira emoji cinza. Use '›' ou '»' ou '⌗' para debug
|
|
179
|
+
case Levels.DEBUG:
|
|
180
|
+
icon = '›';
|
|
181
|
+
baseColor = Colors.FgMagenta;
|
|
182
|
+
break;
|
|
183
|
+
|
|
184
|
+
// ⟳ : Esse costuma funcionar, mas se virar emoji, use '∞' ou '…'
|
|
185
|
+
case 'WAIT':
|
|
186
|
+
icon = '∞';
|
|
187
|
+
baseColor = Colors.FgCyan;
|
|
188
|
+
break;
|
|
189
|
+
|
|
190
|
+
default:
|
|
191
|
+
icon = '•';
|
|
192
|
+
baseColor = color || Colors.FgWhite;
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (color) {
|
|
197
|
+
baseColor = color;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const gray = Colors.FgGray;
|
|
201
|
+
const bold = Colors.Bright;
|
|
202
|
+
const reset = Colors.Reset;
|
|
203
|
+
|
|
204
|
+
const now = new Date();
|
|
205
|
+
const time = now.toLocaleTimeString('pt-BR', { hour12: false });
|
|
206
|
+
|
|
207
|
+
// Retorna a string formatada SEM quebra de linha (quem chama decide onde por)
|
|
208
|
+
return ` ${gray}${time}${reset} ${Colors.Bright + baseColor}${icon} ${bold}${level}${reset} ${message}`;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// --- MÉTODOS CHAMADOS PELA CLASSE DynamicLine ---
|
|
212
|
+
private static registerDynamicLine(id: symbol, content: string): void {
|
|
213
|
+
this.activeLines.push({ id, content });
|
|
214
|
+
this.redrawDynamicLines();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private static updateDynamicLine(id: symbol, newContent: string): void {
|
|
218
|
+
const line = this.activeLines.find(l => l.id === id);
|
|
219
|
+
if (line) {
|
|
220
|
+
line.content = newContent;
|
|
221
|
+
this.redrawDynamicLines();
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
private static endDynamicLine(id: symbol, finalContent: string): void {
|
|
226
|
+
const lineIndex = this.activeLines.findIndex(l => l.id === id);
|
|
227
|
+
if (lineIndex > -1) {
|
|
228
|
+
this.activeLines.splice(lineIndex, 1);
|
|
229
|
+
// ATUALIZADO: Formata a mensagem final como INFO (ou SUCCESS implícito)
|
|
230
|
+
// para manter consistência visual com o resto dos logs.
|
|
231
|
+
this.writeStatic(this.formatLog(Levels.INFO, finalContent) + '\n');
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// --- MÉTODOS DE LOG PÚBLICOS ---
|
|
236
|
+
static error(...args: any[]): void { this.log(Levels.ERROR, null, ...args); }
|
|
237
|
+
static warn(...args: any[]): void { this.log(Levels.WARN, null, ...args);}
|
|
238
|
+
static info(...args: any[]): void { this.log(Levels.INFO, null, ...args); }
|
|
239
|
+
static success(...args: any[]): void { this.log(Levels.SUCCESS, null, ...args); }
|
|
240
|
+
static debug(...args: any[]): void { this.log(Levels.DEBUG, null, ...args); }
|
|
241
|
+
|
|
242
|
+
static logCustomLevel(levelName: string, without: boolean = true, color?: Colors, ...args: any[]): void {
|
|
243
|
+
if (without) { this.logWithout(levelName as Levels, color, ...args); }
|
|
244
|
+
else { this.log(levelName as Levels, color, ...args); }
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
static logWithout(level: Levels, colors?:Colors, ...args: any[]): void {
|
|
248
|
+
this.log(level, colors, ...args);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
static log(level: Levels, colors?: Colors | null, ...args: any[]): void {
|
|
252
|
+
let output = "";
|
|
253
|
+
|
|
254
|
+
for (const arg of args) {
|
|
255
|
+
let msg = (arg instanceof Error) ? arg.stack : (typeof arg === 'string') ? arg : JSON.stringify(arg, null, 2);
|
|
256
|
+
if (msg) {
|
|
257
|
+
// ATUALIZADO: Usa o helper formatLog
|
|
258
|
+
output += this.formatLog(level, msg, colors) + '\n';
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Remove a última quebra de linha porque writeStatic já garante uma
|
|
263
|
+
this.writeStatic(output.replace(/\n$/, ''));
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// --- OUTROS MÉTODOS ---
|
|
267
|
+
static async ask(question: string, defaultValue?: string): Promise<string> {
|
|
268
|
+
const stream = process.stdout;
|
|
269
|
+
if (this.lastRenderedLines > 0) {
|
|
270
|
+
try { readline.moveCursor(stream, 0, -this.lastRenderedLines); } catch (_e) {}
|
|
271
|
+
readline.cursorTo(stream, 0);
|
|
272
|
+
readline.clearScreenDown(stream);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const readlineInterface = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
276
|
+
|
|
277
|
+
const defaultPart = defaultValue ? ` (${defaultValue})` : '';
|
|
278
|
+
const prompt = ` ${Colors.FgCyan}?${Colors.Reset} ${question}${Colors.FgGray}${defaultPart}${Colors.Reset} \n ${Colors.FgCyan}➜${Colors.Reset} `;
|
|
279
|
+
|
|
280
|
+
return new Promise(resolve => {
|
|
281
|
+
readlineInterface.question(prompt, ans => {
|
|
282
|
+
readlineInterface.close();
|
|
283
|
+
const value = ans.trim();
|
|
284
|
+
this.redrawDynamicLines();
|
|
285
|
+
resolve(value === '' && defaultValue !== undefined ? defaultValue : value);
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
static async confirm(message: string, defaultYes = false): Promise<boolean> {
|
|
291
|
+
const suffix = defaultYes ? 'Y/n' : 'y/N';
|
|
292
|
+
while (true) {
|
|
293
|
+
const ans = (await this.ask(`${message} ${Colors.FgGray}[${suffix}]${Colors.Reset}`)).toLowerCase();
|
|
294
|
+
|
|
295
|
+
if (ans === '') return defaultYes;
|
|
296
|
+
if (['y','yes','s','sim'].includes(ans)) return true;
|
|
297
|
+
if (['n','no','nao','não'].includes(ans)) return false;
|
|
298
|
+
|
|
299
|
+
// ATUALIZADO: Formato consistente
|
|
300
|
+
this.writeStatic(` ${Colors.FgRed}✖ Opção inválida.${Colors.Reset}`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
static table(data: Record<string, any> | Array<{ Field: string, Value: any }>): void {
|
|
305
|
+
let rows: Array<{ Field: string, Value: any }>;
|
|
306
|
+
if (Array.isArray(data)) {
|
|
307
|
+
rows = data.map(row => ({ Field: String(row.Field), Value: String(row.Value) }));
|
|
308
|
+
} else {
|
|
309
|
+
rows = Object.entries(data).map(([Field, Value]) => ({ Field, Value: String(Value) }));
|
|
310
|
+
}
|
|
311
|
+
const fieldLen = Math.max(...rows.map(r => r.Field.length), 'Field'.length);
|
|
312
|
+
const valueLen = Math.max(...rows.map(r => r.Value.length), 'Value'.length);
|
|
313
|
+
|
|
314
|
+
const h_line = '─'.repeat(fieldLen + 2);
|
|
315
|
+
const v_line = '─'.repeat(valueLen + 2);
|
|
316
|
+
|
|
317
|
+
const top = `┌${h_line}┬${v_line}┐`;
|
|
318
|
+
const mid = `├${h_line}┼${v_line}┤`;
|
|
319
|
+
const bottom = `└${h_line}┴${v_line}┘`;
|
|
320
|
+
|
|
321
|
+
let output = top + '\n';
|
|
322
|
+
output += `│ ${Colors.Bright}${Colors.FgGreen}${'Field'.padEnd(fieldLen)}${Colors.Reset} │ ${Colors.Bright}${Colors.FgGreen}${'Value'.padEnd(valueLen)}${Colors.Reset} │\n`;
|
|
323
|
+
output += mid + '\n';
|
|
324
|
+
|
|
325
|
+
for (const row of rows) {
|
|
326
|
+
output += `│ ${row.Field.padEnd(fieldLen)} │ ${row.Value.padEnd(valueLen)} │\n`;
|
|
327
|
+
}
|
|
328
|
+
output += bottom + '\n';
|
|
329
|
+
this.writeStatic(output);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
static box(content: string, options?: BoxenOptions): void {
|
|
333
|
+
const defaultOptions: BoxenOptions = {
|
|
334
|
+
padding: 1,
|
|
335
|
+
margin: 1,
|
|
336
|
+
borderStyle: 'round',
|
|
337
|
+
borderColor: 'cyan',
|
|
338
|
+
titleAlignment: 'left',
|
|
339
|
+
};
|
|
340
|
+
const finalOptions = { ...defaultOptions, ...options };
|
|
341
|
+
const boxedContent = boxen(content, finalOptions);
|
|
342
|
+
this.writeStatic(boxedContent + '\n');
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
static dynamicLine(initialContent: string): DynamicLine {
|
|
346
|
+
return new DynamicLine(initialContent);
|
|
347
|
+
}
|
|
348
|
+
}
|