treste 2.5.0 → 2.5.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/README.md +14 -2
- package/dist/scripts/create-app.js +520 -178
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,13 +9,16 @@ Linguagem de programação moderna e profissional, estruturalmente organizada e
|
|
|
9
9
|
|
|
10
10
|
> **🎯 Característica Única:** Trest permite programar usando palavras-chave em cirílico ou latino, mantendo a mesma sintaxe e funcionalidades.
|
|
11
11
|
|
|
12
|
-
> **🔒 Segurança:** Versão 2.5.
|
|
12
|
+
> **🔒 Segurança:** Versão 2.5.1 mantém todas as correções de segurança da cadeia de suprimentos. Veja [DOCUMENTACAO_COMPLETA.md](./DOCUMENTACAO_COMPLETA.md#segurança) para detalhes.
|
|
13
|
+
|
|
14
|
+
> **🚀 Deploy na Vercel:** Versão 2.5.1 inclui suporte completo para deploy na Vercel! Use `npm create trest` para criar projetos otimizados para serverless functions.
|
|
13
15
|
|
|
14
16
|
## 🚀 Principais Funcionalidades
|
|
15
17
|
|
|
16
18
|
- ✅ **Execução Inline** - Execute código direto na linha de comando com `-e`
|
|
17
19
|
- ✅ **Compilação para Web** - Gera JavaScript otimizado
|
|
18
20
|
- ✅ **Compilação para Desktop** - Cria executáveis .exe nativos
|
|
21
|
+
- ✅ **Deploy na Vercel** - Crie projetos otimizados para serverless functions
|
|
19
22
|
- ✅ **Sistema de Módulos** - Import/Export de módulos
|
|
20
23
|
- ✅ **Biblioteca Padrão** - std com funções matemáticas, strings, arrays e I/O
|
|
21
24
|
- ✅ **Tratamento de Erros** - Try/Catch/Throw estendido
|
|
@@ -81,6 +84,15 @@ npm --version # deve ser >= 9
|
|
|
81
84
|
|
|
82
85
|
## 🎯 Guia Rápido
|
|
83
86
|
|
|
87
|
+
### Criar novo projeto (Vercel-ready)
|
|
88
|
+
```bash
|
|
89
|
+
npm create trest meu-projeto
|
|
90
|
+
# ou
|
|
91
|
+
npx create-trest-app meu-projeto
|
|
92
|
+
cd meu-projeto
|
|
93
|
+
npm start
|
|
94
|
+
```
|
|
95
|
+
|
|
84
96
|
### Executar código inline (sem arquivo)
|
|
85
97
|
```bash
|
|
86
98
|
trest -e "печать('Olá, Mundo!')"
|
|
@@ -469,7 +481,7 @@ Veja a pasta `exemplos/` para programas completos demonstrando:
|
|
|
469
481
|
|
|
470
482
|
## 🔒 Segurança
|
|
471
483
|
|
|
472
|
-
**Versão 2.5.
|
|
484
|
+
**Versão 2.5.1** mantém todas as correções de segurança da cadeia de suprimentos:
|
|
473
485
|
- ✅ Scripts de instalação removidos
|
|
474
486
|
- ✅ Sem acesso ao shell durante instalação
|
|
475
487
|
- ✅ Acesso à rede controlado e documentado
|
|
@@ -1,15 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* create-trest-app
|
|
4
|
-
* Script para criar um novo projeto Trest
|
|
3
|
+
* create-trest-app - Versão Otimizada para Vercel
|
|
4
|
+
* Script para criar um novo projeto Trest otimizado para deploy na Vercel
|
|
5
5
|
* Similar ao create-next-app do Next.js
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
const fs = require('fs');
|
|
9
9
|
const path = require('path');
|
|
10
|
-
const { execSync
|
|
10
|
+
const { execSync } = require('child_process');
|
|
11
11
|
const readline = require('readline');
|
|
12
12
|
|
|
13
|
+
// Obter versão atual do Trest
|
|
14
|
+
function getTrestVersion() {
|
|
15
|
+
try {
|
|
16
|
+
// Tentar ler do package.json local (se estiver no repositório)
|
|
17
|
+
const packagePath = path.join(__dirname, '..', 'package.json');
|
|
18
|
+
if (fs.existsSync(packagePath)) {
|
|
19
|
+
const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf-8'));
|
|
20
|
+
return pkg.version;
|
|
21
|
+
}
|
|
22
|
+
} catch (e) {
|
|
23
|
+
// Ignorar erro
|
|
24
|
+
}
|
|
25
|
+
return '2.5.0'; // Versão padrão
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const TREST_VERSION = getTrestVersion();
|
|
29
|
+
|
|
13
30
|
// Cores para terminal
|
|
14
31
|
const colors = {
|
|
15
32
|
reset: '\x1b[0m',
|
|
@@ -38,7 +55,6 @@ function validateProjectName(name) {
|
|
|
38
55
|
return { valid: false, error: 'Nome do projeto não pode estar vazio' };
|
|
39
56
|
}
|
|
40
57
|
|
|
41
|
-
// Validar caracteres permitidos
|
|
42
58
|
const validNameRegex = /^[a-zA-Z0-9-_]+$/;
|
|
43
59
|
if (!validNameRegex.test(name)) {
|
|
44
60
|
return {
|
|
@@ -47,7 +63,6 @@ function validateProjectName(name) {
|
|
|
47
63
|
};
|
|
48
64
|
}
|
|
49
65
|
|
|
50
|
-
// Não pode começar com número
|
|
51
66
|
if (/^[0-9]/.test(name)) {
|
|
52
67
|
return {
|
|
53
68
|
valid: false,
|
|
@@ -73,98 +88,402 @@ function askQuestion(question) {
|
|
|
73
88
|
}
|
|
74
89
|
|
|
75
90
|
function showHelp() {
|
|
76
|
-
log('\n🚀 Create Trest App', 'bright');
|
|
91
|
+
log('\n🚀 Create Trest App (Vercel Ready)', 'bright');
|
|
77
92
|
log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n', 'cyan');
|
|
78
|
-
log('Cria um novo projeto Trest
|
|
93
|
+
log('Cria um novo projeto Trest otimizado para deploy na Vercel', 'cyan');
|
|
79
94
|
log('\nUso:', 'bright');
|
|
95
|
+
log(' npm create trest <nome-projeto>', 'cyan');
|
|
80
96
|
log(' npx create-trest-app <nome-projeto>', 'cyan');
|
|
81
|
-
log(' npx create-treste-app <nome-projeto>', 'cyan');
|
|
82
97
|
log('\nExemplos:', 'bright');
|
|
83
|
-
log('
|
|
84
|
-
log(' npx create-trest-app
|
|
85
|
-
log('\nSe o nome do projeto não for fornecido, será solicitado interativamente.', 'yellow');
|
|
98
|
+
log(' npm create trest meu-projeto', 'cyan');
|
|
99
|
+
log(' npx create-trest-app minha-api', 'cyan');
|
|
86
100
|
log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n', 'cyan');
|
|
87
101
|
process.exit(0);
|
|
88
102
|
}
|
|
89
103
|
|
|
104
|
+
// Template api/index.js para Vercel
|
|
105
|
+
function getApiIndexTemplate() {
|
|
106
|
+
return `/**
|
|
107
|
+
* Vercel Serverless Function Adapter para Trest
|
|
108
|
+
*
|
|
109
|
+
* Este arquivo adapta aplicações Trest que usam HTTP.createServer
|
|
110
|
+
* para funcionar como serverless functions na Vercel.
|
|
111
|
+
*/
|
|
112
|
+
|
|
113
|
+
const { Interpreter } = require('../node_modules/treste/dist/interpreter');
|
|
114
|
+
const { Lexer } = require('../node_modules/treste/dist/lexer');
|
|
115
|
+
const { Parser } = require('../node_modules/treste/dist/parser');
|
|
116
|
+
const { ModuleSystem } = require('../node_modules/treste/dist/module');
|
|
117
|
+
const { StdModules } = require('../node_modules/treste/dist/std-native');
|
|
118
|
+
const fs = require('fs');
|
|
119
|
+
const path = require('path');
|
|
120
|
+
const { URL } = require('url');
|
|
121
|
+
|
|
122
|
+
// Caminho do arquivo Trest
|
|
123
|
+
const TREST_FILE = path.join(__dirname, '../app.trest');
|
|
124
|
+
|
|
125
|
+
// Armazenar rotas coletadas (global para o módulo)
|
|
126
|
+
let globalRoutes = null;
|
|
127
|
+
let appInitialized = false;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Estrutura para armazenar rotas
|
|
131
|
+
*/
|
|
132
|
+
function createRouteMap() {
|
|
133
|
+
const routes = new Map();
|
|
134
|
+
const paramRoutes = [];
|
|
135
|
+
const wildcardRoutes = [];
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
routes,
|
|
139
|
+
paramRoutes,
|
|
140
|
+
wildcardRoutes,
|
|
141
|
+
addRoute(method, path, handler) {
|
|
142
|
+
if (path === '*') {
|
|
143
|
+
wildcardRoutes.push({ method, handler });
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (path.includes(':')) {
|
|
148
|
+
const patternStr = '^' + path.replace(/:[^/]+/g, '([^/]+)') + '$';
|
|
149
|
+
const pattern = new RegExp(patternStr);
|
|
150
|
+
paramRoutes.push({ method, pattern, path, handler });
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (!routes.has(path)) {
|
|
155
|
+
routes.set(path, new Map());
|
|
156
|
+
}
|
|
157
|
+
routes.get(path).set(method, handler);
|
|
158
|
+
},
|
|
159
|
+
findHandler(method, pathname) {
|
|
160
|
+
const handlers = routes.get(pathname);
|
|
161
|
+
const exactHandler = handlers?.get(method);
|
|
162
|
+
if (exactHandler) {
|
|
163
|
+
return { handler: exactHandler };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
for (const paramRoute of paramRoutes) {
|
|
167
|
+
if (paramRoute.method === method || paramRoute.method === '*') {
|
|
168
|
+
const match = pathname.match(paramRoute.pattern);
|
|
169
|
+
if (match) {
|
|
170
|
+
const paramNames = [];
|
|
171
|
+
const pathParts = paramRoute.path.split('/');
|
|
172
|
+
for (const part of pathParts) {
|
|
173
|
+
if (part.startsWith(':')) {
|
|
174
|
+
paramNames.push(part.substring(1));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const params = {};
|
|
179
|
+
for (let i = 0; i < paramNames.length && i + 1 < match.length; i++) {
|
|
180
|
+
params[paramNames[i]] = match[i + 1];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return { handler: paramRoute.handler, params };
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
for (const wildcardRoute of wildcardRoutes) {
|
|
189
|
+
if (wildcardRoute.method === method || wildcardRoute.method === '*') {
|
|
190
|
+
return { handler: wildcardRoute.handler };
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Inicializa a aplicação Trest e coleta rotas
|
|
201
|
+
*/
|
|
202
|
+
function initializeTrestApp() {
|
|
203
|
+
if (appInitialized && globalRoutes) {
|
|
204
|
+
return globalRoutes;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
try {
|
|
208
|
+
// Criar estrutura de rotas
|
|
209
|
+
globalRoutes = createRouteMap();
|
|
210
|
+
|
|
211
|
+
// IMPORTANTE: Fazer monkey-patch ANTES de criar o Interpreter
|
|
212
|
+
const originalCreateServer = StdModules.HTTP.createServer.bind(StdModules.HTTP);
|
|
213
|
+
|
|
214
|
+
// Sobrescrever createServer para coletar rotas em vez de criar servidor
|
|
215
|
+
StdModules.HTTP.createServer = function() {
|
|
216
|
+
return {
|
|
217
|
+
listen: (port, callback) => {
|
|
218
|
+
if (callback && typeof callback === 'function') {
|
|
219
|
+
setImmediate(() => callback());
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
get: (path, handler) => {
|
|
223
|
+
globalRoutes.addRoute('GET', path, handler);
|
|
224
|
+
},
|
|
225
|
+
post: (path, handler) => {
|
|
226
|
+
globalRoutes.addRoute('POST', path, handler);
|
|
227
|
+
},
|
|
228
|
+
put: (path, handler) => {
|
|
229
|
+
globalRoutes.addRoute('PUT', path, handler);
|
|
230
|
+
},
|
|
231
|
+
delete: (path, handler) => {
|
|
232
|
+
globalRoutes.addRoute('DELETE', path, handler);
|
|
233
|
+
},
|
|
234
|
+
use: (path, handler) => {
|
|
235
|
+
globalRoutes.addRoute('*', path === '*' ? '*' : path, handler);
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
// Ler e compilar código Trest
|
|
241
|
+
const code = fs.readFileSync(TREST_FILE, 'utf-8');
|
|
242
|
+
const lexer = new Lexer(code);
|
|
243
|
+
const tokens = lexer.tokenize();
|
|
244
|
+
const parser = new Parser(tokens);
|
|
245
|
+
const program = parser.parse();
|
|
246
|
+
|
|
247
|
+
const moduleSystem = new ModuleSystem(path.dirname(TREST_FILE));
|
|
248
|
+
|
|
249
|
+
// Executar código Trest
|
|
250
|
+
const interpreter = new Interpreter();
|
|
251
|
+
interpreter.interpret(program);
|
|
252
|
+
|
|
253
|
+
// Restaurar createServer original
|
|
254
|
+
StdModules.HTTP.createServer = originalCreateServer;
|
|
255
|
+
|
|
256
|
+
appInitialized = true;
|
|
257
|
+
return globalRoutes;
|
|
258
|
+
} catch (error) {
|
|
259
|
+
console.error('❌ Erro ao inicializar aplicação Trest:', error);
|
|
260
|
+
if (error.stack) {
|
|
261
|
+
console.error(error.stack);
|
|
262
|
+
}
|
|
263
|
+
throw error;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Converte requisição da Vercel para formato Trest
|
|
269
|
+
*/
|
|
270
|
+
function convertVercelRequest(req) {
|
|
271
|
+
const url = new URL(req.url, \`http://\${req.headers.host || 'localhost'}\`);
|
|
272
|
+
|
|
273
|
+
const queryParams = {};
|
|
274
|
+
url.searchParams.forEach((value, key) => {
|
|
275
|
+
queryParams[key] = value;
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
let body = req.body || '';
|
|
279
|
+
if (typeof body === 'object' && body !== null) {
|
|
280
|
+
body = body;
|
|
281
|
+
} else if (typeof body === 'string' && body.trim()) {
|
|
282
|
+
try {
|
|
283
|
+
body = JSON.parse(body);
|
|
284
|
+
} catch (e) {
|
|
285
|
+
// Manter como string
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return {
|
|
290
|
+
url: req.url,
|
|
291
|
+
pathname: url.pathname,
|
|
292
|
+
query: queryParams,
|
|
293
|
+
method: req.method || 'GET',
|
|
294
|
+
headers: req.headers,
|
|
295
|
+
body: body,
|
|
296
|
+
ip: req.headers['x-forwarded-for']?.split(',')[0] ||
|
|
297
|
+
req.headers['x-real-ip'] ||
|
|
298
|
+
'unknown',
|
|
299
|
+
params: {},
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Cria objeto response compatível com Trest
|
|
305
|
+
*/
|
|
306
|
+
function createTrestResponse(res) {
|
|
307
|
+
const responseObj = {
|
|
308
|
+
status: (code) => {
|
|
309
|
+
res.statusCode = code;
|
|
310
|
+
return responseObj;
|
|
311
|
+
},
|
|
312
|
+
send: (data) => {
|
|
313
|
+
try {
|
|
314
|
+
const dataStr = typeof data === 'string' ? data : JSON.stringify(data);
|
|
315
|
+
if (!res.headersSent) {
|
|
316
|
+
if (typeof data === 'string' && !res.getHeader('Content-Type')) {
|
|
317
|
+
res.setHeader('Content-Type', 'text/html; charset=utf-8');
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
res.end(dataStr);
|
|
321
|
+
} catch (error) {
|
|
322
|
+
if (!res.headersSent) {
|
|
323
|
+
res.statusCode = 500;
|
|
324
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
325
|
+
res.end(JSON.stringify({ error: true, message: 'Internal server error' }));
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return responseObj;
|
|
329
|
+
},
|
|
330
|
+
json: (data) => {
|
|
331
|
+
try {
|
|
332
|
+
if (!res.headersSent) {
|
|
333
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
334
|
+
}
|
|
335
|
+
res.end(JSON.stringify(data, null, 2));
|
|
336
|
+
} catch (error) {
|
|
337
|
+
if (!res.headersSent) {
|
|
338
|
+
res.statusCode = 500;
|
|
339
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
340
|
+
res.end(JSON.stringify({ error: true, message: 'Error serializing JSON' }));
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return responseObj;
|
|
344
|
+
},
|
|
345
|
+
header: (name, value) => {
|
|
346
|
+
if (!res.headersSent) {
|
|
347
|
+
res.setHeader(name, value);
|
|
348
|
+
}
|
|
349
|
+
return responseObj;
|
|
350
|
+
},
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
return responseObj;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Serverless function handler da Vercel
|
|
358
|
+
*/
|
|
359
|
+
module.exports = async function handler(req, res) {
|
|
360
|
+
try {
|
|
361
|
+
const routes = initializeTrestApp();
|
|
362
|
+
const trestRequest = convertVercelRequest(req);
|
|
363
|
+
const trestResponse = createTrestResponse(res);
|
|
364
|
+
const handlerResult = routes.findHandler(req.method || 'GET', trestRequest.pathname);
|
|
365
|
+
|
|
366
|
+
if (handlerResult) {
|
|
367
|
+
trestRequest.params = handlerResult.params || {};
|
|
368
|
+
|
|
369
|
+
try {
|
|
370
|
+
const result = handlerResult.handler(trestRequest, trestResponse);
|
|
371
|
+
if (result && typeof result.then === 'function') {
|
|
372
|
+
await result;
|
|
373
|
+
}
|
|
374
|
+
} catch (error) {
|
|
375
|
+
if (!res.headersSent) {
|
|
376
|
+
res.statusCode = 500;
|
|
377
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
378
|
+
res.end(JSON.stringify({
|
|
379
|
+
error: true,
|
|
380
|
+
message: 'Internal server error',
|
|
381
|
+
details: error?.message || String(error),
|
|
382
|
+
timestamp: Date.now()
|
|
383
|
+
}, null, 2));
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
} else {
|
|
387
|
+
res.statusCode = 404;
|
|
388
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
389
|
+
res.end(JSON.stringify({
|
|
390
|
+
error: true,
|
|
391
|
+
message: 'Route not found',
|
|
392
|
+
path: trestRequest.pathname,
|
|
393
|
+
method: req.method || 'GET',
|
|
394
|
+
timestamp: Date.now()
|
|
395
|
+
}, null, 2));
|
|
396
|
+
}
|
|
397
|
+
} catch (error) {
|
|
398
|
+
console.error('❌ Erro na serverless function:', error);
|
|
399
|
+
if (error.stack) {
|
|
400
|
+
console.error(error.stack);
|
|
401
|
+
}
|
|
402
|
+
if (!res.headersSent) {
|
|
403
|
+
res.statusCode = 500;
|
|
404
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
405
|
+
res.end(JSON.stringify({
|
|
406
|
+
error: true,
|
|
407
|
+
message: 'Internal server error',
|
|
408
|
+
details: error?.message || String(error),
|
|
409
|
+
timestamp: Date.now()
|
|
410
|
+
}, null, 2));
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
`;
|
|
415
|
+
}
|
|
416
|
+
|
|
90
417
|
async function main() {
|
|
91
|
-
// Verificar argumentos de ajuda
|
|
92
418
|
const args = process.argv.slice(2);
|
|
93
419
|
if (args.includes('--help') || args.includes('-h') || args.includes('help')) {
|
|
94
420
|
showHelp();
|
|
95
421
|
}
|
|
96
422
|
|
|
97
|
-
log('\n🚀 Create Trest App', 'bright');
|
|
423
|
+
log('\n🚀 Create Trest App (Vercel Ready)', 'bright');
|
|
98
424
|
log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n', 'cyan');
|
|
99
425
|
|
|
100
426
|
let projectName = getProjectName();
|
|
101
427
|
|
|
102
|
-
// Se não fornecido, perguntar
|
|
103
428
|
if (!projectName) {
|
|
104
429
|
projectName = await askQuestion('📁 Nome do projeto: ');
|
|
105
430
|
}
|
|
106
431
|
|
|
107
|
-
// Validar novamente após perguntar
|
|
108
432
|
if (!projectName || projectName.trim().length === 0) {
|
|
109
433
|
log('\n❌ Erro: Nome do projeto não pode estar vazio', 'red');
|
|
110
434
|
process.exit(1);
|
|
111
435
|
}
|
|
112
|
-
|
|
436
|
+
|
|
113
437
|
projectName = projectName.trim();
|
|
114
|
-
|
|
115
|
-
// Validar nome
|
|
116
438
|
const validation = validateProjectName(projectName);
|
|
117
439
|
if (!validation.valid) {
|
|
118
440
|
log(`\n❌ Erro: ${validation.error}`, 'red');
|
|
119
441
|
process.exit(1);
|
|
120
442
|
}
|
|
121
|
-
|
|
122
|
-
// Obter diretório atual de forma mais confiável
|
|
443
|
+
|
|
123
444
|
let currentDir = process.cwd();
|
|
124
|
-
|
|
125
|
-
// Verificar se estamos no diretório correto (pode haver problemas com npx)
|
|
126
445
|
if (!currentDir || currentDir === '/' || currentDir === '\\') {
|
|
127
|
-
// Fallback: usar diretório do usuário
|
|
128
446
|
currentDir = process.env.USERPROFILE || process.env.HOME || process.cwd();
|
|
129
447
|
log(`⚠️ Usando diretório: ${currentDir}`, 'yellow');
|
|
130
448
|
}
|
|
131
|
-
|
|
449
|
+
|
|
132
450
|
const projectPath = path.resolve(currentDir, projectName);
|
|
133
|
-
|
|
134
|
-
// Verificar se a pasta já existe
|
|
451
|
+
|
|
135
452
|
if (fs.existsSync(projectPath)) {
|
|
136
453
|
log(`\n❌ Erro: A pasta "${projectName}" já existe!`, 'red');
|
|
137
454
|
process.exit(1);
|
|
138
455
|
}
|
|
139
|
-
|
|
456
|
+
|
|
140
457
|
log(`\n📦 Criando projeto: ${projectName}`, 'cyan');
|
|
141
458
|
log(`📂 Caminho: ${projectPath}\n`, 'cyan');
|
|
142
|
-
|
|
459
|
+
|
|
143
460
|
try {
|
|
144
|
-
// Criar pasta do projeto
|
|
145
|
-
fs.mkdirSync(projectPath, { recursive: true });
|
|
146
|
-
log('✅ Pasta do projeto criada', 'green');
|
|
147
|
-
|
|
148
461
|
// Criar estrutura de pastas
|
|
149
|
-
fs.mkdirSync(
|
|
150
|
-
fs.mkdirSync(path.join(projectPath, '
|
|
462
|
+
fs.mkdirSync(projectPath, { recursive: true });
|
|
463
|
+
fs.mkdirSync(path.join(projectPath, 'api'), { recursive: true });
|
|
151
464
|
log('✅ Estrutura de pastas criada', 'green');
|
|
152
465
|
|
|
153
466
|
// Criar package.json
|
|
154
467
|
const packageJson = {
|
|
155
468
|
name: projectName,
|
|
156
469
|
version: '1.0.0',
|
|
157
|
-
description: `Projeto Trest: ${projectName}`,
|
|
158
|
-
main: '
|
|
470
|
+
description: `Projeto Trest otimizado para Vercel: ${projectName}`,
|
|
471
|
+
main: 'app.trest',
|
|
159
472
|
scripts: {
|
|
160
|
-
start: 'trest
|
|
161
|
-
dev: 'trest
|
|
162
|
-
build: '
|
|
163
|
-
|
|
473
|
+
start: 'trest app.trest',
|
|
474
|
+
dev: 'trest app.trest --verbose',
|
|
475
|
+
build: 'echo "Build não necessário - Vercel faz isso automaticamente"',
|
|
476
|
+
deploy: 'vercel --prod',
|
|
164
477
|
},
|
|
165
|
-
keywords: ['trest', 'trest-language'],
|
|
478
|
+
keywords: ['trest', 'trest-language', 'vercel', 'serverless'],
|
|
166
479
|
author: '',
|
|
167
480
|
license: 'MIT',
|
|
481
|
+
dependencies: {
|
|
482
|
+
treste: `^${TREST_VERSION}`
|
|
483
|
+
},
|
|
484
|
+
engines: {
|
|
485
|
+
node: '>=18.0.0'
|
|
486
|
+
}
|
|
168
487
|
};
|
|
169
488
|
|
|
170
489
|
fs.writeFileSync(
|
|
@@ -173,140 +492,201 @@ async function main() {
|
|
|
173
492
|
);
|
|
174
493
|
log('✅ package.json criado', 'green');
|
|
175
494
|
|
|
176
|
-
// Criar
|
|
177
|
-
const
|
|
178
|
-
# Arquivo principal
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
495
|
+
// Criar app.trest
|
|
496
|
+
const appTrestContent = `# Aplicação Trest para Vercel
|
|
497
|
+
# Arquivo principal da aplicação
|
|
498
|
+
|
|
499
|
+
импорт * как HTTP измодуля "std/http"
|
|
500
|
+
|
|
501
|
+
пусть servidor = HTTP.создатьСервер()
|
|
502
|
+
|
|
503
|
+
# Rota principal
|
|
504
|
+
servidor.get("/", функция(запрос, ответ) {
|
|
505
|
+
ответ.status(200)
|
|
506
|
+
ответ.send("<h1>Olá da Vercel!</h1><p>Aplicação Trest rodando como serverless function</p>")
|
|
507
|
+
})
|
|
508
|
+
|
|
509
|
+
# API de exemplo
|
|
510
|
+
servidor.get("/api/hello", функция(запрос, ответ) {
|
|
511
|
+
ответ.json({
|
|
512
|
+
message = "Hello from Trest!",
|
|
513
|
+
timestamp = Date.теперь()
|
|
514
|
+
})
|
|
515
|
+
})
|
|
516
|
+
|
|
517
|
+
# Rota com parâmetros
|
|
518
|
+
servidor.get("/api/users/:id", функция(запрос, ответ) {
|
|
519
|
+
пусть userId = запрос.params.id
|
|
520
|
+
ответ.json({
|
|
521
|
+
userId = userId,
|
|
522
|
+
message = "User ID: " + userId
|
|
523
|
+
})
|
|
524
|
+
})
|
|
525
|
+
|
|
526
|
+
# POST example
|
|
527
|
+
servidor.post("/api/echo", функция(запрос, ответ) {
|
|
528
|
+
ответ.json({
|
|
529
|
+
received = запрос.body,
|
|
530
|
+
method = запрос.method
|
|
531
|
+
})
|
|
532
|
+
})
|
|
533
|
+
|
|
534
|
+
# Listen (na Vercel, isso não faz nada, mas não causa erro)
|
|
535
|
+
servidor.listen(3000, функция() {
|
|
536
|
+
печать("✅ Servidor inicializado (modo Vercel)")
|
|
537
|
+
})
|
|
192
538
|
`;
|
|
193
539
|
|
|
194
540
|
fs.writeFileSync(
|
|
195
|
-
path.join(projectPath, '
|
|
196
|
-
|
|
541
|
+
path.join(projectPath, 'app.trest'),
|
|
542
|
+
appTrestContent
|
|
197
543
|
);
|
|
198
|
-
log('✅
|
|
544
|
+
log('✅ app.trest criado', 'green');
|
|
199
545
|
|
|
200
|
-
// Criar
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
546
|
+
// Criar api/index.js
|
|
547
|
+
fs.writeFileSync(
|
|
548
|
+
path.join(projectPath, 'api', 'index.js'),
|
|
549
|
+
getApiIndexTemplate()
|
|
550
|
+
);
|
|
551
|
+
log('✅ api/index.js criado', 'green');
|
|
552
|
+
|
|
553
|
+
// Criar vercel.json
|
|
554
|
+
const vercelJson = {
|
|
555
|
+
version: 2,
|
|
556
|
+
builds: [
|
|
557
|
+
{
|
|
558
|
+
src: "package.json",
|
|
559
|
+
use: "@vercel/node"
|
|
560
|
+
}
|
|
561
|
+
],
|
|
562
|
+
routes: [
|
|
563
|
+
{
|
|
564
|
+
src: "/api/(.*)",
|
|
565
|
+
dest: "/api/index.js"
|
|
566
|
+
},
|
|
567
|
+
{
|
|
568
|
+
src: "/(.*)",
|
|
569
|
+
dest: "/api/index.js"
|
|
570
|
+
}
|
|
571
|
+
],
|
|
572
|
+
functions: {
|
|
573
|
+
"api/index.js": {
|
|
574
|
+
maxDuration: 30
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
};
|
|
218
578
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
579
|
+
fs.writeFileSync(
|
|
580
|
+
path.join(projectPath, 'vercel.json'),
|
|
581
|
+
JSON.stringify(vercelJson, null, 2)
|
|
582
|
+
);
|
|
583
|
+
log('✅ vercel.json criado', 'green');
|
|
584
|
+
|
|
585
|
+
// Criar .gitignore
|
|
586
|
+
const gitignoreContent = `# Dependências
|
|
587
|
+
node_modules/
|
|
588
|
+
package-lock.json
|
|
223
589
|
|
|
224
|
-
#
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
печать("Número é menor ou igual a 10")
|
|
229
|
-
}
|
|
590
|
+
# Build
|
|
591
|
+
dist/
|
|
592
|
+
*.exe
|
|
593
|
+
*.js.map
|
|
230
594
|
|
|
231
|
-
#
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
595
|
+
# Logs
|
|
596
|
+
*.log
|
|
597
|
+
npm-debug.log*
|
|
598
|
+
|
|
599
|
+
# Sistema operacional
|
|
600
|
+
.DS_Store
|
|
601
|
+
Thumbs.db
|
|
602
|
+
|
|
603
|
+
# IDE
|
|
604
|
+
.vscode/
|
|
605
|
+
.idea/
|
|
606
|
+
*.swp
|
|
607
|
+
*.swo
|
|
608
|
+
*~
|
|
609
|
+
|
|
610
|
+
# Trest
|
|
611
|
+
*.trest.js
|
|
612
|
+
*.trest.map
|
|
235
613
|
|
|
236
|
-
|
|
237
|
-
|
|
614
|
+
# Vercel
|
|
615
|
+
.vercel
|
|
238
616
|
`;
|
|
239
617
|
|
|
240
618
|
fs.writeFileSync(
|
|
241
|
-
path.join(projectPath, '
|
|
242
|
-
|
|
619
|
+
path.join(projectPath, '.gitignore'),
|
|
620
|
+
gitignoreContent
|
|
243
621
|
);
|
|
244
|
-
log('✅
|
|
622
|
+
log('✅ .gitignore criado', 'green');
|
|
245
623
|
|
|
246
624
|
// Criar README.md
|
|
247
625
|
const readmeContent = `# ${projectName}
|
|
248
626
|
|
|
249
|
-
Projeto
|
|
627
|
+
Projeto Trest otimizado para deploy na Vercel
|
|
250
628
|
|
|
251
|
-
## 🚀
|
|
629
|
+
## 🚀 Deploy na Vercel
|
|
252
630
|
|
|
253
|
-
###
|
|
631
|
+
### Opção 1: Via CLI da Vercel
|
|
254
632
|
|
|
255
633
|
\`\`\`bash
|
|
256
|
-
|
|
257
|
-
|
|
634
|
+
# Instalar Vercel CLI (se ainda não tiver)
|
|
635
|
+
npm i -g vercel
|
|
258
636
|
|
|
259
|
-
|
|
637
|
+
# Fazer deploy
|
|
638
|
+
vercel
|
|
260
639
|
|
|
261
|
-
|
|
262
|
-
|
|
640
|
+
# Para produção
|
|
641
|
+
vercel --prod
|
|
263
642
|
\`\`\`
|
|
264
643
|
|
|
265
|
-
###
|
|
644
|
+
### Opção 2: Via GitHub/GitLab
|
|
266
645
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
646
|
+
1. Conecte seu repositório na Vercel
|
|
647
|
+
2. Configure o projeto (Vercel detectará automaticamente)
|
|
648
|
+
3. Faça deploy
|
|
270
649
|
|
|
271
|
-
|
|
650
|
+
## 📁 Estrutura do Projeto
|
|
272
651
|
|
|
273
|
-
\`\`\`
|
|
274
|
-
|
|
652
|
+
\`\`\`
|
|
653
|
+
${projectName}/
|
|
654
|
+
├── api/
|
|
655
|
+
│ └── index.js # Serverless function adapter
|
|
656
|
+
├── app.trest # Arquivo principal da aplicação
|
|
657
|
+
├── vercel.json # Configuração Vercel
|
|
658
|
+
├── package.json # Dependências e scripts
|
|
659
|
+
└── README.md # Este arquivo
|
|
275
660
|
\`\`\`
|
|
276
661
|
|
|
277
|
-
|
|
662
|
+
## 🛠️ Desenvolvimento Local
|
|
278
663
|
|
|
279
664
|
\`\`\`bash
|
|
280
|
-
|
|
281
|
-
|
|
665
|
+
# Instalar dependências
|
|
666
|
+
npm install
|
|
282
667
|
|
|
283
|
-
|
|
668
|
+
# Executar localmente
|
|
669
|
+
npm start
|
|
284
670
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
├── src/
|
|
288
|
-
│ └── main.trest # Arquivo principal
|
|
289
|
-
├── exemplos/
|
|
290
|
-
│ └── exemplo.trest # Exemplos de código
|
|
291
|
-
├── package.json # Configuração do projeto
|
|
292
|
-
└── README.md # Este arquivo
|
|
671
|
+
# Modo desenvolvimento (verbose)
|
|
672
|
+
npm run dev
|
|
293
673
|
\`\`\`
|
|
294
674
|
|
|
295
675
|
## 📚 Documentação
|
|
296
676
|
|
|
297
|
-
|
|
298
|
-
- [
|
|
299
|
-
- [
|
|
677
|
+
- [Documentação Completa Trest](https://trest-site.vercel.app)
|
|
678
|
+
- [Guia de Deploy Vercel](./VERCEL_DEPLOY.md) (se disponível)
|
|
679
|
+
- [Site Oficial](https://trest-site.vercel.app)
|
|
300
680
|
|
|
301
681
|
## 📝 Notas
|
|
302
682
|
|
|
303
|
-
-
|
|
304
|
-
-
|
|
305
|
-
-
|
|
683
|
+
- Usando Trest Language v${TREST_VERSION}
|
|
684
|
+
- Projeto otimizado para serverless functions
|
|
685
|
+
- Rotas são definidas em \`app.trest\`
|
|
306
686
|
|
|
307
687
|
---
|
|
308
688
|
|
|
309
|
-
Criado com ❤️ usando Trest Language
|
|
689
|
+
Criado com ❤️ usando Trest Language v${TREST_VERSION}
|
|
310
690
|
`;
|
|
311
691
|
|
|
312
692
|
fs.writeFileSync(
|
|
@@ -315,57 +695,20 @@ Criado com ❤️ usando Trest Language v2.4.9
|
|
|
315
695
|
);
|
|
316
696
|
log('✅ README.md criado', 'green');
|
|
317
697
|
|
|
318
|
-
//
|
|
319
|
-
|
|
320
|
-
node_modules/
|
|
321
|
-
package-lock.json
|
|
322
|
-
|
|
323
|
-
# Build
|
|
324
|
-
dist/
|
|
325
|
-
*.exe
|
|
326
|
-
*.js.map
|
|
327
|
-
|
|
328
|
-
# Logs
|
|
329
|
-
*.log
|
|
330
|
-
npm-debug.log*
|
|
331
|
-
|
|
332
|
-
# Sistema operacional
|
|
333
|
-
.DS_Store
|
|
334
|
-
Thumbs.db
|
|
335
|
-
|
|
336
|
-
# IDE
|
|
337
|
-
.vscode/
|
|
338
|
-
.idea/
|
|
339
|
-
*.swp
|
|
340
|
-
*.swo
|
|
341
|
-
*~
|
|
342
|
-
|
|
343
|
-
# Trest
|
|
344
|
-
*.trest.js
|
|
345
|
-
*.trest.map
|
|
346
|
-
`;
|
|
347
|
-
|
|
348
|
-
fs.writeFileSync(
|
|
349
|
-
path.join(projectPath, '.gitignore'),
|
|
350
|
-
gitignoreContent
|
|
351
|
-
);
|
|
352
|
-
log('✅ .gitignore criado', 'green');
|
|
353
|
-
|
|
354
|
-
// Instalar treste localmente
|
|
355
|
-
log('\n📦 Instalando Trest Language localmente...', 'cyan');
|
|
698
|
+
// Instalar dependências
|
|
699
|
+
log('\n📦 Instalando dependências...', 'cyan');
|
|
356
700
|
log(' (Isso pode levar alguns segundos)\n', 'yellow');
|
|
357
701
|
|
|
358
702
|
try {
|
|
359
|
-
execSync(`npm install
|
|
703
|
+
execSync(`npm install`, {
|
|
360
704
|
stdio: 'inherit',
|
|
361
705
|
cwd: projectPath,
|
|
362
706
|
shell: process.platform === 'win32'
|
|
363
707
|
});
|
|
364
|
-
log('\n✅
|
|
708
|
+
log('\n✅ Dependências instaladas!', 'green');
|
|
365
709
|
} catch (error) {
|
|
366
|
-
log('\n⚠️ Aviso: Não foi possível instalar
|
|
367
|
-
log(
|
|
368
|
-
log(' Execute manualmente: npm install treste@latest', 'yellow');
|
|
710
|
+
log('\n⚠️ Aviso: Não foi possível instalar dependências automaticamente.', 'yellow');
|
|
711
|
+
log(' Execute manualmente: npm install', 'yellow');
|
|
369
712
|
}
|
|
370
713
|
|
|
371
714
|
// Mensagem final
|
|
@@ -374,8 +717,9 @@ Thumbs.db
|
|
|
374
717
|
log(`\n📂 Localização: ${projectPath}`, 'cyan');
|
|
375
718
|
log('\n🚀 Próximos passos:', 'bright');
|
|
376
719
|
log(`\n cd ${projectName}`, 'cyan');
|
|
377
|
-
log(' npm start', 'cyan');
|
|
378
|
-
log('
|
|
720
|
+
log(' npm start # Executar localmente', 'cyan');
|
|
721
|
+
log(' vercel # Deploy na Vercel', 'cyan');
|
|
722
|
+
log('\n💡 Dica: Edite app.trest para criar suas rotas', 'yellow');
|
|
379
723
|
log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n', 'cyan');
|
|
380
724
|
|
|
381
725
|
} catch (error) {
|
|
@@ -384,7 +728,6 @@ Thumbs.db
|
|
|
384
728
|
console.error(error.stack);
|
|
385
729
|
}
|
|
386
730
|
|
|
387
|
-
// Limpar pasta se houver erro
|
|
388
731
|
if (fs.existsSync(projectPath)) {
|
|
389
732
|
try {
|
|
390
733
|
fs.rmSync(projectPath, { recursive: true, force: true });
|
|
@@ -398,7 +741,6 @@ Thumbs.db
|
|
|
398
741
|
}
|
|
399
742
|
}
|
|
400
743
|
|
|
401
|
-
// Executar
|
|
402
744
|
main().catch((error) => {
|
|
403
745
|
log(`\n❌ Erro fatal: ${error.message}`, 'red');
|
|
404
746
|
if (error.stack) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "treste",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.1",
|
|
4
4
|
"description": "Trest - Linguagem de programação moderna e profissional para Web e Desktop com suporte a Cirílico. Inclui módulo HTTP opcional para requisições de rede (acesso controlado pelo usuário, documentado em SECURITY.md).",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|