hightjs 0.3.4 → 0.4.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/index.js CHANGED
@@ -110,48 +110,49 @@ function isLargeProject(projectDir) {
110
110
  }
111
111
  // Função para gerar o arquivo de entrada para o esbuild
112
112
  function createEntryFile(projectDir, routes) {
113
- const tempDir = path_1.default.join(projectDir, '.hweb');
114
- fs_1.default.mkdirSync(tempDir, { recursive: true });
115
- const entryFilePath = path_1.default.join(tempDir, 'entry.client.js');
116
- // Verifica se layout
117
- const layout = (0, router_1.getLayout)();
118
- // Verifica se notFound personalizado
119
- const notFound = (0, router_1.getNotFound)();
120
- // Gera imports dinâmicos para cada componente
121
- const imports = routes
122
- .map((route, index) => {
123
- const relativePath = path_1.default.relative(tempDir, route.componentPath).replace(/\\/g, '/');
124
- return `import route${index} from '${relativePath}';`;
125
- })
126
- .join('\n');
127
- // Import do layout se existir
128
- const layoutImport = layout
129
- ? `import LayoutComponent from '${path_1.default.relative(tempDir, layout.componentPath).replace(/\\/g, '/')}';`
130
- : '';
131
- // Import do notFound se existir
132
- const notFoundImport = notFound
133
- ? `import NotFoundComponent from '${path_1.default.relative(tempDir, notFound.componentPath).replace(/\\/g, '/')}';`
134
- : '';
135
- // Registra os componentes no window para o cliente acessar
136
- const componentRegistration = routes
137
- .map((route, index) => ` '${route.componentPath}': route${index}.component || route${index}.default?.component,`)
138
- .join('\n');
139
- // Registra o layout se existir
140
- const layoutRegistration = layout
141
- ? `window.__HWEB_LAYOUT__ = LayoutComponent.default || LayoutComponent;`
142
- : `window.__HWEB_LAYOUT__ = null;`;
143
- // Registra o notFound se existir
144
- const notFoundRegistration = notFound
145
- ? `window.__HWEB_NOT_FOUND__ = NotFoundComponent.default || NotFoundComponent;`
146
- : `window.__HWEB_NOT_FOUND__ = null;`;
147
- // Caminho correto para o entry.client.tsx
148
- const sdkDir = path_1.default.dirname(__dirname); // Vai para a pasta pai de src (onde está o hweb-sdk)
149
- const entryClientPath = path_1.default.join(sdkDir, 'src', 'client', 'entry.client.tsx');
150
- const relativeEntryPath = path_1.default.relative(tempDir, entryClientPath).replace(/\\/g, '/');
151
- // Import do DefaultNotFound do SDK
152
- const defaultNotFoundPath = path_1.default.join(sdkDir, 'src', 'client', 'DefaultNotFound.tsx');
153
- const relativeDefaultNotFoundPath = path_1.default.relative(tempDir, defaultNotFoundPath).replace(/\\/g, '/');
154
- const entryContent = `// Arquivo gerado automaticamente pelo hweb
113
+ try {
114
+ const tempDir = path_1.default.join(projectDir, '.hight', 'temp');
115
+ fs_1.default.mkdirSync(tempDir, { recursive: true });
116
+ const entryFilePath = path_1.default.join(tempDir, 'entry.client.js');
117
+ // Verifica se layout
118
+ const layout = (0, router_1.getLayout)();
119
+ // Verifica se notFound personalizado
120
+ const notFound = (0, router_1.getNotFound)();
121
+ // Gera imports dinâmicos para cada componente
122
+ const imports = routes
123
+ .map((route, index) => {
124
+ const relativePath = path_1.default.relative(tempDir, route.componentPath).replace(/\\/g, '/');
125
+ return `import route${index} from '${relativePath}';`;
126
+ })
127
+ .join('\n');
128
+ // Import do layout se existir
129
+ const layoutImport = layout
130
+ ? `import LayoutComponent from '${path_1.default.relative(tempDir, layout.componentPath).replace(/\\/g, '/')}';`
131
+ : '';
132
+ // Import do notFound se existir
133
+ const notFoundImport = notFound
134
+ ? `import NotFoundComponent from '${path_1.default.relative(tempDir, notFound.componentPath).replace(/\\/g, '/')}';`
135
+ : '';
136
+ // Registra os componentes no window para o cliente acessar
137
+ const componentRegistration = routes
138
+ .map((route, index) => ` '${route.componentPath}': route${index}.component || route${index}.default?.component,`)
139
+ .join('\n');
140
+ // Registra o layout se existir
141
+ const layoutRegistration = layout
142
+ ? `window.__HWEB_LAYOUT__ = LayoutComponent.default || LayoutComponent;`
143
+ : `window.__HWEB_LAYOUT__ = null;`;
144
+ // Registra o notFound se existir
145
+ const notFoundRegistration = notFound
146
+ ? `window.__HWEB_NOT_FOUND__ = NotFoundComponent.default || NotFoundComponent;`
147
+ : `window.__HWEB_NOT_FOUND__ = null;`;
148
+ // Caminho correto para o entry.client.tsx
149
+ const sdkDir = path_1.default.dirname(__dirname); // Vai para a pasta pai de src (onde está o hweb-sdk)
150
+ const entryClientPath = path_1.default.join(sdkDir, 'src', 'client', 'entry.client.tsx');
151
+ const relativeEntryPath = path_1.default.relative(tempDir, entryClientPath).replace(/\\/g, '/');
152
+ // Import do DefaultNotFound do SDK
153
+ const defaultNotFoundPath = path_1.default.join(sdkDir, 'src', 'client', 'DefaultNotFound.tsx');
154
+ const relativeDefaultNotFoundPath = path_1.default.relative(tempDir, defaultNotFoundPath).replace(/\\/g, '/');
155
+ const entryContent = `// Arquivo gerado automaticamente pelo hweb
155
156
  ${imports}
156
157
  ${layoutImport}
157
158
  ${notFoundImport}
@@ -174,8 +175,18 @@ window.__HWEB_DEFAULT_NOT_FOUND__ = DefaultNotFound;
174
175
  // Importa e executa o entry.client.tsx
175
176
  import '${relativeEntryPath}';
176
177
  `;
177
- fs_1.default.writeFileSync(entryFilePath, entryContent);
178
- return entryFilePath;
178
+ try {
179
+ fs_1.default.writeFileSync(entryFilePath, entryContent);
180
+ }
181
+ catch (e) {
182
+ console.error("sdfijnsdfnijfsdijnfsdnijsdfnijfsdnijfsdnijfsdn", e);
183
+ }
184
+ return entryFilePath;
185
+ }
186
+ catch (e) {
187
+ console_1.default.error("Error creating entry file:", e);
188
+ throw e;
189
+ }
179
190
  }
180
191
  function hweb(options) {
181
192
  const { dev = true, dir = process.cwd(), port = 3000 } = options;
@@ -183,7 +194,7 @@ function hweb(options) {
183
194
  process.hight = options;
184
195
  const userWebDir = path_1.default.join(dir, 'src', 'web');
185
196
  const userWebRoutesDir = path_1.default.join(userWebDir, 'routes');
186
- const userBackendRoutesDir = path_1.default.join(userWebDir, 'backend', 'routes');
197
+ const userBackendRoutesDir = path_1.default.join(dir, 'src', 'backend', 'routes');
187
198
  /**
188
199
  * Executa middlewares sequencialmente e depois o handler final
189
200
  * @param middlewares Array de middlewares para executar
@@ -260,7 +271,7 @@ function hweb(options) {
260
271
  // Carrega layout.tsx ANTES de criar o entry file
261
272
  const layout = (0, router_1.loadLayout)(userWebDir);
262
273
  const notFound = (0, router_1.loadNotFound)(userWebDir);
263
- const outDir = path_1.default.join(dir, 'hweb-dist');
274
+ const outDir = path_1.default.join(dir, '.hight');
264
275
  fs_1.default.mkdirSync(outDir, { recursive: true });
265
276
  entryPoint = createEntryFile(dir, frontendRoutes);
266
277
  clearInterval(spinner1);
@@ -280,6 +291,10 @@ function hweb(options) {
280
291
  clearInterval(spinner); // para o spinner
281
292
  time.update(""); // limpa a linha
282
293
  time.end(` ${console_1.Colors.BgGreen} build ${console_1.Colors.Reset} Client build completed in ${elapsed}ms`);
294
+ // Notifica o hot reload manager que o build foi concluído
295
+ if (hotReloadManager) {
296
+ hotReloadManager.onBuildComplete(true);
297
+ }
283
298
  }
284
299
  else {
285
300
  const time = console_1.default.dynamicLine(` ${console_1.Colors.BgYellow} watcher ${console_1.Colors.Reset} Starting client watch`);
@@ -330,7 +345,7 @@ function hweb(options) {
330
345
  return;
331
346
  }
332
347
  // 2. Primeiro verifica se é um arquivo estático da pasta public
333
- if (pathname !== '/' && !pathname.startsWith('/api/') && !pathname.startsWith('/hweb-')) {
348
+ if (pathname !== '/' && !pathname.startsWith('/api/') && !pathname.startsWith('/.hight')) {
334
349
  const publicDir = path_1.default.join(dir, 'public');
335
350
  const filePath = path_1.default.join(publicDir, pathname);
336
351
  if (fs_1.default.existsSync(filePath) && fs_1.default.statSync(filePath).isFile()) {
@@ -372,10 +387,10 @@ function hweb(options) {
372
387
  return;
373
388
  }
374
389
  }
375
- // 3. Verifica se é um arquivo estático do hweb-dist
376
- if (pathname.startsWith('/hweb-dist/')) {
377
- const staticPath = path_1.default.join(dir, 'hweb-dist');
378
- const filePath = path_1.default.join(staticPath, pathname.replace('/hweb-dist/', ''));
390
+ // 3. Verifica se é um arquivo estático do .hight
391
+ if (pathname.startsWith('/_hight/')) {
392
+ const staticPath = path_1.default.join(dir, '.hight');
393
+ const filePath = path_1.default.join(staticPath, pathname.replace('/_hight/', ''));
379
394
  if (fs_1.default.existsSync(filePath)) {
380
395
  const ext = path_1.default.extname(filePath).toLowerCase();
381
396
  const contentTypes = {
package/dist/renderer.js CHANGED
@@ -7,18 +7,123 @@ exports.render = render;
7
7
  const router_1 = require("./router");
8
8
  const fs_1 = __importDefault(require("fs"));
9
9
  const path_1 = __importDefault(require("path"));
10
- // Funções para codificar/decodificar dados (disfarça o JSON no HTML)
11
- function encodeInitialData(data) {
12
- // Converte para JSON, depois para base64, e adiciona um prefixo fake
10
+ // Função para gerar todas as meta tags
11
+ function generateMetaTags(metadata) {
12
+ const tags = [];
13
+ // Charset
14
+ tags.push(`<meta charset="${metadata.charset || 'UTF-8'}">`);
15
+ // Viewport
16
+ tags.push(`<meta name="viewport" content="${metadata.viewport || 'width=device-width, initial-scale=1.0'}">`);
17
+ // Description
18
+ if (metadata.description) {
19
+ tags.push(`<meta name="description" content="${metadata.description}">`);
20
+ }
21
+ // Keywords
22
+ if (metadata.keywords) {
23
+ const keywordsStr = Array.isArray(metadata.keywords)
24
+ ? metadata.keywords.join(', ')
25
+ : metadata.keywords;
26
+ tags.push(`<meta name="keywords" content="${keywordsStr}">`);
27
+ }
28
+ // Author
29
+ if (metadata.author) {
30
+ tags.push(`<meta name="author" content="${metadata.author}">`);
31
+ }
32
+ // Theme color
33
+ if (metadata.themeColor) {
34
+ tags.push(`<meta name="theme-color" content="${metadata.themeColor}">`);
35
+ }
36
+ // Robots
37
+ if (metadata.robots) {
38
+ tags.push(`<meta name="robots" content="${metadata.robots}">`);
39
+ }
40
+ // Canonical
41
+ if (metadata.canonical) {
42
+ tags.push(`<link rel="canonical" href="${metadata.canonical}">`);
43
+ }
44
+ // Favicon
45
+ if (metadata.favicon) {
46
+ 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
+ if (metadata.openGraph) {
58
+ const og = metadata.openGraph;
59
+ if (og.title)
60
+ tags.push(`<meta property="og:title" content="${og.title}">`);
61
+ if (og.description)
62
+ tags.push(`<meta property="og:description" content="${og.description}">`);
63
+ if (og.type)
64
+ tags.push(`<meta property="og:type" content="${og.type}">`);
65
+ if (og.url)
66
+ 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
+ if (og.image) {
72
+ if (typeof og.image === 'string') {
73
+ tags.push(`<meta property="og:image" content="${og.image}">`);
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
+ }
84
+ }
85
+ }
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
+ if (metadata.other) {
106
+ for (const [key, value] of Object.entries(metadata.other)) {
107
+ tags.push(`<meta name="${key}" content="${value}">`);
108
+ }
109
+ }
110
+ return tags.join('\n');
111
+ }
112
+ // Função para ofuscar dados (não é criptografia, apenas ofuscação)
113
+ function obfuscateData(data) {
114
+ // 1. Serializa para JSON minificado
13
115
  const jsonStr = JSON.stringify(data);
116
+ // 2. Converte para base64
14
117
  const base64 = Buffer.from(jsonStr).toString('base64');
15
- return `hweb_${base64}_config`;
118
+ // 3. Adiciona um hash fake no início para parecer um token
119
+ const hash = Buffer.from(Date.now().toString()).toString('base64').substring(0, 8);
120
+ return `${hash}.${base64}`;
16
121
  }
17
- function createDecodeScript() {
18
- return `
19
-
20
- window.__HWEB_DECODE__ = function(encoded) { const base64 = encoded.replace('hweb_', '').replace('_config', ''); const jsonStr = atob(base64); return JSON.parse(jsonStr); };
21
- `;
122
+ // Função para criar script ofuscado
123
+ function createInitialDataScript(data) {
124
+ const obfuscated = obfuscateData(data);
125
+ // Usa um atributo data-* ao invés de JSON visível
126
+ return `<script id="__hight_data__" type="text/plain" data-h="${obfuscated}"></script>`;
22
127
  }
23
128
  async function render({ req, route, params, allRoutes }) {
24
129
  const { generateMetadata } = route;
@@ -43,22 +148,36 @@ async function render({ req, route, params, allRoutes }) {
43
148
  initialComponentPath: route.componentPath,
44
149
  initialParams: params,
45
150
  };
46
- // Codifica os dados para disfarçar
47
- const encodedData = encodeInitialData(initialData);
151
+ // Cria script JSON limpo
152
+ const initialDataScript = createInitialDataScript(initialData);
48
153
  // Script de hot reload apenas em desenvolvimento
49
154
  const hotReloadScript = !isProduction && hotReloadManager
50
155
  ? hotReloadManager.getClientScript()
51
156
  : '';
52
- const favicon = metadata.favicon ? `<link rel="icon" href="${metadata.favicon}">` : '';
157
+ // Gera todas as meta tags
158
+ const metaTags = generateMetaTags(metadata);
53
159
  // Determina quais arquivos JavaScript carregar
54
160
  const jsFiles = getJavaScriptFiles(req);
161
+ const htmlLang = metadata.language || 'pt-BR';
55
162
  // HTML base sem SSR - apenas o container e scripts para client-side rendering
56
- return `<!DOCTYPE html><html lang="pt-BR"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>${metadata.title || 'App hweb'}</title>${metadata.description ? `<meta name="description" content="${metadata.description}">` : ''}${favicon}</head><body><div id="root"></div><script>${createDecodeScript()}window.__HWEB_INITIAL_DATA__ = window.__HWEB_DECODE__('${encodedData}');</script>${jsFiles}${hotReloadScript}</body></html>`;
163
+ return `<!DOCTYPE html>
164
+ <html lang="${htmlLang}">
165
+ <head>
166
+ ${metaTags}
167
+ <title>${metadata.title || 'App hweb'}</title>
168
+ </head>
169
+ <body>
170
+ <div id="root"></div>
171
+ ${initialDataScript}
172
+ ${jsFiles}
173
+ ${hotReloadScript}
174
+ </body>
175
+ </html>`;
57
176
  }
58
177
  // Função para determinar quais arquivos JavaScript carregar
59
178
  function getJavaScriptFiles(req) {
60
179
  const projectDir = process.cwd();
61
- const distDir = path_1.default.join(projectDir, 'hweb-dist');
180
+ const distDir = path_1.default.join(projectDir, '.hight');
62
181
  try {
63
182
  // Verifica se existe um manifesto de chunks (gerado pelo ESBuild com splitting)
64
183
  const manifestPath = path_1.default.join(distDir, 'manifest.json');
@@ -67,7 +186,7 @@ function getJavaScriptFiles(req) {
67
186
  const manifest = JSON.parse(fs_1.default.readFileSync(manifestPath, 'utf8'));
68
187
  const scripts = Object.values(manifest)
69
188
  .filter((file) => file.endsWith('.js'))
70
- .map((file) => `<script src="/hweb-dist/${file}"></script>`)
189
+ .map((file) => `<script src="/_hight/${file}"></script>`)
71
190
  .join('');
72
191
  return scripts;
73
192
  }
@@ -91,17 +210,17 @@ function getJavaScriptFiles(req) {
91
210
  if (jsFiles.length >= 1) {
92
211
  // Modo chunks sem manifesto
93
212
  return jsFiles
94
- .map(file => `<script src="/hweb-dist/${file}"></script>`)
213
+ .map(file => `<script src="/_hight/${file}"></script>`)
95
214
  .join('');
96
215
  }
97
216
  else {
98
217
  // Modo tradicional - único arquivo
99
- return '<script src="/hweb-dist/main.js"></script>';
218
+ return '<script src="/_hight/main.js"></script>';
100
219
  }
101
220
  }
102
221
  }
103
222
  catch (error) {
104
223
  // Fallback para o modo tradicional
105
- return '<script src="/hweb-dist/main.js"></script>';
224
+ return '<script src="/_hight/main.js"></script>';
106
225
  }
107
226
  }
package/dist/types.d.ts CHANGED
@@ -62,6 +62,11 @@ export interface HightConfig {
62
62
  * Padrão: 2048
63
63
  */
64
64
  maxUrlLength?: number;
65
+ /**
66
+ * Habilita o log de acesso HTTP (ex: GET /api/users 200 15ms).
67
+ * Padrão: false
68
+ */
69
+ accessLogging?: boolean;
65
70
  }
66
71
  /**
67
72
  * Tipo da função de configuração que pode ser exportada no hightjs.config.js
@@ -72,7 +77,41 @@ export type HightConfigFunction = (phase: string, context: {
72
77
  export interface Metadata {
73
78
  title?: string;
74
79
  description?: string;
80
+ keywords?: string | string[];
81
+ author?: string;
75
82
  favicon?: string;
83
+ viewport?: string;
84
+ themeColor?: string;
85
+ canonical?: string;
86
+ robots?: string;
87
+ openGraph?: {
88
+ title?: string;
89
+ description?: string;
90
+ type?: string;
91
+ url?: string;
92
+ image?: string | {
93
+ url: string;
94
+ width?: number;
95
+ height?: number;
96
+ alt?: string;
97
+ };
98
+ siteName?: string;
99
+ locale?: string;
100
+ };
101
+ twitter?: {
102
+ card?: 'summary' | 'summary_large_image' | 'app' | 'player';
103
+ site?: string;
104
+ creator?: string;
105
+ title?: string;
106
+ description?: string;
107
+ image?: string;
108
+ imageAlt?: string;
109
+ };
110
+ language?: string;
111
+ charset?: string;
112
+ appleTouchIcon?: string;
113
+ manifest?: string;
114
+ other?: Record<string, string>;
76
115
  }
77
116
  export interface RouteConfig {
78
117
  pattern: string;
package/docs/checklist.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # ✅ Checklist Mental
2
2
 
3
3
  1. Precisa de página? Crie em `src/web/routes/...`
4
- 2. Precisa de endpoint? Crie em `src/web/backend/routes/...`
4
+ 2. Precisa de endpoint? Crie em `src/backend/routes/...`
5
5
  3. Precisa proteger? Use autenticação nas rotas
6
6
  4. Precisa middleware? `middleware.ts` ou `middleware: []` na rota
7
7
  5. Metadata? `generateMetadata` ou `metadata` no layout
package/docs/config.md CHANGED
@@ -63,9 +63,18 @@ export default config;
63
63
  | `serverTimeout` | `number` | `35000` | Timeout geral do servidor em ms |
64
64
  | `individualRequestTimeout` | `number` | `30000` | Timeout por requisição individual em ms |
65
65
  | `maxUrlLength` | `number` | `2048` | Tamanho máximo da URL em caracteres |
66
+ | `accessLogging` | `boolean` | `false` | Habilita logs de acesso HTTP (ex: `GET /api/users 200 15ms`) |
66
67
 
67
68
  ## 🎯 Casos de Uso
68
69
 
70
+ ### Habilitar Logs de Acesso
71
+
72
+ ```typescript
73
+ const config: HightConfig = {
74
+ accessLogging: true, // Mostra: GET /api/users 200 15ms
75
+ };
76
+ ```
77
+
69
78
  ### Aumentar Timeouts para Debugging
70
79
 
71
80
  ```typescript
@@ -153,6 +162,9 @@ const hightConfig: HightConfigFunction = (phase, { defaultConfig }) => {
153
162
 
154
163
  // Ajustes por ambiente
155
164
  if (phase === 'development') {
165
+ // Habilita logs de acesso em dev
166
+ config.accessLogging = true;
167
+
156
168
  // Timeouts maiores para debugging
157
169
  config.requestTimeout = 120000;
158
170
  config.individualRequestTimeout = 120000;
@@ -160,6 +172,9 @@ const hightConfig: HightConfigFunction = (phase, { defaultConfig }) => {
160
172
  // URLs longas para testes
161
173
  config.maxUrlLength = 4096;
162
174
  } else if (phase === 'production') {
175
+ // Logs de acesso também podem ser úteis em produção
176
+ config.accessLogging = true;
177
+
163
178
  // Mais restritivo em produção
164
179
  config.maxHeadersCount = 50;
165
180
  config.maxUrlLength = 1024;
@@ -17,7 +17,7 @@ export type HightMiddleware = (
17
17
 
18
18
  ## Exemplo por Pasta
19
19
 
20
- `src/web/backend/routes/middleware.ts`:
20
+ `src/backend/routes/middleware.ts`:
21
21
 
22
22
  ```ts
23
23
  import {HightJSRequest, HightJSResponse} from 'hightjs';
@@ -1,11 +1,11 @@
1
1
  # 🌐 Rotas Backend
2
2
 
3
- Qualquer arquivo em `src/web/backend/routes` vira endpoint backend.
3
+ Qualquer arquivo em `src/backend/routes` vira endpoint backend.
4
4
  O _pattern_ pode ser qualquer caminho, não só `/api/...`!
5
5
 
6
6
  ## Exemplo Simples
7
7
 
8
- `src/web/backend/routes/version.ts`:
8
+ `src/backend/routes/version.ts`:
9
9
 
10
10
  ```ts
11
11
  import { HightJSRequest, HightJSResponse, BackendRouteConfig } from 'hightjs';
@@ -29,7 +29,7 @@ Defina `GET`, `POST`, `PUT`, `DELETE` (ou só os necessários).
29
29
 
30
30
  ## Rotas Dinâmicas Backend
31
31
 
32
- `src/web/backend/routes/users/[id].ts` → `/users/123`
32
+ `src/backend/routes/users/[id].ts` → `/users/123`
33
33
 
34
34
  ```ts
35
35
  import { BackendRouteConfig, HightJSResponse } from "hightjs";
package/docs/websocket.md CHANGED
@@ -4,7 +4,7 @@ O HightJS possui suporte nativo a WebSockets nas rotas do backend.
4
4
 
5
5
  ## Exemplo Prático
6
6
 
7
- `src/web/backend/routes/chat.ts`:
7
+ `src/backend/routes/chat.ts`:
8
8
 
9
9
  ```ts
10
10
  import {BackendRouteConfig, HightJSResponse} from 'hightjs';
@@ -47,6 +47,12 @@ const hightConfig: HightConfigFunction = (phase, { defaultConfig }) => {
47
47
  * Default: 2048
48
48
  */
49
49
  maxUrlLength: 2048,
50
+
51
+ /**
52
+ * Enable HTTP access logging (e.g., GET /api/users 200 15ms)
53
+ * Default: false
54
+ */
55
+ accessLogging: true,
50
56
  };
51
57
 
52
58
  // You can customize settings based on the phase
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "..": {
27
27
  "name": "hightjs",
28
- "version": "0.3.3",
28
+ "version": "0.3.5",
29
29
  "license": "Apache-2.0",
30
30
  "dependencies": {
31
31
  "@fastify/cookie": "^11.0.2",
@@ -4,8 +4,8 @@
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "start": "hight start --ssl --port 443",
8
- "dev": "hight dev --ssl --port 443"
7
+ "start": "hight start --port 80",
8
+ "dev": "hight dev --port 80"
9
9
  },
10
10
  "author": "itsmuzin",
11
11
  "license": "ISC",
@@ -0,0 +1,3 @@
1
+ import {authRoutes} from "../auth";
2
+
3
+ export default authRoutes
@@ -6,7 +6,7 @@ const route: BackendRouteConfig = {
6
6
  return HightJSResponse.json({
7
7
  success: true,
8
8
  version: "1.0.0",
9
- name: "HightJS Example App"
9
+ name: "HightJS Example asdadsadsadsdas"
10
10
  })
11
11
  }
12
12
  }