nicola-framework 1.0.4 → 1.0.5

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 (2) hide show
  1. package/README.md +391 -108
  2. package/package.json +5 -2
package/README.md CHANGED
@@ -10,30 +10,60 @@ Nicola expone un **servidor HTTP nativo** con un **router tipo Express** y utili
10
10
 
11
11
  ---
12
12
 
13
- ## Estado actual del proyecto (lo que realmente hay)
13
+ ## 📌 Índice
14
+
15
+ - [Qué incluye](#-qué-incluye)
16
+ - [Instalación](#-instalación)
17
+ - [Crear un proyecto (CLI)](#-crear-un-proyecto-cli)
18
+ - [Levantar el servidor (dev)](#-levantar-el-servidor-dev)
19
+ - [Quickstart (manual)](#-quickstart-manual)
20
+ - [Guía del Router](#-guía-del-router)
21
+ - [Request/Response (lo que hay)](#-requestresponse-lo-que-hay)
22
+ - [Manejo de errores](#-manejo-de-errores)
23
+ - [Middlewares](#-middlewares)
24
+ - [Seguridad (Regulator + JWT)](#-seguridad-regulator--jwt)
25
+ - [Dynamo ORM (Postgres)](#-dynamo-orm-postgres)
26
+ - [Variables de entorno](#-variables-de-entorno)
27
+ - [Tests](#-tests)
28
+ - [Troubleshooting](#-troubleshooting)
29
+
30
+ ---
31
+
32
+ ## ✅ Qué incluye
33
+
34
+ Esta lista está alineada con el **código actual** del repositorio:
14
35
 
15
36
  - **Core/Router**: `Nicola` (default) extiende `Remote`.
16
37
  - **Body parsing**: JSON si `Content-Type` incluye `application/json` (límite ~2MB). Si no, `req.body = {}`.
17
- - **Helpers de response**: `res.json(data)` y `res.send(text)`. (No existe `res.status()`.)
18
- - **CORS**: `EasyCors` permite `*` y responde `OPTIONS` con `204`.
38
+ - **Helpers de response**: `res.json(data)` y `res.send(text)`.
39
+ - Nota: no existe `res.status()`; usa `res.statusCode`.
40
+ - **CORS**: `EasyCors()` permite `*` y responde `OPTIONS` con `204`.
19
41
  - **Security headers**: `Teleforce` aplica headers básicos (no-sniff, frame deny, etc.).
20
42
  - **Logger**: `Shadowgraph` loggea al terminar la respuesta.
21
- - **Errores**: si un handler lanza error o llama `next(err)`, se responde HTML via `BlackBox`. En `NODE_ENV=production` no se envía stacktrace al cliente.
22
- - **JWT**: `Coherer` (HS256) funciona vía métodos **estáticos** y requiere `NICOLA_SECRET` en env.
23
- - **ORM**: `Dynamo` soporta **Postgres** hoy (driver `postgres`). La lib `pg` es **dependencia opcional** (se instala aparte).
24
- - **Hot reload**: `LiveCurrent` reinicia el proceso Node al detectar cambios en el directorio.
43
+ - **Errores**: si un handler lanza error o llama `next(err)`, se responde HTML via `BlackBox`.
44
+ - En `NODE_ENV=production` se ocultan mensaje/stack al cliente.
45
+ - **JWT**: `Coherer` (HS256) via métodos **estáticos** y requiere `NICOLA_SECRET`.
46
+ - **ORM**: `Dynamo` soporta **Postgres** (driver `postgres`). `pg` es dependencia opcional.
47
+ - **Hot reload**: `LiveCurrent` reinicia el proceso Node al detectar cambios (en `process.cwd()`).
25
48
 
26
49
  ---
27
50
 
28
51
  ## 📦 Instalación
29
52
 
53
+ Requisitos:
54
+
55
+ - Node.js >= 16
56
+ - Proyecto ESM (Nicola es ESM)
57
+
58
+ Instalar como dependencia del proyecto:
59
+
30
60
  ```bash
31
61
  npm install nicola-framework
32
62
  ```
33
63
 
34
64
  ### (Opcional) Postgres
35
65
 
36
- El dialecto Postgres usa `pg` por import dinámico.
66
+ El dialecto Postgres usa `pg` por import dinámico. Si vas a usar Dynamo con Postgres:
37
67
 
38
68
  ```bash
39
69
  npm install pg
@@ -41,150 +71,376 @@ npm install pg
41
71
 
42
72
  ---
43
73
 
44
- ## Quickstart
74
+ ## 🧰 Crear un proyecto (CLI)
75
+
76
+ Nicola incluye un CLI con dos comandos:
77
+
78
+ - `init <nombre>`: crea una estructura mínima.
79
+ - `start`: ejecuta `app.js` con hot reload (LiveCurrent).
45
80
 
46
- ### Servidor HTTP básico
81
+ ### Opción A: sin instalar global (recomendado)
82
+
83
+ ```bash
84
+ npx nicola init mi-api
85
+ cd mi-api
86
+ npm install
87
+ npm start
88
+ ```
89
+
90
+ ### Opción B: instalando global
91
+
92
+ ```bash
93
+ npm install -g nicola-framework
94
+ nicola init mi-api
95
+ cd mi-api
96
+ npm install
97
+ nicola start
98
+ ```
99
+
100
+ ### Qué genera `nicola init`
101
+
102
+ La CLI crea:
103
+
104
+ - `app.js`
105
+ - `src/controllers/user.controller.js`
106
+ - `src/routes/user.Routes.js`
107
+ - `package.json` con `"type": "module"` y script `start`.
108
+
109
+ El `app.js` generado monta las rutas así:
47
110
 
48
111
  ```js
49
- import Nicola from 'nicola-framework';
112
+ import Nicola, { Regulator } from "nicola-framework";
113
+ import UserRoute from "./src/routes/user.Routes.js";
114
+
115
+ Regulator.load();
50
116
 
51
117
  const app = new Nicola();
52
118
 
53
- app.get('/', (req, res) => {
54
- res.json({ ok: true, message: 'Hello from Nicola!' });
119
+ app.use("/user", UserRoute);
120
+
121
+ app.get("/", (req, res) => {
122
+ res.json({ message: "Bienvenido a tu proyecto en Nicola" });
55
123
  });
56
124
 
57
125
  app.listen(3000, () => {
58
- console.log('Server running on http://localhost:3000');
126
+ console.log("Servidor corriendo en http://localhost:3000");
59
127
  });
60
-
61
- // Opcional: timeouts del server (en ms)
62
- // NICOLA_REQUEST_TIMEOUT=30000
63
- // NICOLA_HEADERS_TIMEOUT=10000
64
- // NICOLA_KEEP_ALIVE_TIMEOUT=65000
65
128
  ```
66
129
 
67
- ### Router anidado y params
130
+ ---
131
+
132
+ ## 🚀 Levantar el servidor (dev)
133
+
134
+ Si tu entrypoint es `app.js` (como genera la CLI), tienes dos opciones:
135
+
136
+ - `npm start` (en proyecto generado)
137
+ - `nicola start` / `npx nicola start`
138
+
139
+ `start` usa LiveCurrent, que:
140
+
141
+ - observa cambios en el directorio actual (recursivo)
142
+ - ignora `node_modules`
143
+ - reinicia el proceso cuando detecta un cambio
144
+
145
+ ---
146
+
147
+ ## ⚡ Quickstart (manual)
148
+
149
+ Servidor HTTP básico:
68
150
 
69
151
  ```js
70
- import { Nicola, Remote } from 'nicola-framework';
152
+ import Nicola from "nicola-framework";
71
153
 
72
154
  const app = new Nicola();
73
- const api = new Remote();
74
155
 
75
- api.get('/users', (req, res) => {
76
- res.json({ users: ['Alice', 'Bob'] });
156
+ app.get("/", (req, res) => {
157
+ res.json({ ok: true, message: "Hello from Nicola!" });
77
158
  });
78
159
 
79
- api.get('/users/:id', (req, res) => {
80
- res.json({ userId: req.params.id });
160
+ app.listen(3000, () => {
161
+ console.log("Server running on http://localhost:3000");
81
162
  });
163
+ ```
82
164
 
83
- app.use('/api', api);
84
- app.listen(3000);
165
+ Opcional: timeouts del server (en ms). Nicola lee estas variables al llamar `listen()`:
166
+
167
+ ```env
168
+ NICOLA_REQUEST_TIMEOUT=30000
169
+ NICOLA_HEADERS_TIMEOUT=10000
170
+ NICOLA_KEEP_ALIVE_TIMEOUT=65000
85
171
  ```
86
172
 
87
173
  ---
88
174
 
89
- ## 🧠 API (resumen fiel al código)
175
+ ## 🧭 Guía del Router
90
176
 
91
- ### `Nicola` (Core)
177
+ ### 1) Rutas básicas
92
178
 
93
- - `new Nicola()`
94
- - `app.get/post/put/patch/delete(path, ...handlers)`
95
- - `app.use([path], ...handlers | router)`
96
- - `app.listen(port, [callback])`
179
+ `Nicola` y `Remote` soportan:
97
180
 
98
- Notas:
99
- - `Nicola.listen()` ejecuta internamente `Shadowgraph`, `EasyCors` y `Teleforce` en cada request.
100
- - `req.query` se construye desde querystring.
181
+ - `get`, `post`, `put`, `patch`, `delete`
101
182
 
102
- ### `Remote` (Router)
183
+ ```js
184
+ import Nicola from "nicola-framework";
103
185
 
104
- `Remote` es el router base. Soporta middlewares y rutas con params (`/users/:id`).
186
+ const app = new Nicola();
105
187
 
106
- Ejemplo de middleware simple:
188
+ app.get("/ping", (req, res) => {
189
+ res.statusCode = 200;
190
+ res.end("pong");
191
+ });
192
+
193
+ app.listen(3000);
194
+ ```
195
+
196
+ ### 2) Params (`/users/:id`)
197
+
198
+ Cuando la ruta tiene `:param`, Nicola crea:
199
+
200
+ - `req.params` (objeto con strings)
201
+
202
+ ```js
203
+ app.get("/users/:id", (req, res) => {
204
+ res.json({ id: req.params.id });
205
+ });
206
+ ```
207
+
208
+ ### 3) Routers anidados (`use`)
209
+
210
+ Puedes montar un router dentro de otro:
211
+
212
+ ```js
213
+ import { Nicola, Remote } from "nicola-framework";
214
+
215
+ const app = new Nicola();
216
+ const api = new Remote();
217
+
218
+ api.get("/ping", (req, res) => {
219
+ res.end("pong");
220
+ });
221
+
222
+ app.use("/api", api);
223
+ app.listen(3000);
224
+ ```
225
+
226
+ Importante: el mount path es estricto. `/api` hace match con `/api/...` pero NO con `/apix/...`.
227
+
228
+ ### 4) Middlewares
229
+
230
+ Un middleware tiene firma `(req, res, next)`:
107
231
 
108
232
  ```js
109
233
  app.use((req, res, next) => {
110
- // No existe res.status(); usa statusCode
111
- if (req.url === '/blocked') {
234
+ // no existe res.status(); usa res.statusCode
235
+ if (req.url === "/blocked") {
112
236
  res.statusCode = 403;
113
- res.end('Forbidden');
237
+ res.end("Forbidden");
114
238
  return;
115
239
  }
116
240
  next();
117
241
  });
118
242
  ```
119
243
 
120
- Errores:
244
+ Nicola soporta handlers sync y async (Promise). Si un handler async rechaza, el error se propaga a `next(err)`.
245
+
246
+ ---
247
+
248
+ ## 🧾 Request/Response (lo que hay)
249
+
250
+ ### Request (`req`)
251
+
252
+ Nicola trabaja sobre `http.IncomingMessage` y añade:
253
+
254
+ - `req.url`: **solo pathname** (sin querystring). Se reescribe internamente.
255
+ - `req.query`: objeto creado desde `?a=1&b=hola`.
256
+ - `req.params`: solo existe en rutas con `:param`.
257
+ - `req.body`: solo se parsea si `Content-Type` incluye `application/json`.
258
+ - inválido => `400 Bad Request: Invalid JSON`
259
+ - > ~2MB => `413 Request Entity Too Large`
260
+ - si no es JSON => `{}`
261
+
262
+ ### Response (`res`)
263
+
264
+ Nicola trabaja sobre `http.ServerResponse` y añade helpers:
265
+
266
+ - `res.json(data)` → setea `Content-Type: application/json` y serializa.
267
+ - `res.send(text)` → setea `Content-Type: text/plain`.
268
+
269
+ Para status codes, usa:
270
+
271
+ ```js
272
+ res.statusCode = 201;
273
+ res.json({ created: true });
274
+ ```
275
+
276
+ ---
277
+
278
+ ## 💥 Manejo de errores
279
+
280
+ Si ocurre un error en la cadena de handlers:
281
+
282
+ - `throw new Error(...)`
283
+ - o `next(err)`
284
+
285
+ Nicola responde con `BlackBox` (HTML):
286
+
287
+ - en `NODE_ENV=production` el cliente ve `Internal Server Error` sin stack
288
+ - en dev, incluye `err.message` y stack
289
+
290
+ Ejemplo:
121
291
 
122
292
  ```js
123
- app.get('/boom', (req, res) => {
124
- throw new Error('Boom');
293
+ app.get("/boom", (req, res) => {
294
+ throw new Error("Boom");
125
295
  });
126
296
  ```
127
297
 
128
298
  ---
129
299
 
130
- ## 🔐 Seguridad
300
+ ## 🧩 Middlewares
131
301
 
132
- ### `Regulator` (.env)
302
+ ### `Insulator(schema)` (validación de body)
133
303
 
134
- Lee `.env` desde el directorio actual (`process.cwd()`) y lo copia a `process.env`.
304
+ Valida que existan campos y que su tipo coincida con `typeof`.
135
305
 
136
306
  ```js
137
- import { Regulator } from 'nicola-framework';
307
+ import { Insulator } from "nicola-framework";
138
308
 
139
- Regulator.load();
309
+ const schema = {
310
+ name: "string",
311
+ age: "number",
312
+ };
313
+
314
+ app.post("/users", Insulator(schema), (req, res) => {
315
+ res.json({ ok: true });
316
+ });
317
+ ```
318
+
319
+ Respuestas típicas:
320
+
321
+ - falta campo → `400` y mensaje `Falta campo: name`
322
+ - tipo incorrecto → `400` y mensaje `El campo age debe ser number`
323
+
324
+ ### `EasyCors(options)`
325
+
326
+ Soporta:
327
+
328
+ - `origin: "*"` (default)
329
+ - `origin: ["https://app.com", "http://localhost:5173"]`
330
+
331
+ ```js
332
+ import { EasyCors } from "nicola-framework";
333
+
334
+ app.use(EasyCors({ origin: ["https://mi-front.com"] }));
335
+ ```
336
+
337
+ Nota importante sobre `Nicola.listen()`: internamente siempre ejecuta `EasyCors()` **antes** de tu router.
338
+
339
+ - puedes sobreescribir headers CORS en tus handlers para requests normales
340
+ - pero el preflight `OPTIONS` se resuelve ahí mismo (204), antes de que corran tus rutas
341
+
342
+ ### `Teleforce`
343
+
344
+ Agrega headers de seguridad básicos:
345
+
346
+ - `X-Content-Type-Options: nosniff`
347
+ - `X-Frame-Options: Deny`
348
+ - `X-XSS-Protection: 1`
349
+
350
+ ### `Shadowgraph`
351
+
352
+ Logger simple al finalizar la respuesta:
353
+
354
+ `[GET] /ruta - 200 OK - 12ms`
355
+
356
+ ---
357
+
358
+ ## 🔐 Seguridad (Regulator + JWT)
359
+
360
+ ### `Regulator.load()` (.env)
361
+
362
+ Lee `.env` desde `process.cwd()` y copia valores a `process.env`.
363
+
364
+ Formato soportado:
365
+
366
+ - `KEY=value`
367
+ - líneas vacías OK
368
+ - comentarios con `#` al inicio
369
+
370
+ Ejemplo:
371
+
372
+ ```env
373
+ NICOLA_SECRET=mi-secreto-super-seguro
374
+ NODE_ENV=production
140
375
  ```
141
376
 
142
377
  ### `Coherer` (JWT HS256)
143
378
 
144
- `Coherer` es una clase con métodos **estáticos**.
379
+ `Coherer` es una clase con métodos estáticos:
380
+
381
+ - `Coherer.sign(payload, { expiresIn })`
382
+ - `Coherer.verify(token)`
383
+
384
+ `expiresIn` soporta formato **número + unidad**:
385
+
386
+ - `10s`, `15m`, `24h`, `7d`, `1y`
387
+
388
+ Ejemplo:
145
389
 
146
390
  ```js
147
- import { Regulator, Coherer } from 'nicola-framework';
391
+ import { Regulator, Coherer } from "nicola-framework";
148
392
 
149
393
  Regulator.load();
150
394
 
151
395
  const token = Coherer.sign(
152
- { userId: 123, role: 'admin' },
153
- { expiresIn: '24h' }
396
+ { userId: 123, role: "admin" },
397
+ { expiresIn: "24h" }
154
398
  );
155
399
 
156
400
  const payload = Coherer.verify(token);
157
401
  console.log(payload.userId);
158
402
  ```
159
403
 
160
- `.env` mínimo:
404
+ Middleware típico para proteger rutas (Bearer token):
161
405
 
162
- ```env
163
- NICOLA_SECRET=mi-secreto-super-seguro
164
-
165
- # Opcional pero recomendado en producción
166
- NODE_ENV=production
406
+ ```js
407
+ import { Coherer } from "nicola-framework";
408
+
409
+ const auth = (req, res, next) => {
410
+ const authHeader = req.headers.authorization || "";
411
+ const [, token] = authHeader.split(" ");
412
+ try {
413
+ req.user = Coherer.verify(token);
414
+ next();
415
+ } catch (err) {
416
+ res.statusCode = 401;
417
+ res.end("Unauthorized");
418
+ }
419
+ };
167
420
  ```
168
421
 
169
422
  ---
170
423
 
171
- ## 🗃️ Dynamo (ORM)
424
+ ## 🗃️ Dynamo ORM (Postgres)
172
425
 
173
- ### Configuración
426
+ ### Conexión
174
427
 
175
- `Dynamo.connect()` **no recibe config**: toma la configuración desde variables de entorno.
428
+ `Dynamo.connect()` no recibe config: lee variables de entorno.
176
429
 
177
430
  ```js
178
- import { Regulator, Dynamo } from 'nicola-framework';
431
+ import { Regulator, Dynamo } from "nicola-framework";
179
432
 
180
433
  Regulator.load();
181
434
  await Dynamo.connect();
182
435
 
183
- // Recomendado en shutdown (SIGTERM/SIGINT)
436
+ // ... usar modelos/queries ...
437
+
184
438
  await Dynamo.disconnect();
185
439
  ```
186
440
 
187
- `.env` para Postgres:
441
+ ### Variables soportadas
442
+
443
+ Mínimo:
188
444
 
189
445
  ```env
190
446
  DB_DRIVER=postgres
@@ -193,85 +449,112 @@ DB_PORT=5432
193
449
  DB_USER=postgres
194
450
  DB_PASS=postgres
195
451
  DB_NAME=mydb
452
+ ```
453
+
454
+ Alternativa: `DB_URL` (tiene prioridad sobre las variables separadas):
196
455
 
197
- # Opcional: SSL en Postgres (depende de tu hosting)
198
- DB_SSLMODE=require
456
+ ```env
457
+ DB_DRIVER=postgres
458
+ DB_URL=postgres://user:pass@localhost:5432/mydb
199
459
  ```
200
460
 
461
+ SSL opcional via `DB_SSLMODE`:
462
+
463
+ - `require` → SSL sin verificación estricta
464
+ - `verify-ca` / `verify-full` → SSL con verificación
465
+ - `disable` / `prefer` → sin SSL
466
+
201
467
  ### Modelos
202
468
 
469
+ Un modelo es una clase que extiende `Dynamo.Model` y define:
470
+
471
+ - `static tableName` (requerido)
472
+ - `static schema` (opcional, para validar en `create`)
473
+
203
474
  ```js
204
- import { Dynamo } from 'nicola-framework';
475
+ import { Dynamo } from "nicola-framework";
205
476
 
206
477
  export default class User extends Dynamo.Model {
207
- static tableName = 'users';
478
+ static tableName = "users";
208
479
 
209
480
  static schema = {
210
- name: { type: 'string', required: true },
211
- email: { type: 'string', required: true },
212
- age: { type: 'number', required: false }
481
+ name: { type: "string", required: true },
482
+ email: { type: "string", required: true },
483
+ age: { type: "number", required: false },
213
484
  };
214
485
  }
215
486
  ```
216
487
 
217
- ### Queries
488
+ ### Operaciones comunes
218
489
 
219
490
  ```js
220
- // All
491
+ // Obtener todo
221
492
  const users = await User.all();
222
493
 
223
- // Where
224
- const active = await User.where('active', true).get();
494
+ // Where (si omites operador, asume '=')
495
+ const active = await User.where("active", true).get();
225
496
 
226
- // Insert (valida contra schema)
227
- const created = await User.create({ name: 'Alice', email: 'a@a.com', age: 20 });
497
+ // Select (string con comas o array)
498
+ const names = await User.select("name,email").get();
228
499
 
229
- // Update / Delete
230
- await User.where('id', 1).update({ name: 'Alice 2' });
231
- await User.where('id', 1).delete();
500
+ // Insert (valida con schema)
501
+ const created = await User.create({ name: "Alice", email: "a@a.com", age: 20 });
232
502
 
233
- // Select específico (usa string con coma)
234
- const names = await User.select('name,email').get();
503
+ // Update / Delete (recomendado: siempre con where)
504
+ await User.where("id", 1).update({ name: "Alice 2" });
505
+ await User.where("id", 1).delete();
235
506
 
236
- // Order/limit/offset vía QueryBuilder
237
- const latest = await User.query().orderBy('id', 'DESC').limit(10).offset(0).get();
507
+ // Order + limit + offset
508
+ const latest = await User.query().orderBy("id", "DESC").limit(10).offset(0).get();
238
509
  ```
239
510
 
511
+ Notas importantes:
512
+
513
+ - `update()` y `delete()` devuelven `count` (rowCount).
514
+ - Evita `User.update({...})` o `User.delete()` sin `where(...)` porque operaría sobre toda la tabla.
515
+
240
516
  ---
241
517
 
242
- ## 🧩 Middlewares
518
+ ## 🌱 Variables de entorno
243
519
 
244
- ### `Insulator(schema)`
520
+ Nicola lee:
245
521
 
246
- Valida `req.body` con un esquema **simple** de tipos (`typeof`).
522
+ - `NODE_ENV` (`production` activa modo seguro en errores)
523
+ - `NICOLA_SECRET` (JWT)
524
+ - `NICOLA_REQUEST_TIMEOUT`, `NICOLA_HEADERS_TIMEOUT`, `NICOLA_KEEP_ALIVE_TIMEOUT`
525
+ - `DB_DRIVER`, `DB_URL` o `DB_HOST/DB_PORT/DB_USER/DB_PASS/DB_NAME`, `DB_SSLMODE`
247
526
 
248
- ```js
249
- import { Insulator } from 'nicola-framework';
527
+ ---
250
528
 
251
- const schema = {
252
- name: 'string',
253
- age: 'number'
254
- };
529
+ ## 🧪 Tests
255
530
 
256
- app.post('/users', Insulator(schema), (req, res) => {
257
- res.json({ ok: true });
258
- });
531
+ Este repo incluye tests con Jest + Supertest.
532
+
533
+ ```bash
534
+ npm test
259
535
  ```
260
536
 
261
- ### `Shadowgraph`, `Teleforce`, `EasyCors`
537
+ ---
262
538
 
263
- Se ejecutan automáticamente dentro de `Nicola.listen()`. También puedes llamarlos manualmente si estás usando `Remote` por separado.
539
+ ## 🧯 Troubleshooting
264
540
 
265
- ---
541
+ ### 1) "Please configure, NICOLA_SECRET..."
266
542
 
267
- ## 🔥 LiveCurrent (hot reload)
543
+ - define `NICOLA_SECRET` en tu `.env` y corre `Regulator.load()` antes de usar `Coherer`.
268
544
 
269
- ```js
270
- import { LiveCurrent } from 'nicola-framework';
545
+ ### 2) "Por favor utiliza el comando npm install pg"
271
546
 
272
- const dev = new LiveCurrent('app.js');
273
- dev.boot();
274
- ```
547
+ - instala `pg` si vas a usar `DB_DRIVER=postgres`.
548
+
549
+ ### 3) El body llega vacío
550
+
551
+ - Nicola solo parsea JSON cuando `Content-Type` incluye `application/json`.
552
+ - `multipart/form-data` y `application/x-www-form-urlencoded` no están soportados (por ahora).
553
+
554
+ ### 4) CORS en preflight no aplica como esperas
555
+
556
+ - `Nicola.listen()` ejecuta `EasyCors()` y responde `OPTIONS` con `204` antes de tus rutas.
557
+ - si necesitas lógica avanzada de preflight, usa `Remote` + `http.createServer(...)` y monta tus middlewares manualmente.
275
558
 
276
559
  ---
277
560
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nicola-framework",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Web framework for Node.js",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -24,7 +24,10 @@
24
24
  "middleware",
25
25
  "orm"
26
26
  ],
27
- "bin": "./bin/nicola.js",
27
+ "bin": {
28
+ "nicola": "./bin/nicola.js",
29
+ "nicola-framework": "./bin/nicola.js"
30
+ },
28
31
  "author": "Erick Mauricio Tiznado Rodriguez",
29
32
  "license": "MIT",
30
33
  "devDependencies": {