@wu-framework/cli 0.2.5 → 0.3.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.
- package/CHANGELOG.md +105 -0
- package/README.md +215 -296
- package/bin/wu-darwin-arm64 +0 -0
- package/bin/wu-darwin-x64 +0 -0
- package/bin/wu-linux-x64 +0 -0
- package/bin/wu-win32-x64.exe +0 -0
- package/package.json +17 -4
- package/bin/wu.exe +0 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Todos los cambios notables de wu-cli. Formato basado en [Keep a Changelog](https://keepachangelog.com/) y [SemVer](https://semver.org/).
|
|
4
|
+
|
|
5
|
+
## [0.3.0] — 2026-05-17
|
|
6
|
+
|
|
7
|
+
Sesión grande de hardening, refactor de UX y documentación. Sin cambios breaking para usuarios que ya tienen `wu.config.json` válido — pero **una excepción**: el campo `cors` del proxy ahora default `false` (antes hardcoded `true`).
|
|
8
|
+
|
|
9
|
+
### Seguridad
|
|
10
|
+
|
|
11
|
+
- **Sentinel ahora usa la IP real del cliente** (`stream.socket.address`). Antes estaba hardcoded a `0x7F000001` (127.0.0.1) — la tabla per-IP era inútil, rate-limit afectaba a todos los usuarios por igual.
|
|
12
|
+
- **XSS en challenge HTML cerrado**. El path del request se interpolaba sin escape en `location.replace('{s}')`. Ahora hay allowlist `[A-Za-z0-9._\-/?=&%+~]`; cualquier otro carácter fallback a `/`.
|
|
13
|
+
- **Path traversal hardened**. El check `indexOf("..")` original miss-eaba `%2e%2e`, `\\`, NUL bytes y absolute paths. Reemplazado por `isPathSafe()` que se aplica post-URL-decode con tests cubriendo 11 vectores conocidos.
|
|
14
|
+
- **Sentinel ya no marca su propio endpoint como sospechoso**. Quitados de `isSuspiciousPath`: `/.well-known/*` (donde vive `/acp.json`), `/robots.txt`, `/sitemap.xml`, `/api/v1/`, `/graphql`. Antes Googlebot pidiendo `/robots.txt` recibía verdict `.throttle`.
|
|
15
|
+
- **Anti-slowloris**: `setSocketTimeouts(stream, 30s)` aplicado a cada conexión aceptada (`READ_TIMEOUT_MS = 30_000`). Cross-platform: `ws2_32.setsockopt` en Windows, `std.posix.setsockopt` en POSIX.
|
|
16
|
+
- **Body-size cap**: `MAX_REQUEST_BYTES = 16 MB`. Check temprano en `handleRequest` antes de leer el body. POST con `Content-Length` mayor → `413 Payload Too Large` + close.
|
|
17
|
+
- **SSE/WebSocket peer-close detection**. `platformReadNonBlocking` ahora devuelve enum `PollResult { bytes, no_data, eof }`. Antes colapsaba EOF + no-data en `0`, dejando threads zombies hasta el siguiente ping (~30s). Los handlers de HMR (SSE) y WS detectan `.eof` y salen inmediatamente.
|
|
18
|
+
- **CORS opt-in en proxy** (**breaking**): el campo `cors: bool` se agrega a `ProxyRule` con default `false`. Antes el proxy inyectaba `Access-Control-Allow-Origin: *` en TODAS las respuestas. Migración: agregá `"cors": true` explícito a las reglas que lo necesiten.
|
|
19
|
+
- **`looksLikeBrowser` reforzado**: ahora exige `Mozilla/5.0` + engine (`AppleWebKit`/`Gecko`/`Trident`) + product token (`Chrome/`, `Firefox/`, `Safari/`, `Edg/`, `OPR/`, `Brave/`, `Vivaldi/`, `SamsungBrowser/`). Antes "Mozilla/5.0" solo era suficiente — cualquier scraper moderno pasaba.
|
|
20
|
+
|
|
21
|
+
### Agregado
|
|
22
|
+
|
|
23
|
+
- **Wizard interactivo con TUI** (`wu create`). Raw mode cross-platform, navegación con ↑↓/jk, Esc/Ctrl+C para cancelar con cleanup del terminal. Sin defaults escondidos en la elección del shell. Confirm explícito antes de `npm install`.
|
|
24
|
+
- **Nuevo módulo `src/cli/tui.zig`** — primitivas: `enterRawMode`, `forceRestore`, `readKey`, ANSI helpers (cursor up, clear line, hide/show cursor).
|
|
25
|
+
- **Nuevo módulo `src/cli/prompts.zig`** — `Menu`, `Text`, `Confirm`. Re-render in-place sin flicker.
|
|
26
|
+
- **`build.zig.zon`** — manifest oficial de paquete Zig (name `.wu_cli`, fingerprint generado por toolchain, `minimum_zig_version = "0.16.0"`).
|
|
27
|
+
- **Cap de disco para `.wu-cache/`** — `MAX_DISK_BYTES = 500 MB`, sweep cada 64 puts. Borra archivos más viejos por mtime hasta dejar 80 % del cap.
|
|
28
|
+
- **LRU en cache de memoria** — antes era round-robin (evictaba hot entries por suerte). Ahora cada entry tiene `last_access: u64` y eviction busca el mínimo. Test cubre que la entry recién-tocada NO se desaloja.
|
|
29
|
+
- **5 logs estructurados en el hot path** (en lugar de `catch {}` silenciosos): parser fail después de Bad Request, static file serve fail, hot-reload bookkeeping OOM, 404 después de fallar shell index (con sugerencia accionable), WS close frame fail.
|
|
30
|
+
- **Convención de discovery**: el directorio llamado **exactamente `shell`** es el shell del proyecto. Todos los frameworks tratados por igual.
|
|
31
|
+
- **Salt en cache key** (`hashPath(path, salt)`). Para .jsx/.tsx, salt = framework — switching `react` ↔ `preact` ya no sirve output stale.
|
|
32
|
+
- **Header `cors` en `wu.config.json`** — opt-in por regla de proxy.
|
|
33
|
+
- **Tests nuevos**: `isPathSafe` (11 vectores), `findCrlfSimd` chunk boundaries (5 casos), LRU eviction, `MAX_REQUEST_BYTES` sanity, `PollResult` exhaustiveness, escape sequences en `parseConfigJson`, browser fingerprint.
|
|
34
|
+
- **Tres documentos nuevos** en `docs/`: `cli.md`, `configuration.md`, `security.md`, `contributing.md` (movido de root).
|
|
35
|
+
- **`CHANGELOG.md`** — este archivo.
|
|
36
|
+
|
|
37
|
+
### Cambiado
|
|
38
|
+
|
|
39
|
+
- **Parser JSON migrado a `std.json`**. El parser hand-rolled no decodificaba escape sequences (`\n`, `\"`) y tenía un desync sutil en `readBool` que pisaba la siguiente key. `WuConfig` ahora owns un `ArenaAllocator`; `cfg.deinit(allocator)` libera todo en un shot.
|
|
40
|
+
- **Hot-reload de config con cap de generaciones**. `_hot_cfgs` y `_hot_app_bufs` antes crecían sin límite. Ahora se capean a 3 generaciones; la más vieja se libera cuando se inserta la 4ª.
|
|
41
|
+
- **Default del shell sin escondites**. `dev_server.zig:49` declaraba `shell_framework = "astro"`. Cambiado a `"vanilla"`. El color del shell en `wu build`/`wu install` ahora usa `frameworkColor(shell.framework)` real, no `fw_astro` hardcoded.
|
|
42
|
+
- **TypeScript ofrecido a 9/12 frameworks** (antes 6/12). Vue, Svelte, Angular, Stencil ya tienen su pregunta `Use TypeScript?`. Sólo HTMX/Alpine/Stimulus quedan JS-only por convención del ecosistema.
|
|
43
|
+
- **`wu create --template <fw>` ahora también respeta el shell**. Antes el quick mode siempre ponía shell vanilla (inconsistente con la elección del usuario). Default del shell ahora = mismo framework que el template; override con `--shell <fw>`.
|
|
44
|
+
- **`dev_server.zig` adelgazado** 10 %: 3655 → 3298 LOC. `handleProxy` extraído a `handlers/proxy.zig` (188 LOC) y `handleHmr`/`handleWsHmr` a `handlers/hmr.zig` (172 LOC). Cuatro helpers promovidos a `pub`: `sendResponse`, `platformRead`, `platformWrite`, `platformReadNonBlocking`.
|
|
45
|
+
- **README reescrito en español** como entry point con links a `docs/`. CONTRIBUTING raíz convertido en stub que apunta a `docs/contributing.md`.
|
|
46
|
+
|
|
47
|
+
### Removido
|
|
48
|
+
|
|
49
|
+
- **TS-strip line-based** (`stripTypeScript` + helpers `isTypeOnlyLine`, `isTypeAlias`, `skipTypeExpression`, tabla `ts_types`). Era código muerto — `.tsx` ya iba al daemon esbuild desde antes. ~325 LOC borradas de `transform.zig` (1074 → 749). Parámetro `is_tsx` eliminado de `compileJsxNative`.
|
|
50
|
+
|
|
51
|
+
### Arreglado
|
|
52
|
+
|
|
53
|
+
- **`shell/package.json` y `shell/index.html` se generaban incompletos**. Bug serio que llevaba meses escondido: `Writer.Allocating.fromArrayListAligned` toma ownership del buffer y deja la `ArrayList` vacía; `writeFile(io, path, buf.items)` escribía array vacío. Además, `index.html` se escribía en 2 `writeFile` al mismo path que se sobreescribían. Fix: `buf = aw.toArrayList()` antes del writeFile, y concat de las dos halves antes del único write.
|
|
54
|
+
- **`discovery.zig` ya no privilegia astro**. Antes: si encuentra `astro.config.mjs`, promueve a shell automáticamente. Ahora: trato igual para todos los frameworks; sólo el directorio `shell/` es el shell.
|
|
55
|
+
- **Verificación SIMD CRLF**: el código era correcto, pero faltaban tests que pin-eraran el invariante de cross-chunk access. Agregados 5 tests que rompen si alguien "optimiza" y quita el check `idx + 1 < data.len`.
|
|
56
|
+
- **Migración a Zig 0.16.0** completa y validada con `zig build`, `zig build test`, `zig build -Doptimize=ReleaseFast`. La verificación de versión la hace ahora el package manager via `build.zig.zon`, no un check runtime en `build.zig`.
|
|
57
|
+
|
|
58
|
+
### Deprecated / Por hacer
|
|
59
|
+
|
|
60
|
+
- **Modo `wu dev --vite`** está deprecated. El modo nativo es el default desde hace versiones y maneja todo. El modo Vite legacy se mantiene por compat pero **no se está manteniendo**.
|
|
61
|
+
- **`stripTypeScript`** ya no existe — `.tsx` debe ir por el daemon esbuild. Si tenés código que lo importaba directamente, falla en compile.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## [0.2.1] — 2026-04-22
|
|
66
|
+
|
|
67
|
+
Versión publicada previa a esta sesión. Reconstruida del README.md anterior.
|
|
68
|
+
|
|
69
|
+
### Agregado
|
|
70
|
+
|
|
71
|
+
- Guided interactive scaffolding (`wu create`) con step-by-step, naming inteligente, summary card
|
|
72
|
+
- Windows UTF-8 fix (Mojibake)
|
|
73
|
+
- React shell con `<WuSlot />` integrado
|
|
74
|
+
- TypeScript por default en plantillas que lo soportan
|
|
75
|
+
- Production build pipeline (`wu build`) — Vite paralelo + shell de producción
|
|
76
|
+
- Production server (`wu serve`) con clean Ctrl+C shutdown
|
|
77
|
+
- Event-driven mounting en shell de producción (`wu:app:ready` events)
|
|
78
|
+
- Theme system con CSS custom properties (`--surface`, `--text`, `--border`, `--accent`)
|
|
79
|
+
- Design tokens de wu-framework.com (Indigo `#6366f1`, Teal `#14b8a6`, Zinc palette, Inter)
|
|
80
|
+
- 13 plantillas theme-aware (React, Vue, Svelte, Solid, Preact, Lit, Angular, Alpine, Qwik, Stencil, HTMX, Stimulus, Vanilla)
|
|
81
|
+
- Responsive production shell — topbar blur, sidebar con badges, spinners, hamburger móvil
|
|
82
|
+
- `findEntryFromHtml()` correcto en build pipeline
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## [0.2.0] — 2026-03-18
|
|
87
|
+
|
|
88
|
+
Primera versión empaquetada en npm.
|
|
89
|
+
|
|
90
|
+
### Agregado
|
|
91
|
+
|
|
92
|
+
- Servidor HTTP nativo en Zig con SIMD parsing
|
|
93
|
+
- Compilación 3-tier (Native Zig JSX → daemon → fallback)
|
|
94
|
+
- Cache de 2 niveles
|
|
95
|
+
- NPM module resolution en Zig puro
|
|
96
|
+
- WebSocket + SSE HMR
|
|
97
|
+
- Auto-discovery de micro-apps
|
|
98
|
+
- HTTP keep-alive
|
|
99
|
+
- Soporte inicial para 13 frameworks
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
[0.3.0]: https://github.com/LuisPadre25/wu-cli/compare/v0.2.5...HEAD
|
|
104
|
+
[0.2.1]: https://github.com/LuisPadre25/wu-cli/compare/v0.2.0...v0.2.1
|
|
105
|
+
[0.2.0]: https://github.com/LuisPadre25/wu-cli/releases/tag/v0.2.0
|
package/README.md
CHANGED
|
@@ -1,296 +1,215 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<img src="https://raw.githubusercontent.com/LuisPadre25/wu-framework/main/wu-logo.png" width="80" alt="Wu CLI" />
|
|
3
|
-
</p>
|
|
4
|
-
|
|
5
|
-
<h1 align="center">Wu CLI</h1>
|
|
6
|
-
|
|
7
|
-
<p align="center">
|
|
8
|
-
<strong>
|
|
9
|
-
</p>
|
|
10
|
-
|
|
11
|
-
<p align="center">
|
|
12
|
-
<a href="https://www.npmjs.com/package/@wu-framework/cli"><img src="https://img.shields.io/npm/v/@wu-framework/cli.svg?color=6366f1&label=npm" alt="npm version" /></a>
|
|
13
|
-
<img src="https://img.shields.io/badge/zig-0.
|
|
14
|
-
<img src="https://img.shields.io/badge/frameworks-13-14b8a6" alt="13 frameworks" />
|
|
15
|
-
<img src="https://img.shields.io/badge/dependencies-0-6366f1" alt="zero deps" />
|
|
16
|
-
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License" /></a>
|
|
17
|
-
</p>
|
|
18
|
-
|
|
19
|
-
<p align="center">
|
|
20
|
-
<a href="
|
|
21
|
-
<a href="
|
|
22
|
-
<a href="
|
|
23
|
-
</
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
##
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
- **
|
|
36
|
-
- **
|
|
37
|
-
- **
|
|
38
|
-
- **
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
wu
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
mime.zig MIME type detection
|
|
217
|
-
config/ Configuration loading and validation
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
## Compilation Pipeline
|
|
221
|
-
|
|
222
|
-
```
|
|
223
|
-
.jsx/.tsx (React/Preact) ----> Native Zig JSX ----> JS (~0-2ms)
|
|
224
|
-
.jsx/.tsx (Solid) ----> Compiler Daemon ----> JS (~10-50ms)
|
|
225
|
-
.svelte ----> Compiler Daemon ----> JS (~10-50ms)
|
|
226
|
-
.vue ----> Compiler Daemon ----> JS (~10-50ms)
|
|
227
|
-
.ts (Angular) ----> esbuild bundle ----> JS (~10-50ms)
|
|
228
|
-
.ts ----> TS Strip ----> JS (~0-1ms)
|
|
229
|
-
.js (Alpine/HTMX/etc) ----> passthrough ----> JS (~0ms)
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
The three tiers are tried in order. Native Zig handles React and Preact JSX with zero external processes. The Compiler Daemon keeps a long-running Node.js process for frameworks that require their own compilers (Svelte, Vue, Solid). If the daemon is unavailable, a one-shot `node -e` fallback is used.
|
|
233
|
-
|
|
234
|
-
Cache hits bypass all tiers: source mtime is compared against the cached entry, and cached output is served directly (~3ms).
|
|
235
|
-
|
|
236
|
-
## Supported Frameworks
|
|
237
|
-
|
|
238
|
-
| Framework | Extensions | Compile Tier | Native JSX |
|
|
239
|
-
|-----------|-----------|-------------|------------|
|
|
240
|
-
| React | .jsx, .tsx | Native Zig | Yes |
|
|
241
|
-
| Preact | .jsx, .tsx | Native Zig | Yes |
|
|
242
|
-
| Vue | .vue | Daemon / Node | -- |
|
|
243
|
-
| Svelte | .svelte | Daemon / Node | -- |
|
|
244
|
-
| Solid.js | .jsx, .tsx | Daemon / Node | -- |
|
|
245
|
-
| Angular | .ts | esbuild bundle | -- |
|
|
246
|
-
| Lit | .ts, .js | TS strip only | -- |
|
|
247
|
-
| Alpine.js | .js | Passthrough | -- |
|
|
248
|
-
| Qwik | .jsx | Passthrough | -- |
|
|
249
|
-
| Stencil | .js | Passthrough | -- |
|
|
250
|
-
| HTMX | .js | Passthrough | -- |
|
|
251
|
-
| Stimulus | .js | Passthrough | -- |
|
|
252
|
-
| Vanilla | .js, .ts | TS strip only | -- |
|
|
253
|
-
|
|
254
|
-
## Theme System
|
|
255
|
-
|
|
256
|
-
Generated shells and app templates support dark/light theme switching via CSS custom properties:
|
|
257
|
-
|
|
258
|
-
| Variable | Dark | Light | Purpose |
|
|
259
|
-
|----------|------|-------|---------|
|
|
260
|
-
| `--bg` | `#09090b` | `#fafafa` | Page background |
|
|
261
|
-
| `--surface` | `#111113` | `#ffffff` | Card/panel background |
|
|
262
|
-
| `--border` | `#27272a` | `#d4d4d8` | Borders |
|
|
263
|
-
| `--text` | `#fafafa` | `#09090b` | Primary text |
|
|
264
|
-
| `--text2` | `#a1a1aa` | `#52525b` | Secondary text |
|
|
265
|
-
| `--text-muted` | `#3f3f46` | `#a1a1aa` | Muted/label text |
|
|
266
|
-
| `--accent` | `#6366f1` | `#6366f1` | Brand accent (Indigo) |
|
|
267
|
-
| `--teal` | `#14b8a6` | `#14b8a6` | Status/success accent |
|
|
268
|
-
|
|
269
|
-
All 13 app templates use `var(--surface, #111)` etc. with fallback defaults, so they work both inside a themed shell and standalone.
|
|
270
|
-
|
|
271
|
-
## Requirements
|
|
272
|
-
|
|
273
|
-
- **Node.js 16+** -- for installing via npm
|
|
274
|
-
- **Node.js 18+** -- needed at runtime for Svelte, Vue, and Solid compilation (React/Preact use native Zig JSX)
|
|
275
|
-
- **Zig 0.15.2+** -- only needed if building from source
|
|
276
|
-
|
|
277
|
-
## Project Stats
|
|
278
|
-
|
|
279
|
-
- 22 Zig source files, ~3000 lines of runtime code
|
|
280
|
-
- 13 framework app component templates (embedded at compile time)
|
|
281
|
-
- ~250-460KB release binary per platform (Windows, Linux, macOS x64/arm64)
|
|
282
|
-
- Zero external Zig dependencies
|
|
283
|
-
- Single-process architecture replaces 12+ simultaneous Vite dev servers
|
|
284
|
-
- Part of the [wu-framework](https://www.wu-framework.com) microfrontend platform
|
|
285
|
-
|
|
286
|
-
## License
|
|
287
|
-
|
|
288
|
-
MIT
|
|
289
|
-
|
|
290
|
-
## Author
|
|
291
|
-
|
|
292
|
-
Luis Garcia -- Creator of [wu-framework](https://www.wu-framework.com)
|
|
293
|
-
|
|
294
|
-
---
|
|
295
|
-
|
|
296
|
-
*2026 Wu Framework*
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/LuisPadre25/wu-framework/main/wu-logo.png" width="80" alt="Wu CLI" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">Wu CLI</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>Un binario. Un puerto. Todas tus micro-apps.</strong>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://www.npmjs.com/package/@wu-framework/cli"><img src="https://img.shields.io/npm/v/@wu-framework/cli.svg?color=6366f1&label=npm" alt="npm version" /></a>
|
|
13
|
+
<img src="https://img.shields.io/badge/zig-0.16.0-f7a41d" alt="Zig 0.16.0" />
|
|
14
|
+
<img src="https://img.shields.io/badge/frameworks-13-14b8a6" alt="13 frameworks" />
|
|
15
|
+
<img src="https://img.shields.io/badge/dependencies-0-6366f1" alt="zero deps" />
|
|
16
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License" /></a>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<a href="docs/cli.md">Comandos</a> ·
|
|
21
|
+
<a href="docs/configuration.md">Configuración</a> ·
|
|
22
|
+
<a href="docs/security.md">Seguridad</a> ·
|
|
23
|
+
<a href="docs/contributing.md">Contribuir</a> ·
|
|
24
|
+
<a href="CHANGELOG.md">Changelog</a>
|
|
25
|
+
</p>
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## ¿Qué es wu-cli?
|
|
30
|
+
|
|
31
|
+
**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.
|
|
32
|
+
|
|
33
|
+
## Lo nuevo en v0.3.0
|
|
34
|
+
|
|
35
|
+
- **TUI interactiva** — `wu create` con menús navegables (↑↓ enter), sin defaults escondidos, raw mode cross-platform.
|
|
36
|
+
- **DoS hardening** — read/write timeouts (30s), límite de body (16 MB), detección de peer-close en SSE/WebSocket. `wu serve` ya no se cuelga con slowloris.
|
|
37
|
+
- **Sentinel real** — anti-bot con IP del cliente real (antes hardcoded 127.0.0.1), allowlist de paths legítimos (`/robots.txt`, `/.well-known/*`), challenge HTML libre de XSS.
|
|
38
|
+
- **Cache LRU + cap de disco** — eviction inteligente en memoria, `.wu-cache/` capado a 500 MB con sweep periódico.
|
|
39
|
+
- **Configuración robusta** — parser `wu.config.json` migrado a `std.json` (escape sequences correctos, sin desincronizaciones).
|
|
40
|
+
- **CORS opt-in en proxy** — el `Access-Control-Allow-Origin: *` ya no se inyecta por defecto; ahora es por regla (`cors: true`).
|
|
41
|
+
- **Modularización** — `dev_server.zig` adelgazó 10 % extrayendo `handlers/proxy.zig` y `handlers/hmr.zig`.
|
|
42
|
+
- **`build.zig.zon`** — manifest oficial de paquete Zig (consumible como dependencia, valida versión mínima).
|
|
43
|
+
|
|
44
|
+
[Ver el changelog completo →](CHANGELOG.md)
|
|
45
|
+
|
|
46
|
+
## Instalación
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm install -g @wu-framework/cli
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
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).
|
|
53
|
+
|
|
54
|
+
### Desde fuente
|
|
55
|
+
|
|
56
|
+
Requiere **Zig 0.16.0**:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git clone https://github.com/LuisPadre25/wu-cli.git
|
|
60
|
+
cd wu-cli
|
|
61
|
+
zig build -Doptimize=ReleaseFast
|
|
62
|
+
./zig-out/bin/wu --help
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Quick Start
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
wu create my-shop # Wizard interactivo: nombre, shell, micro-apps, TS
|
|
69
|
+
cd my-shop
|
|
70
|
+
wu dev # Servidor nativo en http://localhost:3000
|
|
71
|
+
wu build # Producción → dist/
|
|
72
|
+
wu serve # Servir dist/
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
El wizard genera estructura tipo:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
my-shop/
|
|
79
|
+
├── wu.config.json ← configuración del proyecto
|
|
80
|
+
├── package.json ← deps unificadas
|
|
81
|
+
├── shell/ ← el "host" que monta los micro-apps
|
|
82
|
+
│ ├── package.json
|
|
83
|
+
│ ├── index.html
|
|
84
|
+
│ └── src/main.tsx (o .js)
|
|
85
|
+
├── mf-catalog/ ← micro-app 1
|
|
86
|
+
│ ├── package.json
|
|
87
|
+
│ ├── vite.config.js
|
|
88
|
+
│ └── src/App.tsx (o .jsx)
|
|
89
|
+
└── mf-cart/ ← micro-app 2
|
|
90
|
+
└── ...
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Comandos
|
|
94
|
+
|
|
95
|
+
| Comando | Qué hace |
|
|
96
|
+
|---|---|
|
|
97
|
+
| `wu create [name]` | Wizard interactivo (TUI). Con `--template <fw>` modo no-interactivo. |
|
|
98
|
+
| `wu dev` | Servidor de desarrollo nativo. Un solo proceso, un solo puerto. |
|
|
99
|
+
| `wu build` | Compila todos los micro-apps en paralelo (Vite) → `dist/`. |
|
|
100
|
+
| `wu serve` | Sirve `dist/` con headers de seguridad (timeouts, body-cap). |
|
|
101
|
+
| `wu add <framework> <name>` | Agrega un micro-app a un proyecto existente. |
|
|
102
|
+
| `wu install` | Instala dependencias de todos los micro-apps. |
|
|
103
|
+
| `wu info` | Estado actual del proyecto (apps detectados, puertos, framework del shell). |
|
|
104
|
+
|
|
105
|
+
Referencia completa con todas las flags: **[docs/cli.md](docs/cli.md)**.
|
|
106
|
+
|
|
107
|
+
## Configuración
|
|
108
|
+
|
|
109
|
+
`wu.config.json` en la raíz del proyecto:
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"name": "my-shop",
|
|
114
|
+
"version": "0.3.0",
|
|
115
|
+
"shell": {
|
|
116
|
+
"dir": "shell",
|
|
117
|
+
"port": 4321,
|
|
118
|
+
"framework": "react"
|
|
119
|
+
},
|
|
120
|
+
"apps": [
|
|
121
|
+
{ "name": "catalog", "dir": "mf-catalog", "framework": "react", "port": 5001 },
|
|
122
|
+
{ "name": "cart", "dir": "mf-cart", "framework": "vue", "port": 5002 }
|
|
123
|
+
],
|
|
124
|
+
"proxy": {
|
|
125
|
+
"port": 3000,
|
|
126
|
+
"open_browser": true,
|
|
127
|
+
"/api": { "target": "http://localhost:8080", "rewrite": true, "cors": false }
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
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.
|
|
133
|
+
|
|
134
|
+
Schema completo, defaults, ejemplos de proxy: **[docs/configuration.md](docs/configuration.md)**.
|
|
135
|
+
|
|
136
|
+
## Frameworks soportados
|
|
137
|
+
|
|
138
|
+
13 frameworks en una sola CLI. Cada micro-app puede usar uno distinto del shell.
|
|
139
|
+
|
|
140
|
+
| Framework | Extensiones | Compilación | TypeScript |
|
|
141
|
+
|---|---|---|---|
|
|
142
|
+
| React | .jsx, .tsx | Zig nativo (JSX) → daemon (TSX) | ✓ |
|
|
143
|
+
| Preact | .jsx, .tsx | Zig nativo (JSX) → daemon (TSX) | ✓ |
|
|
144
|
+
| Vue | .vue | Daemon (esbuild) | ✓ |
|
|
145
|
+
| Svelte | .svelte | Daemon (esbuild) | ✓ |
|
|
146
|
+
| Solid.js | .jsx, .tsx | Daemon (babel-preset-solid) | ✓ |
|
|
147
|
+
| Angular | .ts | Daemon (esbuild bundle) | ✓ |
|
|
148
|
+
| Lit | .ts, .js | TS strip | ✓ |
|
|
149
|
+
| Stencil | .js | Passthrough | ✓ |
|
|
150
|
+
| Alpine.js | .js | Passthrough | – |
|
|
151
|
+
| Qwik | .jsx | Passthrough | ✓ |
|
|
152
|
+
| HTMX | .js | Passthrough | – |
|
|
153
|
+
| Stimulus | .js | Passthrough | – |
|
|
154
|
+
| Vanilla | .js, .ts | TS strip | ✓ |
|
|
155
|
+
|
|
156
|
+
## Arquitectura (resumen)
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
src/
|
|
160
|
+
cli/ args, banner, TUI primitives (raw mode, prompts)
|
|
161
|
+
commands/ dev, build, create, add, install, serve, info
|
|
162
|
+
templates/ 13 plantillas embebidas en el binario
|
|
163
|
+
config/ loader (std.json) + auto-discovery
|
|
164
|
+
runtime/ ← núcleo del dev server
|
|
165
|
+
dev_server.zig thread-per-connection HTTP server (~3.3k LOC)
|
|
166
|
+
handlers/ proxy.zig, hmr.zig (extraídos del monolítico)
|
|
167
|
+
http_parser.zig SIMD HTTP/1.1, 16 bytes/ciclo
|
|
168
|
+
transform.zig reescritura de imports + alias @/ ~/
|
|
169
|
+
jsx_transform.zig JSX nativo en Zig (React/Preact)
|
|
170
|
+
compile.zig pipeline 3-tier (Zig → daemon → fallback)
|
|
171
|
+
resolve.zig resolución NPM pura en Zig
|
|
172
|
+
cache.zig 2 niveles (LRU 256 entradas + disco capado 500MB)
|
|
173
|
+
ws_protocol.zig WebSocket RFC 6455
|
|
174
|
+
hypervisor/ watcher OS-nativo + trie router + transform pool
|
|
175
|
+
sentinel/ anti-bot + ACP (AI Content Protocol)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Detalles: **[docs/contributing.md](docs/contributing.md)**.
|
|
179
|
+
|
|
180
|
+
## Seguridad
|
|
181
|
+
|
|
182
|
+
Wu integra varias defensas de bajo nivel:
|
|
183
|
+
|
|
184
|
+
- **Anti-slowloris**: timeouts de 30 s en sockets aceptados.
|
|
185
|
+
- **Body-size cap**: 16 MB máx por request, 413 si excede.
|
|
186
|
+
- **Path-traversal**: validación post-URL-decode (`isPathSafe`).
|
|
187
|
+
- **Sentinel**: clasificador zero-alloc para bots; AI agents redirigidos a ACP (`/.well-known/acp.json`).
|
|
188
|
+
- **CORS opt-in**: el proxy no relaja CORS sin consentimiento explícito.
|
|
189
|
+
|
|
190
|
+
Configuración para producción y modelo de amenazas: **[docs/security.md](docs/security.md)**.
|
|
191
|
+
|
|
192
|
+
## Estadísticas
|
|
193
|
+
|
|
194
|
+
- **35** archivos Zig fuente, **~9.7k LOC** de runtime
|
|
195
|
+
- **~250-460 KB** binario release por plataforma
|
|
196
|
+
- **0** dependencias Zig externas
|
|
197
|
+
- **0** procesos Vite simultáneos en dev (un solo binario)
|
|
198
|
+
|
|
199
|
+
## Requisitos
|
|
200
|
+
|
|
201
|
+
- **Node.js 16+** para `npm install -g @wu-framework/cli`
|
|
202
|
+
- **Node.js 18+** a runtime sólo para Vue, Svelte, Solid o Angular (React/Preact corren en Zig puro)
|
|
203
|
+
- **Zig 0.16.0** sólo si construyes desde fuente
|
|
204
|
+
|
|
205
|
+
## Licencia
|
|
206
|
+
|
|
207
|
+
MIT — ver [LICENSE](LICENSE).
|
|
208
|
+
|
|
209
|
+
## Autor
|
|
210
|
+
|
|
211
|
+
Luis Garcia — creador de [wu-framework](https://www.wu-framework.com).
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
*© 2026 Wu Framework*
|
package/bin/wu-darwin-arm64
CHANGED
|
Binary file
|
package/bin/wu-darwin-x64
CHANGED
|
Binary file
|
package/bin/wu-linux-x64
CHANGED
|
Binary file
|
package/bin/wu-win32-x64.exe
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wu-framework/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Native Zig dev server + CLI for wu-framework microfrontends. One binary, one port, all your micro-apps.",
|
|
5
5
|
"license": "MIT",
|
|
6
|
+
"author": "Luis Garcia",
|
|
7
|
+
"homepage": "https://www.wu-framework.com",
|
|
8
|
+
"bugs": {
|
|
9
|
+
"url": "https://github.com/LuisPadre25/wu-cli/issues"
|
|
10
|
+
},
|
|
6
11
|
"bin": {
|
|
7
12
|
"wu": "bin/wu.js"
|
|
8
13
|
},
|
|
9
14
|
"files": [
|
|
10
15
|
"bin/",
|
|
11
16
|
"README.md",
|
|
17
|
+
"CHANGELOG.md",
|
|
12
18
|
"LICENSE"
|
|
13
19
|
],
|
|
14
20
|
"scripts": {
|
|
@@ -20,6 +26,9 @@
|
|
|
20
26
|
"cli",
|
|
21
27
|
"scaffold",
|
|
22
28
|
"dev-server",
|
|
29
|
+
"hmr",
|
|
30
|
+
"vite-alternative",
|
|
31
|
+
"zig",
|
|
23
32
|
"react",
|
|
24
33
|
"vue",
|
|
25
34
|
"svelte",
|
|
@@ -27,11 +36,15 @@
|
|
|
27
36
|
"preact",
|
|
28
37
|
"lit",
|
|
29
38
|
"angular",
|
|
30
|
-
"
|
|
39
|
+
"qwik",
|
|
40
|
+
"stencil",
|
|
41
|
+
"alpine",
|
|
42
|
+
"htmx",
|
|
43
|
+
"stimulus"
|
|
31
44
|
],
|
|
32
45
|
"repository": {
|
|
33
46
|
"type": "git",
|
|
34
|
-
"url": "https://github.com/LuisPadre25/wu-cli"
|
|
47
|
+
"url": "git+https://github.com/LuisPadre25/wu-cli.git"
|
|
35
48
|
},
|
|
36
49
|
"engines": {
|
|
37
50
|
"node": ">=16"
|
package/bin/wu.exe
DELETED
|
Binary file
|