vatts 1.2.0-alpha.1 → 1.2.0-test.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/express.js +5 -1
- package/dist/adapters/factory.js +58 -21
- package/dist/adapters/fastify.js +5 -1
- package/dist/adapters/native.js +5 -1
- package/dist/api/console.js +25 -17
- package/dist/api/framework.js +22 -15
- package/dist/api/http.js +7 -2
- package/dist/builder.js +19 -10
- package/dist/client/clientRouter.js +6 -2
- package/dist/client/rpc.js +7 -4
- package/dist/env/env.js +18 -11
- package/dist/global/global.d.ts +177 -122
- package/dist/helpers.js +108 -67
- package/dist/hotReload.d.ts +6 -0
- package/dist/hotReload.js +179 -31
- package/dist/index.js +159 -115
- package/dist/loaders.js +29 -13
- package/dist/react/BuildingPage.d.ts +2 -1
- package/dist/react/BuildingPage.js +47 -4
- package/dist/react/DefaultNotFound.d.ts +2 -1
- package/dist/react/DefaultNotFound.js +92 -17
- package/dist/react/DevIndicator.js +66 -23
- package/dist/react/ErrorModal.js +91 -40
- package/dist/react/Link.d.ts +2 -2
- package/dist/react/Link.js +27 -5
- package/dist/react/client.js +16 -5
- package/dist/react/entry.client.js +70 -30
- package/dist/react/image/Image.js +8 -3
- package/dist/react/renderer-react.js +53 -25
- package/dist/renderer.d.ts +4 -0
- package/dist/renderer.js +13 -5
- package/dist/router.js +82 -63
- package/dist/rpc/annotations.js +7 -3
- package/dist/rpc/server.js +21 -15
- package/dist/rpc/types.js +4 -1
- package/dist/types/framework.js +2 -1
- package/dist/types.js +2 -1
- package/dist/vue/App.vue +34 -37
- package/dist/vue/BuildingPage.vue +118 -102
- package/dist/vue/ErrorModal.vue +19 -37
- package/dist/vue/Link.vue +8 -7
- package/dist/vue/client.js +16 -6
- package/dist/vue/entry.client.js +8 -3
- package/dist/vue/image/Image.vue +25 -19
- package/dist/vue/renderer.vue.js +80 -26
- package/package.json +25 -12
- package/dist/global/global.js +0 -17
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/*
|
|
2
3
|
* This file is part of the Vatts.js Project.
|
|
3
4
|
* Copyright (c) 2026 itsmuzin
|
|
@@ -14,23 +15,64 @@
|
|
|
14
15
|
* See the License for the specific language governing permissions and
|
|
15
16
|
* limitations under the License.
|
|
16
17
|
*/
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
21
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
22
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
23
|
+
}
|
|
24
|
+
Object.defineProperty(o, k2, desc);
|
|
25
|
+
}) : (function(o, m, k, k2) {
|
|
26
|
+
if (k2 === undefined) k2 = k;
|
|
27
|
+
o[k2] = m[k];
|
|
28
|
+
}));
|
|
29
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
30
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
31
|
+
}) : function(o, v) {
|
|
32
|
+
o["default"] = v;
|
|
33
|
+
});
|
|
34
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
35
|
+
var ownKeys = function(o) {
|
|
36
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
37
|
+
var ar = [];
|
|
38
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
39
|
+
return ar;
|
|
40
|
+
};
|
|
41
|
+
return ownKeys(o);
|
|
42
|
+
};
|
|
43
|
+
return function (mod) {
|
|
44
|
+
if (mod && mod.__esModule) return mod;
|
|
45
|
+
var result = {};
|
|
46
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
47
|
+
__setModuleDefault(result, mod);
|
|
48
|
+
return result;
|
|
49
|
+
};
|
|
50
|
+
})();
|
|
51
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
52
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
53
|
+
};
|
|
54
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
55
|
+
exports.app = exports.FrameworkAdapterFactory = exports.FastifyAdapter = exports.ExpressAdapter = exports.VattsResponse = exports.VattsRequest = void 0;
|
|
56
|
+
exports.default = vatts;
|
|
57
|
+
const path_1 = __importDefault(require("path"));
|
|
58
|
+
const fs_1 = __importDefault(require("fs"));
|
|
59
|
+
const crypto_1 = __importDefault(require("crypto")); // Adicionado para gerar hash do cache
|
|
60
|
+
const express_1 = require("./adapters/express");
|
|
61
|
+
const builder_1 = require("./builder");
|
|
62
|
+
const router_1 = require("./router");
|
|
23
63
|
// import { renderAsStream } from './renderer'; // REMOVIDO: Carregamento dinâmico agora
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
64
|
+
const http_1 = require("./api/http");
|
|
65
|
+
Object.defineProperty(exports, "VattsRequest", { enumerable: true, get: function () { return http_1.VattsRequest; } });
|
|
66
|
+
Object.defineProperty(exports, "VattsResponse", { enumerable: true, get: function () { return http_1.VattsResponse; } });
|
|
67
|
+
const hotReload_1 = require("./hotReload");
|
|
68
|
+
const factory_1 = require("./adapters/factory");
|
|
69
|
+
const console_1 = __importStar(require("./api/console"));
|
|
70
|
+
const env_1 = require("./env/env");
|
|
29
71
|
// RPC
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
72
|
+
const server_1 = require("./rpc/server");
|
|
73
|
+
const types_1 = require("./rpc/types");
|
|
74
|
+
const helpers_1 = require("./helpers");
|
|
75
|
+
const framework_1 = __importDefault(require("./api/framework"));
|
|
34
76
|
// Helpers de segurança para servir arquivos estáticos sem path traversal
|
|
35
77
|
function isSuspiciousPathname(p) {
|
|
36
78
|
try {
|
|
@@ -43,9 +85,9 @@ function isSuspiciousPathname(p) {
|
|
|
43
85
|
}
|
|
44
86
|
function resolveWithin(baseDir, unsafePath) {
|
|
45
87
|
const rel = unsafePath.replace(/^\/+/, '');
|
|
46
|
-
const absBase =
|
|
47
|
-
const abs =
|
|
48
|
-
const baseWithSep = absBase.endsWith(
|
|
88
|
+
const absBase = path_1.default.resolve(baseDir);
|
|
89
|
+
const abs = path_1.default.resolve(absBase, rel);
|
|
90
|
+
const baseWithSep = absBase.endsWith(path_1.default.sep) ? absBase : absBase + path_1.default.sep;
|
|
49
91
|
if (abs !== absBase && !abs.startsWith(baseWithSep))
|
|
50
92
|
return null;
|
|
51
93
|
return abs;
|
|
@@ -71,13 +113,13 @@ async function handleImageOptimization(req, res, projectDir) {
|
|
|
71
113
|
if (imageUrl.startsWith('/_vatts/')) {
|
|
72
114
|
// Arquivos de build (assets gerados pelo Rollup)
|
|
73
115
|
const relPath = imageUrl.replace('/_vatts/', '');
|
|
74
|
-
filePath = resolveWithin(
|
|
116
|
+
filePath = resolveWithin(path_1.default.join(projectDir, '.vatts'), relPath);
|
|
75
117
|
}
|
|
76
118
|
else {
|
|
77
119
|
// Arquivos públicos
|
|
78
|
-
filePath = resolveWithin(
|
|
120
|
+
filePath = resolveWithin(path_1.default.join(projectDir, 'public'), imageUrl);
|
|
79
121
|
}
|
|
80
|
-
if (!filePath || !
|
|
122
|
+
if (!filePath || !fs_1.default.existsSync(filePath)) {
|
|
81
123
|
res.status(404).text('Image not found');
|
|
82
124
|
return;
|
|
83
125
|
}
|
|
@@ -93,29 +135,29 @@ async function handleImageOptimization(req, res, projectDir) {
|
|
|
93
135
|
catch (e) {
|
|
94
136
|
// Se não tiver sharp, avisa uma vez e serve o arquivo original
|
|
95
137
|
if (!global.__vatts_sharp_warned) {
|
|
96
|
-
|
|
138
|
+
console_1.default.warn('Package "sharp" not found. Image optimization is disabled. Install it with: npm install sharp');
|
|
97
139
|
global.__vatts_sharp_warned = true;
|
|
98
140
|
}
|
|
99
141
|
}
|
|
100
142
|
// Se não tiver Sharp ou parâmetros, serve original
|
|
101
143
|
if (!sharp || (!widthStr && !heightStr && !qualityStr)) {
|
|
102
|
-
const ext =
|
|
144
|
+
const ext = path_1.default.extname(filePath).toLowerCase();
|
|
103
145
|
const contentTypes = {
|
|
104
146
|
'.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg',
|
|
105
147
|
'.webp': 'image/webp', '.avif': 'image/avif', '.gif': 'image/gif',
|
|
106
148
|
'.svg': 'image/svg+xml'
|
|
107
149
|
};
|
|
108
150
|
res.header('Content-Type', contentTypes[ext] || 'application/octet-stream');
|
|
109
|
-
const fileBuffer = await
|
|
151
|
+
const fileBuffer = await fs_1.default.promises.readFile(filePath);
|
|
110
152
|
res.send(fileBuffer);
|
|
111
153
|
return;
|
|
112
154
|
}
|
|
113
155
|
try {
|
|
114
156
|
// --- SISTEMA DE CACHE EM DISCO (TEMPORÁRIO EM .vatts) ---
|
|
115
|
-
const cacheDir =
|
|
157
|
+
const cacheDir = path_1.default.join(projectDir, '.vatts', 'cache', 'images');
|
|
116
158
|
// Garante que a pasta existe (síncrono na primeira vez é ok, ou async)
|
|
117
|
-
if (!
|
|
118
|
-
|
|
159
|
+
if (!fs_1.default.existsSync(cacheDir)) {
|
|
160
|
+
fs_1.default.mkdirSync(cacheDir, { recursive: true });
|
|
119
161
|
}
|
|
120
162
|
const width = widthStr ? parseInt(widthStr, 10) : undefined;
|
|
121
163
|
const height = heightStr ? parseInt(heightStr, 10) : undefined;
|
|
@@ -123,17 +165,17 @@ async function handleImageOptimization(req, res, projectDir) {
|
|
|
123
165
|
// Gera um hash único baseado em TODOS os parâmetros
|
|
124
166
|
// Ex: /img.png?w=100&h=200&q=80 -> hash unico
|
|
125
167
|
const cacheKey = `${imageUrl}?w=${width}&h=${height}&q=${quality}`;
|
|
126
|
-
const hash =
|
|
168
|
+
const hash = crypto_1.default.createHash('md5').update(cacheKey).digest('hex');
|
|
127
169
|
// Define a extensão do arquivo de cache
|
|
128
|
-
const extOriginal =
|
|
170
|
+
const extOriginal = path_1.default.extname(filePath).toLowerCase();
|
|
129
171
|
let extOutput = '.webp'; // Padrão é converter para WebP
|
|
130
172
|
// Exceções que não viram WebP
|
|
131
173
|
if (extOriginal === '.svg' || extOriginal === '.gif') {
|
|
132
174
|
extOutput = extOriginal;
|
|
133
175
|
}
|
|
134
|
-
const cachedFilePath =
|
|
176
|
+
const cachedFilePath = path_1.default.join(cacheDir, `${hash}${extOutput}`);
|
|
135
177
|
// 1. VERIFICA SE JÁ EXISTE NO CACHE
|
|
136
|
-
if (
|
|
178
|
+
if (fs_1.default.existsSync(cachedFilePath)) {
|
|
137
179
|
// Serve direto do cache (Disco)
|
|
138
180
|
// console.log(`[Vatts] Serving cached image: ${imageUrl}`);
|
|
139
181
|
const contentTypes = {
|
|
@@ -142,7 +184,7 @@ async function handleImageOptimization(req, res, projectDir) {
|
|
|
142
184
|
'.gif': 'image/gif'
|
|
143
185
|
};
|
|
144
186
|
res.header('Content-Type', contentTypes[extOutput] || 'application/octet-stream');
|
|
145
|
-
const cachedBuffer = await
|
|
187
|
+
const cachedBuffer = await fs_1.default.promises.readFile(cachedFilePath);
|
|
146
188
|
res.send(cachedBuffer);
|
|
147
189
|
return;
|
|
148
190
|
}
|
|
@@ -171,44 +213,46 @@ async function handleImageOptimization(req, res, projectDir) {
|
|
|
171
213
|
// 3. SALVA NO CACHE PARA A PRÓXIMA VEZ
|
|
172
214
|
// Escreve em background para não bloquear totalmente, mas aguarda para segurança
|
|
173
215
|
try {
|
|
174
|
-
await
|
|
216
|
+
await fs_1.default.promises.writeFile(cachedFilePath, optimizedBuffer);
|
|
175
217
|
}
|
|
176
218
|
catch (writeErr) {
|
|
177
|
-
|
|
219
|
+
console_1.default.error('Failed to write image cache:', writeErr);
|
|
178
220
|
}
|
|
179
221
|
res.send(optimizedBuffer);
|
|
180
222
|
}
|
|
181
223
|
catch (error) {
|
|
182
|
-
|
|
224
|
+
console_1.default.error('Error optimizing image:', error);
|
|
183
225
|
res.status(500).text('Image optimization failed');
|
|
184
226
|
}
|
|
185
227
|
}
|
|
186
|
-
// Exporta apenas os tipos e classes para o backend
|
|
187
|
-
export { VattsRequest, VattsResponse };
|
|
188
228
|
// Exporta os adapters para uso manual se necessário
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
229
|
+
var express_2 = require("./adapters/express");
|
|
230
|
+
Object.defineProperty(exports, "ExpressAdapter", { enumerable: true, get: function () { return express_2.ExpressAdapter; } });
|
|
231
|
+
var fastify_1 = require("./adapters/fastify");
|
|
232
|
+
Object.defineProperty(exports, "FastifyAdapter", { enumerable: true, get: function () { return fastify_1.FastifyAdapter; } });
|
|
233
|
+
var factory_2 = require("./adapters/factory");
|
|
234
|
+
Object.defineProperty(exports, "FrameworkAdapterFactory", { enumerable: true, get: function () { return factory_2.FrameworkAdapterFactory; } });
|
|
192
235
|
// Exporta os helpers para facilitar integração
|
|
193
|
-
|
|
236
|
+
var helpers_2 = require("./helpers");
|
|
237
|
+
Object.defineProperty(exports, "app", { enumerable: true, get: function () { return helpers_2.app; } });
|
|
194
238
|
// Função para verificar se o projeto é grande o suficiente para se beneficiar de chunks
|
|
195
239
|
function isLargeProject(projectDir) {
|
|
196
240
|
try {
|
|
197
|
-
const srcDir =
|
|
198
|
-
if (!
|
|
241
|
+
const srcDir = path_1.default.join(projectDir, 'src');
|
|
242
|
+
if (!fs_1.default.existsSync(srcDir))
|
|
199
243
|
return false;
|
|
200
244
|
let totalFiles = 0;
|
|
201
245
|
let totalSize = 0;
|
|
202
246
|
function scanDirectory(dir) {
|
|
203
|
-
const items =
|
|
247
|
+
const items = fs_1.default.readdirSync(dir, { withFileTypes: true });
|
|
204
248
|
for (const item of items) {
|
|
205
|
-
const fullPath =
|
|
249
|
+
const fullPath = path_1.default.join(dir, item.name);
|
|
206
250
|
if (item.isDirectory() && item.name !== 'node_modules' && item.name !== '.git') {
|
|
207
251
|
scanDirectory(fullPath);
|
|
208
252
|
}
|
|
209
253
|
else if (item.isFile() && /\.(tsx?|jsx?|css|scss|less)$/i.test(item.name)) {
|
|
210
254
|
totalFiles++;
|
|
211
|
-
totalSize +=
|
|
255
|
+
totalSize += fs_1.default.statSync(fullPath).size;
|
|
212
256
|
}
|
|
213
257
|
}
|
|
214
258
|
}
|
|
@@ -222,25 +266,25 @@ function isLargeProject(projectDir) {
|
|
|
222
266
|
// Função para gerar o arquivo de entrada para o esbuild
|
|
223
267
|
function createEntryFile(projectDir, routes, framework) {
|
|
224
268
|
try {
|
|
225
|
-
const tempDir =
|
|
226
|
-
|
|
227
|
-
const entryFilePath =
|
|
228
|
-
const layout = getLayout();
|
|
229
|
-
const notFound = getNotFound();
|
|
269
|
+
const tempDir = path_1.default.join(projectDir, '.vatts', 'temp');
|
|
270
|
+
fs_1.default.mkdirSync(tempDir, { recursive: true });
|
|
271
|
+
const entryFilePath = path_1.default.join(tempDir, 'entry.client.js');
|
|
272
|
+
const layout = (0, router_1.getLayout)();
|
|
273
|
+
const notFound = (0, router_1.getNotFound)();
|
|
230
274
|
const imports = routes
|
|
231
275
|
.map((route, index) => {
|
|
232
|
-
const relativePath =
|
|
276
|
+
const relativePath = path_1.default.relative(tempDir, route.componentPath).replace(/\\/g, '/');
|
|
233
277
|
return `import route${index} from '${relativePath}';`;
|
|
234
278
|
})
|
|
235
279
|
.join('\n');
|
|
236
280
|
const layoutImport = layout
|
|
237
|
-
? `import LayoutComponent from '${
|
|
281
|
+
? `import LayoutComponent from '${path_1.default.relative(tempDir, layout.componentPath).replace(/\\/g, '/')}';`
|
|
238
282
|
: '';
|
|
239
283
|
const notFoundImport = notFound
|
|
240
|
-
? `import NotFoundComponent from '${
|
|
284
|
+
? `import NotFoundComponent from '${path_1.default.relative(tempDir, notFound.componentPath).replace(/\\/g, '/')}';`
|
|
241
285
|
: '';
|
|
242
286
|
let componentRegistration;
|
|
243
|
-
if (config?.pathRouter === true) {
|
|
287
|
+
if (helpers_1.config?.pathRouter === true) {
|
|
244
288
|
componentRegistration = routes
|
|
245
289
|
.map((route, index) => ` '${route.componentPath}': route${index} || route${index}.default,`)
|
|
246
290
|
.join('\n');
|
|
@@ -266,12 +310,12 @@ function createEntryFile(projectDir, routes, framework) {
|
|
|
266
310
|
// Define os nomes dos arquivos baseados no framework
|
|
267
311
|
const entryClientFilename = framework === 'vue' ? 'entry.client.js' : 'entry.client.js';
|
|
268
312
|
const defaultNotFoundFilename = framework === 'vue' ? 'DefaultNotFound.vue' : 'DefaultNotFound.js';
|
|
269
|
-
const sdkDir =
|
|
313
|
+
const sdkDir = path_1.default.dirname(__dirname);
|
|
270
314
|
// --- MODIFICAÇÃO: Usando a variável 'framework' para definir o diretório (react ou vue) ---
|
|
271
|
-
const entryClientPath =
|
|
272
|
-
const relativeEntryPath =
|
|
273
|
-
const defaultNotFoundPath =
|
|
274
|
-
const relativeDefaultNotFoundPath =
|
|
315
|
+
const entryClientPath = path_1.default.join(sdkDir, 'dist', framework, entryClientFilename);
|
|
316
|
+
const relativeEntryPath = path_1.default.relative(tempDir, entryClientPath).replace(/\\/g, '/');
|
|
317
|
+
const defaultNotFoundPath = path_1.default.join(sdkDir, 'dist', framework, defaultNotFoundFilename);
|
|
318
|
+
const relativeDefaultNotFoundPath = path_1.default.relative(tempDir, defaultNotFoundPath).replace(/\\/g, '/');
|
|
275
319
|
const entryContent = `// Arquivo gerado automaticamente pelo vatts
|
|
276
320
|
${imports}
|
|
277
321
|
${layoutImport}
|
|
@@ -290,7 +334,7 @@ window.__VATTS_DEFAULT_NOT_FOUND__ = DefaultNotFound;
|
|
|
290
334
|
import '${relativeEntryPath}';
|
|
291
335
|
`;
|
|
292
336
|
try {
|
|
293
|
-
|
|
337
|
+
fs_1.default.writeFileSync(entryFilePath, entryContent);
|
|
294
338
|
}
|
|
295
339
|
catch (e) {
|
|
296
340
|
console.error("Error writing entry file", e);
|
|
@@ -298,22 +342,22 @@ import '${relativeEntryPath}';
|
|
|
298
342
|
return entryFilePath;
|
|
299
343
|
}
|
|
300
344
|
catch (e) {
|
|
301
|
-
|
|
345
|
+
console_1.default.error("Error creating entry file:", e);
|
|
302
346
|
throw e;
|
|
303
347
|
}
|
|
304
348
|
}
|
|
305
|
-
|
|
349
|
+
function vatts(options) {
|
|
306
350
|
const { dev = true, dir = process.cwd(), port = 3000, envFiles } = options;
|
|
307
|
-
loadEnv({ dir, dev, envFiles });
|
|
351
|
+
(0, env_1.loadEnv)({ dir, dev, envFiles });
|
|
308
352
|
// @ts-ignore
|
|
309
353
|
process.vatts = options;
|
|
310
354
|
// @ts-ignore
|
|
311
355
|
process.env.PORT = options.port;
|
|
312
|
-
const userWebDir =
|
|
313
|
-
const userWebRoutesDir =
|
|
314
|
-
const userBackendRoutesDir =
|
|
356
|
+
const userWebDir = path_1.default.join(dir, 'src', 'web');
|
|
357
|
+
const userWebRoutesDir = path_1.default.join(userWebDir, 'routes');
|
|
358
|
+
const userBackendRoutesDir = path_1.default.join(dir, 'src', 'backend', 'routes');
|
|
315
359
|
// --- DETECÇÃO DO FRAMEWORK ---
|
|
316
|
-
const framework =
|
|
360
|
+
const framework = (0, framework_1.default)(dir);
|
|
317
361
|
// --- CARREGAMENTO DO RENDERER ---
|
|
318
362
|
let renderAsStream = require("./renderer").renderAsStream;
|
|
319
363
|
async function executeMiddlewareChain(middlewares, finalHandler, request, params) {
|
|
@@ -337,9 +381,9 @@ export default function vatts(options) {
|
|
|
337
381
|
let hotReloadManager = null;
|
|
338
382
|
let entryPoint;
|
|
339
383
|
const regenerateEntryFile = () => {
|
|
340
|
-
const newFrontendRoutes = loadRoutes(userWebRoutesDir);
|
|
341
|
-
const newLayout = loadLayout(userWebDir);
|
|
342
|
-
const newNotFound = loadNotFound(userWebDir);
|
|
384
|
+
const newFrontendRoutes = (0, router_1.loadRoutes)(userWebRoutesDir);
|
|
385
|
+
const newLayout = (0, router_1.loadLayout)(userWebDir);
|
|
386
|
+
const newNotFound = (0, router_1.loadNotFound)(userWebDir);
|
|
343
387
|
const oldKey = frontendRoutes.map(r => `${r.pattern ?? ''}:${r.componentPath}`).join('|');
|
|
344
388
|
const newKey = newFrontendRoutes.map(r => `${r.pattern ?? ''}:${r.componentPath}`).join('|');
|
|
345
389
|
if (oldKey === newKey) {
|
|
@@ -353,44 +397,44 @@ export default function vatts(options) {
|
|
|
353
397
|
prepare: async () => {
|
|
354
398
|
const isProduction = !dev;
|
|
355
399
|
if (!isProduction) {
|
|
356
|
-
hotReloadManager = new HotReloadManager(dir);
|
|
400
|
+
hotReloadManager = new hotReload_1.HotReloadManager(dir);
|
|
357
401
|
await hotReloadManager.start();
|
|
358
402
|
hotReloadManager.onBackendApiChange(() => {
|
|
359
|
-
loadBackendRoutes(userBackendRoutesDir);
|
|
360
|
-
processWebSocketRoutes();
|
|
403
|
+
(0, router_1.loadBackendRoutes)(userBackendRoutesDir);
|
|
404
|
+
(0, router_1.processWebSocketRoutes)();
|
|
361
405
|
});
|
|
362
406
|
hotReloadManager.onFrontendChange(() => {
|
|
363
407
|
regenerateEntryFile();
|
|
364
408
|
});
|
|
365
409
|
}
|
|
366
410
|
const now = Date.now();
|
|
367
|
-
const timee =
|
|
411
|
+
const timee = console_1.default.dynamicLine(`Loading routes and components`);
|
|
368
412
|
const spinnerFrames1 = ['|', '/', '-', '\\'];
|
|
369
413
|
let frameIndex1 = 0;
|
|
370
414
|
const spinner1 = setInterval(() => {
|
|
371
|
-
timee.update(` ${Colors.FgYellow}${spinnerFrames1[frameIndex1]}${Colors.Reset} Loading routes and components...`);
|
|
415
|
+
timee.update(` ${console_1.Colors.FgYellow}${spinnerFrames1[frameIndex1]}${console_1.Colors.Reset} Loading routes and components...`);
|
|
372
416
|
frameIndex1 = (frameIndex1 + 1) % spinnerFrames1.length;
|
|
373
417
|
}, 100);
|
|
374
|
-
frontendRoutes = loadRoutes(userWebRoutesDir);
|
|
375
|
-
loadBackendRoutes(userBackendRoutesDir);
|
|
376
|
-
processWebSocketRoutes();
|
|
377
|
-
const layout = loadLayout(userWebDir);
|
|
378
|
-
const notFound = loadNotFound(userWebDir);
|
|
379
|
-
const outDir =
|
|
380
|
-
|
|
418
|
+
frontendRoutes = (0, router_1.loadRoutes)(userWebRoutesDir);
|
|
419
|
+
(0, router_1.loadBackendRoutes)(userBackendRoutesDir);
|
|
420
|
+
(0, router_1.processWebSocketRoutes)();
|
|
421
|
+
const layout = (0, router_1.loadLayout)(userWebDir);
|
|
422
|
+
const notFound = (0, router_1.loadNotFound)(userWebDir);
|
|
423
|
+
const outDir = path_1.default.join(dir, '.vatts');
|
|
424
|
+
fs_1.default.mkdirSync(outDir, { recursive: true });
|
|
381
425
|
entryPoint = createEntryFile(dir, frontendRoutes, framework);
|
|
382
426
|
clearInterval(spinner1);
|
|
383
427
|
timee.end(`Routes and components loaded in ${Date.now() - now}ms`);
|
|
384
428
|
if (isProduction) {
|
|
385
|
-
const time =
|
|
429
|
+
const time = console_1.default.dynamicLine(`Starting client build`);
|
|
386
430
|
const spinnerFrames = ['|', '/', '-', '\\'];
|
|
387
431
|
let frameIndex = 0;
|
|
388
432
|
const spinner = setInterval(() => {
|
|
389
|
-
time.update(` ${Colors.FgYellow}${spinnerFrames[frameIndex]}${Colors.Reset} Building...`);
|
|
433
|
+
time.update(` ${console_1.Colors.FgYellow}${spinnerFrames[frameIndex]}${console_1.Colors.Reset} Building...`);
|
|
390
434
|
frameIndex = (frameIndex + 1) % spinnerFrames.length;
|
|
391
435
|
}, 100);
|
|
392
436
|
const now = Date.now();
|
|
393
|
-
await buildWithChunks(entryPoint, outDir, isProduction);
|
|
437
|
+
await (0, builder_1.buildWithChunks)(entryPoint, outDir, isProduction);
|
|
394
438
|
const elapsed = Date.now() - now;
|
|
395
439
|
clearInterval(spinner);
|
|
396
440
|
time.update("");
|
|
@@ -400,18 +444,18 @@ export default function vatts(options) {
|
|
|
400
444
|
}
|
|
401
445
|
}
|
|
402
446
|
else {
|
|
403
|
-
const time =
|
|
447
|
+
const time = console_1.default.dynamicLine(` ${console_1.Colors.BgYellow} watcher ${console_1.Colors.Reset} Starting client watch`);
|
|
404
448
|
// @ts-ignore
|
|
405
|
-
watchWithChunks(entryPoint, outDir, hotReloadManager).catch(err => {
|
|
406
|
-
|
|
449
|
+
(0, builder_1.watchWithChunks)(entryPoint, outDir, hotReloadManager).catch(err => {
|
|
450
|
+
console_1.default.error(`Error starting watch`, err);
|
|
407
451
|
});
|
|
408
452
|
time.end(`Client Watch started`);
|
|
409
453
|
}
|
|
410
454
|
},
|
|
411
455
|
executeInstrumentation: () => {
|
|
412
|
-
const instrumentationFile =
|
|
456
|
+
const instrumentationFile = fs_1.default.readdirSync(path_1.default.join(dir, 'src')).find(file => /^vattsweb\.(js|ts)$/.test(file));
|
|
413
457
|
if (instrumentationFile) {
|
|
414
|
-
const instrumentationPath =
|
|
458
|
+
const instrumentationPath = path_1.default.join(dir, 'src', instrumentationFile);
|
|
415
459
|
const instrumentation = require(instrumentationPath);
|
|
416
460
|
if (instrumentation.hotReloadListener && typeof instrumentation.hotReloadListener === 'function') {
|
|
417
461
|
if (hotReloadManager) {
|
|
@@ -425,13 +469,13 @@ export default function vatts(options) {
|
|
|
425
469
|
instrumentation.default();
|
|
426
470
|
}
|
|
427
471
|
else {
|
|
428
|
-
|
|
472
|
+
console_1.default.warn(`The instrumentation file ${instrumentationFile} does not export a default function.`);
|
|
429
473
|
}
|
|
430
474
|
}
|
|
431
475
|
},
|
|
432
476
|
getRequestHandler: () => {
|
|
433
477
|
return async (req, res) => {
|
|
434
|
-
const adapter = FrameworkAdapterFactory.detectFramework(req, res);
|
|
478
|
+
const adapter = factory_1.FrameworkAdapterFactory.detectFramework(req, res);
|
|
435
479
|
const genericReq = adapter.parseRequest(req);
|
|
436
480
|
const genericRes = adapter.createResponse(res);
|
|
437
481
|
genericReq.hwebDev = dev;
|
|
@@ -440,9 +484,9 @@ export default function vatts(options) {
|
|
|
440
484
|
const method = (genericReq.method || 'GET').toUpperCase();
|
|
441
485
|
const urlObj = new URL(genericReq.url, `http://${hostname}:${port}`);
|
|
442
486
|
const pathname = urlObj.pathname;
|
|
443
|
-
if (pathname === RPC_ENDPOINT && method === 'POST') {
|
|
487
|
+
if (pathname === types_1.RPC_ENDPOINT && method === 'POST') {
|
|
444
488
|
try {
|
|
445
|
-
const result = await executeRpc({
|
|
489
|
+
const result = await (0, server_1.executeRpc)({
|
|
446
490
|
projectDir: dir,
|
|
447
491
|
request: genericReq
|
|
448
492
|
}, genericReq.body);
|
|
@@ -466,11 +510,11 @@ export default function vatts(options) {
|
|
|
466
510
|
}
|
|
467
511
|
// ---------------------------------------
|
|
468
512
|
if (pathname !== '/' && !pathname.startsWith('/api/') && !pathname.startsWith('/.vatts')) {
|
|
469
|
-
const publicDir =
|
|
513
|
+
const publicDir = path_1.default.join(dir, 'public');
|
|
470
514
|
if (!isSuspiciousPathname(pathname)) {
|
|
471
515
|
const filePath = resolveWithin(publicDir, pathname);
|
|
472
|
-
if (filePath &&
|
|
473
|
-
const ext =
|
|
516
|
+
if (filePath && fs_1.default.existsSync(filePath) && fs_1.default.statSync(filePath).isFile()) {
|
|
517
|
+
const ext = path_1.default.extname(filePath).toLowerCase();
|
|
474
518
|
const contentTypes = {
|
|
475
519
|
'.html': 'text/html',
|
|
476
520
|
'.css': 'text/css',
|
|
@@ -497,11 +541,11 @@ export default function vatts(options) {
|
|
|
497
541
|
res.sendFile(filePath);
|
|
498
542
|
}
|
|
499
543
|
else if (adapter.type === 'fastify') {
|
|
500
|
-
const fileContent =
|
|
544
|
+
const fileContent = fs_1.default.readFileSync(filePath);
|
|
501
545
|
genericRes.send(fileContent);
|
|
502
546
|
}
|
|
503
547
|
else if (adapter.type === 'native') {
|
|
504
|
-
const fileContent =
|
|
548
|
+
const fileContent = fs_1.default.readFileSync(filePath);
|
|
505
549
|
genericRes.send(fileContent);
|
|
506
550
|
}
|
|
507
551
|
return;
|
|
@@ -509,12 +553,12 @@ export default function vatts(options) {
|
|
|
509
553
|
}
|
|
510
554
|
}
|
|
511
555
|
if (pathname.startsWith('/_vatts/')) {
|
|
512
|
-
const staticPath =
|
|
556
|
+
const staticPath = path_1.default.join(dir, '.vatts');
|
|
513
557
|
const requestPath = pathname.replace('/_vatts/', '');
|
|
514
558
|
if (!isSuspiciousPathname(requestPath)) {
|
|
515
559
|
const filePath = resolveWithin(staticPath, requestPath);
|
|
516
|
-
if (filePath &&
|
|
517
|
-
const ext =
|
|
560
|
+
if (filePath && fs_1.default.existsSync(filePath) && fs_1.default.statSync(filePath).isFile()) {
|
|
561
|
+
const ext = path_1.default.extname(filePath).toLowerCase();
|
|
518
562
|
const contentTypes = {
|
|
519
563
|
'.js': 'application/javascript',
|
|
520
564
|
'.css': 'text/css',
|
|
@@ -526,36 +570,36 @@ export default function vatts(options) {
|
|
|
526
570
|
res.sendFile(filePath);
|
|
527
571
|
}
|
|
528
572
|
else if (adapter.type === 'fastify') {
|
|
529
|
-
const fileContent =
|
|
573
|
+
const fileContent = fs_1.default.readFileSync(filePath);
|
|
530
574
|
genericRes.send(fileContent);
|
|
531
575
|
}
|
|
532
576
|
else if (adapter.type === 'native') {
|
|
533
|
-
const fileContent =
|
|
577
|
+
const fileContent = fs_1.default.readFileSync(filePath);
|
|
534
578
|
genericRes.send(fileContent);
|
|
535
579
|
}
|
|
536
580
|
return;
|
|
537
581
|
}
|
|
538
582
|
}
|
|
539
583
|
}
|
|
540
|
-
const backendMatch = findMatchingBackendRoute(pathname, method);
|
|
584
|
+
const backendMatch = (0, router_1.findMatchingBackendRoute)(pathname, method);
|
|
541
585
|
if (backendMatch) {
|
|
542
586
|
try {
|
|
543
587
|
const handler = backendMatch.route[method];
|
|
544
588
|
if (handler) {
|
|
545
|
-
const hwebReq = new VattsRequest(genericReq);
|
|
589
|
+
const hwebReq = new http_1.VattsRequest(genericReq);
|
|
546
590
|
const hwebRes = await executeMiddlewareChain(backendMatch.route.middleware, handler, hwebReq, backendMatch.params);
|
|
547
591
|
hwebRes._applyTo(genericRes);
|
|
548
592
|
return;
|
|
549
593
|
}
|
|
550
594
|
}
|
|
551
595
|
catch (error) {
|
|
552
|
-
|
|
596
|
+
console_1.default.error(`API route error ${pathname}:`, error);
|
|
553
597
|
genericRes.status(500).text('Internal server error in API');
|
|
554
598
|
return;
|
|
555
599
|
}
|
|
556
600
|
}
|
|
557
601
|
// Renderização de Página (Frontend)
|
|
558
|
-
const pageMatch = findMatchingRoute(pathname);
|
|
602
|
+
const pageMatch = (0, router_1.findMatchingRoute)(pathname);
|
|
559
603
|
// Determina o objeto de resposta "cru" para o stream do React
|
|
560
604
|
// Se for Fastify, o Writable stream está em res.raw. Se for Express/Native, é o próprio res.
|
|
561
605
|
const rawRes = (res.raw || res);
|
|
@@ -567,11 +611,11 @@ export default function vatts(options) {
|
|
|
567
611
|
componentPath: '__404__'
|
|
568
612
|
};
|
|
569
613
|
// Tenta usar componente 404 customizado se houver
|
|
570
|
-
const notFound = getNotFound();
|
|
614
|
+
const notFound = (0, router_1.getNotFound)();
|
|
571
615
|
if (notFound) {
|
|
572
616
|
// Carrega o componente 404 real para o SSR funcionar
|
|
573
617
|
try {
|
|
574
|
-
const nfModule = require(
|
|
618
|
+
const nfModule = require(path_1.default.resolve(process.cwd(), notFound.componentPath));
|
|
575
619
|
// @ts-ignore
|
|
576
620
|
notFoundRoute.component = nfModule.default || nfModule;
|
|
577
621
|
}
|
|
@@ -592,7 +636,7 @@ export default function vatts(options) {
|
|
|
592
636
|
return;
|
|
593
637
|
}
|
|
594
638
|
catch (error) {
|
|
595
|
-
|
|
639
|
+
console_1.default.error(`Error rendering page 404:`, error);
|
|
596
640
|
genericRes.status(404).text('Page not found');
|
|
597
641
|
return;
|
|
598
642
|
}
|
|
@@ -608,7 +652,7 @@ export default function vatts(options) {
|
|
|
608
652
|
});
|
|
609
653
|
}
|
|
610
654
|
catch (error) {
|
|
611
|
-
|
|
655
|
+
console_1.default.error(`Error rendering page ${pathname}:`, error);
|
|
612
656
|
// Se o stream já começou, não dá pra enviar erro 500 limpo.
|
|
613
657
|
// O renderAsStream tenta lidar com isso no onError.
|
|
614
658
|
if (!rawRes.headersSent) {
|
|
@@ -618,9 +662,9 @@ export default function vatts(options) {
|
|
|
618
662
|
};
|
|
619
663
|
},
|
|
620
664
|
setupWebSocket: (server) => {
|
|
621
|
-
const isExpressServer = FrameworkAdapterFactory.getCurrentAdapter() instanceof ExpressAdapter;
|
|
665
|
+
const isExpressServer = factory_1.FrameworkAdapterFactory.getCurrentAdapter() instanceof express_1.ExpressAdapter;
|
|
622
666
|
const actualServer = isExpressServer ? server : (server.server || server);
|
|
623
|
-
setupWebSocketUpgrade(actualServer, hotReloadManager);
|
|
667
|
+
(0, router_1.setupWebSocketUpgrade)(actualServer, hotReloadManager);
|
|
624
668
|
},
|
|
625
669
|
stop: () => {
|
|
626
670
|
if (hotReloadManager) {
|