slicejs-cli 3.4.0 → 3.4.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 (35) hide show
  1. package/AGENTS.md +247 -0
  2. package/client.js +63 -64
  3. package/commands/Print.js +11 -15
  4. package/commands/Validations.js +12 -23
  5. package/commands/buildProduction/buildProduction.js +23 -26
  6. package/commands/bundle/bundle.js +10 -11
  7. package/commands/createComponent/createComponent.js +14 -16
  8. package/commands/deleteComponent/deleteComponent.js +6 -6
  9. package/commands/doctor/doctor.js +11 -14
  10. package/commands/getComponent/getComponent.js +99 -162
  11. package/commands/init/init.js +25 -21
  12. package/commands/listComponents/listComponents.js +18 -21
  13. package/commands/startServer/startServer.js +21 -24
  14. package/commands/startServer/watchServer.js +7 -7
  15. package/commands/types/types.js +53 -18
  16. package/commands/utils/PathHelper.js +9 -2
  17. package/commands/utils/VersionChecker.js +3 -3
  18. package/commands/utils/bundling/DependencyAnalyzer.js +8 -16
  19. package/commands/utils/loadConfig.js +31 -0
  20. package/commands/utils/updateManager.js +3 -4
  21. package/docs/superpowers/specs/2026-05-10-pwa-generate-design.md +105 -105
  22. package/package.json +15 -3
  23. package/post.js +2 -2
  24. package/tests/bundle-generator.test.js +3 -20
  25. package/tests/component-registry-parse.test.js +34 -0
  26. package/tests/fixtures/components.js +8 -0
  27. package/tests/fixtures/sliceConfig.json +74 -0
  28. package/tests/getcomponent.test.js +407 -0
  29. package/tests/helpers/setup.js +97 -0
  30. package/tests/init-command-contract.test.js +46 -0
  31. package/tests/local-cli-delegation.test.js +7 -5
  32. package/tests/path-helper.test.js +206 -0
  33. package/tests/types-breakage.test.js +491 -0
  34. package/tests/types-generator-errors.test.js +361 -0
  35. package/tests/types-generator.test.js +172 -184
@@ -1,64 +1,64 @@
1
- # Diseno de `slice generate-pwa` (V1)
1
+ # Design of `slice generate-pwa` (V1)
2
2
 
3
- ## Objetivo
3
+ ## Objective
4
4
 
5
- Agregar un comando dedicado de CLI, `slice generate-pwa`, que convierta un build de Slice en una PWA usable offline, con estrategia de cache configurable y exclusion explicita de dominios de backend para evitar cache accidental de APIs REST.
5
+ Add a dedicated CLI command, `slice generate-pwa`, that converts a Slice build into an offline-capable PWA, with configurable cache strategy and explicit backend domain exclusion to prevent accidental REST API caching.
6
6
 
7
- El comando debe ser postbundle, operar sobre `dist/` y mantener una experiencia simple de V1.
7
+ The command must be post-bundle, operate on `dist/`, and maintain a simple V1 experience.
8
8
 
9
- ## Alcance V1
9
+ ## V1 Scope
10
10
 
11
- - Nuevo comando `slice generate-pwa`.
12
- - Ejecutar `build` automaticamente antes del proceso PWA.
13
- - Generar `manifest.json` en `dist/`.
14
- - Generar `sw.js` en `dist/`.
15
- - Registrar Service Worker en el HTML de entrada de `dist`.
16
- - Soportar estrategias: `hybrid` (default), `offline-first`, `network-first`.
17
- - Persistir y leer configuracion desde `src/sliceConfig.json` en:
11
+ - New `slice generate-pwa` command.
12
+ - Automatically run `build` before the PWA process.
13
+ - Generate `manifest.json` in `dist/`.
14
+ - Generate `sw.js` in `dist/`.
15
+ - Register Service Worker in the entry HTML of `dist`.
16
+ - Support strategies: `hybrid` (default), `offline-first`, `network-first`.
17
+ - Persist and read configuration from `src/sliceConfig.json` in:
18
18
  - `pwa.cache.excludeDomains`.
