@randomdev/pulsedev 0.1.2

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/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026, randomdev
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,585 @@
1
+ <p align="center">
2
+ <img src="web/assets/logo.png" alt="PulseDev Logo" width="128">
3
+ </p>
4
+
5
+ # ⚡ PulseDev
6
+
7
+ **Native Node.js development server — static files, hot reload, and logging in 1.9MB**
8
+
9
+ [![npm version](https://img.shields.io/badge/npm-0.1.1-blueviolet?style=flat-square)](https://www.npmjs.com/package/pulsedev)
10
+ [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D22.0.0-green?style=flat-square&logo=node.js)](https://nodejs.org/)
11
+ [![License: ISC](https://img.shields.io/badge/License-ISC-blue?style=flat-square)](https://opensource.org/licenses/ISC)
12
+ [![Status](https://img.shields.io/badge/status-active-success?style=flat-square)]()
13
+ [![Zero deps](https://img.shields.io/badge/dependencies-zero-orange?style=flat-square)]()
14
+
15
+ ---
16
+
17
+ # English
18
+
19
+ > Two commands. No `node_modules` in your project. No complicated setup.
20
+ > Just `pulsedev init` and `pulsedev run`.
21
+
22
+ ## What is PulseDev?
23
+
24
+ PulseDev is a CLI tool for Node.js that starts a local HTTP server, watches your files for changes, and reloads the server automatically. It's built **100% with Node.js native modules**, with zero production dependencies.
25
+
26
+ Designed for developers who need a fast, lightweight dev environment without Webpack, Vite, or any other bundler.
27
+
28
+ **What it does:**
29
+
30
+ - 🖥️ native HTTP server (no Express, no Fastify)
31
+ - 👁️ file system watching with `fs.watch`, reloads on real changes
32
+ - 🔁 automatic cache busting: MD5 hash injection into `src` and `href` attributes
33
+ - 📝 HTTP request logging to terminal or persistent file with auto-rotation
34
+ - 📁 project scaffolding with a single command
35
+ - 🎨 extended MIME types: images, video, audio, fonts, documents, and more
36
+ - ⚙️ configurable via `pulsedev.json`
37
+ - ⚡ zero production dependencies — all native Node.js
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ npm install -g pulsedev
43
+ ```
44
+
45
+ Installation is **global**. No `node_modules` in your project.
46
+
47
+ > **Requirement:** Node.js 22 LTS or higher
48
+
49
+ **Local development:**
50
+
51
+ ```bash
52
+ git clone https://github.com/pabloacisera/pulsedev_linux.git
53
+ cd pulsedev
54
+ npm link
55
+ ```
56
+
57
+ ## Quick start
58
+
59
+ ### 1 — Initialize the project
60
+
61
+ ```bash
62
+ pulsedev init
63
+ ```
64
+
65
+ Automatically generates:
66
+
67
+ ```
68
+ your-project/
69
+ ├── pulsedev.json ← configuration
70
+ └── src/
71
+ ├── index.html ← main page
72
+ ├── css/
73
+ │ └── index.css ← base styles
74
+ ├── js/
75
+ │ ├── index.js ← main script
76
+ │ └── socket-client.js ← WebSocket client
77
+ └── assets/
78
+ └── Arimo-VariableFont_wght.ttf
79
+ ```
80
+
81
+ ### 2 — Start the server
82
+
83
+ ```bash
84
+ pulsedev run
85
+ ```
86
+
87
+ The server runs at `http://localhost:3003` (or your configured port).
88
+ From that moment, any file change in `src/` triggers an automatic reload.
89
+
90
+ ### 3 — Help and version
91
+
92
+ ```bash
93
+ pulsedev --help
94
+ pulsedev --version
95
+ ```
96
+
97
+ ## Configuration — `pulsedev.json`
98
+
99
+ ```json
100
+ {
101
+ "watchPath": ["*"],
102
+ "runFile": "index.html",
103
+ "port": 3003,
104
+ "outputPath": "terminal",
105
+ "ignoreExtensions": ["*.txt", "*.log", "*.env", "*.md"],
106
+ "debounceDelay": 0.5,
107
+ "recursive": true,
108
+ "logLimit": 5
109
+ }
110
+ ```
111
+
112
+ | Property | Type | Description | Default |
113
+ |----------|------|-------------|---------|
114
+ | `watchPath` | `string[]` | Directories to watch. `["*"]` watches everything | `["*"]` |
115
+ | `runFile` | `string` | Entry HTML file | `"index.html"` |
116
+ | `port` | `number` | HTTP server port | `3003` |
117
+ | `outputPath` | `string` | Log destination: `"terminal"` or folder path | `"terminal"` |
118
+ | `ignoreExtensions` | `string[]` | Extensions the watcher ignores | `["*.txt","*.log","*.env","*.md"]` |
119
+ | `debounceDelay` | `number` | Seconds to wait before reload (prevents duplicate events) | `0.5` |
120
+ | `recursive` | `boolean` | Watch subdirectories. See note below. | `true` |
121
+ | `logLimit` | `number` | Max log file size in KB before rotation | `5` |
122
+
123
+ ---
124
+
125
+ `recursive` controls whether the watcher enters subdirectories.
126
+ Its behavior depends on `watchPath`:
127
+
128
+ **Case 1 — `watchPath: ["*"]` with `recursive: false` → Invalid**
129
+
130
+ ```json
131
+ {
132
+ "watchPath": ["*"],
133
+ "recursive": false
134
+ }
135
+ ```
136
+
137
+ With `watchPath: ["*"]` the server listens from the project root.
138
+ If `recursive` were `false`, it would only detect changes in files directly
139
+ at the root (where normally only `pulsedev.json` lives). Changes in `src/`
140
+ would never be detected, breaking hot reload.
141
+
142
+ PulseDev detects this combination, ignores the `false`, forces `recursive: true`
143
+ automatically, and shows a warning explaining why.
144
+
145
+ **Case 2 — Specific `watchPath` with `recursive: false` → Valid**
146
+
147
+ ```json
148
+ {
149
+ "watchPath": ["./src/css", "./src/js"],
150
+ "recursive": false
151
+ }
152
+ ```
153
+
154
+ With specific paths the user controls exactly which directories to watch.
155
+ `recursive: false` is valid here: the watcher only monitors files at the root
156
+ of each configured path, without entering subdirectories.
157
+ PulseDev shows an info message confirming the active mode.
158
+
159
+ **Case 3 — Any `watchPath` with `recursive: true` or unset → Correct**
160
+
161
+ ```json
162
+ {
163
+ "watchPath": ["*"],
164
+ "recursive": true
165
+ }
166
+ ```
167
+
168
+ Standard behavior. The watcher enters all subdirectories
169
+ of the configured paths. Recommended for most projects.
170
+
171
+ ## How hot reload works
172
+
173
+ PulseDev does not reload on every file system event. Before triggering a
174
+ reload, it computes the MD5 hash of the modified file and compares it to the
175
+ previous hash stored in memory. **It only reloads if the content actually changed.**
176
+
177
+ ```
178
+ file saved to disk
179
+ → fs.watch detects the event
180
+ → stat() verifies it's a file (not a directory)
181
+ → compareChanges() computes MD5 and compares with in-memory Map
182
+ → if changed → debounce → reloadServer()
183
+ ```
184
+
185
+ Additionally, when serving HTML, the server automatically injects the hash of
186
+ each referenced CSS and JS file:
187
+
188
+ ```html
189
+ <!-- what you write -->
190
+ <link rel="stylesheet" href="css/index.css">
191
+
192
+ <!-- what the browser receives -->
193
+ <link rel="stylesheet" href="css/index.css?v=a3f2c1b4">
194
+ ```
195
+
196
+ ### WebSocket auto-reload system
197
+
198
+ PulseDev notifies the browser when the server restarts via a persistent **WebSocket** connection. The flow:
199
+
200
+ ```
201
+ file changed → watcher detects → reloadServer()
202
+ → closeAllConnections() closes WS sockets
203
+ → HTTP server restarts with new config
204
+ → browser detects closed socket (onclose)
205
+ → location.reload() refreshes the page
206
+ ```
207
+
208
+ **Injected WebSocket client** (`socket-client.js`):
209
+
210
+ ```javascript
211
+ let ws = new WebSocket("ws://localhost:" + location.port);
212
+ ws.onclose = () => location.reload(); // server restarted
213
+ ws.onerror = () => setTimeout(() => location.reload(), 500); // connection error
214
+ ```
215
+
216
+ **Why WebSocket over SSE or polling?**
217
+
218
+ - **Bidirectional**: server can notify the client instantly
219
+ - **Low overhead**: single open TCP connection, no multiple HTTP requests
220
+ - **Zero latency**: no polling interval, notification is immediate
221
+ - **Native in the browser**: no additional dependencies
222
+ - **Persistent**: connection stays open while the browser is on the page
223
+
224
+ ## Logging system
225
+
226
+ By default, HTTP requests are logged to `logs/requests.log`. A native Worker Thread
227
+ handles file rotation when it exceeds the `logLimit` threshold, without blocking
228
+ the main thread:
229
+
230
+ ```
231
+ server running at http://localhost:3003
232
+ - watching for changes in /path/to/project
233
+ - log written to logs/requests.log
234
+ ```
235
+
236
+ To see logs in the terminal instead, set `"outputPath"` to `"terminal"` in your
237
+ `pulsedev.json`.
238
+
239
+ ## Supported content types
240
+
241
+ The server recognizes and correctly serves over 40 file types:
242
+
243
+ | Category | Extensions |
244
+ |----------|------------|
245
+ | Web | `html`, `css`, `js`, `mjs`, `json`, `xml`, `txt` |
246
+ | Images | `png`, `jpg`, `gif`, `webp`, `avif`, `svg`, `ico`, `bmp`, `tiff` |
247
+ | Fonts | `ttf`, `otf`, `woff`, `woff2`, `eot` |
248
+ | Audio | `mp3`, `wav`, `ogg`, `aac`, `flac`, `opus` |
249
+ | Video | `mp4`, `webm`, `avi`, `mov`, `mkv` |
250
+ | Documents | `pdf`, `doc`, `docx`, `xls`, `xlsx`, `zip` |
251
+
252
+ ## Project architecture
253
+
254
+ ```
255
+ pulsedev/
256
+ ├── bin/
257
+ │ └── cli.js ← CLI entry point (init / run / --help / --version)
258
+ ├── core/
259
+ │ ├── init.js ← Project scaffolding
260
+ │ ├── run.js ← Re-export of serverManager
261
+ │ └── serverManager.js ← HTTP server, state, and reload
262
+ ├── helpers/
263
+ │ ├── watcher.js ← File watcher with fs.watch and debounce
264
+ │ ├── hashFingerprint.js ← MD5 comparison and cache busting
265
+ │ ├── resourceHasher.js ← Hash injection into HTML
266
+ │ ├── mimeTypes.js ← MIME types and binary extensions
267
+ │ ├── writter.js ← File read/write + log Worker
268
+ │ └── counterChar.js ← Worker Thread for log rotation
269
+ └── web/
270
+ ├── assets/
271
+ │ ├── Arimo-VariableFont_wght.ttf
272
+ │ ├── github.svg
273
+ │ └── npm.svg
274
+ └── templates/
275
+ ├── pulsedev.json ← Default config
276
+ ├── index.html ← Welcome page
277
+ ├── index.css ← Base styles
278
+ ├── index.js ← Main script
279
+ └── socket-client.js ← WebSocket client
280
+ ```
281
+
282
+ ## Built with
283
+
284
+ PulseDev is built **100% with Node.js native modules**. Zero production dependencies.
285
+
286
+ | Module | Usage |
287
+ |--------|-------|
288
+ | `node:http` | HTTP server |
289
+ | `node:fs` / `node:fs/promises` | File reading, writing, and watching |
290
+ | `node:path` | Path resolution |
291
+ | `node:os` | Hostname for logs |
292
+ | `node:crypto` | MD5 hash for fingerprinting and cache busting |
293
+ | `node:worker_threads` | Worker Thread for log rotation |
294
+ | `node:util` → `styleText` | Terminal colors |
295
+ | `node:url` | `__dirname` resolution in ESM |
296
+
297
+ ---
298
+
299
+ ---
300
+
301
+ # Español
302
+
303
+ > Dos comandos. Sin `node_modules` en tu proyecto. Sin configuración complicada.
304
+ > Solo `pulsedev init` y `pulsedev run`.
305
+
306
+ ## ¿Qué es PulseDev?
307
+
308
+ PulseDev es una herramienta CLI para Node.js que levanta un servidor HTTP local, vigila los cambios en tus archivos y recarga el servidor automáticamente. Está construida **100% con módulos nativos de Node.js**, sin ninguna dependencia de producción.
309
+
310
+ Está pensada para developers que necesitan un entorno de desarrollo rápido y liviano, sin instalar Webpack, Vite ni nada por el estilo.
311
+
312
+ **¿Qué hace exactamente?**
313
+
314
+ - 🖥️ Levanta un servidor HTTP nativo (sin Express, sin Fastify)
315
+ - 👁️ Vigila el sistema de archivos con `fs.watch` y recarga ante cambios reales
316
+ - 🔁 Cache busting automático: inyecta hashes MD5 en los `src` y `href` del HTML
317
+ - 📝 Logs de peticiones HTTP en terminal o archivo persistente con rotación automática
318
+ - 📁 Genera la estructura base del proyecto con un solo comando
319
+ - 🎨 Tipos MIME extendidos: imágenes, video, audio, fuentes, documentos y más
320
+ - ⚙️ Configurable vía `pulsedev.json`
321
+ - ⚡ Cero dependencias de producción — todo Node.js nativo
322
+
323
+ ## Instalación
324
+
325
+ ```bash
326
+ npm install -g pulsedev
327
+ ```
328
+
329
+ La instalación es **global**. No se genera `node_modules` en tu proyecto.
330
+
331
+ > **Requisito:** Node.js 22 LTS o superior
332
+
333
+ **Desarrollo local:**
334
+
335
+ ```bash
336
+ git clone https://github.com/pabloacisera/pulsedev_linux.git
337
+ cd pulsedev
338
+ npm link
339
+ ```
340
+
341
+ ## Uso rápido
342
+
343
+ ### 1 — Inicializar el proyecto
344
+
345
+ ```bash
346
+ pulsedev init
347
+ ```
348
+
349
+ Genera automáticamente:
350
+
351
+ ```
352
+ tu-proyecto/
353
+ ├── pulsedev.json ← configuración
354
+ └── src/
355
+ ├── index.html ← página principal
356
+ ├── css/
357
+ │ └── index.css ← estilos base
358
+ ├── js/
359
+ │ ├── index.js ← script principal
360
+ │ └── socket-client.js ← cliente WebSocket
361
+ └── assets/
362
+ └── Arimo-VariableFont_wght.ttf
363
+ ```
364
+
365
+ ### 2 — Levantar el servidor
366
+
367
+ ```bash
368
+ pulsedev run
369
+ ```
370
+
371
+ El servidor queda corriendo en `http://localhost:3003` (o el puerto configurado).
372
+ Desde ese momento, cualquier cambio en los archivos de `src/` dispara un reload automático.
373
+
374
+ ### 3 — Ayuda y versión
375
+
376
+ ```bash
377
+ pulsedev --help
378
+ pulsedev --version
379
+ ```
380
+
381
+ ## Configuración — `pulsedev.json`
382
+
383
+ ```json
384
+ {
385
+ "watchPath": ["*"],
386
+ "runFile": "index.html",
387
+ "port": 3003,
388
+ "outputPath": "terminal",
389
+ "ignoreExtensions": ["*.txt", "*.log", "*.env", "*.md"],
390
+ "debounceDelay": 0.5,
391
+ "recursive": true,
392
+ "logLimit": 5
393
+ }
394
+ ```
395
+
396
+ | Propiedad | Tipo | Descripción | Default |
397
+ |-----------|------|-------------|---------|
398
+ | `watchPath` | `string[]` | Directorios a vigilar. `["*"]` vigila todo el proyecto | `["*"]` |
399
+ | `runFile` | `string` | Archivo HTML de entrada | `"index.html"` |
400
+ | `port` | `number` | Puerto del servidor HTTP | `3003` |
401
+ | `outputPath` | `string` | Destino de logs: `"terminal"` o ruta de carpeta | `"terminal"` |
402
+ | `ignoreExtensions` | `string[]` | Extensiones que el watcher ignora | `["*.txt","*.log","*.env","*.md"]` |
403
+ | `debounceDelay` | `number` | Segundos de espera antes del reload (evita eventos repetidos) | `0.5` |
404
+ | `recursive` | `boolean` | Vigilar subdirectorios. Ver nota importante abajo. | `true` |
405
+ | `logLimit` | `number` | Tamaño máximo del log en KB antes de rotar | `5` |
406
+
407
+ ---
408
+
409
+ `recursive` controla si el watcher entra en subdirectorios al vigilar cambios.
410
+ Su comportamiento depende de cómo esté configurado `watchPath`:
411
+
412
+ **Caso 1 — `watchPath: ["*"]` con `recursive: false` → Configuración inválida**
413
+
414
+ ```json
415
+ {
416
+ "watchPath": ["*"],
417
+ "recursive": false
418
+ }
419
+ ```
420
+
421
+ Con `watchPath: ["*"]` el servidor escucha desde la raíz del proyecto.
422
+ Si `recursive` fuera `false`, solo detectaría cambios en archivos ubicados
423
+ directamente en esa raíz (donde normalmente solo está `pulsedev.json`).
424
+ Ningún cambio en `src/` sería detectado y el hot reload nunca funcionaría.
425
+
426
+ PulseDev detecta esta combinación, ignora el `false`, fuerza `recursive: true`
427
+ automáticamente y muestra una advertencia en terminal explicando el motivo.
428
+
429
+ **Caso 2 — `watchPath` con rutas propias y `recursive: false` → Válido**
430
+
431
+ ```json
432
+ {
433
+ "watchPath": ["./src/css", "./src/js"],
434
+ "recursive": false
435
+ }
436
+ ```
437
+
438
+ Con rutas específicas el usuario controla exactamente qué directorios vigilar.
439
+ `recursive: false` es válido acá: el watcher escucha solo los archivos
440
+ en la raíz de cada ruta configurada, sin entrar en subdirectorios.
441
+ PulseDev muestra un mensaje informativo confirmando el modo activo.
442
+
443
+ **Caso 3 — Cualquier `watchPath` con `recursive: true` o sin configurar → Correcto**
444
+
445
+ ```json
446
+ {
447
+ "watchPath": ["*"],
448
+ "recursive": true
449
+ }
450
+ ```
451
+
452
+ Comportamiento estándar. El watcher entra en todos los subdirectorios
453
+ de las rutas configuradas. Es el modo recomendado para la mayoría de los proyectos.
454
+
455
+ ## Cómo funciona el hot reload
456
+
457
+ PulseDev no recarga ante cualquier evento del sistema de archivos. Antes de disparar el
458
+ reload, calcula el hash MD5 del archivo modificado y lo compara con el hash anterior
459
+ guardado en memoria. **Solo recarga si el contenido realmente cambió.**
460
+
461
+ ```
462
+ archivo guardado en disco
463
+ → fs.watch detecta el evento
464
+ → stat() verifica que sea un archivo (no carpeta)
465
+ → compareChanges() calcula MD5 y compara con Map en memoria
466
+ → si cambió → debounce → reloadServer()
467
+ ```
468
+
469
+ Adicionalmente, al servir el HTML el servidor inyecta automáticamente el hash del
470
+ contenido actual de cada CSS y JS referenciado:
471
+
472
+ ```html
473
+ <!-- lo que escribís -->
474
+ <link rel="stylesheet" href="css/index.css">
475
+
476
+ <!-- lo que el browser recibe -->
477
+ <link rel="stylesheet" href="css/index.css?v=a3f2c1b4">
478
+ ```
479
+
480
+ ### Sistema de reload automático por WebSocket
481
+
482
+ PulseDev notifica al navegador cuando el servidor se reinicia mediante una conexión **WebSocket** persistente. El flujo es:
483
+
484
+ ```
485
+ archivo modificado → watcher detecta cambio → reloadServer()
486
+ → closeAllConnections() cierra sockets WS
487
+ → servidor HTTP se reinicia con nueva config
488
+ → navegador detecta socket cerrado (onclose)
489
+ → location.reload() actualiza la página
490
+ ```
491
+
492
+ **Cliente WebSocket inyectado** (`socket-client.js`):
493
+
494
+ ```javascript
495
+ let ws = new WebSocket("ws://localhost:" + location.port);
496
+ ws.onclose = () => location.reload(); // servidor reiniciado
497
+ ws.onerror = () => setTimeout(() => location.reload(), 500); // error de conexión
498
+ ```
499
+
500
+ **¿Por qué WebSocket en vez de SSE o polling?**
501
+
502
+ - **Bidireccional**: el servidor puede notificar al cliente al instante
503
+ - **Bajo overhead**: una sola conexión TCP abierta, no múltiples requests HTTP
504
+ - **Latencia cero**: no hay polling interval, la notificación es inmediata
505
+ - **Nativo en el browser**: no requiere dependencias adicionales
506
+ - **Persistente**: la conexión permanece abierta mientras el navegador esté en la página
507
+
508
+ ## Sistema de logs
509
+
510
+ Por defecto, las peticiones HTTP se registran en `logs/requests.log`. Un Worker Thread
511
+ nativo se encarga de rotar el archivo cuando supera el límite configurado en `logLimit`,
512
+ sin bloquear el hilo principal:
513
+
514
+ ```
515
+ servidor corriendo en http://localhost:3003
516
+ - watching for changes in /path/to/project
517
+ - log written to logs/requests.log
518
+ ```
519
+
520
+ Si preferís ver los logs en terminal, cambiá `"outputPath"` a `"terminal"` en tu
521
+ `pulsedev.json`.
522
+
523
+ ## Tipos de contenido soportados
524
+
525
+ El servidor reconoce y sirve correctamente más de 40 tipos de archivos:
526
+
527
+ | Categoría | Extensiones |
528
+ |-----------|-------------|
529
+ | Web | `html`, `css`, `js`, `mjs`, `json`, `xml`, `txt` |
530
+ | Imágenes | `png`, `jpg`, `gif`, `webp`, `avif`, `svg`, `ico`, `bmp`, `tiff` |
531
+ | Fuentes | `ttf`, `otf`, `woff`, `woff2`, `eot` |
532
+ | Audio | `mp3`, `wav`, `ogg`, `aac`, `flac`, `opus` |
533
+ | Video | `mp4`, `webm`, `avi`, `mov`, `mkv` |
534
+ | Documentos | `pdf`, `doc`, `docx`, `xls`, `xlsx`, `zip` |
535
+
536
+ ## Arquitectura del proyecto
537
+
538
+ ```
539
+ pulsedev/
540
+ ├── bin/
541
+ │ └── cli.js ← Punto de entrada CLI (init / run / --help / --version)
542
+ ├── core/
543
+ │ ├── init.js ← Genera la estructura del proyecto
544
+ │ ├── run.js ← Re-export de serverManager
545
+ │ └── serverManager.js ← Servidor HTTP, estado y reload
546
+ ├── helpers/
547
+ │ ├── watcher.js ← File watcher con fs.watch y debounce
548
+ │ ├── hashFingerprint.js ← Comparación MD5 y cache busting
549
+ │ ├── resourceHasher.js ← Inyección de hashes en HTML
550
+ │ ├── mimeTypes.js ← Tipos MIME y extensiones binarias
551
+ │ ├── writter.js ← Lectura/escritura de archivos + Worker de logs
552
+ │ └── counterChar.js ← Worker Thread para rotación de logs
553
+ └── web/
554
+ ├── assets/
555
+ │ ├── Arimo-VariableFont_wght.ttf
556
+ │ ├── github.svg
557
+ │ └── npm.svg
558
+ └── templates/
559
+ ├── pulsedev.json ← Config por defecto
560
+ ├── index.html ← Página de bienvenida
561
+ ├── index.css ← Estilos base
562
+ ├── index.js ← Script principal
563
+ └── socket-client.js ← Cliente WebSocket
564
+ ```
565
+
566
+ ## Tecnologías utilizadas
567
+
568
+ PulseDev está construido **100% con módulos nativos de Node.js**. Sin dependencias de producción.
569
+
570
+ | Módulo | Uso |
571
+ |--------|-----|
572
+ | `node:http` | Servidor HTTP |
573
+ | `node:fs` / `node:fs/promises` | Lectura, escritura y vigilancia de archivos |
574
+ | `node:path` | Resolución de rutas |
575
+ | `node:os` | Hostname para logs |
576
+ | `node:crypto` | Hash MD5 para fingerprinting y cache busting |
577
+ | `node:worker_threads` | Worker Thread para rotación de logs |
578
+ | `node:util` → `styleText` | Colores en terminal |
579
+ | `node:url` | Resolución de `__dirname` en ESM |
580
+
581
+ ---
582
+
583
+ ## Autor
584
+
585
+ Desarrollado por **randomdev** · Licencia [ISC](https://opensource.org/licenses/ISC)
package/bin/cli.js ADDED
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env node
2
+ import { styleText } from "node:util";
3
+ import { argv, cwd } from "node:process";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ // --- Guard de versión: PulseDev requiere Node.js 22+ por fs.watch recursive en Linux ---
9
+ const major = parseInt(process.versions.node.split(".")[0], 10);
10
+ if (Number.isNaN(major) || major < 22) {
11
+ console.error(
12
+ styleText("bgRed", " error ") +
13
+ ` PulseDev requiere Node.js 22 o superior. Versión detectada: v${process.versions.node}`
14
+ );
15
+ process.exit(1);
16
+ }
17
+
18
+ const currentDirectory = cwd();
19
+
20
+ // --- Leer la versión desde el package.json de forma segura en ESM ---
21
+ const __filename = fileURLToPath(import.meta.url);
22
+ const __dirname = path.dirname(__filename);
23
+ const packageJsonPath = path.resolve(__dirname, "../package.json");
24
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
25
+ const version = packageJson.version;
26
+
27
+ // verificar que comando se ejecuto
28
+ let executeCommand = argv[2];
29
+ let helpCommands = `
30
+ ${styleText("bold", "PulseDev - Vigilante de archivos para Node.js")}
31
+
32
+ ${styleText("underline", "Uso:")}
33
+ pulsedev <comando>
34
+
35
+ ${styleText("underline", "Comandos disponibles:")}
36
+ init Genera el archivo de configuración "pulsedev.json"
37
+ run Ejecuta el servidor y vigila los cambios
38
+
39
+ ${styleText("underline", "Opciones globales:")}
40
+ --version, -v Muestra la versión
41
+ --help, -h Muestra la ayuda
42
+
43
+ ${styleText("underline", "Opciones de run:")}
44
+ --list-flags Muestra los flags disponibles (= claves de tu pulsedev.json)
45
+ --persist Si se usan flags, persiste el override al JSON
46
+ (por defecto los flags son override en memoria, no destructivo)
47
+ --<clave> <valor> Cualquier clave de tu pulsedev.json (ej: --port 4000)
48
+
49
+ ${styleText("underline", "Ejemplos:")}
50
+ pulsedev init Crea la configuración inicial
51
+ pulsedev run Inicia el vigilante
52
+ pulsedev run --list-flags Muestra los flags disponibles
53
+ pulsedev run --port 4000 Override en memoria (no toca el JSON)
54
+ pulsedev run --port 4000 --persist Override + escribe el JSON
55
+
56
+ ${styleText("dim", "Documentación: https://github.com/pabloacisera/pulsedev_linux")}
57
+ `;
58
+
59
+ // Estructura de control de comandos
60
+ if (executeCommand === "init") {
61
+ import("../core/init.js").then(m => m.runInit(currentDirectory)).catch(e => { console.error(e); process.exit(1); });
62
+ } else if (executeCommand === "run") {
63
+ import("../core/run.js").then(m => m.runCommand(currentDirectory)).catch(e => { console.error(e); process.exit(1); });
64
+ } else if (executeCommand === "--help" || executeCommand === "-h") {
65
+ console.log(helpCommands);
66
+ } else if (executeCommand === "--version" || executeCommand === "-v") {
67
+ // Mostramos la versión dinámica con un toque de estilo
68
+ console.log(`v${version}`);
69
+ } else {
70
+ console.log(
71
+ styleText("bgMagenta", " Advertencia ") +
72
+ " No se ha ejecutado ningún comando válido. Usá " +
73
+ styleText("bold", "--help") + " para ver las opciones."
74
+ );
75
+ }