hightjs 0.3.5 → 0.5.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.
Files changed (123) hide show
  1. package/README.md +48 -116
  2. package/dist/bin/hightjs.js +51 -23
  3. package/dist/builder.js +198 -8
  4. package/dist/client/DefaultNotFound.d.ts +1 -1
  5. package/dist/client/DefaultNotFound.js +72 -46
  6. package/dist/client/client.d.ts +3 -0
  7. package/dist/{client.js → client/client.js} +4 -4
  8. package/dist/client/entry.client.js +77 -9
  9. package/dist/global/global.d.ts +117 -0
  10. package/dist/{auth/types.js → global/global.js} +0 -1
  11. package/dist/helpers.js +80 -2
  12. package/dist/hotReload.js +84 -4
  13. package/dist/index.js +72 -61
  14. package/dist/loaders.d.ts +1 -0
  15. package/dist/loaders.js +46 -0
  16. package/dist/renderer.js +158 -4
  17. package/dist/types.d.ts +44 -0
  18. package/package.json +37 -30
  19. package/.idea/HightJS.iml +0 -9
  20. package/.idea/copilot.data.migration.agent.xml +0 -6
  21. package/.idea/copilot.data.migration.ask.xml +0 -6
  22. package/.idea/copilot.data.migration.ask2agent.xml +0 -6
  23. package/.idea/copilot.data.migration.edit.xml +0 -6
  24. package/.idea/copilotDiffState.xml +0 -67
  25. package/.idea/inspectionProfiles/Project_Default.xml +0 -13
  26. package/.idea/libraries/test_package.xml +0 -9
  27. package/.idea/libraries/ts_commonjs_default_export.xml +0 -9
  28. package/.idea/misc.xml +0 -7
  29. package/.idea/modules.xml +0 -8
  30. package/.idea/vcs.xml +0 -6
  31. package/dist/auth/client.d.ts +0 -24
  32. package/dist/auth/client.js +0 -146
  33. package/dist/auth/components.d.ts +0 -29
  34. package/dist/auth/components.js +0 -100
  35. package/dist/auth/core.d.ts +0 -55
  36. package/dist/auth/core.js +0 -189
  37. package/dist/auth/index.d.ts +0 -7
  38. package/dist/auth/index.js +0 -45
  39. package/dist/auth/jwt.d.ts +0 -41
  40. package/dist/auth/jwt.js +0 -185
  41. package/dist/auth/providers/credentials.d.ts +0 -60
  42. package/dist/auth/providers/credentials.js +0 -97
  43. package/dist/auth/providers/discord.d.ts +0 -63
  44. package/dist/auth/providers/discord.js +0 -190
  45. package/dist/auth/providers/google.d.ts +0 -63
  46. package/dist/auth/providers/google.js +0 -186
  47. package/dist/auth/providers/index.d.ts +0 -2
  48. package/dist/auth/providers/index.js +0 -35
  49. package/dist/auth/providers.d.ts +0 -3
  50. package/dist/auth/providers.js +0 -26
  51. package/dist/auth/react/index.d.ts +0 -6
  52. package/dist/auth/react/index.js +0 -48
  53. package/dist/auth/react.d.ts +0 -22
  54. package/dist/auth/react.js +0 -199
  55. package/dist/auth/routes.d.ts +0 -16
  56. package/dist/auth/routes.js +0 -152
  57. package/dist/auth/types.d.ts +0 -76
  58. package/dist/client.d.ts +0 -3
  59. package/docs/README.md +0 -58
  60. package/docs/arquivos-especiais.md +0 -10
  61. package/docs/autenticacao.md +0 -212
  62. package/docs/checklist.md +0 -9
  63. package/docs/cli.md +0 -72
  64. package/docs/config.md +0 -216
  65. package/docs/estrutura.md +0 -20
  66. package/docs/faq.md +0 -10
  67. package/docs/hot-reload.md +0 -5
  68. package/docs/integracoes.md +0 -240
  69. package/docs/middlewares.md +0 -73
  70. package/docs/rotas-backend.md +0 -45
  71. package/docs/rotas-frontend.md +0 -66
  72. package/docs/seguranca.md +0 -8
  73. package/docs/websocket.md +0 -45
  74. package/example/certs/cert.pem +0 -20
  75. package/example/certs/key.pem +0 -27
  76. package/example/hightjs.config.ts +0 -87
  77. package/example/package-lock.json +0 -1174
  78. package/example/package.json +0 -26
  79. package/example/postcss.config.js +0 -8
  80. package/example/src/auth.ts +0 -42
  81. package/example/src/web/backend/routes/auth.ts +0 -3
  82. package/example/src/web/backend/routes/version.ts +0 -13
  83. package/example/src/web/globals.css +0 -5
  84. package/example/src/web/layout.tsx +0 -100
  85. package/example/src/web/routes/index.tsx +0 -153
  86. package/example/src/web/routes/login.tsx +0 -175
  87. package/example/tailwind.config.js +0 -12
  88. package/example/tsconfig.json +0 -15
  89. package/src/adapters/express.ts +0 -87
  90. package/src/adapters/factory.ts +0 -112
  91. package/src/adapters/fastify.ts +0 -104
  92. package/src/adapters/native.ts +0 -234
  93. package/src/api/console.ts +0 -305
  94. package/src/api/http.ts +0 -535
  95. package/src/auth/client.ts +0 -171
  96. package/src/auth/components.tsx +0 -125
  97. package/src/auth/core.ts +0 -215
  98. package/src/auth/index.ts +0 -25
  99. package/src/auth/jwt.ts +0 -210
  100. package/src/auth/providers/credentials.ts +0 -139
  101. package/src/auth/providers/discord.ts +0 -239
  102. package/src/auth/providers/google.ts +0 -234
  103. package/src/auth/providers/index.ts +0 -20
  104. package/src/auth/providers.ts +0 -20
  105. package/src/auth/react/index.ts +0 -25
  106. package/src/auth/react.tsx +0 -234
  107. package/src/auth/routes.ts +0 -183
  108. package/src/auth/types.ts +0 -108
  109. package/src/bin/hightjs.js +0 -222
  110. package/src/builder.js +0 -411
  111. package/src/client/DefaultNotFound.tsx +0 -84
  112. package/src/client/clientRouter.ts +0 -153
  113. package/src/client/entry.client.tsx +0 -444
  114. package/src/client.ts +0 -24
  115. package/src/components/Link.tsx +0 -38
  116. package/src/helpers.ts +0 -542
  117. package/src/hotReload.ts +0 -489
  118. package/src/index.ts +0 -546
  119. package/src/renderer.tsx +0 -263
  120. package/src/router.ts +0 -730
  121. package/src/types/framework.ts +0 -58
  122. package/src/types.ts +0 -207
  123. package/tsconfig.json +0 -17
