vatts 1.1.0 → 1.1.2
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 +5 -4
- package/dist/builder.js +55 -7
- package/dist/client/BuildingPage.d.ts +1 -0
- package/dist/client/BuildingPage.js +209 -0
- package/dist/client/DefaultNotFound.js +30 -32
- package/dist/client/DevIndicator.d.ts +2 -1
- package/dist/client/DevIndicator.js +102 -104
- package/dist/client/ErrorModal.js +50 -47
- package/dist/client/client.d.ts +2 -0
- package/dist/client/client.js +8 -1
- package/dist/client/image/Image.d.ts +10 -0
- package/dist/client/image/Image.js +35 -0
- package/dist/index.js +142 -1
- package/dist/renderer.js +8 -266
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -56,6 +56,7 @@ exports.app = exports.FrameworkAdapterFactory = exports.FastifyAdapter = exports
|
|
|
56
56
|
exports.default = vatts;
|
|
57
57
|
const path_1 = __importDefault(require("path"));
|
|
58
58
|
const fs_1 = __importDefault(require("fs"));
|
|
59
|
+
const crypto_1 = __importDefault(require("crypto")); // Adicionado para gerar hash do cache
|
|
59
60
|
const express_1 = require("./adapters/express");
|
|
60
61
|
const builder_1 = require("./builder");
|
|
61
62
|
const router_1 = require("./router");
|
|
@@ -90,6 +91,139 @@ function resolveWithin(baseDir, unsafePath) {
|
|
|
90
91
|
return null;
|
|
91
92
|
return abs;
|
|
92
93
|
}
|
|
94
|
+
// Handler de Otimização de Imagem
|
|
95
|
+
async function handleImageOptimization(req, res, projectDir) {
|
|
96
|
+
const urlObj = new URL(req.url, `http://localhost`);
|
|
97
|
+
const params = urlObj.searchParams;
|
|
98
|
+
const imageUrl = params.get('url');
|
|
99
|
+
const widthStr = params.get('w');
|
|
100
|
+
const heightStr = params.get('h');
|
|
101
|
+
const qualityStr = params.get('q');
|
|
102
|
+
if (!imageUrl) {
|
|
103
|
+
res.status(400).text('Missing "url" parameter');
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (isSuspiciousPathname(imageUrl)) {
|
|
107
|
+
res.status(400).text('Invalid path');
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
// Resolve o caminho do arquivo no disco
|
|
111
|
+
let filePath = null;
|
|
112
|
+
if (imageUrl.startsWith('/_vatts/')) {
|
|
113
|
+
// Arquivos de build (assets gerados pelo Rollup)
|
|
114
|
+
const relPath = imageUrl.replace('/_vatts/', '');
|
|
115
|
+
filePath = resolveWithin(path_1.default.join(projectDir, '.vatts'), relPath);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
// Arquivos públicos
|
|
119
|
+
filePath = resolveWithin(path_1.default.join(projectDir, 'public'), imageUrl);
|
|
120
|
+
}
|
|
121
|
+
if (!filePath || !fs_1.default.existsSync(filePath)) {
|
|
122
|
+
res.status(404).text('Image not found');
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
// Cache headers agressivos (o navegador deve cachear isso por muito tempo)
|
|
126
|
+
res.header('Cache-Control', 'public, max-age=31536000, immutable');
|
|
127
|
+
res.header('Vary', 'Accept');
|
|
128
|
+
// Tenta carregar o sharp
|
|
129
|
+
let sharp;
|
|
130
|
+
try {
|
|
131
|
+
// @ts-ignore
|
|
132
|
+
sharp = require('sharp');
|
|
133
|
+
}
|
|
134
|
+
catch (e) {
|
|
135
|
+
// Se não tiver sharp, avisa uma vez e serve o arquivo original
|
|
136
|
+
if (!global.__vatts_sharp_warned) {
|
|
137
|
+
console_1.default.warn('Package "sharp" not found. Image optimization is disabled. Install it with: npm install sharp');
|
|
138
|
+
global.__vatts_sharp_warned = true;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Se não tiver Sharp ou parâmetros, serve original
|
|
142
|
+
if (!sharp || (!widthStr && !heightStr && !qualityStr)) {
|
|
143
|
+
const ext = path_1.default.extname(filePath).toLowerCase();
|
|
144
|
+
const contentTypes = {
|
|
145
|
+
'.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg',
|
|
146
|
+
'.webp': 'image/webp', '.avif': 'image/avif', '.gif': 'image/gif',
|
|
147
|
+
'.svg': 'image/svg+xml'
|
|
148
|
+
};
|
|
149
|
+
res.header('Content-Type', contentTypes[ext] || 'application/octet-stream');
|
|
150
|
+
const fileBuffer = await fs_1.default.promises.readFile(filePath);
|
|
151
|
+
res.send(fileBuffer);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
// --- SISTEMA DE CACHE EM DISCO (TEMPORÁRIO EM .vatts) ---
|
|
156
|
+
const cacheDir = path_1.default.join(projectDir, '.vatts', 'cache', 'images');
|
|
157
|
+
// Garante que a pasta existe (síncrono na primeira vez é ok, ou async)
|
|
158
|
+
if (!fs_1.default.existsSync(cacheDir)) {
|
|
159
|
+
fs_1.default.mkdirSync(cacheDir, { recursive: true });
|
|
160
|
+
}
|
|
161
|
+
const width = widthStr ? parseInt(widthStr, 10) : undefined;
|
|
162
|
+
const height = heightStr ? parseInt(heightStr, 10) : undefined;
|
|
163
|
+
const quality = qualityStr ? parseInt(qualityStr, 10) : 75;
|
|
164
|
+
// Gera um hash único baseado em TODOS os parâmetros
|
|
165
|
+
// Ex: /img.png?w=100&h=200&q=80 -> hash unico
|
|
166
|
+
const cacheKey = `${imageUrl}?w=${width}&h=${height}&q=${quality}`;
|
|
167
|
+
const hash = crypto_1.default.createHash('md5').update(cacheKey).digest('hex');
|
|
168
|
+
// Define a extensão do arquivo de cache
|
|
169
|
+
const extOriginal = path_1.default.extname(filePath).toLowerCase();
|
|
170
|
+
let extOutput = '.webp'; // Padrão é converter para WebP
|
|
171
|
+
// Exceções que não viram WebP
|
|
172
|
+
if (extOriginal === '.svg' || extOriginal === '.gif') {
|
|
173
|
+
extOutput = extOriginal;
|
|
174
|
+
}
|
|
175
|
+
const cachedFilePath = path_1.default.join(cacheDir, `${hash}${extOutput}`);
|
|
176
|
+
// 1. VERIFICA SE JÁ EXISTE NO CACHE
|
|
177
|
+
if (fs_1.default.existsSync(cachedFilePath)) {
|
|
178
|
+
// Serve direto do cache (Disco)
|
|
179
|
+
// console.log(`[Vatts] Serving cached image: ${imageUrl}`);
|
|
180
|
+
const contentTypes = {
|
|
181
|
+
'.webp': 'image/webp',
|
|
182
|
+
'.svg': 'image/svg+xml',
|
|
183
|
+
'.gif': 'image/gif'
|
|
184
|
+
};
|
|
185
|
+
res.header('Content-Type', contentTypes[extOutput] || 'application/octet-stream');
|
|
186
|
+
const cachedBuffer = await fs_1.default.promises.readFile(cachedFilePath);
|
|
187
|
+
res.send(cachedBuffer);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
// 2. SE NÃO EXISTIR, PROCESSA COM SHARP
|
|
191
|
+
// console.log(`[Vatts] Processing image: ${imageUrl}`);
|
|
192
|
+
const transformer = sharp(filePath);
|
|
193
|
+
transformer.rotate();
|
|
194
|
+
const isValidWidth = width && !isNaN(width);
|
|
195
|
+
const isValidHeight = height && !isNaN(height);
|
|
196
|
+
if (isValidWidth || isValidHeight) {
|
|
197
|
+
transformer.resize(isValidWidth ? width : null, isValidHeight ? height : null, { withoutEnlargement: true });
|
|
198
|
+
}
|
|
199
|
+
if (extOriginal === '.png' || extOriginal === '.jpg' || extOriginal === '.jpeg' || extOriginal === '.webp') {
|
|
200
|
+
transformer.webp({ quality });
|
|
201
|
+
res.header('Content-Type', 'image/webp');
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
// Outros tipos mantêm original
|
|
205
|
+
const contentTypes = {
|
|
206
|
+
'.svg': 'image/svg+xml',
|
|
207
|
+
'.gif': 'image/gif'
|
|
208
|
+
};
|
|
209
|
+
res.header('Content-Type', contentTypes[extOriginal] || 'application/octet-stream');
|
|
210
|
+
}
|
|
211
|
+
const optimizedBuffer = await transformer.toBuffer();
|
|
212
|
+
// 3. SALVA NO CACHE PARA A PRÓXIMA VEZ
|
|
213
|
+
// Escreve em background para não bloquear totalmente, mas aguarda para segurança
|
|
214
|
+
try {
|
|
215
|
+
await fs_1.default.promises.writeFile(cachedFilePath, optimizedBuffer);
|
|
216
|
+
}
|
|
217
|
+
catch (writeErr) {
|
|
218
|
+
console_1.default.error('Failed to write image cache:', writeErr);
|
|
219
|
+
}
|
|
220
|
+
res.send(optimizedBuffer);
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
console_1.default.error('Error optimizing image:', error);
|
|
224
|
+
res.status(500).text('Image optimization failed');
|
|
225
|
+
}
|
|
226
|
+
}
|
|
93
227
|
// Exporta os adapters para uso manual se necessário
|
|
94
228
|
var express_2 = require("./adapters/express");
|
|
95
229
|
Object.defineProperty(exports, "ExpressAdapter", { enumerable: true, get: function () { return express_2.ExpressAdapter; } });
|
|
@@ -332,7 +466,8 @@ function vatts(options) {
|
|
|
332
466
|
genericReq.hotReloadManager = hotReloadManager;
|
|
333
467
|
const { hostname } = req.headers;
|
|
334
468
|
const method = (genericReq.method || 'GET').toUpperCase();
|
|
335
|
-
const
|
|
469
|
+
const urlObj = new URL(genericReq.url, `http://${hostname}:${port}`);
|
|
470
|
+
const pathname = urlObj.pathname;
|
|
336
471
|
if (pathname === types_1.RPC_ENDPOINT && method === 'POST') {
|
|
337
472
|
try {
|
|
338
473
|
const result = await (0, server_1.executeRpc)({
|
|
@@ -352,6 +487,12 @@ function vatts(options) {
|
|
|
352
487
|
if (pathname === '/hweb-hotreload/' && genericReq.headers.upgrade === 'websocket' && hotReloadManager) {
|
|
353
488
|
return;
|
|
354
489
|
}
|
|
490
|
+
// --- SISTEMA DE OTIMIZAÇÃO DE IMAGEM ---
|
|
491
|
+
if (pathname.includes('/_vatts/image')) {
|
|
492
|
+
await handleImageOptimization(genericReq, genericRes, dir);
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
// ---------------------------------------
|
|
355
496
|
if (pathname !== '/' && !pathname.startsWith('/api/') && !pathname.startsWith('/.vatts')) {
|
|
356
497
|
const publicDir = path_1.default.join(dir, 'public');
|
|
357
498
|
if (!isSuspiciousPathname(pathname)) {
|
package/dist/renderer.js
CHANGED
|
@@ -10,6 +10,7 @@ const server_1 = require("react-dom/server");
|
|
|
10
10
|
const router_1 = require("./router");
|
|
11
11
|
const fs_1 = __importDefault(require("fs"));
|
|
12
12
|
const path_1 = __importDefault(require("path"));
|
|
13
|
+
const BuildingPage_1 = __importDefault(require("./client/BuildingPage"));
|
|
13
14
|
// --- Helpers de Servidor ---
|
|
14
15
|
// Função auxiliar para importar módulos ignorando CSS (mesma lógica do router.ts)
|
|
15
16
|
function requireWithoutStyles(modulePath) {
|
|
@@ -241,8 +242,13 @@ async function renderAsStream({ req, res, route, params, allRoutes }) {
|
|
|
241
242
|
if (!assets || assets.scripts.length === 0) {
|
|
242
243
|
// Se falhar o build, restauramos o console para o erro aparecer se necessário
|
|
243
244
|
restoreConsole();
|
|
244
|
-
|
|
245
|
-
|
|
245
|
+
// Usando stream para a tela de loading também, agora via React Component
|
|
246
|
+
const { pipe } = (0, server_1.renderToPipeableStream)((0, jsx_runtime_1.jsx)(BuildingPage_1.default, {}), {
|
|
247
|
+
onShellReady() {
|
|
248
|
+
res.setHeader('Content-Type', 'text/html');
|
|
249
|
+
pipe(res);
|
|
250
|
+
}
|
|
251
|
+
});
|
|
246
252
|
return;
|
|
247
253
|
}
|
|
248
254
|
// 2. Preparar Layout
|
|
@@ -343,267 +349,3 @@ async function renderAsStream({ req, res, route, params, allRoutes }) {
|
|
|
343
349
|
async function render(options) {
|
|
344
350
|
return "";
|
|
345
351
|
}
|
|
346
|
-
// Função para retornar HTML de "Build em andamento" com auto-refresh
|
|
347
|
-
function getBuildingHTML() {
|
|
348
|
-
let version = "1.0.0";
|
|
349
|
-
try {
|
|
350
|
-
version = require("../package.json").version;
|
|
351
|
-
}
|
|
352
|
-
catch (e) { }
|
|
353
|
-
return `
|
|
354
|
-
<!DOCTYPE html>
|
|
355
|
-
<html lang="en">
|
|
356
|
-
<head>
|
|
357
|
-
<meta charset="UTF-8">
|
|
358
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
359
|
-
<title>Vatts.js | Building...</title>
|
|
360
|
-
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
361
|
-
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
362
|
-
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700;900&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
363
|
-
<style>
|
|
364
|
-
:root {
|
|
365
|
-
--bg-solid: #0d0d0d;
|
|
366
|
-
--card-bg: rgba(10, 10, 12, 0.95);
|
|
367
|
-
/* CORES ALTERADAS: Cyan para Laranja/Vermelho */
|
|
368
|
-
--primary: #ff6b35;
|
|
369
|
-
--primary-glow: rgba(255, 107, 53, 0.5);
|
|
370
|
-
--text-main: #f8fafc;
|
|
371
|
-
--text-muted: #94a3b8;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
body {
|
|
375
|
-
margin: 0;
|
|
376
|
-
padding: 0;
|
|
377
|
-
width: 100vw;
|
|
378
|
-
height: 100vh;
|
|
379
|
-
background-color: var(--bg-solid);
|
|
380
|
-
font-family: 'Inter', sans-serif;
|
|
381
|
-
color: var(--text-main);
|
|
382
|
-
overflow: hidden;
|
|
383
|
-
position: relative;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
/* Centralização Absoluta Perfeita */
|
|
387
|
-
.container {
|
|
388
|
-
position: absolute;
|
|
389
|
-
top: 50%;
|
|
390
|
-
left: 50%;
|
|
391
|
-
transform: translate(-50%, -50%);
|
|
392
|
-
display: flex;
|
|
393
|
-
justify-content: center;
|
|
394
|
-
align-items: center;
|
|
395
|
-
width: 100%;
|
|
396
|
-
pointer-events: none;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
.build-card {
|
|
400
|
-
pointer-events: auto;
|
|
401
|
-
position: relative;
|
|
402
|
-
width: 100%;
|
|
403
|
-
max-width: 420px;
|
|
404
|
-
background: var(--card-bg);
|
|
405
|
-
/* COR ALTERADA: Borda laranja sutil */
|
|
406
|
-
box-shadow: 0 0 0 1px rgba(255, 107, 53, 0.15), 0 40px 80px -20px rgba(0, 0, 0, 0.8);
|
|
407
|
-
border-radius: 20px;
|
|
408
|
-
overflow: hidden;
|
|
409
|
-
display: flex;
|
|
410
|
-
flex-direction: column;
|
|
411
|
-
align-items: center;
|
|
412
|
-
text-align: center;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
.neon-line {
|
|
417
|
-
height: 1px;
|
|
418
|
-
width: 100%;
|
|
419
|
-
/* COR ALTERADA: Gradiente Laranja/Vermelho */
|
|
420
|
-
background: linear-gradient(90deg, transparent, #e85d04, #ff6b35, transparent);
|
|
421
|
-
box-shadow: 0 0 15px var(--primary-glow);
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
.content {
|
|
425
|
-
padding: 40px 32px;
|
|
426
|
-
width: 100%;
|
|
427
|
-
box-sizing: border-box;
|
|
428
|
-
display: flex;
|
|
429
|
-
flex-direction: column;
|
|
430
|
-
align-items: center;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
/* Logo Animation */
|
|
434
|
-
.logo-wrapper {
|
|
435
|
-
position: relative;
|
|
436
|
-
margin-bottom: 24px;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
.logo-wrapper img {
|
|
440
|
-
width: 64px;
|
|
441
|
-
height: 64px;
|
|
442
|
-
object-fit: contain;
|
|
443
|
-
position: relative;
|
|
444
|
-
z-index: 2;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
.logo-glow {
|
|
448
|
-
position: absolute;
|
|
449
|
-
top: 50%;
|
|
450
|
-
left: 50%;
|
|
451
|
-
transform: translate(-50%, -50%);
|
|
452
|
-
width: 100%;
|
|
453
|
-
height: 100%;
|
|
454
|
-
/* COR ALTERADA: Brilho da logo */
|
|
455
|
-
background: var(--primary);
|
|
456
|
-
filter: blur(25px);
|
|
457
|
-
opacity: 0.2;
|
|
458
|
-
border-radius: 50%;
|
|
459
|
-
animation: pulse 2s ease-in-out infinite;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
h1 {
|
|
463
|
-
margin: 0;
|
|
464
|
-
font-size: 2rem;
|
|
465
|
-
font-weight: 800;
|
|
466
|
-
letter-spacing: -0.03em;
|
|
467
|
-
background: linear-gradient(180deg, #ffffff 0%, #94a3b8 100%);
|
|
468
|
-
-webkit-background-clip: text;
|
|
469
|
-
-webkit-text-fill-color: transparent;
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
h1 span {
|
|
473
|
-
/* COR ALTERADA: ".js" */
|
|
474
|
-
color: var(--primary);
|
|
475
|
-
-webkit-text-fill-color: var(--primary);
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
p {
|
|
479
|
-
margin: 8px 0 32px 0;
|
|
480
|
-
color: var(--text-muted);
|
|
481
|
-
font-size: 0.9rem;
|
|
482
|
-
font-weight: 500;
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
/* Terminal de Progresso Falso */
|
|
486
|
-
.terminal-box {
|
|
487
|
-
width: 100%;
|
|
488
|
-
background: rgba(0, 0, 0, 0.4);
|
|
489
|
-
border: 1px solid rgba(255, 255, 255, 0.05);
|
|
490
|
-
border-radius: 12px;
|
|
491
|
-
padding: 16px;
|
|
492
|
-
text-align: left;
|
|
493
|
-
font-family: 'JetBrains Mono', monospace;
|
|
494
|
-
font-size: 0.75rem;
|
|
495
|
-
color: #64748b;
|
|
496
|
-
box-sizing: border-box;
|
|
497
|
-
display: flex;
|
|
498
|
-
flex-direction: column;
|
|
499
|
-
gap: 8px;
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
.term-line {
|
|
503
|
-
display: flex;
|
|
504
|
-
align-items: center;
|
|
505
|
-
gap: 8px;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
.term-spinner {
|
|
509
|
-
width: 10px;
|
|
510
|
-
height: 10px;
|
|
511
|
-
/* COR ALTERADA: Spinner animado */
|
|
512
|
-
border: 2px solid rgba(255, 107, 53, 0.2);
|
|
513
|
-
border-top-color: var(--primary);
|
|
514
|
-
border-radius: 50%;
|
|
515
|
-
animation: spin 0.6s linear infinite;
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
.file-name { color: var(--text-muted); }
|
|
519
|
-
/* COR ALTERADA: Texto de destaque no terminal */
|
|
520
|
-
.accent { color: var(--primary); }
|
|
521
|
-
|
|
522
|
-
/* Footer Status */
|
|
523
|
-
.card-footer {
|
|
524
|
-
width: 100%;
|
|
525
|
-
padding: 12px 32px;
|
|
526
|
-
background: rgba(0,0,0,0.3);
|
|
527
|
-
border-top: 1px solid rgba(255,255,255,0.03);
|
|
528
|
-
display: flex;
|
|
529
|
-
justify-content: space-between;
|
|
530
|
-
align-items: center;
|
|
531
|
-
font-size: 11px;
|
|
532
|
-
color: rgba(255,255,255,0.2);
|
|
533
|
-
box-sizing: border-box;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
.status-active {
|
|
537
|
-
display: flex;
|
|
538
|
-
align-items: center;
|
|
539
|
-
gap: 6px;
|
|
540
|
-
/* COR ALTERADA: Texto Hot Reload */
|
|
541
|
-
color: var(--primary);
|
|
542
|
-
font-weight: 600;
|
|
543
|
-
text-transform: uppercase;
|
|
544
|
-
letter-spacing: 0.05em;
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
.dot {
|
|
548
|
-
width: 6px;
|
|
549
|
-
height: 6px;
|
|
550
|
-
/* COR ALTERADA: Pontinho brilhante */
|
|
551
|
-
background-color: var(--primary);
|
|
552
|
-
border-radius: 50%;
|
|
553
|
-
box-shadow: 0 0 8px var(--primary);
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
@keyframes pulse {
|
|
557
|
-
0%, 100% { opacity: 0.15; transform: translate(-50%, -50%) scale(1); }
|
|
558
|
-
50% { opacity: 0.25; transform: translate(-50%, -50%) scale(1.2); }
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
@keyframes spin {
|
|
562
|
-
to { transform: rotate(360deg); }
|
|
563
|
-
}
|
|
564
|
-
</style>
|
|
565
|
-
</head>
|
|
566
|
-
<body>
|
|
567
|
-
<div class="container">
|
|
568
|
-
<div class="build-card">
|
|
569
|
-
<div class="neon-line"></div>
|
|
570
|
-
|
|
571
|
-
<div class="content">
|
|
572
|
-
<div class="logo-wrapper">
|
|
573
|
-
<div class="logo-glow"></div>
|
|
574
|
-
<img src="https://raw.githubusercontent.com/mfrazlab/vatts.js/master/docs/public/logo-v.png" alt="Vatts Logo">
|
|
575
|
-
</div>
|
|
576
|
-
|
|
577
|
-
<h1>Vatts<span>.js</span></h1>
|
|
578
|
-
<p>Building your masterpiece...</p>
|
|
579
|
-
|
|
580
|
-
<div class="terminal-box">
|
|
581
|
-
<div class="term-line">
|
|
582
|
-
<div class="term-spinner"></div>
|
|
583
|
-
<span class="file-name">Compiling <span class="accent">src/vatts.ts</span>...</span>
|
|
584
|
-
</div>
|
|
585
|
-
<div class="term-line" style="opacity: 0.5;">
|
|
586
|
-
<span>✓</span>
|
|
587
|
-
<span class="file-name">Optimizing assets</span>
|
|
588
|
-
</div>
|
|
589
|
-
</div>
|
|
590
|
-
</div>
|
|
591
|
-
|
|
592
|
-
<div class="card-footer">
|
|
593
|
-
<span>Building...</span>
|
|
594
|
-
<div class="status-active">
|
|
595
|
-
<div class="dot"></div>
|
|
596
|
-
v${version}
|
|
597
|
-
</div>
|
|
598
|
-
</div>
|
|
599
|
-
</div>
|
|
600
|
-
</div>
|
|
601
|
-
|
|
602
|
-
<script>
|
|
603
|
-
setTimeout(() => {
|
|
604
|
-
window.location.reload();
|
|
605
|
-
}, 2500);
|
|
606
|
-
</script>
|
|
607
|
-
</body>
|
|
608
|
-
</html>`;
|
|
609
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vatts",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "Vatts.js is a high-level framework for building web applications with ease and speed. It provides a robust set of tools and features to streamline development and enhance productivity.",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"author": "itsmuzin",
|
|
@@ -80,6 +80,7 @@
|
|
|
80
80
|
"commander": "^14.0.2",
|
|
81
81
|
"rollup": "^4.55.2",
|
|
82
82
|
"rollup-plugin-esbuild": "^6.2.1",
|
|
83
|
+
"sharp": "^0.34.5",
|
|
83
84
|
"ts-loader": "9.5.4",
|
|
84
85
|
"ts-node": "^10.9.2",
|
|
85
86
|
"typescript": "^5.9.3",
|
|
@@ -94,7 +95,8 @@
|
|
|
94
95
|
"@types/express": "^4.17.25",
|
|
95
96
|
"@types/react": "^19.2.9",
|
|
96
97
|
"@types/react-dom": "^19.2.3",
|
|
97
|
-
"@types/ws": "^8.18.1"
|
|
98
|
+
"@types/ws": "^8.18.1",
|
|
99
|
+
"image-size": "^2.0.2"
|
|
98
100
|
},
|
|
99
101
|
"scripts": {
|
|
100
102
|
"build": "tsc"
|