vatts 1.0.2-alpha.2 → 1.0.2-alpha.4
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/bin/vatts.js +91 -100
- package/dist/builder.js +111 -123
- package/dist/client/clientRouter.d.ts +11 -54
- package/dist/client/clientRouter.js +39 -94
- package/dist/client/rpc.d.ts +1 -1
- package/dist/client/rpc.js +19 -2
- package/dist/env/env.d.ts +5 -0
- package/dist/env/env.js +69 -0
- package/dist/helpers.js +4 -1
- package/dist/index.js +44 -86
- package/dist/renderer.d.ts +3 -1
- package/dist/renderer.js +151 -170
- package/dist/types.d.ts +5 -0
- package/package.json +1 -1
package/dist/renderer.js
CHANGED
|
@@ -3,57 +3,65 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.renderAsStream = renderAsStream;
|
|
6
7
|
exports.render = render;
|
|
8
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
9
|
+
const server_1 = require("react-dom/server");
|
|
7
10
|
const router_1 = require("./router");
|
|
8
11
|
const fs_1 = __importDefault(require("fs"));
|
|
9
12
|
const path_1 = __importDefault(require("path"));
|
|
10
|
-
//
|
|
13
|
+
// --- Helpers de Servidor ---
|
|
14
|
+
// Função auxiliar para importar módulos ignorando CSS (mesma lógica do router.ts)
|
|
15
|
+
function requireWithoutStyles(modulePath) {
|
|
16
|
+
const extensions = ['.css', '.scss', '.sass', '.less', '.png', '.jpg', '.jpeg', '.gif', '.svg'];
|
|
17
|
+
const originalHandlers = {};
|
|
18
|
+
extensions.forEach(ext => {
|
|
19
|
+
originalHandlers[ext] = require.extensions[ext];
|
|
20
|
+
require.extensions[ext] = (m, filename) => {
|
|
21
|
+
m.exports = {};
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
try {
|
|
25
|
+
const resolved = require.resolve(modulePath);
|
|
26
|
+
if (require.cache[resolved])
|
|
27
|
+
delete require.cache[resolved];
|
|
28
|
+
return require(modulePath);
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
return require(modulePath);
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
extensions.forEach(ext => {
|
|
35
|
+
if (originalHandlers[ext]) {
|
|
36
|
+
require.extensions[ext] = originalHandlers[ext];
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
delete require.extensions[ext];
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// --- Funções de Metadata e Scripts ---
|
|
11
45
|
function generateMetaTags(metadata) {
|
|
12
46
|
const tags = [];
|
|
13
|
-
// Charset
|
|
14
47
|
tags.push(`<meta charset="${metadata.charset || 'UTF-8'}">`);
|
|
15
|
-
// Viewport
|
|
16
48
|
tags.push(`<meta name="viewport" content="${metadata.viewport || 'width=device-width, initial-scale=1.0'}">`);
|
|
17
|
-
|
|
18
|
-
if (metadata.description) {
|
|
49
|
+
if (metadata.description)
|
|
19
50
|
tags.push(`<meta name="description" content="${metadata.description}">`);
|
|
20
|
-
}
|
|
21
|
-
// Keywords
|
|
22
51
|
if (metadata.keywords) {
|
|
23
|
-
const keywordsStr = Array.isArray(metadata.keywords)
|
|
24
|
-
? metadata.keywords.join(', ')
|
|
25
|
-
: metadata.keywords;
|
|
52
|
+
const keywordsStr = Array.isArray(metadata.keywords) ? metadata.keywords.join(', ') : metadata.keywords;
|
|
26
53
|
tags.push(`<meta name="keywords" content="${keywordsStr}">`);
|
|
27
54
|
}
|
|
28
|
-
|
|
29
|
-
if (metadata.author) {
|
|
55
|
+
if (metadata.author)
|
|
30
56
|
tags.push(`<meta name="author" content="${metadata.author}">`);
|
|
31
|
-
|
|
32
|
-
// Theme color
|
|
33
|
-
if (metadata.themeColor) {
|
|
57
|
+
if (metadata.themeColor)
|
|
34
58
|
tags.push(`<meta name="theme-color" content="${metadata.themeColor}">`);
|
|
35
|
-
|
|
36
|
-
// Robots
|
|
37
|
-
if (metadata.robots) {
|
|
59
|
+
if (metadata.robots)
|
|
38
60
|
tags.push(`<meta name="robots" content="${metadata.robots}">`);
|
|
39
|
-
|
|
40
|
-
// Canonical
|
|
41
|
-
if (metadata.canonical) {
|
|
61
|
+
if (metadata.canonical)
|
|
42
62
|
tags.push(`<link rel="canonical" href="${metadata.canonical}">`);
|
|
43
|
-
|
|
44
|
-
// Favicon
|
|
45
|
-
if (metadata.favicon) {
|
|
63
|
+
if (metadata.favicon)
|
|
46
64
|
tags.push(`<link rel="icon" href="${metadata.favicon}">`);
|
|
47
|
-
}
|
|
48
|
-
// Apple Touch Icon
|
|
49
|
-
if (metadata.appleTouchIcon) {
|
|
50
|
-
tags.push(`<link rel="apple-touch-icon" href="${metadata.appleTouchIcon}">`);
|
|
51
|
-
}
|
|
52
|
-
// Manifest
|
|
53
|
-
if (metadata.manifest) {
|
|
54
|
-
tags.push(`<link rel="manifest" href="${metadata.manifest}">`);
|
|
55
|
-
}
|
|
56
|
-
// Open Graph
|
|
57
65
|
if (metadata.openGraph) {
|
|
58
66
|
const og = metadata.openGraph;
|
|
59
67
|
if (og.title)
|
|
@@ -64,44 +72,11 @@ function generateMetaTags(metadata) {
|
|
|
64
72
|
tags.push(`<meta property="og:type" content="${og.type}">`);
|
|
65
73
|
if (og.url)
|
|
66
74
|
tags.push(`<meta property="og:url" content="${og.url}">`);
|
|
67
|
-
if (og.siteName)
|
|
68
|
-
tags.push(`<meta property="og:site_name" content="${og.siteName}">`);
|
|
69
|
-
if (og.locale)
|
|
70
|
-
tags.push(`<meta property="og:locale" content="${og.locale}">`);
|
|
71
75
|
if (og.image) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
tags.push(`<meta property="og:image" content="${og.image.url}">`);
|
|
77
|
-
if (og.image.width)
|
|
78
|
-
tags.push(`<meta property="og:image:width" content="${og.image.width}">`);
|
|
79
|
-
if (og.image.height)
|
|
80
|
-
tags.push(`<meta property="og:image:height" content="${og.image.height}">`);
|
|
81
|
-
if (og.image.alt)
|
|
82
|
-
tags.push(`<meta property="og:image:alt" content="${og.image.alt}">`);
|
|
83
|
-
}
|
|
76
|
+
const imgUrl = typeof og.image === 'string' ? og.image : og.image.url;
|
|
77
|
+
tags.push(`<meta property="og:image" content="${imgUrl}">`);
|
|
84
78
|
}
|
|
85
79
|
}
|
|
86
|
-
// Twitter Card
|
|
87
|
-
if (metadata.twitter) {
|
|
88
|
-
const tw = metadata.twitter;
|
|
89
|
-
if (tw.card)
|
|
90
|
-
tags.push(`<meta name="twitter:card" content="${tw.card}">`);
|
|
91
|
-
if (tw.site)
|
|
92
|
-
tags.push(`<meta name="twitter:site" content="${tw.site}">`);
|
|
93
|
-
if (tw.creator)
|
|
94
|
-
tags.push(`<meta name="twitter:creator" content="${tw.creator}">`);
|
|
95
|
-
if (tw.title)
|
|
96
|
-
tags.push(`<meta name="twitter:title" content="${tw.title}">`);
|
|
97
|
-
if (tw.description)
|
|
98
|
-
tags.push(`<meta name="twitter:description" content="${tw.description}">`);
|
|
99
|
-
if (tw.image)
|
|
100
|
-
tags.push(`<meta name="twitter:image" content="${tw.image}">`);
|
|
101
|
-
if (tw.imageAlt)
|
|
102
|
-
tags.push(`<meta name="twitter:image:alt" content="${tw.imageAlt}">`);
|
|
103
|
-
}
|
|
104
|
-
// Custom meta tags
|
|
105
80
|
if (metadata.other) {
|
|
106
81
|
for (const [key, value] of Object.entries(metadata.other)) {
|
|
107
82
|
tags.push(`<meta name="${key}" content="${value}">`);
|
|
@@ -109,39 +84,83 @@ function generateMetaTags(metadata) {
|
|
|
109
84
|
}
|
|
110
85
|
return tags.join('\n');
|
|
111
86
|
}
|
|
112
|
-
// Função para ofuscar dados (não é criptografia, apenas ofuscação)
|
|
113
87
|
function obfuscateData(data) {
|
|
114
|
-
// 1. Serializa para JSON minificado
|
|
115
88
|
const jsonStr = JSON.stringify(data);
|
|
116
|
-
// 2. Converte para base64
|
|
117
89
|
const base64 = Buffer.from(jsonStr).toString('base64');
|
|
118
|
-
// 3. Adiciona um hash fake no início para parecer um token
|
|
119
90
|
const hash = Buffer.from(Date.now().toString()).toString('base64').substring(0, 8);
|
|
120
91
|
return `${hash}.${base64}`;
|
|
121
92
|
}
|
|
122
|
-
//
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
93
|
+
// Retorna as URLs dos scripts para o bootstrapModules do React
|
|
94
|
+
// Retorna null se não encontrar scripts (indica que o build ainda não terminou)
|
|
95
|
+
function getJavaScriptUrls(req) {
|
|
96
|
+
const projectDir = process.cwd();
|
|
97
|
+
const distDir = path_1.default.join(projectDir, '.vatts');
|
|
98
|
+
if (!fs_1.default.existsSync(distDir))
|
|
99
|
+
return null;
|
|
100
|
+
try {
|
|
101
|
+
const manifestPath = path_1.default.join(distDir, 'manifest.json');
|
|
102
|
+
if (fs_1.default.existsSync(manifestPath)) {
|
|
103
|
+
const manifest = JSON.parse(fs_1.default.readFileSync(manifestPath, 'utf8'));
|
|
104
|
+
const files = Object.values(manifest)
|
|
105
|
+
.filter((file) => file.endsWith('.js'))
|
|
106
|
+
.map((file) => `/_vatts/${file}`);
|
|
107
|
+
return files.length > 0 ? files : null;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
const jsFiles = fs_1.default.readdirSync(distDir)
|
|
111
|
+
.filter(file => file.endsWith('.js') && !file.endsWith('.map'))
|
|
112
|
+
.sort((a, b) => {
|
|
113
|
+
if (a.includes('main'))
|
|
114
|
+
return -1;
|
|
115
|
+
if (b.includes('main'))
|
|
116
|
+
return 1;
|
|
117
|
+
return a.localeCompare(b);
|
|
118
|
+
});
|
|
119
|
+
return jsFiles.length > 0 ? jsFiles.map(file => `/_vatts/${file}`) : null;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function ServerRoot({ lang, title, metaTagsHtml, initialDataScript, hotReloadScript, dataScript, children }) {
|
|
127
|
+
return ((0, jsx_runtime_1.jsxs)("html", { lang: lang, children: [(0, jsx_runtime_1.jsxs)("head", { children: [(0, jsx_runtime_1.jsx)("title", { children: title }), (0, jsx_runtime_1.jsx)("script", { dangerouslySetInnerHTML: { __html: initialDataScript } }), (0, jsx_runtime_1.jsx)("span", { dangerouslySetInnerHTML: { __html: metaTagsHtml } })] }), (0, jsx_runtime_1.jsxs)("body", { children: [dataScript, (0, jsx_runtime_1.jsx)("div", { id: "root", children: children }), hotReloadScript && (0, jsx_runtime_1.jsx)("span", { dangerouslySetInnerHTML: { __html: hotReloadScript } })] })] }));
|
|
127
128
|
}
|
|
128
|
-
async function
|
|
129
|
+
async function renderAsStream({ req, res, route, params, allRoutes }) {
|
|
129
130
|
const { generateMetadata } = route;
|
|
130
|
-
// Pega a opção dev e hot reload manager do req
|
|
131
131
|
const isProduction = !req.hwebDev;
|
|
132
132
|
const hotReloadManager = req.hotReloadManager;
|
|
133
|
-
//
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
133
|
+
// 1. Verificar Build - Se não tiver scripts, retorna tela de Loading
|
|
134
|
+
const bootstrapScripts = getJavaScriptUrls(req);
|
|
135
|
+
if (!bootstrapScripts) {
|
|
136
|
+
res.setHeader('Content-Type', 'text/html');
|
|
137
|
+
// Usamos .end() diretamente para garantir que a resposta seja enviada sem stream
|
|
138
|
+
res.end(getBuildingHTML());
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
// 2. Preparar Layout
|
|
142
|
+
const layoutInfo = (0, router_1.getLayout)();
|
|
143
|
+
let LayoutComponent = null;
|
|
144
|
+
if (layoutInfo) {
|
|
145
|
+
try {
|
|
146
|
+
// Recarrega o componente de layout para ter acesso à função (o router só guarda metadata)
|
|
147
|
+
const layoutModule = requireWithoutStyles(path_1.default.resolve(process.cwd(), layoutInfo.componentPath));
|
|
148
|
+
LayoutComponent = layoutModule.default;
|
|
149
|
+
}
|
|
150
|
+
catch (e) {
|
|
151
|
+
console.error("Error loading layout component for SSR:", e);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// 3. Preparar Metadata
|
|
155
|
+
let metadata = { title: 'Vatts App' };
|
|
156
|
+
if (layoutInfo && layoutInfo.metadata) {
|
|
157
|
+
metadata = { ...metadata, ...layoutInfo.metadata };
|
|
139
158
|
}
|
|
140
|
-
// Depois sobrescreve com metadata específico da rota se existir
|
|
141
159
|
if (generateMetadata) {
|
|
142
160
|
const routeMetadata = await Promise.resolve(generateMetadata(params, req));
|
|
143
161
|
metadata = { ...metadata, ...routeMetadata };
|
|
144
162
|
}
|
|
163
|
+
// 4. Preparar Dados Iniciais
|
|
145
164
|
const results = await Promise.all(allRoutes.map(async (r) => {
|
|
146
165
|
let routeMeta = {};
|
|
147
166
|
if (r.generateMetadata) {
|
|
@@ -153,99 +172,61 @@ async function render({ req, route, params, allRoutes }) {
|
|
|
153
172
|
metadata: routeMeta,
|
|
154
173
|
};
|
|
155
174
|
}));
|
|
156
|
-
// Prepara os dados para injetar na janela do navegador
|
|
157
175
|
const initialData = {
|
|
158
176
|
routes: results,
|
|
159
177
|
initialComponentPath: route.componentPath,
|
|
160
178
|
initialParams: params,
|
|
161
179
|
};
|
|
162
|
-
//
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
const
|
|
166
|
-
? hotReloadManager.getClientScript()
|
|
167
|
-
: '';
|
|
168
|
-
// Gera todas as meta tags
|
|
169
|
-
const metaTags = generateMetaTags(metadata);
|
|
170
|
-
// Determina quais arquivos JavaScript carregar
|
|
171
|
-
const jsFiles = getJavaScriptFiles(req);
|
|
180
|
+
// Scripts
|
|
181
|
+
const obfuscatedData = obfuscateData(initialData);
|
|
182
|
+
const hotReloadScript = !isProduction && hotReloadManager ? hotReloadManager.getClientScript() : '';
|
|
183
|
+
const metaTagsHtml = generateMetaTags(metadata);
|
|
172
184
|
const htmlLang = metadata.language || 'pt-BR';
|
|
173
|
-
//
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
</head>
|
|
180
|
-
<body>
|
|
181
|
-
<div id="root"></div>
|
|
182
|
-
${initialDataScript}
|
|
183
|
-
${jsFiles}
|
|
184
|
-
${hotReloadScript}
|
|
185
|
-
</body>
|
|
186
|
-
</html>`;
|
|
187
|
-
}
|
|
188
|
-
// Função para determinar quais arquivos JavaScript carregar
|
|
189
|
-
function getJavaScriptFiles(req) {
|
|
190
|
-
const projectDir = process.cwd();
|
|
191
|
-
const distDir = path_1.default.join(projectDir, '.vatts');
|
|
192
|
-
// Verifica se o diretório de build existe
|
|
193
|
-
if (!fs_1.default.existsSync(distDir)) {
|
|
194
|
-
// Diretório não existe - build ainda não foi executado
|
|
195
|
-
return getBuildingHTML();
|
|
185
|
+
// 5. Componente da Página Atual
|
|
186
|
+
const PageComponent = route.component;
|
|
187
|
+
// Monta a árvore da aplicação
|
|
188
|
+
let AppTree = (0, jsx_runtime_1.jsx)(PageComponent, { params: params });
|
|
189
|
+
if (LayoutComponent) {
|
|
190
|
+
AppTree = (0, jsx_runtime_1.jsx)(LayoutComponent, { children: AppTree });
|
|
196
191
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
//
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
.
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
192
|
+
// 6. Streaming
|
|
193
|
+
return new Promise((resolve, reject) => {
|
|
194
|
+
let didError = false;
|
|
195
|
+
const { pipe } = (0, server_1.renderToPipeableStream)((0, jsx_runtime_1.jsx)(ServerRoot, { lang: htmlLang, title: metadata.title || 'Vatts.js', metaTagsHtml: metaTagsHtml,
|
|
196
|
+
// Recriando o script de dados exatamente como o client espera
|
|
197
|
+
initialDataScript: `/* Data Injection */`, hotReloadScript: hotReloadScript, dataScript: (0, jsx_runtime_1.jsx)("script", { id: "__vatts_data__", type: "text/plain", "data-h": obfuscatedData }), children: AppTree }), {
|
|
198
|
+
// Usar bootstrapModules para scripts tipo módulo (ESM)
|
|
199
|
+
bootstrapModules: bootstrapScripts,
|
|
200
|
+
onShellReady() {
|
|
201
|
+
res.setHeader('Content-Type', 'text/html');
|
|
202
|
+
pipe(res);
|
|
203
|
+
resolve();
|
|
204
|
+
},
|
|
205
|
+
onShellError(error) {
|
|
206
|
+
console.error('Streaming Shell Error:', error);
|
|
207
|
+
res.statusCode = 500;
|
|
208
|
+
res.setHeader('Content-Type', 'text/html');
|
|
209
|
+
res.end('<h1>Internal Server Error</h1>');
|
|
210
|
+
resolve();
|
|
211
|
+
},
|
|
212
|
+
onError(error) {
|
|
213
|
+
didError = true;
|
|
214
|
+
console.error('Streaming Error:', error);
|
|
210
215
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
.sort((a, b) => {
|
|
218
|
-
// Ordena para carregar arquivos principais primeiro
|
|
219
|
-
if (a.includes('main'))
|
|
220
|
-
return -1;
|
|
221
|
-
if (b.includes('main'))
|
|
222
|
-
return 1;
|
|
223
|
-
if (a.includes('vendor') || a.includes('react'))
|
|
224
|
-
return -1;
|
|
225
|
-
if (b.includes('vendor') || b.includes('react'))
|
|
226
|
-
return 1;
|
|
227
|
-
return a.localeCompare(b);
|
|
228
|
-
});
|
|
229
|
-
// @ts-ignore
|
|
230
|
-
if (jsFiles.length >= 1) {
|
|
231
|
-
// Modo chunks sem manifesto
|
|
232
|
-
return jsFiles
|
|
233
|
-
.map(file => `<script type="module" src="/_vatts/${file}"></script>`)
|
|
234
|
-
.join('');
|
|
235
|
-
}
|
|
236
|
-
else {
|
|
237
|
-
// Nenhum arquivo JS encontrado - build em andamento ou erro
|
|
238
|
-
return getBuildingHTML();
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
catch (error) {
|
|
243
|
-
// Erro ao ler diretório - build em andamento ou erro
|
|
244
|
-
return getBuildingHTML();
|
|
245
|
-
}
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
// Mantemos a função antiga para compatibilidade
|
|
220
|
+
async function render(options) {
|
|
221
|
+
return "";
|
|
246
222
|
}
|
|
247
223
|
// Função para retornar HTML de "Build em andamento" com auto-refresh
|
|
248
224
|
function getBuildingHTML() {
|
|
225
|
+
let version = "1.0.0";
|
|
226
|
+
try {
|
|
227
|
+
version = require("../package.json").version;
|
|
228
|
+
}
|
|
229
|
+
catch (e) { }
|
|
249
230
|
return `
|
|
250
231
|
<!DOCTYPE html>
|
|
251
232
|
<html lang="en">
|
|
@@ -489,7 +470,7 @@ function getBuildingHTML() {
|
|
|
489
470
|
<span>Building...</span>
|
|
490
471
|
<div class="status-active">
|
|
491
472
|
<div class="dot"></div>
|
|
492
|
-
v${
|
|
473
|
+
v${version}
|
|
493
474
|
</div>
|
|
494
475
|
</div>
|
|
495
476
|
</div>
|
package/dist/types.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export interface VattsOptions {
|
|
|
26
26
|
cert: string;
|
|
27
27
|
ca?: string;
|
|
28
28
|
};
|
|
29
|
+
envFiles?: string[];
|
|
29
30
|
}
|
|
30
31
|
/**
|
|
31
32
|
* Interface para as configurações avançadas do servidor Vatts.js.
|
|
@@ -137,6 +138,10 @@ export interface VattsConfig {
|
|
|
137
138
|
* Exemplo: { 'X-Custom-Header': 'value', 'X-Powered-By': 'Vatts.js' }
|
|
138
139
|
*/
|
|
139
140
|
customHeaders?: Record<string, string>;
|
|
141
|
+
/**
|
|
142
|
+
* Arquivos .env adicionais para carregar. O .env padrão é sempre carregado.
|
|
143
|
+
*/
|
|
144
|
+
envFiles?: string[];
|
|
140
145
|
}
|
|
141
146
|
/**
|
|
142
147
|
* Tipo da função de configuração que pode ser exportada no vatts.config.js
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vatts",
|
|
3
|
-
"version": "1.0.2-alpha.
|
|
3
|
+
"version": "1.0.2-alpha.4",
|
|
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",
|