slicejs-web-framework 3.4.4 → 3.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.
Files changed (110) hide show
  1. package/Slice/Components/Structural/Controller/Controller.js +135 -0
  2. package/Slice/Components/Structural/EventManager/EventManager.js +289 -4
  3. package/Slice/Components/Structural/EventManager/EventManagerDebugger.js +368 -30
  4. package/Slice/Components/Structural/LeakInspector/LeakInspector.js +296 -0
  5. package/Slice/Components/Structural/StylesManager/ThemeManager/ThemeManager.js +56 -0
  6. package/Slice/Slice.js +14 -1
  7. package/Slice/tests/event-emitters.test.js +79 -0
  8. package/Slice/tests/event-registry.test.js +141 -0
  9. package/Slice/tests/leak-orphans.test.js +131 -0
  10. package/api/{middleware → framework}/securityMiddleware.js +18 -74
  11. package/api/framework/server.js +333 -0
  12. package/api/index.js +5 -279
  13. package/api/tests/public-env-resolver.test.js +1 -1
  14. package/package.json +4 -2
  15. package/sliceConfig.schema.json +10 -1
  16. package/src/App/index.html +31 -1
  17. package/src/manifest.json +15 -0
  18. package/src/robots.txt +4 -0
  19. package/src/sitemap.xml +8 -0
  20. package/src/sliceConfig.json +5 -1
  21. package/types/index.d.ts +12 -0
  22. package/slicejs-cli/.github/workflows/ci.yml +0 -43
  23. package/slicejs-cli/LICENSE +0 -21
  24. package/slicejs-cli/assets/Slice.js-logo.png +0 -0
  25. package/slicejs-cli/client.js +0 -740
  26. package/slicejs-cli/commands/Print.js +0 -164
  27. package/slicejs-cli/commands/Validations.js +0 -92
  28. package/slicejs-cli/commands/build/build.js +0 -40
  29. package/slicejs-cli/commands/buildProduction/buildProduction.js +0 -577
  30. package/slicejs-cli/commands/bundle/bundle.js +0 -236
  31. package/slicejs-cli/commands/createComponent/VisualComponentTemplate.js +0 -55
  32. package/slicejs-cli/commands/createComponent/createComponent.js +0 -128
  33. package/slicejs-cli/commands/deleteComponent/deleteComponent.js +0 -81
  34. package/slicejs-cli/commands/doctor/doctor.js +0 -516
  35. package/slicejs-cli/commands/getComponent/getComponent.js +0 -695
  36. package/slicejs-cli/commands/init/init.js +0 -473
  37. package/slicejs-cli/commands/listComponents/listComponents.js +0 -172
  38. package/slicejs-cli/commands/startServer/startServer.js +0 -240
  39. package/slicejs-cli/commands/startServer/watchServer.js +0 -66
  40. package/slicejs-cli/commands/types/types.js +0 -583
  41. package/slicejs-cli/commands/utils/LocalCliDelegation.js +0 -53
  42. package/slicejs-cli/commands/utils/PackageManager.js +0 -148
  43. package/slicejs-cli/commands/utils/PathHelper.js +0 -75
  44. package/slicejs-cli/commands/utils/VersionChecker.js +0 -169
  45. package/slicejs-cli/commands/utils/bundling/BundleGenerator.js +0 -2525
  46. package/slicejs-cli/commands/utils/bundling/DependencyAnalyzer.js +0 -933
  47. package/slicejs-cli/commands/utils/loadConfig.js +0 -31
  48. package/slicejs-cli/commands/utils/sliceScripts.js +0 -48
  49. package/slicejs-cli/commands/utils/updateManager.js +0 -471
  50. package/slicejs-cli/package.json +0 -71
  51. package/slicejs-cli/playwright.config.js +0 -51
  52. package/slicejs-cli/pnpm-lock.yaml +0 -1629
  53. package/slicejs-cli/tests/build-command-integration.test.js +0 -87
  54. package/slicejs-cli/tests/build-mangling-e2e.test.js +0 -290
  55. package/slicejs-cli/tests/build-production-e2e.test.js +0 -140
  56. package/slicejs-cli/tests/builder-edge-cases.test.js +0 -322
  57. package/slicejs-cli/tests/bundle-generate-e2e.test.js +0 -115
  58. package/slicejs-cli/tests/bundle-generator.test.js +0 -691
  59. package/slicejs-cli/tests/bundle-v2-register-output.test.js +0 -470
  60. package/slicejs-cli/tests/bundling-dependency-edges.test.js +0 -127
  61. package/slicejs-cli/tests/bundling-imports-unit.test.js +0 -267
  62. package/slicejs-cli/tests/client-launcher-contract.test.js +0 -211
  63. package/slicejs-cli/tests/commands-component-crud.test.js +0 -128
  64. package/slicejs-cli/tests/commands-doctor.test.js +0 -152
  65. package/slicejs-cli/tests/commands-version-checker.test.js +0 -37
  66. package/slicejs-cli/tests/component-registry-parse.test.js +0 -34
  67. package/slicejs-cli/tests/dependency-analyzer.test.js +0 -24
  68. package/slicejs-cli/tests/e2e/bundles.spec.js +0 -91
  69. package/slicejs-cli/tests/e2e/dependency-scenarios.spec.js +0 -56
  70. package/slicejs-cli/tests/e2e/fixtures/components/Service/FetchManager/FetchManager.js +0 -136
  71. package/slicejs-cli/tests/e2e/fixtures/components/Service/IndexedDbManager/IndexedDbManager.js +0 -149
  72. package/slicejs-cli/tests/e2e/fixtures/components/Service/LocalStorageManager/LocalStorageManager.js +0 -45
  73. package/slicejs-cli/tests/e2e/fixtures/components/Visual/Button/Button.css +0 -106
  74. package/slicejs-cli/tests/e2e/fixtures/components/Visual/Button/Button.html +0 -5
  75. package/slicejs-cli/tests/e2e/fixtures/components/Visual/Button/Button.js +0 -158
  76. package/slicejs-cli/tests/e2e/fixtures/components/Visual/Link/Link.js +0 -33
  77. package/slicejs-cli/tests/e2e/fixtures/components/Visual/Loading/Loading.css +0 -56
  78. package/slicejs-cli/tests/e2e/fixtures/components/Visual/Loading/Loading.html +0 -83
  79. package/slicejs-cli/tests/e2e/fixtures/components/Visual/Loading/Loading.js +0 -164
  80. package/slicejs-cli/tests/e2e/fixtures/components/Visual/MultiRoute/MultiRoute.js +0 -167
  81. package/slicejs-cli/tests/e2e/fixtures/components/Visual/Navbar/Navbar.css +0 -116
  82. package/slicejs-cli/tests/e2e/fixtures/components/Visual/Navbar/Navbar.html +0 -44
  83. package/slicejs-cli/tests/e2e/fixtures/components/Visual/Navbar/Navbar.js +0 -180
  84. package/slicejs-cli/tests/e2e/fixtures/components/Visual/NotFound/NotFound.js +0 -20
  85. package/slicejs-cli/tests/e2e/fixtures/components/Visual/Route/Route.js +0 -181
  86. package/slicejs-cli/tests/e2e/fixtures/components/registry.json +0 -12
  87. package/slicejs-cli/tests/e2e/fixtures/vendor-components.mjs +0 -65
  88. package/slicejs-cli/tests/e2e/navigation.spec.js +0 -44
  89. package/slicejs-cli/tests/e2e/render.spec.js +0 -34
  90. package/slicejs-cli/tests/e2e/serve.mjs +0 -264
  91. package/slicejs-cli/tests/e2e/shared-deps.spec.js +0 -61
  92. package/slicejs-cli/tests/e2e/unminified.spec.js +0 -33
  93. package/slicejs-cli/tests/e2e-serve.test.js +0 -148
  94. package/slicejs-cli/tests/fixtures/components.js +0 -8
  95. package/slicejs-cli/tests/fixtures/sliceConfig.json +0 -74
  96. package/slicejs-cli/tests/getcomponent.test.js +0 -435
  97. package/slicejs-cli/tests/helpers/setup.js +0 -102
  98. package/slicejs-cli/tests/init-command-contract.test.js +0 -101
  99. package/slicejs-cli/tests/init-e2e.test.js +0 -82
  100. package/slicejs-cli/tests/init-project-isolation.test.js +0 -98
  101. package/slicejs-cli/tests/local-cli-delegation.test.js +0 -81
  102. package/slicejs-cli/tests/package-manager.test.js +0 -127
  103. package/slicejs-cli/tests/path-helper.test.js +0 -206
  104. package/slicejs-cli/tests/perf-budget.test.js +0 -84
  105. package/slicejs-cli/tests/postinstall-command.test.js +0 -103
  106. package/slicejs-cli/tests/property-mangling-regression.test.js +0 -182
  107. package/slicejs-cli/tests/types-breakage.test.js +0 -491
  108. package/slicejs-cli/tests/types-generator-errors.test.js +0 -361
  109. package/slicejs-cli/tests/types-generator.test.js +0 -348
  110. /package/api/{utils → framework}/publicEnvResolver.js +0 -0
