slicejs-web-framework 3.5.4 → 4.0.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.
Files changed (71) hide show
  1. package/.opencode/opencode.json +14 -14
  2. package/LICENSE +21 -21
  3. package/README.md +97 -97
  4. package/Slice/Components/Structural/ContextManager/ContextManager.js +422 -422
  5. package/Slice/Components/Structural/ContextManager/ContextManagerDebugger.js +470 -470
  6. package/Slice/Components/Structural/Controller/Controller.js +1406 -1406
  7. package/Slice/Components/Structural/Controller/allowedValuesValidation.js +52 -52
  8. package/Slice/Components/Structural/Debugger/Debugger.html +72 -72
  9. package/Slice/Components/Structural/Debugger/Debugger.js +1505 -1505
  10. package/Slice/Components/Structural/EventManager/EventManager.js +651 -651
  11. package/Slice/Components/Structural/EventManager/EventManagerDebugger.js +985 -985
  12. package/Slice/Components/Structural/LeakInspector/LeakInspector.js +296 -296
  13. package/Slice/Components/Structural/Logger/Log.js +10 -10
  14. package/Slice/Components/Structural/Logger/LogViewer/LogViewer.js +662 -662
  15. package/Slice/Components/Structural/Logger/Logger.js +225 -225
  16. package/Slice/Components/Structural/Router/Router.js +793 -793
  17. package/Slice/Components/Structural/StylesManager/StylesManager.js +82 -82
  18. package/Slice/Components/Structural/StylesManager/ThemeManager/ThemeManager.js +162 -162
  19. package/Slice/Slice.js +686 -697
  20. package/Slice/tests/build-bundled-component-without-category.test.js +103 -103
  21. package/Slice/tests/build-js-only-visual-components.test.js +144 -144
  22. package/Slice/tests/build-singleton.test.js +244 -244
  23. package/Slice/tests/bundle-v2-runtime-contract.test.js +738 -738
  24. package/Slice/tests/context-patch-use.test.js +95 -95
  25. package/Slice/tests/destroy-cascade.test.js +215 -215
  26. package/Slice/tests/event-emitters.test.js +79 -79
  27. package/Slice/tests/event-registry.test.js +141 -141
  28. package/Slice/tests/fixtures/real-runtime-loader.mjs +21 -21
  29. package/Slice/tests/leak-orphans.test.js +131 -131
  30. package/Slice/tests/props-allowed-values-validation.test.js +119 -119
  31. package/Slice/tests/public-env-runtime-accessors.test.js +44 -44
  32. package/Slice/tests/public-env-typed-accessors.test.js +66 -66
  33. package/Slice/tests/router-loading-finally.test.js +68 -68
  34. package/api/framework/devDepsOptimizer.js +335 -0
  35. package/api/framework/express.js +3 -3
  36. package/api/framework/precompressedStatic.js +93 -0
  37. package/api/framework/publicEnvResolver.js +123 -123
  38. package/api/framework/securityMiddleware.js +197 -197
  39. package/api/framework/server.js +411 -340
  40. package/api/index.js +7 -7
  41. package/api/tests/dev-deps-optimizer.test.js +137 -0
  42. package/api/tests/dev-server-external.test.js +56 -0
  43. package/api/tests/precompressed-static.test.js +119 -0
  44. package/api/tests/public-env-resolver.test.js +193 -193
  45. package/package.json +49 -46
  46. package/sliceConfig.schema.json +122 -126
  47. package/src/App/index.html +69 -69
  48. package/src/App/index.js +20 -20
  49. package/src/App/style.css +11 -11
  50. package/src/Components/AppComponents/AboutSection/AboutSection.css +9 -9
  51. package/src/Components/AppComponents/AboutSection/AboutSection.html +8 -8
  52. package/src/Components/AppComponents/AboutSection/AboutSection.js +12 -12
  53. package/src/Components/AppComponents/AppShell/AppShell.css +10 -10
  54. package/src/Components/AppComponents/AppShell/AppShell.html +4 -4
  55. package/src/Components/AppComponents/AppShell/AppShell.js +36 -36
  56. package/src/Components/AppComponents/HomeSection/HomeSection.css +20 -20
  57. package/src/Components/AppComponents/HomeSection/HomeSection.html +10 -10
  58. package/src/Components/AppComponents/HomeSection/HomeSection.js +19 -19
  59. package/src/Components/components.js +8 -8
  60. package/src/{Styles → public/Styles}/sliceStyles.css +34 -34
  61. package/src/{Themes → public/Themes}/Dark.css +42 -42
  62. package/src/{Themes → public/Themes}/Light.css +31 -31
  63. package/src/{Themes → public/Themes}/Slice.css +47 -47
  64. package/src/{manifest.json → public/manifest.json} +15 -15
  65. package/src/{robots.txt → public/robots.txt} +4 -4
  66. package/src/{sitemap.xml → public/sitemap.xml} +8 -8
  67. package/src/routes.js +9 -9
  68. package/src/sliceConfig.json +72 -78
  69. package/tests/router-emit-ordering.test.js +63 -63
  70. package/types/index.d.ts +219 -219
  71. /package/src/{images → public/images}/favicon.ico +0 -0
