hightjs 0.5.0 → 0.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.
@@ -0,0 +1,252 @@
1
+ #!/usr/bin/env node
2
+
3
+ /*
4
+ * This file is part of the HightJS Project.
5
+ * Copyright (c) 2025 itsmuzin
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+
20
+
21
+ // Registra o ts-node para que o Node.js entenda TypeScript/TSX
22
+ require('ts-node').register();
23
+
24
+ // Registra loaders customizados para arquivos markdown, imagens, etc.
25
+ const { registerLoaders } = require('../loaders');
26
+ registerLoaders();
27
+
28
+ const { program } = require('commander');
29
+
30
+
31
+ program
32
+ .version('1.0.0')
33
+ .description('CLI to manage the application.');
34
+
35
+ // --- Comando DEV ---
36
+ const fs = require('fs');
37
+ const path = require('path');
38
+ // 'program' já deve estar definido no seu arquivo
39
+ // const { program } = require('commander');
40
+
41
+ /**
42
+ * Função centralizada para iniciar a aplicação
43
+ * @param {object} options - Opções vindas do commander
44
+ * @param {boolean} isDev - Define se é modo de desenvolvimento
45
+ */
46
+ function initializeApp(options, isDev) {
47
+ const appOptions = {
48
+ dev: isDev,
49
+ port: options.port,
50
+ hostname: options.hostname,
51
+ framework: 'native',
52
+ ssl: null, // Default
53
+ };
54
+
55
+ // 1. Verifica se a flag --ssl foi ativada
56
+ if (options.ssl) {
57
+ const C = require("../api/console")
58
+ const { Levels } = C;
59
+ const Console = C.default
60
+ const sslDir = path.resolve(process.cwd(), 'certs');
61
+ const keyPath = path.join(sslDir, 'key.pem'); // Padrão 1: key.pem
62
+ const certPath = path.join(sslDir, 'cert.pem'); // Padrão 2: cert.pem
63
+ // (Você pode mudar para 'cert.key' se preferir, apenas ajuste os nomes aqui)
64
+
65
+ // 2. Verifica se os arquivos existem
66
+ if (fs.existsSync(keyPath) && fs.existsSync(certPath)) {
67
+ appOptions.ssl = {
68
+ key: keyPath,
69
+ cert: certPath
70
+ };
71
+
72
+ // 3. Adiciona a porta de redirecionamento (útil para o initNativeServer)
73
+ appOptions.ssl.redirectPort = options.httpRedirectPort || 80;
74
+
75
+ } else {
76
+ Console.logWithout(Levels.ERROR, null, `Ensure that './certs/key.pem' and './certs/cert.pem' exist.`, `--ssl flag was used, but the files were not found.`)
77
+
78
+
79
+ process.exit(1); // Encerra o processo com erro
80
+ }
81
+ }
82
+
83
+ // 4. Inicia o helper com as opções
84
+ const teste = require("../helpers");
85
+ const t = teste.default(appOptions);
86
+ t.init();
87
+ }
88
+
89
+ // --- Comando DEV ---
90
+ program
91
+ .command('dev')
92
+ .description('Starts the application in development mode.')
93
+ .option('-p, --port <number>', 'Specifies the port to run on', '3000')
94
+ .option('-H, --hostname <string>', 'Specifies the hostname to run on', '0.0.0.0')
95
+ .option('--ssl', 'Activates HTTPS/SSL mode (requires ./ssl/key.pem and ./ssl/cert.pem)')
96
+ .option('--http-redirect-port <number>', 'Port for HTTP->HTTPS redirection', '80')
97
+ .action((options) => {
98
+ initializeApp(options, true); // Chama a função com dev: true
99
+ });
100
+
101
+ // --- Comando START (Produção) ---
102
+ program
103
+ .command('start')
104
+ .description('Starts the application in production mode.')
105
+ .option('-p, --port <number>', 'Specifies the port to run on', '3000')
106
+ .option('-H, --hostname <string>', 'Specifies the hostname to run on', '0.0.0.0')
107
+ .option('--ssl', 'Activates HTTPS/SSL mode (requires ./ssl/key.pem and ./ssl/cert.pem)')
108
+ .option('--http-redirect-port <number>', 'Port for HTTP->HTTPS redirection', '80')
109
+ .action((options) => {
110
+ initializeApp(options, false); // Chama a função com dev: false
111
+ });
112
+
113
+ /**
114
+ * Função corrigida para copiar diretórios recursivamente.
115
+ * Ela agora verifica se um item é um arquivo ou um diretório.
116
+ */
117
+ function copyDirRecursive(src, dest) {
118
+ try {
119
+ // Garante que o diretório de destino exista
120
+ fs.mkdirSync(dest, { recursive: true });
121
+
122
+ // Usamos { withFileTypes: true } para evitar uma chamada extra de fs.statSync
123
+ const entries = fs.readdirSync(src, { withFileTypes: true });
124
+
125
+ for (let entry of entries) {
126
+ const srcPath = path.join(src, entry.name);
127
+ const destPath = path.join(dest, entry.name);
128
+
129
+ if (entry.isDirectory()) {
130
+ // Se for um diretório, chama a si mesma (recursão)
131
+ copyDirRecursive(srcPath, destPath);
132
+ } else {
133
+ // Se for um arquivo, apenas copia
134
+ fs.copyFileSync(srcPath, destPath);
135
+ }
136
+ }
137
+ } catch (error) {
138
+ console.error(`❌ Erro ao copiar ${src} para ${dest}:`, error);
139
+ // Lança o erro para parar o processo de exportação se a cópia falhar
140
+ throw error;
141
+ }
142
+ }
143
+
144
+
145
+ // --- INÍCIO DO SEU CÓDIGO (AGORA CORRIGIDO) ---
146
+
147
+ program
148
+ .command('export')
149
+ .description('Exports the application as static HTML to the "exported" folder.')
150
+ .option('-o, --output <path>', 'Specifies the output directory', 'exported')
151
+ .action(async (options) => {
152
+ const projectDir = process.cwd();
153
+ // Usar path.resolve é mais seguro para garantir um caminho absoluto
154
+ const exportDir = path.resolve(projectDir, options.output);
155
+
156
+ console.log('🚀 Starting export...\n');
157
+
158
+ try {
159
+ // 1. Cria a pasta exported (limpa se já existir)
160
+ if (fs.existsSync(exportDir)) {
161
+ console.log('🗑️ Cleaning existing export folder...');
162
+ fs.rmSync(exportDir, { recursive: true, force: true });
163
+ }
164
+ fs.mkdirSync(exportDir, { recursive: true });
165
+ console.log('✅ Export folder created\n');
166
+
167
+ // 2. Inicializa e prepara o build
168
+ console.log('🔨 Building application...');
169
+ // ATENÇÃO: Ajuste o caminho deste 'require' conforme a estrutura do seu projeto!
170
+ const teste = require("../helpers");
171
+ const app = teste.default({ dev: false, port: 3000, hostname: '0.0.0.0', framework: 'native' });
172
+ await app.prepare();
173
+ console.log('✅ Build complete\n');
174
+
175
+ // 3. Copia a pasta .hight para exported (*** CORRIGIDO ***)
176
+ const distDir = path.join(projectDir, '.hight');
177
+ if (fs.existsSync(distDir)) {
178
+ console.log('📦 Copying JavaScript files...');
179
+ const exportDistDir = path.join(exportDir, '.hight');
180
+
181
+ // --- Lógica de cópia substituída ---
182
+ // A função copyDirRecursive agora lida com tudo (arquivos e subpastas)
183
+ copyDirRecursive(distDir, exportDistDir);
184
+ // --- Fim da substituição ---
185
+
186
+ console.log('✅ JavaScript files copied\n');
187
+ }
188
+
189
+ // 4. Copia a pasta public se existir (*** CORRIGIDO ***)
190
+ const publicDir = path.join(projectDir, 'public');
191
+ if (fs.existsSync(publicDir)) {
192
+ console.log('📁 Copying public files...');
193
+ const exportPublicDir = path.join(exportDir, 'public');
194
+
195
+ // --- Lógica de cópia substituída ---
196
+ // Reutilizamos a mesma função corrigida
197
+ copyDirRecursive(publicDir, exportPublicDir);
198
+ // --- Fim da substituição ---
199
+
200
+ console.log('✅ Public files copied\n');
201
+ }
202
+
203
+ // 5. Gera o index.html
204
+ console.log('📝 Generating index.html...');
205
+ // ATENÇÃO: Ajuste os caminhos destes 'requires' conforme a estrutura do seu projeto!
206
+ const { render } = require('../renderer');
207
+ const { loadRoutes, loadLayout, loadNotFound } = require('../router');
208
+
209
+ // Carrega as rotas para gerar o HTML
210
+ const userWebDir = path.join(projectDir, 'src', 'web');
211
+ const userWebRoutesDir = path.join(userWebDir, 'routes');
212
+
213
+ const routes = loadRoutes(userWebRoutesDir);
214
+ loadLayout(userWebDir);
215
+ loadNotFound(userWebDir);
216
+
217
+ // Gera HTML para a rota raiz
218
+ const rootRoute = routes.find(r => r.pattern === '/') || routes[0];
219
+
220
+ if (rootRoute) {
221
+ const mockReq = {
222
+ url: '/',
223
+ method: 'GET',
224
+ headers: { host: 'localhost' },
225
+ hwebDev: false,
226
+ hotReloadManager: null
227
+ };
228
+
229
+ const html = await render({
230
+ req: mockReq,
231
+ route: rootRoute,
232
+ params: {},
233
+ allRoutes: routes
234
+ });
235
+ const scriptReplaced = html.replace('/_hight/', './.hight/');
236
+ const indexPath = path.join(exportDir, 'index.html');
237
+ fs.writeFileSync(indexPath, scriptReplaced, 'utf8');
238
+ console.log('✅ index.html generated\n');
239
+ }
240
+
241
+ console.log('🎉 Export completed successfully!');
242
+ console.log(`📂 Files exported to: ${exportDir}\n`);
243
+
244
+ } catch (error) {
245
+ // Logar o erro completo (com stack trace) é mais útil
246
+ console.error('❌ Error during export:', error);
247
+ process.exit(1);
248
+ }
249
+ });
250
+
251
+ // Faz o "parse" dos argumentos passados na linha de comando
252
+ program.parse(process.argv);