@@ -1,53 +1,79 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = DefaultNotFound;
3
+ exports.default = App;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- function DefaultNotFound() {
6
- return ((0, jsx_runtime_1.jsx)("div", { style: {
7
- fontFamily: 'system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"',
8
- height: '100vh',
9
- textAlign: 'center',
10
- display: 'flex',
11
- flexDirection: 'column',
12
- alignItems: 'center',
13
- justifyContent: 'center'
14
- }, children: (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("style", { dangerouslySetInnerHTML: {
15
- __html: `
16
- body {
17
- color: #000;
18
- /* Alterado de cor sólida para gradiente */
19
- background: linear-gradient(to bottom, #e9e9e9, #ffffff);
20
- margin: 0;
21
- }
5
+ function App() {
6
+ const globalStyles = `
7
+
8
+ html, body {
9
+ margin: 0;
10
+ padding: 0;
11
+ width: 100%;
12
+ height: 100%;
13
+ font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
14
+ -webkit-font-smoothing: antialiased;
15
+ -moz-osx-font-smoothing: grayscale;
16
+ box-sizing: border-box;
17
+ }
22
18
 
23
- .next-error-h1 {
24
- border-right: 1px solid rgba(0, 0, 0, .3);
25
- }
19
+ *, *:before, *:after {
20
+ box-sizing: inherit;
21
+ }
26
22
 
27
- @media (prefers-color-scheme: dark) {
28
- body {
29
- color: #fff;
30
- /* Alterado de cor sólida para gradiente escuro */
31
- background: linear-gradient(to bottom, #222, #000);
32
- }
23
+ body {
24
+ color: #000;
25
+ background: linear-gradient(to bottom, #e9e9e9, #ffffff);
26
+ background-attachment: fixed;
27
+
28
+ display: flex;
29
+ align-items: center;
30
+ justify-content: center;
31
+ min-height: 100vh;
32
+ text-align: center;
33
+ padding: 20px;
34
+ }
35
+
36
+ .error-container {
37
+ /* Remove qualquer estilo de "card" anterior */
38
+ }
33
39
 
34
- .next-error-h1 {
35
- border-right: 1px solid rgba(255, 255, 255, .3);
36
- }
37
- }
38
- `
39
- } }), (0, jsx_runtime_1.jsx)("h1", { className: "next-error-h1", style: {
40
- display: 'inline-block',
41
- margin: '0px 20px 0px 0px',
42
- padding: '0px 23px 0px 0px',
43
- fontSize: '24px',
44
- fontWeight: '500',
45
- verticalAlign: 'top',
46
- lineHeight: '49px'
47
- }, children: "404" }), (0, jsx_runtime_1.jsx)("div", { style: { display: 'inline-block' }, children: (0, jsx_runtime_1.jsx)("h2", { style: {
48
- fontSize: '14px',
49
- fontWeight: '400',
50
- lineHeight: '49px',
51
- margin: '0px'
52
- }, children: "This page cannot be found." }) })] }) }));
40
+ .hight-error-h1 {
41
+ border-right: 1px solid rgba(0, 0, 0, .3);
42
+ }
43
+
44
+ @media (prefers-color-scheme: dark) {
45
+ body {
46
+ color: #fff;
47
+ background: linear-gradient(to bottom, #222, #000);
48
+ }
49
+ .hight-error-h2 {
50
+ color: white;
51
+ }
52
+ .hight-error-h1 {
53
+ color: white;
54
+ border-right: 1px solid rgba(255, 255, 255, .3);
55
+ }
56
+ }
57
+ `;
58
+ // Estilos inline do seu exemplo original
59
+ const h1Styles = {
60
+ display: 'inline-block',
61
+ margin: '0px 20px 0px 0px',
62
+ padding: '0px 23px 0px 0px',
63
+ fontSize: '24px',
64
+ fontWeight: '500',
65
+ verticalAlign: 'top',
66
+ lineHeight: '49px'
67
+ };
68
+ const h2ContainerStyles = {
69
+ display: 'inline-block',
70
+ verticalAlign: 'top', // Alinha com o topo do H1
71
+ };
72
+ const h2Styles = {
73
+ fontSize: '14px',
74
+ fontWeight: '400',
75
+ lineHeight: '49px',
76
+ margin: '0px'
77
+ };
78
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("style", { dangerouslySetInnerHTML: { __html: globalStyles } }), (0, jsx_runtime_1.jsxs)("div", { className: "error-container", children: [(0, jsx_runtime_1.jsx)("h1", { className: "hight-error-h1", style: h1Styles, children: "404" }), (0, jsx_runtime_1.jsx)("div", { style: h2ContainerStyles, children: (0, jsx_runtime_1.jsx)("h2", { style: h2Styles, className: "hight-error-h2", children: "This page cannot be found." }) })] })] }));
53
79
  }
@@ -0,0 +1,3 @@
1
+ export { Link } from '../components/Link';
2
+ export { RouteConfig, Metadata } from "../types";
3
+ export { router } from './clientRouter';
@@ -1,6 +1,4 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.router = exports.Link = void 0;
4
2
  /*
5
3
  * This file is part of the HightJS Project.
6
4
  * Copyright (c) 2025 itsmuzin
@@ -17,8 +15,10 @@ exports.router = exports.Link = void 0;
17
15
  * See the License for the specific language governing permissions and
18
16
  * limitations under the License.
19
17
  */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.router = exports.Link = void 0;
20
20
  // Este arquivo exporta apenas código seguro para o cliente (navegador)
21
- var Link_1 = require("./components/Link");
21
+ var Link_1 = require("../components/Link");
22
22
  Object.defineProperty(exports, "Link", { enumerable: true, get: function () { return Link_1.Link; } });
23
- var clientRouter_1 = require("./client/clientRouter");
23
+ var clientRouter_1 = require("./clientRouter");
24
24
  Object.defineProperty(exports, "router", { enumerable: true, get: function () { return clientRouter_1.router; } });
@@ -55,14 +55,8 @@ const client_1 = require("react-dom/client");
55
55
  const clientRouter_1 = require("./clientRouter");
56
56
  function App({ componentMap, routes, initialComponentPath, initialParams, layoutComponent }) {
57
57
  // Estado que guarda o componente a ser renderizado atualmente
58
- const [CurrentPageComponent, setCurrentPageComponent] = (0, react_1.useState)(() => {
59
- // Se for a rota especial __404__, não busca no componentMap
60
- if (initialComponentPath === '__404__') {
61
- return null;
62
- }
63
- return componentMap[initialComponentPath];
64
- });
65
- const [params, setParams] = (0, react_1.useState)(initialParams);
58
+ const [hmrTimestamp, setHmrTimestamp] = (0, react_1.useState)(Date.now());
59
+ // Helper para encontrar rota baseado no path
66
60
  const findRouteForPath = (0, react_1.useCallback)((path) => {
67
61
  for (const route of routes) {
68
62
  const regexPattern = route.pattern
@@ -87,6 +81,79 @@ function App({ componentMap, routes, initialComponentPath, initialParams, layout
87
81
  }
88
82
  return null;
89
83
  }, [routes]);
84
+ // Inicializa o componente e params baseado na URL ATUAL (não no initialComponentPath)
85
+ const [CurrentPageComponent, setCurrentPageComponent] = (0, react_1.useState)(() => {
86
+ // Pega a rota atual da URL
87
+ const currentPath = window.location.pathname;
88
+ const match = findRouteForPath(currentPath);
89
+ if (match) {
90
+ return componentMap[match.componentPath];
91
+ }
92
+ // Se não encontrou rota, retorna null para mostrar 404
93
+ return null;
94
+ });
95
+ const [params, setParams] = (0, react_1.useState)(() => {
96
+ // Pega os params da URL atual
97
+ const currentPath = window.location.pathname;
98
+ const match = findRouteForPath(currentPath);
99
+ return match ? match.params : {};
100
+ });
101
+ // HMR: Escuta eventos de hot reload
102
+ (0, react_1.useEffect)(() => {
103
+ // Ativa o sistema de HMR
104
+ window.__HWEB_HMR__ = true;
105
+ const handleHMRUpdate = async (event) => {
106
+ const { file, timestamp } = event.detail;
107
+ const fileName = file ? file.split('/').pop()?.split('\\').pop() : 'unknown';
108
+ console.log('🔥 HMR: Hot reloading...', fileName);
109
+ try {
110
+ // Aguarda um pouco para o esbuild terminar de recompilar
111
+ await new Promise(resolve => setTimeout(resolve, 300));
112
+ // Re-importa o módulo principal com cache busting
113
+ const mainScript = document.querySelector('script[src*="main.js"]');
114
+ if (mainScript) {
115
+ const mainSrc = mainScript.src.split('?')[0];
116
+ const cacheBustedSrc = `${mainSrc}?t=${timestamp}`;
117
+ // Cria novo script
118
+ const newScript = document.createElement('script');
119
+ newScript.type = 'module';
120
+ newScript.src = cacheBustedSrc;
121
+ // Quando o novo script carregar, força re-render
122
+ newScript.onload = () => {
123
+ console.log('✅ HMR: Modules reloaded');
124
+ // Força re-render do componente
125
+ setHmrTimestamp(timestamp);
126
+ // Marca sucesso
127
+ window.__HMR_SUCCESS__ = true;
128
+ setTimeout(() => {
129
+ window.__HMR_SUCCESS__ = false;
130
+ }, 3000);
131
+ };
132
+ newScript.onerror = () => {
133
+ console.error('❌ HMR: Failed to reload modules');
134
+ window.__HMR_SUCCESS__ = false;
135
+ };
136
+ // Remove o script antigo e adiciona o novo
137
+ // (não remove para não quebrar o app)
138
+ document.head.appendChild(newScript);
139
+ }
140
+ else {
141
+ // Se não encontrou o script, apenas força re-render
142
+ console.log('⚡ HMR: Forcing re-render');
143
+ setHmrTimestamp(timestamp);
144
+ window.__HMR_SUCCESS__ = true;
145
+ }
146
+ }
147
+ catch (error) {
148
+ console.error('❌ HMR Error:', error);
149
+ window.__HMR_SUCCESS__ = false;
150
+ }
151
+ };
152
+ window.addEventListener('hmr:component-update', handleHMRUpdate);
153
+ return () => {
154
+ window.removeEventListener('hmr:component-update', handleHMRUpdate);
155
+ };
156
+ }, []);
90
157
  const updateRoute = (0, react_1.useCallback)(() => {
91
158
  const currentPath = clientRouter_1.router.pathname;
92
159
  const match = findRouteForPath(currentPath);
@@ -138,7 +205,8 @@ function App({ componentMap, routes, initialComponentPath, initialParams, layout
138
205
  }
139
206
  }
140
207
  // Renderiza o componente atual (sem Context, usa o router diretamente)
141
- const PageContent = (0, jsx_runtime_1.jsx)(CurrentPageComponent, { params: params });
208
+ // Usa key com timestamp para forçar re-mount durante HMR
209
+ const PageContent = (0, jsx_runtime_1.jsx)(CurrentPageComponent, { params: params }, `page-${hmrTimestamp}`);
142
210
  // SEMPRE usa o layout - se não existir, cria um wrapper padrão
143
211
  const content = layoutComponent
144
212
  ? react_1.default.createElement(layoutComponent, { children: PageContent })
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Type declarations for asset imports
3
+ * This allows TypeScript to understand imports of various file types
4
+ */
5
+ declare module "*.md" {
6
+ const content: string;
7
+ export default content;
8
+ }
9
+ declare module "*.png" {
10
+ const src: string;
11
+ export default src;
12
+ }
13
+ declare module "*.jpg" {
14
+ const src: string;
15
+ export default src;
16
+ }
17
+ declare module "*.jpeg" {
18
+ const src: string;
19
+ export default src;
20
+ }
21
+ declare module "*.gif" {
22
+ const src: string;
23
+ export default src;
24
+ }
25
+ declare module "*.webp" {
26
+ const src: string;
27
+ export default src;
28
+ }
29
+ declare module "*.avif" {
30
+ const src: string;
31
+ export default src;
32
+ }
33
+ declare module "*.ico" {
34
+ const src: string;
35
+ export default src;
36
+ }
37
+ declare module "*.bmp" {
38
+ const src: string;
39
+ export default src;
40
+ }
41
+ declare module "*.tif" {
42
+ const src: string;
43
+ export default src;
44
+ }
45
+ declare module "*.tiff" {
46
+ const src: string;
47
+ export default src;
48
+ }
49
+ declare module "*.svg" {
50
+ const src: string;
51
+ export const svgContent: string;
52
+ export default src;
53
+ }
54
+ declare module "*.json" {
55
+ const value: any;
56
+ export default value;
57
+ }
58
+ declare module "*.txt" {
59
+ const content: string;
60
+ export default content;
61
+ }
62
+ declare module "*.woff" {
63
+ const src: string;
64
+ export default src;
65
+ }
66
+ declare module "*.woff2" {
67
+ const src: string;
68
+ export default src;
69
+ }
70
+ declare module "*.ttf" {
71
+ const src: string;
72
+ export default src;
73
+ }
74
+ declare module "*.otf" {
75
+ const src: string;
76
+ export default src;
77
+ }
78
+ declare module "*.eot" {
79
+ const src: string;
80
+ export default src;
81
+ }
82
+ declare module "*.mp3" {
83
+ const src: string;
84
+ export default src;
85
+ }
86
+ declare module "*.wav" {
87
+ const src: string;
88
+ export default src;
89
+ }
90
+ declare module "*.ogg" {
91
+ const src: string;
92
+ export default src;
93
+ }
94
+ declare module "*.m4a" {
95
+ const src: string;
96
+ export default src;
97
+ }
98
+ declare module "*.aac" {
99
+ const src: string;
100
+ export default src;
101
+ }
102
+ declare module "*.flac" {
103
+ const src: string;
104
+ export default src;
105
+ }
106
+ declare module "*.mp4" {
107
+ const src: string;
108
+ export default src;
109
+ }
110
+ declare module "*.webm" {
111
+ const src: string;
112
+ export default src;
113
+ }
114
+ declare module "*.ogv" {
115
+ const src: string;
116
+ export default src;
117
+ }
@@ -15,4 +15,3 @@
15
15
  * See the License for the specific language governing permissions and
16
16
  * limitations under the License.
17
17
  */
18
- Object.defineProperty(exports, "__esModule", { value: true });
package/dist/helpers.js CHANGED
@@ -64,6 +64,9 @@ const index_1 = __importStar(require("./index")); // Importando o tipo
64
64
  const console_1 = __importStar(require("./api/console"));
65
65
  const https_1 = __importDefault(require("https")); // <-- ADICIONAR
66
66
  const fs_1 = __importDefault(require("fs")); // <-- ADICIONAR
67
+ // Registra loaders customizados para importar arquivos não-JS
68
+ const { registerLoaders } = require('./loaders');
69
+ registerLoaders();
67
70
  // --- Helpers ---
68
71
  /**
69
72
  * Encontra o IP externo local (rede)
@@ -164,9 +167,74 @@ async function loadHightConfig(projectDir, phase) {
164
167
  }
165
168
  }
166
169
  /**
167
- * Middleware para parsing do body com proteções de segurança (versão melhorada).
168
- * Rejeita a promise em caso de erro de parsing ou estouro de limite.
170
+ * Aplica headers CORS na resposta baseado na configuração.
171
+ * @param req Requisição HTTP
172
+ * @param res Resposta HTTP
173
+ * @param corsConfig Configuração de CORS
174
+ * @returns true se a requisição foi finalizada (OPTIONS), false caso contrário
169
175
  */
176
+ function applyCors(req, res, corsConfig) {
177
+ if (!corsConfig || !corsConfig.enabled) {
178
+ return false;
179
+ }
180
+ const origin = req.headers.origin || req.headers.referer;
181
+ // Verifica se a origem é permitida
182
+ let allowOrigin = false;
183
+ if (corsConfig.origin === '*') {
184
+ res.setHeader('Access-Control-Allow-Origin', '*');
185
+ allowOrigin = true;
186
+ }
187
+ else if (typeof corsConfig.origin === 'string' && origin === corsConfig.origin) {
188
+ res.setHeader('Access-Control-Allow-Origin', corsConfig.origin);
189
+ allowOrigin = true;
190
+ }
191
+ else if (Array.isArray(corsConfig.origin) && origin && corsConfig.origin.includes(origin)) {
192
+ res.setHeader('Access-Control-Allow-Origin', origin);
193
+ allowOrigin = true;
194
+ }
195
+ else if (typeof corsConfig.origin === 'function' && origin) {
196
+ try {
197
+ if (corsConfig.origin(origin)) {
198
+ res.setHeader('Access-Control-Allow-Origin', origin);
199
+ allowOrigin = true;
200
+ }
201
+ }
202
+ catch (error) {
203
+ console_1.default.warn(`${console_1.Colors.FgYellow}[CORS]${console_1.Colors.Reset} Error validating origin: ${error instanceof Error ? error.message : 'Unknown error'}`);
204
+ }
205
+ }
206
+ // Se a origem não for permitida e não for wildcard, não aplica outros headers
207
+ if (!allowOrigin && corsConfig.origin !== '*') {
208
+ return false;
209
+ }
210
+ // Credenciais (não pode ser usado com origin: '*')
211
+ if (corsConfig.credentials && corsConfig.origin !== '*') {
212
+ res.setHeader('Access-Control-Allow-Credentials', 'true');
213
+ }
214
+ // Métodos permitidos
215
+ const methods = corsConfig.methods || ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'];
216
+ res.setHeader('Access-Control-Allow-Methods', methods.join(', '));
217
+ // Headers permitidos
218
+ const allowedHeaders = corsConfig.allowedHeaders || ['Content-Type', 'Authorization'];
219
+ res.setHeader('Access-Control-Allow-Headers', allowedHeaders.join(', '));
220
+ // Headers expostos
221
+ if (corsConfig.exposedHeaders && corsConfig.exposedHeaders.length > 0) {
222
+ res.setHeader('Access-Control-Expose-Headers', corsConfig.exposedHeaders.join(', '));
223
+ }
224
+ // Max age para cache de preflight
225
+ const maxAge = corsConfig.maxAge !== undefined ? corsConfig.maxAge : 86400;
226
+ res.setHeader('Access-Control-Max-Age', maxAge.toString());
227
+ // Responde requisições OPTIONS (preflight)
228
+ if (req.method === 'OPTIONS') {
229
+ res.statusCode = 204; // No Content
230
+ res.end();
231
+ return true;
232
+ }
233
+ return false;
234
+ }
235
+ /**
236
+ * Middleware para parsing do body com proteções de segurança (versão melhorada).
237
+ */
170
238
  const parseBody = (req) => {
171
239
  // Constantes para limites de segurança
172
240
  const MAX_BODY_SIZE = 10 * 1024 * 1024; // 10MB limite total
@@ -254,6 +322,16 @@ async function initNativeServer(hwebApp, options, port, hostname) {
254
322
  const requestStartTime = Date.now();
255
323
  const method = req.method || 'GET';
256
324
  const url = req.url || '/';
325
+ // Aplica CORS se configurado
326
+ const corsHandled = applyCors(req, res, hightConfig.cors);
327
+ if (corsHandled) {
328
+ // Requisição OPTIONS foi respondida pelo CORS
329
+ if (hightConfig.accessLogging) {
330
+ const duration = Date.now() - requestStartTime;
331
+ console_1.default.logCustomLevel('OPTIONS', true, console_1.Colors.BgMagenta, `${url} ${console_1.Colors.FgGreen}204${console_1.Colors.Reset} ${console_1.Colors.FgGray}${duration}ms${console_1.Colors.Reset} ${console_1.Colors.FgCyan}[CORS]${console_1.Colors.Reset}`);
332
+ }
333
+ return;
334
+ }
257
335
  // Configurações de segurança básicas
258
336
  res.setHeader('X-Content-Type-Options', 'nosniff');
259
337
  res.setHeader('X-Frame-Options', 'DENY');
package/dist/hotReload.js CHANGED
@@ -195,8 +195,7 @@ class HotReloadManager {
195
195
  filePath.includes('not-found.tsx') ||
196
196
  filePath.endsWith('.tsx') ||
197
197
  filePath.endsWith('.jsx');
198
- const isBackendFile = filePath.includes(path.join('src', 'web', 'backend')) ||
199
- (filePath.includes(path.join('src', 'web')) && !isFrontendFile);
198
+ const isBackendFile = filePath.includes(path.join('src', 'backend')) && !isFrontendFile;
200
199
  // Limpa o cache do arquivo alterado
201
200
  (0, router_1.clearFileCache)(filePath);
202
201
  this.clearBackendCache(filePath);
@@ -214,6 +213,7 @@ class HotReloadManager {
214
213
  setTimeout(() => reject(new Error('Build timeout')), 30000);
215
214
  });
216
215
  try {
216
+ this.frontendChangeCallback?.();
217
217
  await Promise.race([buildPromise, timeoutPromise]);
218
218
  console_1.default.logWithout(console_1.Levels.INFO, console_1.Colors.BgRed, `✅ Build complete, reloading frontend...`);
219
219
  this.frontendChangeCallback?.();
@@ -342,10 +342,11 @@ class HotReloadManager {
342
342
 
343
343
  switch(message.type) {
344
344
  case 'frontend-reload':
345
- window.location.reload();
345
+ handleFrontendReload(message.data);
346
346
  break;
347
347
  case 'backend-api-reload':
348
- // Recarrega apenas se necessário
348
+ // Backend sempre precisa recarregar
349
+ console.log('🔄 Backend changed, reloading...');
349
350
  window.location.reload();
350
351
  break;
351
352
  case 'server-restart':
@@ -357,12 +358,91 @@ class HotReloadManager {
357
358
  case 'frontend-error':
358
359
  console.error('❌ Frontend error:', message.data);
359
360
  break;
361
+ case 'hmr-update':
362
+ handleHMRUpdate(message.data);
363
+ break;
360
364
  }
361
365
  } catch (e) {
362
366
  console.error('Erro ao processar mensagem do hot-reload:', e);
363
367
  }
364
368
  };
365
369
 
370
+ function handleFrontendReload(data) {
371
+ if (!data || !data.file) {
372
+ window.location.reload();
373
+ return;
374
+ }
375
+
376
+ const file = data.file.toLowerCase();
377
+
378
+ // Mudanças que exigem reload completo
379
+ const needsFullReload =
380
+ file.includes('layout.tsx') ||
381
+ file.includes('layout.jsx') ||
382
+ file.includes('not-found.tsx') ||
383
+ file.includes('not-found.jsx') ||
384
+ file.endsWith('.css');
385
+
386
+ if (needsFullReload) {
387
+ console.log('⚡ Layout/CSS changed, full reload...');
388
+ window.location.reload();
389
+ return;
390
+ }
391
+
392
+ // Mudanças em rotas: tenta HMR
393
+ if (file.includes('/routes/') || file.includes('\\\\routes\\\\')) {
394
+ console.log('⚡ Route component changed, hot reloading...');
395
+
396
+ // Dispara evento para forçar re-render
397
+ const event = new CustomEvent('hmr:component-update', {
398
+ detail: { file: data.file, timestamp: Date.now() }
399
+ });
400
+ window.dispatchEvent(event);
401
+
402
+ // Aguarda 500ms para ver se o HMR foi bem-sucedido
403
+ setTimeout(() => {
404
+ const hmrSuccess = window.__HMR_SUCCESS__;
405
+ if (!hmrSuccess) {
406
+ console.log('⚠️ HMR failed, falling back to full reload');
407
+ window.location.reload();
408
+ } else {
409
+ console.log('✅ HMR successful!');
410
+ }
411
+ }, 500);
412
+ } else {
413
+ // Outros arquivos: reload completo por segurança
414
+ window.location.reload();
415
+ }
416
+ }
417
+
418
+ function handleHMRUpdate(data) {
419
+ console.log('🔥 HMR Update:', data);
420
+
421
+ // Dispara evento customizado para o React capturar
422
+ const event = new CustomEvent('hmr:update', {
423
+ detail: data
424
+ });
425
+ window.dispatchEvent(event);
426
+ }
427
+
428
+ function attemptHMR(changedFile) {
429
+ // Tenta fazer Hot Module Replacement
430
+ // Dispara evento para o React App capturar
431
+ const event = new CustomEvent('hmr:component-update', {
432
+ detail: { file: changedFile, timestamp: Date.now() }
433
+ });
434
+ window.dispatchEvent(event);
435
+
436
+ // Fallback: se após 2s não houve sucesso, reload
437
+ setTimeout(() => {
438
+ const hmrSuccess = window.__HMR_SUCCESS__;
439
+ if (!hmrSuccess) {
440
+ console.log('⚠️ HMR failed, falling back to full reload');
441
+ window.location.reload();
442
+ }
443
+ }, 2000);
444
+ }
445
+
366
446
  ws.onclose = function(event) {
367
447
  isConnected = false;
368
448