@@ -1,197 +1,197 @@
1
- // api/framework/securityMiddleware.js
2
- import path from 'path';
3
-
4
- /**
5
- * Middleware de seguridad para prevenir acceso directo malicioso
6
- * pero permitir que la aplicación cargue sus dependencias normalmente
7
- */
8
- export function securityMiddleware(options = {}) {
9
- const {
10
- allowedExtensions = [
11
- '.js', '.mjs', '.cjs',
12
- '.css',
13
- '.html', '.htm',
14
- '.json',
15
- '.svg', '.png', '.jpg', '.jpeg', '.gif', '.webp', '.avif', '.ico',
16
- '.woff', '.woff2', '.ttf', '.otf', '.eot',
17
- '.txt', '.xml', '.pdf',
18
- '.webm', '.mp4', '.mp3', '.wav', '.ogg',
19
- '.wasm'
20
- ],
21
- blockedPaths = [
22
- '/node_modules',
23
- '/package.json',
24
- '/package-lock.json',
25
- '/.env',
26
- '/.git'
27
- ],
28
- allowPublicAssets = true,
29
- publicPaths = ['/assets', '/public', '/images', '/styles']
30
- } = options;
31
-
32
- return (req, res, next) => {
33
- const requestPath = req.path;
34
-
35
- // 1. Bloquear acceso a rutas definitivamente sensibles (configuración, dependencias)
36
- const isBlockedPath = blockedPaths.some(blocked =>
37
- requestPath.startsWith(blocked) || requestPath.includes(blocked)
38
- );
39
-
40
- if (isBlockedPath) {
41
- console.warn(`🚫 Blocked access to sensitive path: ${requestPath}`);
42
- return res.status(403).json({
43
- error: 'Forbidden',
44
- message: 'Access to this resource is not allowed',
45
- path: requestPath
46
- });
47
- }
48
-
49
- // 2. Permitir acceso a assets públicos (según sliceConfig.publicFolders)
50
- if (allowPublicAssets) {
51
- const isPublicAsset = publicPaths.some(publicPath =>
52
- requestPath.startsWith(publicPath)
53
- );
54
-
55
- if (isPublicAsset) {
56
- return next();
57
- }
58
- }
59
-
60
- // 3. Validar extensiones de archivo
61
- const fileExtension = path.extname(requestPath).toLowerCase();
62
-
63
- if (fileExtension && !allowedExtensions.includes(fileExtension)) {
64
- console.warn(`🚫 Blocked file type: ${requestPath}`);
65
- return res.status(403).json({
66
- error: 'Forbidden',
67
- message: 'File type not allowed',
68
- extension: fileExtension
69
- });
70
- }
71
-
72
- // 4. Prevenir path traversal attacks
73
- const normalizedPath = path.normalize(requestPath);
74
- if (normalizedPath.includes('..') || normalizedPath.includes('~')) {
75
- console.warn(`🚫 Path traversal attempt: ${requestPath}`);
76
- return res.status(403).json({
77
- error: 'Forbidden',
78
- message: 'Invalid path',
79
- path: requestPath
80
- });
81
- }
82
-
83
- // Todo está bien, continuar
84
- next();
85
- };
86
- }
87
-
88
- /**
89
- * Middleware específico para proteger archivos del framework Slice.js
90
- * PERMITE acceso cuando viene desde la propia aplicación (Referer válido)
91
- * BLOQUEA acceso directo desde navegador o herramientas externas
92
- */
93
- export function sliceFrameworkProtection(options = {}) {
94
- const {
95
- port = 3000,
96
- strictMode = false,
97
- allowedDomains = [] // Dominios personalizados permitidos
98
- } = options;
99
-
100
- return (req, res, next) => {
101
- const requestPath = req.path;
102
-
103
- // Rutas del framework que requieren verificación
104
- const frameworkPaths = [
105
- '/Slice/Components/Structural'
106
- ];
107
-
108
- const isFrameworkFile = frameworkPaths.some(fwPath =>
109
- requestPath.startsWith(fwPath)
110
- );
111
-
112
- if (!isFrameworkFile) {
113
- return next();
114
- }
115
-
116
- // Verificar el origen de la petición
117
- const referer = req.get('Referer') || req.get('Referrer');
118
- const origin = req.get('Origin');
119
- const host = req.get('Host');
120
-
121
- // Construir lista de orígenes válidos dinámicamente
122
- const validOrigins = [
123
- `http://localhost:${port}`,
124
- `http://127.0.0.1:${port}`,
125
- `http://0.0.0.0:${port}`,
126
- `https://localhost:${port}`,
127
- ...allowedDomains // Dominios personalizados del usuario
128
- ];
129
-
130
- // Si hay un Host header, agregarlo automáticamente
131
- if (host) {
132
- validOrigins.push(`http://${host}`);
133
- validOrigins.push(`https://${host}`);
134
- }
135
-
136
- // Verificar si la petición viene de un origen válido
137
- const hasValidReferer = referer && validOrigins.some(valid => referer.startsWith(valid));
138
- const hasValidOrigin = origin && validOrigins.some(valid => origin === valid);
139
- const isSameHost = host && referer && referer.includes(host);
140
-
141
- // Permitir si viene desde la aplicación
142
- if (hasValidReferer || hasValidOrigin || isSameHost) {
143
- return next();
144
- }
145
-
146
- // En modo estricto, bloquear todo acceso sin referer válido
147
- if (strictMode) {
148
- console.warn(`🚫 Blocked direct framework file access: ${requestPath}`);
149
- return res.status(403).json({
150
- error: 'Framework Protection',
151
- message: 'Direct access to Slice.js framework files is blocked',
152
- tip: 'Framework files must be loaded through the application',
153
- path: requestPath
154
- });
155
- }
156
-
157
- // En modo normal (desarrollo), permitir pero advertir
158
- console.warn(`⚠️ Framework file accessed without valid referer: ${requestPath}`);
159
- next();
160
- };
161
- }
162
-
163
- /**
164
- * Middleware para logging de peticiones sospechosas
165
- */
166
- export function suspiciousRequestLogger() {
167
- const suspiciousPatterns = [
168
- /\.\.\//, // Path traversal
169
- /~/, // Home directory access
170
- /\.env/, // Environment files
171
- /\.git/, // Git files
172
- /package\.json/, // Package files
173
- /package-lock\.json/,
174
- /node_modules/, // Dependencies
175
- ];
176
-
177
- return (req, res, next) => {
178
- const requestPath = req.path;
179
-
180
- const isSuspicious = suspiciousPatterns.some(pattern =>
181
- pattern.test(requestPath)
182
- );
183
-
184
- if (isSuspicious) {
185
- const clientIp = req.ip || req.connection.remoteAddress;
186
- console.warn(`⚠️ Suspicious request: ${requestPath} from ${clientIp}`);
187
- }
188
-
189
- next();
190
- };
191
- }
192
-
193
- export default {
194
- securityMiddleware,
195
- sliceFrameworkProtection,
196
- suspiciousRequestLogger
197
- };
1
+ // api/framework/securityMiddleware.js
2
+ import path from 'path';
3
+
4
+ /**
5
+ * Middleware de seguridad para prevenir acceso directo malicioso
6
+ * pero permitir que la aplicación cargue sus dependencias normalmente
7
+ */
8
+ export function securityMiddleware(options = {}) {
9
+ const {
10
+ allowedExtensions = [
11
+ '.js', '.mjs', '.cjs',
12
+ '.css',
13
+ '.html', '.htm',
14
+ '.json',
15
+ '.svg', '.png', '.jpg', '.jpeg', '.gif', '.webp', '.avif', '.ico',
16
+ '.woff', '.woff2', '.ttf', '.otf', '.eot',
17
+ '.txt', '.xml', '.pdf',
18
+ '.webm', '.mp4', '.mp3', '.wav', '.ogg',
19
+ '.wasm'
20
+ ],
21
+ blockedPaths = [
22
+ '/node_modules',
23
+ '/package.json',
24
+ '/package-lock.json',
25
+ '/.env',
26
+ '/.git'
27
+ ],
28
+ allowPublicAssets = true,
29
+ publicPaths = ['/assets', '/public', '/images', '/styles']
30
+ } = options;
31
+
32
+ return (req, res, next) => {
33
+ const requestPath = req.path;
34
+
35
+ // 1. Bloquear acceso a rutas definitivamente sensibles (configuración, dependencias)
36
+ const isBlockedPath = blockedPaths.some(blocked =>
37
+ requestPath.startsWith(blocked) || requestPath.includes(blocked)
38
+ );
39
+
40
+ if (isBlockedPath) {
41
+ console.warn(`🚫 Blocked access to sensitive path: ${requestPath}`);
42
+ return res.status(403).json({
43
+ error: 'Forbidden',
44
+ message: 'Access to this resource is not allowed',
45
+ path: requestPath
46
+ });
47
+ }
48
+
49
+ // 2. Permitir acceso a assets públicos (servidos desde src/public/)
50
+ if (allowPublicAssets) {
51
+ const isPublicAsset = publicPaths.some(publicPath =>
52
+ requestPath.startsWith(publicPath)
53
+ );
54
+
55
+ if (isPublicAsset) {
56
+ return next();
57
+ }
58
+ }
59
+
60
+ // 3. Validar extensiones de archivo
61
+ const fileExtension = path.extname(requestPath).toLowerCase();
62
+
63
+ if (fileExtension && !allowedExtensions.includes(fileExtension)) {
64
+ console.warn(`🚫 Blocked file type: ${requestPath}`);
65
+ return res.status(403).json({
66
+ error: 'Forbidden',
67
+ message: 'File type not allowed',
68
+ extension: fileExtension
69
+ });
70
+ }
71
+
72
+ // 4. Prevenir path traversal attacks
73
+ const normalizedPath = path.normalize(requestPath);
74
+ if (normalizedPath.includes('..') || normalizedPath.includes('~')) {
75
+ console.warn(`🚫 Path traversal attempt: ${requestPath}`);
76
+ return res.status(403).json({
77
+ error: 'Forbidden',
78
+ message: 'Invalid path',
79
+ path: requestPath
80
+ });
81
+ }
82
+
83
+ // Todo está bien, continuar
84
+ next();
85
+ };
86
+ }
87
+
88
+ /**
89
+ * Middleware específico para proteger archivos del framework Slice.js
90
+ * PERMITE acceso cuando viene desde la propia aplicación (Referer válido)
91
+ * BLOQUEA acceso directo desde navegador o herramientas externas
92
+ */
93
+ export function sliceFrameworkProtection(options = {}) {
94
+ const {
95
+ port = 3000,
96
+ strictMode = false,
97
+ allowedDomains = [] // Dominios personalizados permitidos
98
+ } = options;
99
+
100
+ return (req, res, next) => {
101
+ const requestPath = req.path;
102
+
103
+ // Rutas del framework que requieren verificación
104
+ const frameworkPaths = [
105
+ '/Slice/Components/Structural'
106
+ ];
107
+
108
+ const isFrameworkFile = frameworkPaths.some(fwPath =>
109
+ requestPath.startsWith(fwPath)
110
+ );
111
+
112
+ if (!isFrameworkFile) {
113
+ return next();
114
+ }
115
+
116
+ // Verificar el origen de la petición
117
+ const referer = req.get('Referer') || req.get('Referrer');
118
+ const origin = req.get('Origin');
119
+ const host = req.get('Host');
120
+
121
+ // Construir lista de orígenes válidos dinámicamente
122
+ const validOrigins = [
123
+ `http://localhost:${port}`,
124
+ `http://127.0.0.1:${port}`,
125
+ `http://0.0.0.0:${port}`,
126
+ `https://localhost:${port}`,
127
+ ...allowedDomains // Dominios personalizados del usuario
128
+ ];
129
+
130
+ // Si hay un Host header, agregarlo automáticamente
131
+ if (host) {
132
+ validOrigins.push(`http://${host}`);
133
+ validOrigins.push(`https://${host}`);
134
+ }
135
+
136
+ // Verificar si la petición viene de un origen válido
137
+ const hasValidReferer = referer && validOrigins.some(valid => referer.startsWith(valid));
138
+ const hasValidOrigin = origin && validOrigins.some(valid => origin === valid);
139
+ const isSameHost = host && referer && referer.includes(host);
140
+
141
+ // Permitir si viene desde la aplicación
142
+ if (hasValidReferer || hasValidOrigin || isSameHost) {
143
+ return next();
144
+ }
145
+
146
+ // En modo estricto, bloquear todo acceso sin referer válido
147
+ if (strictMode) {
148
+ console.warn(`🚫 Blocked direct framework file access: ${requestPath}`);
149
+ return res.status(403).json({
150
+ error: 'Framework Protection',
151
+ message: 'Direct access to Slice.js framework files is blocked',
152
+ tip: 'Framework files must be loaded through the application',
153
+ path: requestPath
154
+ });
155
+ }
156
+
157
+ // En modo normal (desarrollo), permitir pero advertir
158
+ console.warn(`⚠️ Framework file accessed without valid referer: ${requestPath}`);
159
+ next();
160
+ };
161
+ }
162
+
163
+ /**
164
+ * Middleware para logging de peticiones sospechosas
165
+ */
166
+ export function suspiciousRequestLogger() {
167
+ const suspiciousPatterns = [
168
+ /\.\.\//, // Path traversal
169
+ /~/, // Home directory access
170
+ /\.env/, // Environment files
171
+ /\.git/, // Git files
172
+ /package\.json/, // Package files
173
+ /package-lock\.json/,
174
+ /node_modules/, // Dependencies
175
+ ];
176
+
177
+ return (req, res, next) => {
178
+ const requestPath = req.path;
179
+
180
+ const isSuspicious = suspiciousPatterns.some(pattern =>
181
+ pattern.test(requestPath)
182
+ );
183
+
184
+ if (isSuspicious) {
185
+ const clientIp = req.ip || req.connection.remoteAddress;
186
+ console.warn(`⚠️ Suspicious request: ${requestPath} from ${clientIp}`);
187
+ }
188
+
189
+ next();
190
+ };
191
+ }
192
+
193
+ export default {
194
+ securityMiddleware,
195
+ sliceFrameworkProtection,
196
+ suspiciousRequestLogger
197
+ };