19
- - Aplicar exclusion efectiva de `localhost` y `127.0.0.1` en desarrollo.
19
+ - Apply effective exclusion of `localhost` and `127.0.0.1` in development.
20
20
 
21
- ## Fuera de alcance V1
21
+ ## Out of V1 Scope
22
22
 
23
- - Exclusion por paths o headers (`excludePaths`, `excludeHeaders`).
24
- - UI interactiva avanzada para crear iconos PWA.
25
- - Soporte de push notifications, background sync o runtime caching avanzado por tipo de API.
26
- - Plugin system formal; se deja preparado para evolucion futura.
23
+ - Exclusion by paths or headers (`excludePaths`, `excludeHeaders`).
24
+ - Advanced interactive UI for creating PWA icons.
25
+ - Support for push notifications, background sync, or advanced runtime caching by API type.
26
+ - Formal plugin system; left prepared for future evolution.
27
27
 
28
- ## UX del comando
28
+ ## Command UX
29
29
 
30
- ### Sintaxis
30
+ ### Syntax
31
31
 
32
32
  ```bash
33
33
  slice generate-pwa
34
34
  slice generate-pwa --strategy hybrid
35
35
  slice generate-pwa --strategy offline-first
36
36
  slice generate-pwa --strategy network-first
37
- slice generate-pwa --name "Mi App" --short-name "MiApp"
37
+ slice generate-pwa --name "My App" --short-name "MyApp"
38
38
  ```
39
39
 
40
- ### Flags V1
40
+ ### V1 Flags
41
41
 
42
42
  - `--strategy <hybrid|offline-first|network-first>` (default: `hybrid`)
43
43
  - `--name <string>`
44
44
  - `--short-name <string>`
45
45
 
46
- ### Flujo de ejecucion
46
+ ### Execution flow
47
47
 
48
- 1. Ejecuta build de produccion.
49
- 2. Lee y normaliza configuracion PWA en `src/sliceConfig.json`.
50
- 3. Genera manifiesto de assets para precache desde `dist/`.
51
- 4. Genera `dist/manifest.json`.
52
- 5. Genera `dist/sw.js` con la estrategia seleccionada.
53
- 6. Inyecta (o asegura) registro SW en HTML de entrada de `dist`.
54
- 7. Imprime resumen final:
55
- - estrategia usada,
56
- - cantidad de assets precacheados,
57
- - dominios excluidos efectivos.
48
+ 1. Run production build.
49
+ 2. Read and normalize PWA configuration from `src/sliceConfig.json`.
50
+ 3. Generate asset manifest for precache from `dist/`.
51
+ 4. Generate `dist/manifest.json`.
52
+ 5. Generate `dist/sw.js` with the selected strategy.
53
+ 6. Inject (or ensure) SW registration in entry HTML of `dist`.
54
+ 7. Print final summary:
55
+ - strategy used,
56
+ - number of precached assets,
57
+ - effective excluded domains.
58
58
 
59
- ## Configuracion en `sliceConfig.json`
59
+ ## Configuration in `sliceConfig.json`
60
60
 
61
- Seccion minima V1:
61
+ V1 minimal section:
62
62
 
63
63
  ```json
64
64
  {
@@ -70,113 +70,113 @@ Seccion minima V1:
70
70
  }
71
71
  ```
72
72
 
73
- Reglas:
73
+ Rules:
74
74
 
75
- - Si `pwa` no existe, el comando crea la seccion sin romper configuracion previa.
76
- - `excludeDomains` acepta hosts exactos (ej: `api.midominio.com`).
77
- - En ejecucion de desarrollo, se agregan de forma efectiva (no necesariamente persistida) `localhost` y `127.0.0.1`.
75
+ - If `pwa` does not exist, the command creates the section without breaking existing configuration.
76
+ - `excludeDomains` accepts exact hosts (e.g., `api.mydomain.com`).
77
+ - In development execution, `localhost` and `127.0.0.1` are effectively added (not necessarily persisted).
78
78
 