package/api/index.js CHANGED
@@ -1,281 +1,7 @@
1
- // api/index.js - Seguridad automática sin configuración
2
- import express from 'slicejs-web-framework/api/framework/express.js';
3
- import path from 'path';
4
- import fs from 'fs';
5
- import { fileURLToPath } from 'url';
6
- import { dirname } from 'path';
7
- import {
8
- securityMiddleware,
9
- sliceFrameworkProtection,
10
- suspiciousRequestLogger
11
- } from './middleware/securityMiddleware.js';
12
- import { createPublicEnvProvider } from './utils/publicEnvResolver.js';
1
+ // api/index.js - Punto de entrada del servidor
2
+ import { createSliceServer } from 'slicejs-web-framework/api/framework/server.js';
13
3
 
14
- const __filename = fileURLToPath(import.meta.url);
15
- const __dirname = dirname(__filename);
16
- import sliceConfig from '../src/sliceConfig.json' with { type: 'json' };
4
+ const server = createSliceServer();
5
+ server.start();
17
6
 
18
- let server;
19
- const app = express();
20
-
21
- // Parsear argumentos de línea de comandos
22
- const args = process.argv.slice(2);
23
-
24
- const runMode = process.env.NODE_ENV === 'production' ? 'production' : 'development';
25
- const folderDeployed = runMode === 'production' ? 'dist' : 'src';
26
- const publicEnvProvider = createPublicEnvProvider({
27
- mode: runMode,
28
- envFilePath: path.join(__dirname, '..', '.env')
29
- });
30
-
31
- // Obtener puerto desde process.env.PORT con fallback a sliceConfig.json
32
- const PORT = process.env.PORT || sliceConfig.server?.port || 3001;
33
-
34
- // ==============================================
35
- // MIDDLEWARES DE SEGURIDAD (APLICAR PRIMERO)
36
- // ==============================================
37
-
38
- // 1. Logger de peticiones sospechosas (solo observación, no bloquea)
39
- app.use(suspiciousRequestLogger());
40
-
41
- // 2. Protección del framework - TOTALMENTE AUTOMÁTICA
42
- // Detecta automáticamente el dominio desde los headers
43
- // Funciona en localhost, IP, y cualquier dominio
44
- app.use(sliceFrameworkProtection());
45
-
46
- // 3. Middleware de seguridad general
47
- app.use(securityMiddleware({
48
- allowedExtensions: [
49
- '.js', '.css', '.html', '.json',
50
- '.svg', '.png', '.jpg', '.jpeg', '.gif',
51
- '.woff', '.woff2', '.ttf', '.ico'
52
- ],
53
- blockedPaths: [
54
- '/node_modules',
55
- '/package.json',
56
- '/package-lock.json',
57
- '/.env',
58
- '/.git',
59
- '/api/middleware'
60
- ],
61
- allowPublicAssets: true
62
- }));
63
-
64
- // ==============================================
65
- // MIDDLEWARES DE APLICACIÓN
66
- // ==============================================
67
-
68
- // Middleware global para archivos JavaScript con MIME types correctos
69
- app.use((req, res, next) => {
70
- if (req.path.endsWith('.js')) {
71
- // Forzar headers correctos para TODOS los archivos .js
72
- res.setHeader('Content-Type', 'application/javascript; charset=utf-8');
73
- }
74
- next();
75
- });
76
-
77
- // Middleware para parsear JSON y formularios
78
- app.use(express.json());
79
- app.use(express.urlencoded({ extended: true }));
80
-
81
- // Configurar headers de CORS
82
- app.use((req, res, next) => {
83
- res.header('Access-Control-Allow-Origin', '*');
84
- res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
85
- res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
86
-
87
- if (req.method === 'OPTIONS') {
88
- res.sendStatus(200);
89
- } else {
90
- next();
91
- }
92
- });
93
-
94
- // ==============================================
95
- // RUNTIME MODE ENDPOINT
96
- // ==============================================
97
-
98
- app.get('/slice-env.json', (req, res) => {
99
- const payload = publicEnvProvider.getPayload();
100
- res.setHeader('Cache-Control', 'no-store');
101
- res.setHeader('Pragma', 'no-cache');
102
- res.setHeader('Expires', '0');
103
- res.json(payload);
104
- });
105
-
106
- // ==============================================
107
- // ARCHIVOS ESTÁTICOS (DESPUÉS DE SEGURIDAD)
108
- // ==============================================
109
-
110
- if (runMode === 'production') {
111
- app.get('/Slice/Slice.js', (req, res) => {
112
- const slicePath = path.join(__dirname, '..', 'node_modules', 'slicejs-web-framework', 'Slice', 'Slice.js');
113
- try {
114
- if (fs.existsSync(slicePath)) {
115
- res.setHeader('Content-Type', 'application/javascript; charset=utf-8');
116
- return res.send(fs.readFileSync(slicePath, 'utf8'));
117
- }
118
- } catch (error) {
119
- console.error(`Error reading Slice.js:`, error);
120
- return res.status(500).send('Error loading framework');
121
- }
122
- return res.status(404).send('Slice.js not found');
123
- });
124
-
125
- app.use('/Slice', (req, res) => res.status(404).send('Not found'));
126
- app.use('/Components', (req, res) => res.status(404).send('Not found'));
127
- }
128
-
129
- // Middleware personalizado para archivos de bundles con MIME types correctos
130
- // ⚠️ DEBE IR ANTES del middleware general para tener prioridad
131
- app.use('/bundles/', (req, res, next) => {
132
- // Solo procesar archivos .js
133
- if (req.path.endsWith('.js')) {
134
- const filePath = path.join(__dirname, `../${folderDeployed}`, 'bundles', req.path);
135
- console.log(`📂 Processing bundle: ${req.path} -> ${filePath}`);
136
-
137
- // Verificar que el archivo existe
138
- if (fs.existsSync(filePath)) {
139
- try {
140
- // Leer y servir el archivo con headers correctos
141
- const fileContent = fs.readFileSync(filePath, 'utf8');
142
- res.setHeader('Content-Type', 'application/javascript; charset=utf-8');
143
- res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate'); // No cachear para permitir actualizaciones en tiempo real
144
- res.setHeader('Pragma', 'no-cache');
145
- res.setHeader('Expires', '0');
146
- console.log(`✅ Serving bundle: ${req.path} (${fileContent.length} bytes, ${Buffer.byteLength(fileContent, 'utf8')} bytes UTF-8)`);
147
- return res.send(fileContent);
148
- } catch (error) {
149
- console.error(`Error reading bundle file:`, error);
150
- return res.status(500).send('Error reading bundle file');
151
- }
152
- } else {
153
- console.log(`❌ Bundle file not found: ${filePath}`);
154
- return res.status(404).send('Bundle file not found');
155
- }
156
- }
157
-
158
- // Para archivos no .js, continuar con el middleware estático normal
159
- next();
160
- });
161
-
162
- // Servir otros archivos de bundles (JSON, CSS, etc.) con el middleware estático normal
163
- app.use('/bundles/', express.static(path.join(__dirname, `../${folderDeployed}`, 'bundles')));
164
- console.log(`📦 Serving bundles from /${folderDeployed}/bundles`);
165
-
166
- // Servir framework Slice.js (solo development)
167
- if (runMode === 'development') {
168
- app.use('/Slice/', express.static(path.join(__dirname, '..', 'node_modules', 'slicejs-web-framework', 'Slice')));
169
- }
170
-
171
- // Servir archivos estáticos del proyecto con allowlist
172
- const publicFolders = Array.isArray(sliceConfig.publicFolders) ? sliceConfig.publicFolders : [];
173
- const normalizedPublicFolders = publicFolders
174
- .filter((entry) => typeof entry === 'string')
175
- .map((entry) => entry.trim())
176
- .filter((entry) => entry.length > 0)
177
- .map((entry) => (entry.startsWith('/') ? entry : `/${entry}`));
178
-
179
- if (runMode === 'development') {
180
- app.use(express.static(path.join(__dirname, `../${folderDeployed}`)));
181
- } else {
182
- app.use('/App', express.static(path.join(__dirname, `../${folderDeployed}`, 'App')));
183
- const serveStaticFile = (req, res, filePath, contentType, fileName) => {
184
- try {
185
- if (fs.existsSync(filePath)) {
186
- res.setHeader('Content-Type', contentType);
187
- return res.send(fs.readFileSync(filePath, 'utf8'));
188
- }
189
- } catch (error) {
190
- console.error(`Error reading ${fileName}:`, error);
191
- return res.status(500).send(`Error reading ${fileName}`);
192
- }
193
- return res.status(404).send(`${fileName} not found`);
194
- };
195
-
196
- app.get('/manifest.json', (req, res) => {
197
- const manifestPath = path.join(__dirname, `../${folderDeployed}`, 'manifest.json');
198
- serveStaticFile(req, res, manifestPath, 'application/json; charset=utf-8', 'manifest.json');
199
- });
200
- app.get('/service-worker.js', (req, res) => {
201
- const workerPath = path.join(__dirname, `../${folderDeployed}`, 'service-worker.js');
202
- serveStaticFile(req, res, workerPath, 'application/javascript; charset=utf-8', 'service-worker.js');
203
- });
204
- app.get('/routes.js', (req, res) => {
205
- const routesPath = path.join(__dirname, `../${folderDeployed}`, 'routes.js');
206
- serveStaticFile(req, res, routesPath, 'application/javascript; charset=utf-8', 'routes.js');
207
- });
208
- app.get('/sliceConfig.json', (req, res) => {
209
- const configPath = path.join(__dirname, `../${folderDeployed}`, 'sliceConfig.json');
210
- serveStaticFile(req, res, configPath, 'application/json; charset=utf-8', 'sliceConfig.json');
211
- });
212
- for (const folder of normalizedPublicFolders) {
213
- app.use(folder, express.static(path.join(__dirname, `../${folderDeployed}`, folder)));
214
- }
215
- app.use('/bundles/', express.static(path.join(__dirname, `../${folderDeployed}`, 'bundles')));
216
- app.use('/dist/', express.static(path.join(__dirname, '..', 'dist')));
217
- }
218
-
219
- // ==============================================
220
- // RUTAS DE API
221
- // ==============================================
222
-
223
- // Ruta de ejemplo para API
224
- app.get('/api/status', (req, res) => {
225
- res.json({
226
- status: 'ok',
227
- mode: runMode,
228
- folder: folderDeployed,
229
- timestamp: new Date().toISOString(),
230
- framework: 'Slice.js',
231
- version: '2.0.0',
232
- security: {
233
- enabled: true,
234
- mode: 'automatic',
235
- description: 'Zero-config security - works with any domain'
236
- }
237
- });
238
- });
239
-
240
-
241
- // ==============================================
242
- // SPA FALLBACK
243
- // ==============================================
244
-
245
- // SPA fallback - servir index.html para rutas no encontradas
246
- app.get('*', (req, res) => {
247
- const indexPath = path.join(__dirname, `../${folderDeployed}`, "App", 'index.html');
248
- res.sendFile(indexPath, (err) => {
249
- if (err) {
250
- console.error(`[SPA Fallback] Error sending ${indexPath}:`, err);
251
- res.status(500).send(`<h1>500 - Internal Server Error</h1><p>Could not serve application file</p>`);
252
- }
253
- });
254
- });
255
-
256
- // ==============================================
257
- // INICIO DEL SERVIDOR
258
- // ==============================================
259
-
260
- function startServer() {
261
- server = app.listen(PORT, () => {
262
- console.log(`🔒 Security middleware: active (zero-config, automatic)`);
263
- console.log(`🚀 Slice.js server running on port ${PORT}`);
264
- });
265
- }
266
-
267
- // Manejar cierre del proceso
268
- process.on('SIGINT', () => {
269
- console.log('\n🛑 Slice server stopped');
270
- process.exit(0);
271
- });
272
-
273
- process.on('SIGTERM', () => {
274
- console.log('\n🛑 Server terminated');
275
- process.exit(0);
276
- });
277
-
278
- // Iniciar servidor
279
- startServer();
280
-
281
- export default app;
7
+ export default server.app;
@@ -4,7 +4,7 @@ import { mkdtemp, rm, writeFile } from 'node:fs/promises';
4
4
  import path from 'node:path';
