@wu-framework/cli 0.4.0 → 0.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,77 @@
2
2
 
3
3
  Todos los cambios notables de wu-cli. Formato basado en [Keep a Changelog](https://keepachangelog.com/) y [SemVer](https://semver.org/).
4
4
 
5
+ ## [0.5.1] — 2026-08-29 — fiabilidad del desarrollo local
6
+
7
+ ### Corregido
8
+
9
+ - El compilador Angular resuelve las hojas CSS importadas desde TypeScript sin
10
+ tratarlas como imports JavaScript, tanto en desarrollo como en HMR.
11
+ - `wu dev` y `wu serve` rechazan de forma inmediata y legible un puerto ya
12
+ ocupado, incluido Windows, en vez de anunciar un servidor que no inició o
13
+ dejar dos procesos disputando el mismo listener.
14
+ - `wu doctor` reconoce dependencias locales absolutas `file:C:/...` en Windows.
15
+ - Los scaffolds conservan metadatos completos, usan estilos externos compatibles
16
+ con CSP y evitan HTML dinámico inseguro en el shell vanilla.
17
+ - Las plantillas Vanilla, Svelte, Solid, Stencil, Alpine, HTMX y Stimulus usan
18
+ CSS externo y controles accesibles, sin atributos de estilo que la CSP de
19
+ producción termine bloqueando.
20
+ - El scaffold Stimulus conserva el contrato `{ controllers, template }` que
21
+ consume su adapter; el controlador y sus acciones se mantienen aislados en
22
+ la configuración generada.
23
+ - Alpine se genera con el runtime oficial `@alpinejs/csp` inyectado y un
24
+ proveedor aislado por app; HTMX se importa realmente, desactiva evaluación y
25
+ scripts inline mediante su meta-config previa al import, usa estilos de
26
+ indicadores externos y limpia sus listeners al desmontar.
27
+ - Los proyectos nuevos fijan `wu-framework@^3.0.1`, la primera versión estable
28
+ que expone la inyección de runtime usada por estos scaffolds.
29
+
30
+ ## [0.5.0] — 2026-08-29 — alineación con wu-framework 3
31
+
32
+ ### Cambiado
33
+
34
+ - Los proyectos nuevos usan la versión estable `wu-framework@^3.0.0`, declaran Node 20+ y
35
+ `wu doctor` detecta rangos de registro que todavía resuelven a V2.
36
+ - Los shells generados conservan el objeto completo de cada micro-app al
37
+ inicializar Wu; ya no pierden `framework`, ownership DOM, grants ni
38
+ compatibilidad al recalcular su URL.
39
+ - Los shells Vite nativos usan una hoja CSS externa compartida y el shell
40
+ vanilla construye sus nodos con DOM seguro. Esto elimina atributos `style`
41
+ dinámicos y concatenaciones `innerHTML` sin relajar la CSP de producción.
42
+ - Cada shell incluye un favicon SVG real en `public/`; desarrollo ya no genera
43
+ un 404 por depender del icono implícito del navegador.
44
+ - `wu install` conserva correctamente rutas `file:C:/...` y `file:C:\\...` en
45
+ Windows; antes las convertía en junctions relativos inválidos aunque npm
46
+ terminara con éxito. Las pruebas de `install.zig` ya forman parte de la suite
47
+ agregada y dejan de ser tests escritos que nunca se ejecutaban.
48
+ - `wu doctor` reconoce esas mismas rutas absolutas de Windows y UNC como un
49
+ único destino en todos los `package.json`; ya no inventa rutas como
50
+ `shell/C:/...` ni contradice el resultado correcto de `wu install`.
51
+ - Los listeners de `wu dev` y `wu serve` ya no solicitan `SO_REUSEADDR` ni
52
+ `SO_REUSEPORT`; además mantienen una lease de host/puerto entre procesos Wu
53
+ en Windows, donde el backend AFD de Zig acepta dos binds aun sin reuse. Un
54
+ segundo servidor termina con un error claro en vez de arrancar aparentemente
55
+ y repartir tráfico entre dos proyectos; `wu serve` sólo anuncia su URL
56
+ después de poseer realmente el puerto.
57
+ - Las apps React generadas inyectan en el adapter el mismo runtime que compiló
58
+ el componente y esperan su registro. Esto evita dos copias de React en chunks
59
+ de producción y el fallo de hooks que sólo aparecía después de `wu build`.
60
+ - El componente React inicial usa `App.css`, clases y controles accesibles en
61
+ lugar de objetos `style`; el scaffold funciona con la CSP estricta que el
62
+ propio `wu build` publica.
63
+ - `apps[].grants` y `apps[].compatibility` forman parte del schema del CLI y se
64
+ propagan sin pérdida por desarrollo, build, `apps.json`, `wu-manifest.json` y
65
+ shells generados.
66
+ - `wu build` fusiona el `wu.json` de la app con la entry final: conserva sus
67
+ solicitudes V3 y rechaza JSON malformado en lugar de borrarlo en silencio.
68
+ - El launcher npm ya no ejecuta el binario al importarlo desde tests y vuelve a
69
+ despachar Linux ARM64, que se distribuía pero faltaba en su mapa de plataforma.
70
+
71
+ ### Pruebas
72
+
73
+ - Cobertura para rangos V3/locales, rechazo de V2, persistencia de grants y
74
+ compatibilidad, y conservación de permisos en manifiestos de producción.
75
+
5
76
  ## [0.4.0] — 2026-08-27 — cabeceras, CSP generada y ficheros que no debían salir
6
77
 
7
78
  Todo lo de aquí sale de un informe de escaneo contra un sitio wu: `.env` servido, sin CSP, sin `X-Frame-Options`, `package.json` público, `Access-Control-Allow-Origin: *`. Nueve de los once hallazgos los producía wu, no el hosting.
@@ -252,4 +323,3 @@ Primera versión con el pipeline completo. (La 0.1.0, del 2026-02-27, fue el pri
252
323
  - Soporte inicial para 13 frameworks
253
324
 
254
325
  ---
255
-
package/README.md CHANGED
@@ -32,7 +32,7 @@
32
32
 
33
33
  **Wu CLI** es un CLI + dev-server nativo en **Zig 0.16** para arquitecturas microfrontend ([wu-framework](https://www.wu-framework.com)). Reemplaza **N procesos Vite** (uno por micro-app) con **un único proceso en un solo puerto** que descubre, compila, sirve y hace HMR. Sin dependencias Zig, binario de ~250-460 KB por plataforma, distribuido vía npm.
34
34
 
35
- ## Estado actual (código v0.4.0)
35
+ ## Estado actual (código v0.5.1)
36
36
 
37
37
  Las versiones de `package.json`, `src/main.zig` y `build.zig.zon` están
38
38
  sincronizadas y una invariante de CI evita que vuelvan a divergir. Consulta el
@@ -70,7 +70,8 @@ sincronizadas y una invariante de CI evita que vuelvan a divergir. Consulta el
70
70
  npm install -g @wu-framework/cli
71
71
  ```
72
72
 
73
- Requiere **Node.js 16+** para instalar. Node.js 18+ a runtime sólo si usas Vue, Svelte, Solid o Angular (React/Preact corren en Zig puro).
73
+ Requiere **Node.js 20+**. El requisito coincide con wu-framework 3 y con las
74
+ plantillas actuales de Astro, Next y Angular.
74
75
 
75
76
  ### Desde fuente
76
77
 
@@ -168,7 +169,14 @@ Referencia completa con todas las flags: **[docs/cli.md](docs/cli.md)**.
168
169
  "framework": "react"
169
170
  },
170
171
  "apps": [
171
- { "name": "catalog", "dir": "mf-catalog", "framework": "react", "port": 5001 },
172
+ {
173
+ "name": "catalog",
174
+ "dir": "mf-catalog",
175
+ "framework": "react",
176
+ "port": 5001,
177
+ "grants": ["events.emit:catalog:*", "events.subscribe:catalog:*"],
178
+ "compatibility": "strict"
179
+ },
172
180
  { "name": "cart", "dir": "mf-cart", "framework": "vue", "port": 5002 }
173
181
  ],
174
182
  "shared": ["react", "react-dom", "react-dom/client"],
@@ -180,6 +188,10 @@ Referencia completa con todas las flags: **[docs/cli.md](docs/cli.md)**.
180
188
  }
181
189
  ```
182
190
 
191
+ En wu-framework 3, `grants` es autoridad del shell y se cruza con lo que cada
192
+ app solicita en `wu.json`; declarar un grant que la app no pidió no le concede
193
+ nada. `compatibility: "v2"` es un puente temporal por app, no el nuevo default.
194
+
183
195
  Si no existe, `wu` auto-descubre micro-apps escaneando subdirectorios con `vite.config.*` + `package.json`. El directorio llamado **`shell`** se promueve a shell del proyecto.
184
196
 
185
197
  Schema completo, defaults, ejemplos de proxy: **[docs/configuration.md](docs/configuration.md)**.
@@ -266,13 +278,12 @@ Configuración para producción y modelo de amenazas: **[docs/security.md](docs/
266
278
  - **47** archivos Zig fuente, **~18.4k LOC** totales en `src/` (runtime + cli + config + commands)
267
279
  - **~250-460 KB** binario release por plataforma (con `-Doptimize=ReleaseFast`)
268
280
  - **0** dependencias Zig externas
269
- - **138** tests Zig descubiertos, más launcher npm, invariantes, fuzzing y smokes
281
+ - Suite Zig, launcher npm, invariantes, fuzzing y smokes de proyectos generados
270
282
  - **0** procesos Vite simultáneos en `wu dev` (modo nativo). `wu dev --vite` legacy sí spawnea N procesos.
271
283
 
272
284
  ## Requisitos
273
285
 
274
- - **Node.js 16+** para `npm install -g @wu-framework/cli`
275
- - **Node.js 18+** a runtime sólo para Vue, Svelte, Solid o Angular (React/Preact corren en Zig puro)
286
+ - **Node.js 20+** para instalar el CLI y ejecutar los toolchains generados
276
287
  - **Zig 0.16.0** sólo si construyes desde fuente
277
288
 
278
289
  ## Licencia
Binary file
package/bin/wu-darwin-x64 CHANGED
Binary file
Binary file
package/bin/wu-linux-x64 CHANGED
Binary file
Binary file
package/bin/wu.js CHANGED
@@ -5,57 +5,74 @@ const path = require('path');
5
5
  const fs = require('fs');
6
6
  const os = require('os');
7
7
 
8
- const PLATFORM_MAP = {
9
- 'win32-x64': 'wu-win32-x64.exe',
10
- 'linux-x64': 'wu-linux-x64',
11
- 'darwin-x64': 'wu-darwin-x64',
12
- 'darwin-arm64': 'wu-darwin-arm64',
13
- };
14
-
15
- const platform = os.platform();
16
- const arch = os.arch();
17
- const key = `${platform}-${arch}`;
18
- const binaryName = PLATFORM_MAP[key];
19
-
20
- if (!binaryName) {
21
- console.error(`wu-cli: unsupported platform ${platform}-${arch}`);
22
- console.error(`Supported: ${Object.keys(PLATFORM_MAP).join(', ')}`);
23
- process.exit(1);
24
- }
25
-
26
- const binaryPath = path.join(__dirname, binaryName);
27
-
28
- if (!fs.existsSync(binaryPath)) {
29
- console.error(`wu-cli: binary not found at ${binaryPath}`);
30
- console.error('This may mean the package was not built for your platform.');
31
- console.error('Try reinstalling: npm install -g wu-cli');
32
- process.exit(1);
33
- }
34
-
35
- const args = process.argv.slice(2);
36
-
37
- let result = spawnSync(binaryPath, args, {
38
- stdio: 'inherit',
39
- env: process.env,
40
- });
41
-
42
- // Handle EACCES — try chmod +x and retry (Linux/macOS)
43
- if (result.error && result.error.code === 'EACCES') {
44
- try {
45
- fs.chmodSync(binaryPath, 0o755);
46
- result = spawnSync(binaryPath, args, {
47
- stdio: 'inherit',
48
- env: process.env,
49
- });
50
- } catch (chmodErr) {
51
- console.error(`wu-cli: permission denied and could not chmod: ${chmodErr.message}`);
52
- process.exit(1);
53
- }
54
- }
55
-
56
- if (result.error) {
57
- console.error(`wu-cli: failed to execute binary: ${result.error.message}`);
58
- process.exit(1);
59
- }
60
-
61
- process.exit(result.status ?? 1);
8
+ const PLATFORM_MAP = {
9
+ 'win32-x64': 'wu-win32-x64.exe',
10
+ 'linux-x64': 'wu-linux-x64',
11
+ 'linux-arm64': 'wu-linux-arm64',
12
+ 'darwin-x64': 'wu-darwin-x64',
13
+ 'darwin-arm64': 'wu-darwin-arm64',
14
+ };
15
+
16
+ function binaryNameFor(platform, arch) {
17
+ return PLATFORM_MAP[`${platform}-${arch}`];
18
+ }
19
+
20
+ function executeBinary(binaryPath, args, runtime = {}) {
21
+ const spawn = runtime.spawn ?? spawnSync;
22
+ const chmod = runtime.chmod ?? fs.chmodSync;
23
+ const reportError = runtime.reportError ?? console.error;
24
+ const options = {
25
+ stdio: 'inherit',
26
+ env: runtime.env ?? process.env,
27
+ };
28
+
29
+ let result = spawn(binaryPath, args, options);
30
+
31
+ // npm pack on Windows cannot preserve POSIX executable bits. Repair the
32
+ // packaged Linux/macOS binary only when the operating system rejects it.
33
+ if (result.error && result.error.code === 'EACCES') {
34
+ try {
35
+ chmod(binaryPath, 0o755);
36
+ result = spawn(binaryPath, args, options);
37
+ } catch (chmodErr) {
38
+ reportError(`wu-cli: permission denied and could not chmod: ${chmodErr.message}`);
39
+ return 1;
40
+ }
41
+ }
42
+
43
+ if (result.error) {
44
+ reportError(`wu-cli: failed to execute binary: ${result.error.message}`);
45
+ return 1;
46
+ }
47
+
48
+ return result.status ?? 1;
49
+ }
50
+
51
+ function runCli(args = process.argv.slice(2)) {
52
+ const platform = os.platform();
53
+ const arch = os.arch();
54
+ const binaryName = binaryNameFor(platform, arch);
55
+
56
+ if (!binaryName) {
57
+ console.error(`wu-cli: unsupported platform ${platform}-${arch}`);
58
+ console.error(`Supported: ${Object.keys(PLATFORM_MAP).join(', ')}`);
59
+ return 1;
60
+ }
61
+
62
+ const binaryPath = path.join(__dirname, binaryName);
63
+
64
+ if (!fs.existsSync(binaryPath)) {
65
+ console.error(`wu-cli: binary not found at ${binaryPath}`);
66
+ console.error('This may mean the package was not built for your platform.');
67
+ console.error('Try reinstalling: npm install -g @wu-framework/cli');
68
+ return 1;
69
+ }
70
+
71
+ return executeBinary(binaryPath, args);
72
+ }
73
+
74
+ module.exports = { PLATFORM_MAP, binaryNameFor, executeBinary, runCli };
75
+
76
+ if (require.main === module) {
77
+ process.exit(runCli());
78
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wu-framework/cli",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "description": "Native Zig dev server + CLI for wu-framework microfrontends. One binary, one port, all your micro-apps.",
5
5
  "license": "MIT",
6
6
  "author": "Wu Framework Team",
@@ -15,8 +15,11 @@
15
15
  "LICENSE"
16
16
  ],
17
17
  "scripts": {
18
- "prepublishOnly": "bash scripts/build-all.sh",
19
- "test:wrapper": "node --test \"tests/*.test.cjs\""
18
+ "build:binaries": "node scripts/build-all.mjs",
19
+ "test": "npm run test:invariants && npm run test:wrapper",
20
+ "test:invariants": "node scripts/check-invariants.mjs",
21
+ "test:wrapper": "node --test \"tests/*.test.cjs\"",
22
+ "prepublishOnly": "npm test && npm run build:binaries"
20
23
  },
21
24
  "keywords": [
22
25
  "micro-frontend",
@@ -41,7 +44,7 @@
41
44
  "stimulus"
42
45
  ],
43
46
  "engines": {
44
- "node": ">=16"
47
+ "node": ">=20"
45
48
  },
46
49
  "publishConfig": {
47
50
  "access": "public"