79
- ## Arquitectura propuesta
79
+ ## Proposed Architecture
80
80
 
81
- ### Integracion CLI
81
+ ### CLI Integration
82
82
 
83
- - Agregar comando en `client.js`:
83
+ - Add command in `client.js`:
84
84
  - `generate-pwa`
85
- - opcion `--strategy`
86
- - opciones de nombre para manifest
85
+ - `--strategy` option
86
+ - name options for manifest
87
87
 
88
- ### Modulos nuevos
88
+ ### New Modules
89
89
 
90
90
  - `commands/pwa/generatePwa.js`
91
- - Orquestador del flujo completo.
91
+ - Orchestrator of the complete flow.
92
92
  - `commands/pwa/ConfigResolver.js`
93
- - Lee/crea/normaliza `pwa.cache.excludeDomains`.
93
+ - Reads/creates/normalizes `pwa.cache.excludeDomains`.
94
94
  - `commands/pwa/AssetManifestBuilder.js`
95
- - Recorre `dist/` y arma lista precache.
95
+ - Iterates `dist/` and builds precache list.
96
96
  - `commands/pwa/ManifestGenerator.js`
97
- - Genera `manifest.json` con defaults y overrides por flags.
97
+ - Generates `manifest.json` with defaults and flag overrides.
98
98
  - `commands/pwa/ServiceWorkerGenerator.js`
99
- - Genera `sw.js` con estrategia seleccionada y exclusiones.
99
+ - Generates `sw.js` with selected strategy and exclusions.
100
100
 
101
- ## Diseno de cache
101
+ ## Cache Design
102
102
 
103
- ### Reglas globales
103
+ ### Global Rules
104
104
 
105
- - Interceptar solo requests `GET`.
106
- - Si el host esta en `excludeDomains`, hacer `fetch` directo (sin cache).
107
- - Versionado de cache por build id (timestamp o hash de build).
108
- - Al activar nuevo SW, limpiar caches viejas automaticamente.
105
+ - Intercept only `GET` requests.
106
+ - If the host is in `excludeDomains`, do a direct `fetch` (no cache).
107
+ - Cache versioning by build id (timestamp or build hash).
108
+ - On new SW activation, automatically clean old caches.
109
109
 
110
- ### Estrategias
110
+ ### Strategies
111
111
 
112
112
  - `hybrid` (default):
113
- - assets estaticos -> `cache-first`.
114
- - navegacion HTML -> `network-first` con fallback offline.
113
+ - static assets -> `cache-first`.
114
+ - HTML navigation -> `network-first` with offline fallback.
115
115
  - `offline-first`:
116
- - navegacion + estaticos -> `cache-first`.
117
- - update en background cuando haya red.
116
+ - navigation + static -> `cache-first`.
117
+ - background update when online.
118
118
  - `network-first`:
119
- - navegacion -> `network-first`.
120
- - estaticos precacheados como respaldo.
119
+ - navigation -> `network-first`.
120
+ - precached static assets as fallback.
121
121
 
122
- ## Manejo de API REST y seguridad
122
+ ## REST API and Security Handling
123
123
 
124
- Para evitar cache de backend no deseado:
124
+ To prevent unwanted backend caching:
125
125
 
126
- - Exclusion por dominio con `excludeDomains` (regla principal de V1).
127
- - Limitar runtime cache a activos del frontend y navegacion segun estrategia.
128
- - No cachear metodos distintos de `GET`.
126
+ - Domain exclusion via `excludeDomains` (main V1 rule).
127
+ - Limit runtime cache to frontend assets and navigation per strategy.
128
+ - Do not cache methods other than `GET`.
129
129
 
130
- Resultado: los assets del cliente se aceleran offline, pero el backend queda fuera de cache por configuracion explicita.
130
+ Result: client assets are accelerated offline, but the backend stays out of the cache via explicit configuration.
131
131
 