5
5
  import { tmpdir } from 'node:os';
6
6
 
7
- const resolverModulePath = new URL('../utils/publicEnvResolver.js', import.meta.url);
7
+ const resolverModulePath = new URL('../framework/publicEnvResolver.js', import.meta.url);
8
8
 
9
9
  async function withTempEnvFile(contents, callback) {
10
10
  const dir = await mkdtemp(path.join(tmpdir(), 'slice-public-env-'));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slicejs-web-framework",
3
- "version": "3.4.4",
3
+ "version": "3.5.1",
4
4
  "description": "",
5
5
  "engines": {
6
6
  "node": ">=20"
@@ -25,10 +25,12 @@
25
25
  "type": "module",
26
26
  "exports": {
27
27
  ".": "./Slice/Slice.js",
28
- "./api/framework/express.js": "./api/framework/express.js"
28
+ "./api/framework/express.js": "./api/framework/express.js",
29
+ "./api/framework/server.js": "./api/framework/server.js"
29
30
  },
30
31
  "types": "./types/index.d.ts",
31
32
  "dependencies": {
33
+ "compression": "^1.8.1",
32
34
  "express": "^4.19.2"
33
35
  },
34
36
  "devDependencies": {
@@ -10,7 +10,16 @@
10
10
  "additionalProperties": true,
11
11
  "properties": {
12
12
  "enabled": { "type": "boolean" },
13
- "click": { "type": "string", "enum": ["right", "left"] }
13
+ "click": { "type": "string", "enum": ["right", "left"] },
14
+ "leakInspector": {
15
+ "type": "object",
16
+ "additionalProperties": true,
17
+ "description": "Dev-only memory-leak panel. Disabled in production regardless of this flag.",
18
+ "properties": {
19
+ "enabled": { "type": "boolean" },
20
+ "shortcut": { "type": "string" }
21
+ }
22
+ }
14
23
  }
15
24
  },
16
25
  "stylesManager": {
@@ -3,9 +3,39 @@
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Slice App</title>
6
+ <title>Slice.js Web Framework</title>
7
+ <meta name="description" content="Slice.js — a lightweight web framework built on native Web Components. Build web apps one slice at a time. No build step required." />
8
+ <meta name="robots" content="index, follow" />
9
+ <meta name="author" content="vkneider.dev" />
10
+ <link rel="canonical" href="https://slicejs.com" />
7
11
  <link rel="icon" type="image/x-icon" href="/images/favicon.ico" />
12
+ <link rel="manifest" href="/manifest.json" />
13
+ <meta name="theme-color" content="#F8F4FF" />
14
+ <meta name="color-scheme" content="light dark" />
15
+ <meta property="og:type" content="website" />
16
+ <meta property="og:title" content="Slice.js Web Framework" />
17
+ <meta property="og:description" content="Slice.js — a lightweight web framework built on native Web Components. Build web apps one slice at a time. No build step required." />
18
+ <meta property="og:url" content="https://slicejs.com" />
19
+ <meta property="og:image" content="https://slicejs.com/images/og-image.png" />
20
+ <meta name="twitter:card" content="summary_large_image" />
21
+ <meta name="twitter:title" content="Slice.js Web Framework" />
22
+ <meta name="twitter:description" content="Slice.js — a lightweight web framework built on native Web Components." />
23
+ <meta name="twitter:image" content="https://slicejs.com/images/og-image.png" />
8
24
  <link rel="stylesheet" type="text/css" href="/App/style.css" />
25
+ <script type="application/ld+json">
26
+ {
27
+ "@context": "https://schema.org",
28
+ "@type": "WebSite",
29
+ "name": "Slice.js Web Framework",
30
+ "url": "https://slicejs.com",
31
+ "description": "Slice.js — a lightweight web framework built on native Web Components. Build web apps one slice at a time.",
32
+ "author": {
33
+ "@type": "Organization",
34
+ "name": "VKneider",
35
+ "url": "https://github.com/VKneider"
36
+ }
37
+ }
38
+ </script>
9
39
  </head>
10
40
 
11
41
  <body>
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "Slice.js Web Framework",
3
+ "short_name": "Slice.js",
4
+ "start_url": "/",
5
+ "display": "standalone",
6
+ "background_color": "#F8F4FF",
7
+ "theme_color": "#F8F4FF",
8
+ "icons": [
9
+ {
10
+ "src": "/images/favicon.ico",
11
+ "sizes": "192x192 512x512",
12
+ "type": "image/x-icon"
13
+ }
14
+ ]
15
+ }
package/src/robots.txt ADDED
@@ -0,0 +1,4 @@
1
+ User-agent: *
2
+ Allow: /
3
+
4
+ Sitemap: https://slicejs.com/sitemap.xml
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3
+ <url>
4
+ <loc>https://slicejs.com/</loc>
5
+ <priority>1.0</priority>
6
+ <changefreq>weekly</changefreq>
7
+ </url>
8
+ </urlset>
@@ -5,7 +5,11 @@
5
5
  },
6
6
  "debugger": {
7
7
  "enabled": false,
8
- "click": "right"
8
+ "click": "right",
9
+ "leakInspector": {
10
+ "enabled": true,
11
+ "shortcut": "alt+shift+k"
12
+ }
9
13
  },
10
14
  "events": {
11
15
  "enabled": true,
package/types/index.d.ts CHANGED
@@ -44,6 +44,10 @@ export interface SliceControllerApi {
44
44
  destroyComponent(components: HTMLElement | string | Array<HTMLElement | string>): number;
45
45
  destroyByContainer(container: HTMLElement): number;
46
46
  destroyByPattern(pattern: string | RegExp): number;
47
+ findOrphans(): Array<{ sliceId: string; name: string; reason: string; retainPath: string[] }>;
48
+ registerLeakExclusion(predicate: (component: HTMLElement) => boolean): void;
49
+ sampleComponentGrowth(): void;
50
+ isGrowthMonotonic(): boolean;
47
51
  }
48
52
 
49
53
  export interface SliceStylesManagerApi {
@@ -88,6 +92,13 @@ export interface SliceEventManagerApi {
88
92
  unsubscribe(eventName: string, subscriptionId: string): boolean;
89
93
  emit(eventName: string, ...data: unknown[]): void;
90
94
  bind(component: HTMLElement): SliceEventBindingApi | null;
95
+ register(namespace: string, catalog: Record<string, { description?: string; payload?: unknown }>): SliceEventManagerApi;
96
+ register(catalog: Record<string, { description?: string; payload?: unknown }>): SliceEventManagerApi;
97
+ loadGraph(graph: { events: Record<string, unknown>; dynamic?: unknown }): SliceEventManagerApi;
98
+ staticEmittersOf(eventName: string): Array<{ file: string; line: number; component: string | null }>;
99
+ staticListenersOf(eventName: string): Array<{ file: string; line: number; component: string | null }>;
100
+ isDeclared(eventName: string): boolean;
101
+ namespaceOf(eventName: string): string | null;
91
102
  cleanupComponent(sliceId: string): number;
92
103
  hasSubscribers(eventName: string): boolean;
93
104
  subscriberCount(eventName: string): number;
@@ -178,6 +189,7 @@ export interface SliceApi {
178
189
  debugger?: SliceDebuggerApi;
179
190
  eventsDebugger?: SlicePanelDebuggerApi;
180
191
  contextDebugger?: SlicePanelDebuggerApi;
192
+ leakInspector?: SlicePanelDebuggerApi;
181
193
  loading?: SliceLoadingApi;
182
194
  paths: SlicePaths;
183
195
  _mode: SliceMode;
@@ -1,43 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- push:
5
- branches: [master, main]
6
- pull_request:
7
-
8
- jobs:
9
- test:
10
- runs-on: ubuntu-latest
11
- timeout-minutes: 20
12
- steps:
13
- - uses: actions/checkout@v4
14
-
15
- - uses: pnpm/action-setup@v4
16
- with:
17
- version: 11
18
-
19
- - uses: actions/setup-node@v4
20
- with:
21
- node-version: 22
22
- cache: pnpm
23
-
24
- - name: Install dependencies
25
- run: pnpm install --frozen-lockfile
26
-
27
- - name: Install Playwright browser
28
- run: pnpm exec playwright install --with-deps chromium
29
-
30
- # Serialized to avoid resource contention between the build-heavy
31
- # integration tests under parallel runners.
32
- - name: Unit & integration tests
33
- run: node --test --test-concurrency=1
34
-
35
- - name: Browser E2E tests
36
- run: pnpm exec playwright test
37
-
38
- - uses: actions/upload-artifact@v4
39
- if: ${{ !cancelled() }}
40
- with:
41
- name: playwright-report
42
- path: playwright-report/
43
- retention-days: 7
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 Victor Jose Kneider Alnahi and Julio Antonio Graterol Bracho
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.