132
132
  ## Error handling
133
133
 
134
- - Si build falla, abortar `generate-pwa` con mensaje claro.
135
- - Si `dist/` no existe tras build, abortar con diagnostico.
136
- - Si `sliceConfig.json` es invalido, mostrar error con sugerencia de reparacion.
137
- - Si no se puede inyectar registro SW en HTML, reportar warning y ruta objetivo.
134
+ - If build fails, abort `generate-pwa` with a clear message.
135
+ - If `dist/` does not exist after build, abort with diagnostics.
136
+ - If `sliceConfig.json` is invalid, show error with repair suggestion.
137
+ - If SW registration cannot be injected into HTML, report warning and target path.
138
138
 
139
139
  ## Testing
140
140
 
141
141
  ### Unit tests
142
142
 
143
143
  - `ConfigResolver`:
144
- - crea seccion `pwa.cache.excludeDomains` cuando no existe,
145
- - respeta config existente.
144
+ - creates `pwa.cache.excludeDomains` section when it does not exist,
145
+ - respects existing config.
146
146
  - `AssetManifestBuilder`:
147
- - incluye assets esperados,
148
- - excluye archivos no aptos.
147
+ - includes expected assets,
148
+ - excludes unsuitable files.
149
149
  - `ServiceWorkerGenerator`:
150
- - genera logica correcta por estrategia,
151
- - respeta `excludeDomains`.
150
+ - generates correct logic per strategy,
151
+ - respects `excludeDomains`.
152
152
 
153
- ### Integracion
153
+ ### Integration
154
154
 
155
- - `slice generate-pwa` ejecuta build y crea `dist/manifest.json` + `dist/sw.js`.
156
- - registro SW presente en HTML de salida.
157
- - exclusiones de dominio aplicadas en codigo generado.
155
+ - `slice generate-pwa` runs build and creates `dist/manifest.json` + `dist/sw.js`.
156
+ - SW registration present in output HTML.
157
+ - domain exclusions applied in generated code.
158
158
 
159
- ### E2E manual minima
159
+ ### Minimal E2E manual
160
160
 
161
161
  - Build + generate-pwa.
162
- - Abrir app, validar installability (manifest).
163
- - Apagar red, validar navegacion offline en `hybrid`.
164
- - Verificar que requests a dominio excluido no se sirven desde cache SW.
165
-
166
- ## Plan de evolucion (post V1)
167
-
168
- - `excludePaths` y `excludeHeaders`.
169
- - soporte de iconos y shortcuts PWA asistidos.
170
- - estrategia por ruta (ej: `/api/*` network-only).
171
- - extraer pipeline postbundle reusable para otras features.
172
-
173
- ## Criterios de aceptacion
174
-
175
- - Existe comando `slice generate-pwa` funcional.
176
- - Ejecuta build antes de generar artefactos PWA.
177
- - Genera `manifest.json` y `sw.js` en `dist/`.
178
- - Registra SW en HTML principal de salida.
179
- - `hybrid` es default con HTML `network-first` y fallback offline.
180
- - Lee/escribe `pwa.cache.excludeDomains` en `src/sliceConfig.json`.
181
- - Excluye dominios configurados del cache runtime.
182
- - Muestra resumen final legible al usuario.
162
+ - Open app, validate installability (manifest).
163
+ - Turn off network, validate offline navigation in `hybrid`.
164
+ - Verify that requests to excluded domain are not served from SW cache.
165
+
166
+ ## Evolution Plan (post V1)
167
+
168
+ - `excludePaths` and `excludeHeaders`.
169
+ - Assisted PWA icon and shortcut support.
170
+ - Per-route strategy (e.g., `/api/*` network-only).
171
+ - Extract reusable postbundle pipeline for other features.
172
+
173
+ ## Acceptance Criteria
174
+
175
+ - Functional `slice generate-pwa` command exists.
176
+ - Runs build before generating PWA artifacts.
177
+ - Generates `manifest.json` and `sw.js` in `dist/`.
178
+ - Registers SW in main output HTML.
179
+ - `hybrid` is default with HTML `network-first` and offline fallback.
180
+ - Reads/writes `pwa.cache.excludeDomains` in `src/sliceConfig.json`.
181
+ - Excludes configured domains from runtime cache.
182
+ - Shows a readable final summary to the user.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slicejs-cli",
3
- "version": "3.4.0",
3
+ "version": "3.4.1",
4
4
  "description": "Command client for developing web applications with Slice.js framework",
5
5
  "main": "client.js",
6
6
  "bin": {
@@ -12,7 +12,19 @@
12
12
  },
13
13
  "scripts": {
14
14
  "test": "node --test",
15
- "postinstall": "node post.js"
15
+ "postinstall": "node post.js",
16
+ "slice:dev": "slice dev",
17
+ "slice:start": "slice start",
18
+ "slice:create": "slice component create",
19
+ "slice:list": "slice component list",
20
+ "slice:delete": "slice component delete",
21
+ "slice:init": "slice init",
22
+ "slice:get": "slice get",
23
+ "slice:browse": "slice browse",
24
+ "slice:sync": "slice sync",
25
+ "slice:version": "slice version",
26
+ "slice:update": "slice update",
27
+ "slice:types": "slice types generate"
16
28
  },
17
29
  "keywords": [
18
30
  "framework",
@@ -43,4 +55,4 @@
43
55
  "slicejs-web-framework": "latest",
44
56
  "terser": "^5.43.1"
45
57
  }
46
- }
58
+ }
package/post.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
3
  import { fileURLToPath } from 'url';
4
- import { getProjectRoot } from './commands/utils/PathHelper.js';
4
+ import { getProjectRoot, getPath } from './commands/utils/PathHelper.js';
5
5
 
6
6
  const __filename = fileURLToPath(import.meta.url);
7
7
 
@@ -15,7 +15,7 @@ if (isGlobal) {
15
15
  }
16
16
 
17
17
  const projectRoot = getProjectRoot(import.meta.url);
18
- const pkgPath = path.join(projectRoot, 'package.json');
18
+ const pkgPath = getPath(import.meta.url, 'package.json');
19
19
 
20
20
  const sliceScripts = {
21
21
  'slice:dev': 'slice dev',
@@ -4,6 +4,7 @@ import fs from 'fs-extra';
4
4
  import os from 'node:os';
5
5
  import path from 'node:path';
6
6
  import BundleGenerator from '../commands/utils/bundling/BundleGenerator.js';
7
+ import { withTestProject } from './helpers/setup.js';
7
8
 
8
9
  const createComponent = (name, deps = []) => ({
9
10
  name,
@@ -78,18 +79,7 @@ test('loading policy is enabled when sliceConfig loading.enabled is true', () =>
78
79
  });
79
80
 
80
81
  test('loading policy falls back to project sliceConfig when analysisData lacks sliceConfig', async () => {
81
- const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'slice-bundle-test-'));
82
- const srcDir = path.join(tempRoot, 'src');
83
- const previousInitCwd = process.env.INIT_CWD;
84
-
85
- await fs.ensureDir(srcDir);
86
- await fs.writeJson(path.join(srcDir, 'sliceConfig.json'), {
87
- loading: { enabled: true }
88
- });
89
-
90
- process.env.INIT_CWD = tempRoot;
91
-
92
- try {
82
+ await withTestProject(async () => {
93
83
  const generator = new BundleGenerator(import.meta.url, {
94
84
  components: [],
95
85
  routes: [],
@@ -103,14 +93,7 @@ test('loading policy falls back to project sliceConfig when analysisData lacks s
103
93
 
104
94
  const config = generator.generateBundleConfig(null);
105
95
  assert.equal(config.loadingPolicy, 'enabled');
106
- } finally {
107
- if (previousInitCwd === undefined) {
108
- delete process.env.INIT_CWD;
109
- } else {
110
- process.env.INIT_CWD = previousInitCwd;
111
- }
112
- await fs.remove(tempRoot);
113
- }
96
+ });
114
97
  });
115
98
 
116
99
  test('loading enabled always includes Loading component in critical bundle', () => {
@@ -0,0 +1,34 @@
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { createTestProject, cleanupTestProject, withTestProject } from './helpers/setup.js';
6
+
7
+ test('generateTypesFile parses JSON from components.js (no eval)', async () => {
8
+ const tmpRoot = await createTestProject({ visualComponents: ['Button'] });
9
+
10
+ try {
11
+ const srcDir = path.join(tmpRoot, 'src');
12
+ const { generateTypesFile } = await import('../commands/types/types.js');
13
+ const result = await generateTypesFile({
14
+ projectRoot: tmpRoot,
15
+ outputPath: path.join(srcDir, 'slice-build.generated.d.ts')
16
+ });
17
+
18
+ assert.ok(result.componentsProcessed > 0);
19
+ assert.equal(fs.existsSync(result.outputPath), true);
20
+
21
+ const declaration = fs.readFileSync(result.outputPath, 'utf8');
22
+ assert.match(declaration, /export interface ButtonProps/);
23
+ } finally {
24
+ await cleanupTestProject(tmpRoot);
25
+ }
26
+ });
27
+
28
+ test('Validations componentExists with JSON.parse (no eval)', async () => {
29
+ await withTestProject(async (tmpDir) => {
30
+ const validations = (await import('../commands/Validations.js')).default;
31
+ assert.equal(validations.componentExists('Button'), true);
32
+ assert.equal(validations.componentExists('NonExistent'), false);
33
+ });
34
+ });
@@ -0,0 +1,8 @@
1
+ const components = {
2
+ "Button": "Visual",
3
+ "Link": "Visual",
4
+ "Loading": "Visual",
5
+ "Navbar": "Visual",
6
+ "NotFound": "Visual",
7
+ "FetchManager": "Service"
8
+ }; export default components;
@@ -0,0 +1,74 @@
1
+ {
2
+ "server": {
3
+ "port": 3001,
4
+ "host": "localhost"
5
+ },
6
+ "debugger": {
7
+ "enabled": false,
8
+ "click": "right"
9
+ },
10
+ "events": {
11
+ "enabled": true,
12
+ "ui": {
13
+ "enabled": true,
14
+ "shortcut": "alt+shift+e"
15
+ }
16
+ },
17
+ "context": {
18
+ "enabled": true,
19
+ "ui": {
20
+ "enabled": true,
21
+ "shortcut": "alt+shift+c"
22
+ }
23
+ },
24
+ "stylesManager": {
25
+ "requestedStyles": ["sliceStyles"]
26
+ },
27
+ "themeManager": {
28
+ "enabled": true,
29
+ "defaultTheme": "Slice",
30
+ "saveThemeLocally": false,
31
+ "useBrowserTheme": false
32
+ },
33
+ "logger": {
34
+ "enabled": true,
35
+ "showLogs": {
36
+ "console": {
37
+ "error": true,
38
+ "warning": true,
39
+ "info": false
40
+ }
41
+ }
42
+ },
43
+ "paths": {
44
+ "components": {
45
+ "AppComponents": {
46
+ "path": "/Components/AppComponents",
47
+ "type": "Visual"
48
+ },
49
+ "Visual": {
50
+ "path": "/Components/Visual",
51
+ "type": "Visual"
52
+ },
53
+ "Service": {
54
+ "path": "/Components/Service",
55
+ "type": "Service"
56
+ }
57
+ },
58
+ "themes": "/Themes",
59
+ "styles": "/Styles",
60
+ "routesFile": "/routes.js"
61
+ },
62
+ "router": {
63
+ "defaultRoute": "/"
64
+ },
65
+ "loading": {
66
+ "enabled": true
67
+ },
68
+ "publicFolders": [
69
+ "/Themes",
70
+ "/Styles",
71
+ "/assets",
72
+ "/images"
73
+ ]
74
+ }