nicola-framework 1.0.0 → 1.0.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/README.md +629 -0
- package/dev-tools/DevRunner.js +1 -1
- package/index.js +5 -6
- package/package.json +2 -2
- package/security/Coherer.js +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,629 @@
|
|
|
1
|
+
# ⚡ Nicola Framework
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/nicola-framework)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://nodejs.org)
|
|
6
|
+
[](https://www.npmjs.com/package/nicola-framework)
|
|
7
|
+
|
|
8
|
+
> **Performance de bajo nivel con DX de alto nivel.**
|
|
9
|
+
|
|
10
|
+
Nicola es un framework web moderno para Node.js con arquitectura **Zero-Dependency**. Diseñado para ser ligero, seguro por defecto y con todas las herramientas que necesitas integradas.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 🚀 ¿Por qué Nicola?
|
|
15
|
+
|
|
16
|
+
- **🎯 Zero Dependencies** - Sin librerías externas, 100% código nativo
|
|
17
|
+
- **⚡ Alto Rendimiento** - Servidor HTTP nativo sin overhead
|
|
18
|
+
- **🔐 Seguro por Defecto** - JWT nativo, validación de schemas, headers de seguridad
|
|
19
|
+
- **🗃️ ORM Incluido** - Dynamo ORM con soporte MySQL y PostgreSQL
|
|
20
|
+
- **🔥 Hot Reload Nativo** - Recarga automática sin nodemon
|
|
21
|
+
- **🎨 Error Handler Visual** - Interfaz elegante para debugging
|
|
22
|
+
- **📦 Todo Incluido** - Router, middlewares, ORM, seguridad, logging
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 📦 Instalación
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install nicola-framework
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## ⚡ Quickstart
|
|
35
|
+
|
|
36
|
+
### Servidor HTTP Básico
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
import Nicola from 'nicola-framework';
|
|
40
|
+
|
|
41
|
+
const app = new Nicola();
|
|
42
|
+
|
|
43
|
+
app.get('/', (req, res) => {
|
|
44
|
+
res.json({ message: 'Hello from Nicola!' });
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
app.listen(3000, () => {
|
|
48
|
+
console.log('🚀 Server running on http://localhost:3000');
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Con Router y Middlewares
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
import { Nicola, Remote, Shadowgraph, Teleforce } from 'nicola-framework';
|
|
56
|
+
|
|
57
|
+
const app = new Nicola();
|
|
58
|
+
const router = new Remote();
|
|
59
|
+
|
|
60
|
+
// Middlewares globales
|
|
61
|
+
app.use(Shadowgraph); // Logger HTTP
|
|
62
|
+
app.use(Teleforce); // Security headers
|
|
63
|
+
|
|
64
|
+
// Router con rutas anidadas
|
|
65
|
+
router.get('/users', (req, res) => {
|
|
66
|
+
res.json({ users: ['Alice', 'Bob'] });
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
router.get('/users/:id', (req, res) => {
|
|
70
|
+
res.json({ userId: req.params.id });
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
app.use('/api', router);
|
|
74
|
+
|
|
75
|
+
app.listen(3000);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Con ORM (Dynamo)
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
import { Nicola, Dynamo } from 'nicola-framework';
|
|
82
|
+
import User from './models/User.js';
|
|
83
|
+
|
|
84
|
+
// Configurar base de datos
|
|
85
|
+
await Dynamo.connect({
|
|
86
|
+
dialect: 'mysql',
|
|
87
|
+
host: 'localhost',
|
|
88
|
+
user: 'root',
|
|
89
|
+
password: '',
|
|
90
|
+
database: 'mydb'
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const app = new Nicola();
|
|
94
|
+
|
|
95
|
+
// Crear usuario
|
|
96
|
+
app.post('/users', async (req, res) => {
|
|
97
|
+
const user = await User.create(req.body);
|
|
98
|
+
res.json(user);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Buscar usuarios
|
|
102
|
+
app.get('/users', async (req, res) => {
|
|
103
|
+
const users = await User.where('active', true).get();
|
|
104
|
+
res.json(users);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
app.listen(3000);
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 🏗️ Arquitectura Modular
|
|
113
|
+
|
|
114
|
+
Nicola está compuesto por módulos independientes que trabajan en armonía:
|
|
115
|
+
|
|
116
|
+
| Módulo | Función | Descripción |
|
|
117
|
+
|--------|---------|-------------|
|
|
118
|
+
| **Core** | El Motor | Servidor HTTP nativo con body parsing y middleware system |
|
|
119
|
+
| **Remote** | El Cerebro | Router avanzado con soporte MVC, regex y rutas dinámicas |
|
|
120
|
+
| **Dynamo** | La Base | ORM completo con QueryBuilder y Active Record |
|
|
121
|
+
| **Coherer** | El Notario | Sistema JWT nativo (HMAC SHA256) |
|
|
122
|
+
| **Shadowgraph** | El Observador | Logger HTTP de alto rendimiento |
|
|
123
|
+
| **Teleforce** | El Escudo | Suite de seguridad (XSS, NoSniff, CORS) |
|
|
124
|
+
| **BlackBox** | El Forense | Error handler visual estilo terminal |
|
|
125
|
+
| **Insulator** | El Portero | Validador de schemas |
|
|
126
|
+
| **Regulator** | El Gestor | Parser de variables .env |
|
|
127
|
+
| **LiveCurrent** | El Fénix | Hot reload automático |
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 📚 Documentación Completa
|
|
132
|
+
|
|
133
|
+
### 1. Core (Servidor HTTP)
|
|
134
|
+
|
|
135
|
+
El servidor HTTP principal con soporte de middlewares.
|
|
136
|
+
|
|
137
|
+
```javascript
|
|
138
|
+
import Nicola from 'nicola-framework';
|
|
139
|
+
|
|
140
|
+
const app = new Nicola();
|
|
141
|
+
|
|
142
|
+
// Métodos HTTP
|
|
143
|
+
app.get('/users', handler);
|
|
144
|
+
app.post('/users', handler);
|
|
145
|
+
app.put('/users/:id', handler);
|
|
146
|
+
app.delete('/users/:id', handler);
|
|
147
|
+
app.patch('/users/:id', handler);
|
|
148
|
+
|
|
149
|
+
// Middleware global
|
|
150
|
+
app.use((req, res, next) => {
|
|
151
|
+
console.log(`${req.method} ${req.url}`);
|
|
152
|
+
next();
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Prefijo de ruta
|
|
156
|
+
app.use('/api', router);
|
|
157
|
+
|
|
158
|
+
app.listen(3000);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### 2. Remote (Router)
|
|
162
|
+
|
|
163
|
+
Sistema de routing recursivo con soporte de rutas dinámicas.
|
|
164
|
+
|
|
165
|
+
```javascript
|
|
166
|
+
import { Remote } from 'nicola-framework';
|
|
167
|
+
|
|
168
|
+
const router = new Remote();
|
|
169
|
+
|
|
170
|
+
// Rutas básicas
|
|
171
|
+
router.get('/users', getUsers);
|
|
172
|
+
router.post('/users', createUser);
|
|
173
|
+
|
|
174
|
+
// Parámetros dinámicos
|
|
175
|
+
router.get('/users/:id', getUser); // req.params.id
|
|
176
|
+
router.get('/posts/:slug/comments/:id', getComment);
|
|
177
|
+
|
|
178
|
+
// Routers anidados
|
|
179
|
+
const adminRouter = new Remote();
|
|
180
|
+
adminRouter.get('/dashboard', adminDashboard);
|
|
181
|
+
router.use('/admin', adminRouter); // /admin/dashboard
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 3. Dynamo ORM
|
|
185
|
+
|
|
186
|
+
ORM completo con Active Record pattern.
|
|
187
|
+
|
|
188
|
+
#### Configuración
|
|
189
|
+
|
|
190
|
+
```javascript
|
|
191
|
+
import { Dynamo } from 'nicola-framework';
|
|
192
|
+
|
|
193
|
+
await Dynamo.connect({
|
|
194
|
+
dialect: 'mysql', // o 'postgres'
|
|
195
|
+
host: 'localhost',
|
|
196
|
+
port: 3306,
|
|
197
|
+
user: 'root',
|
|
198
|
+
password: 'secret',
|
|
199
|
+
database: 'mydb'
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
#### Definir Modelos
|
|
204
|
+
|
|
205
|
+
```javascript
|
|
206
|
+
import { Dynamo } from 'nicola-framework';
|
|
207
|
+
|
|
208
|
+
class User extends Dynamo.Model {
|
|
209
|
+
static table = 'users';
|
|
210
|
+
|
|
211
|
+
static schema = {
|
|
212
|
+
name: { type: 'string', required: true },
|
|
213
|
+
email: { type: 'string', required: true },
|
|
214
|
+
age: { type: 'number' }
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export default User;
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
#### Query Builder
|
|
222
|
+
|
|
223
|
+
```javascript
|
|
224
|
+
// Seleccionar todos
|
|
225
|
+
const users = await User.all();
|
|
226
|
+
|
|
227
|
+
// Buscar por ID
|
|
228
|
+
const user = await User.find(1);
|
|
229
|
+
|
|
230
|
+
// Condiciones
|
|
231
|
+
const activeUsers = await User.where('active', true).get();
|
|
232
|
+
const adults = await User.where('age', '>', 18).get();
|
|
233
|
+
|
|
234
|
+
// Múltiples condiciones
|
|
235
|
+
const results = await User
|
|
236
|
+
.where('country', 'US')
|
|
237
|
+
.where('age', '>=', 21)
|
|
238
|
+
.get();
|
|
239
|
+
|
|
240
|
+
// Crear
|
|
241
|
+
const newUser = await User.create({
|
|
242
|
+
name: 'Alice',
|
|
243
|
+
email: 'alice@example.com'
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
// Actualizar
|
|
247
|
+
await User.where('id', 5).update({ name: 'Bob' });
|
|
248
|
+
|
|
249
|
+
// Eliminar
|
|
250
|
+
await User.where('id', 5).delete();
|
|
251
|
+
|
|
252
|
+
// Select específico
|
|
253
|
+
const names = await User.select('name', 'email').get();
|
|
254
|
+
|
|
255
|
+
// Límite
|
|
256
|
+
const first10 = await User.limit(10).get();
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### 4. Coherer (JWT Nativo)
|
|
260
|
+
|
|
261
|
+
Sistema de autenticación JWT sin dependencias externas.
|
|
262
|
+
|
|
263
|
+
```javascript
|
|
264
|
+
import { Coherer } from 'nicola-framework';
|
|
265
|
+
|
|
266
|
+
const jwt = new Coherer('mi-secreto-super-seguro');
|
|
267
|
+
|
|
268
|
+
// Generar token
|
|
269
|
+
const token = jwt.sign({
|
|
270
|
+
userId: 123,
|
|
271
|
+
role: 'admin'
|
|
272
|
+
}, '24h'); // Expira en 24 horas
|
|
273
|
+
|
|
274
|
+
// Verificar token
|
|
275
|
+
const payload = jwt.verify(token);
|
|
276
|
+
if (payload) {
|
|
277
|
+
console.log('Token válido:', payload);
|
|
278
|
+
} else {
|
|
279
|
+
console.log('Token inválido o expirado');
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Middleware de autenticación
|
|
283
|
+
function authMiddleware(req, res, next) {
|
|
284
|
+
const token = req.headers.authorization?.split(' ')[1];
|
|
285
|
+
|
|
286
|
+
const payload = jwt.verify(token);
|
|
287
|
+
if (!payload) {
|
|
288
|
+
return res.status(401).json({ error: 'No autorizado' });
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
req.user = payload;
|
|
292
|
+
next();
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
app.use('/protected', authMiddleware);
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### 5. Regulator (Variables de Entorno)
|
|
299
|
+
|
|
300
|
+
Parser seguro de archivos .env
|
|
301
|
+
|
|
302
|
+
```javascript
|
|
303
|
+
import { Regulator } from 'nicola-framework';
|
|
304
|
+
|
|
305
|
+
// Cargar .env
|
|
306
|
+
Regulator.load();
|
|
307
|
+
|
|
308
|
+
// Acceder a variables
|
|
309
|
+
const port = process.env.PORT || 3000;
|
|
310
|
+
const dbUrl = process.env.DATABASE_URL;
|
|
311
|
+
const secret = process.env.JWT_SECRET;
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**.env example:**
|
|
315
|
+
```env
|
|
316
|
+
PORT=3000
|
|
317
|
+
DATABASE_URL=mysql://root:password@localhost:3306/mydb
|
|
318
|
+
JWT_SECRET=mi-super-secreto-jwt
|
|
319
|
+
NODE_ENV=development
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### 6. Middlewares Incluidos
|
|
323
|
+
|
|
324
|
+
#### Shadowgraph (Logger HTTP)
|
|
325
|
+
|
|
326
|
+
```javascript
|
|
327
|
+
import { Shadowgraph } from 'nicola-framework';
|
|
328
|
+
|
|
329
|
+
app.use(Shadowgraph);
|
|
330
|
+
// Output: GET /users → 200 (15ms)
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
#### Teleforce (Security Headers)
|
|
334
|
+
|
|
335
|
+
```javascript
|
|
336
|
+
import { Teleforce } from 'nicola-framework';
|
|
337
|
+
|
|
338
|
+
app.use(Teleforce);
|
|
339
|
+
// Añade: X-XSS-Protection, X-Content-Type-Options, etc.
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
#### EasyCors (CORS Management)
|
|
343
|
+
|
|
344
|
+
```javascript
|
|
345
|
+
import { EasyCors } from 'nicola-framework';
|
|
346
|
+
|
|
347
|
+
app.use(EasyCors({
|
|
348
|
+
origin: 'https://mi-frontend.com',
|
|
349
|
+
methods: ['GET', 'POST', 'PUT', 'DELETE'],
|
|
350
|
+
credentials: true
|
|
351
|
+
}));
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
#### BlackBox (Error Handler)
|
|
355
|
+
|
|
356
|
+
```javascript
|
|
357
|
+
import { BlackBox } from 'nicola-framework';
|
|
358
|
+
|
|
359
|
+
app.use(BlackBox); // Debe ser el último middleware
|
|
360
|
+
// Captura errores y muestra interfaz visual
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
#### Insulator (Schema Validation)
|
|
364
|
+
|
|
365
|
+
```javascript
|
|
366
|
+
import { Insulator } from 'nicola-framework';
|
|
367
|
+
|
|
368
|
+
const userSchema = {
|
|
369
|
+
name: { type: 'string', required: true, min: 3 },
|
|
370
|
+
email: { type: 'string', required: true, pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/ },
|
|
371
|
+
age: { type: 'number', min: 18 }
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
app.post('/users', Insulator(userSchema), (req, res) => {
|
|
375
|
+
// req.body ya está validado
|
|
376
|
+
res.json({ message: 'Usuario válido' });
|
|
377
|
+
});
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### 7. LiveCurrent (Hot Reload)
|
|
381
|
+
|
|
382
|
+
Para desarrollo con recarga automática:
|
|
383
|
+
|
|
384
|
+
```javascript
|
|
385
|
+
import { DevRunner } from 'nicola-framework';
|
|
386
|
+
|
|
387
|
+
// dev.js
|
|
388
|
+
DevRunner.start('./app.js', {
|
|
389
|
+
watch: ['src/', 'config/'],
|
|
390
|
+
ignore: ['node_modules/', 'logs/']
|
|
391
|
+
});
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
node dev.js
|
|
396
|
+
# El servidor se recarga automáticamente al editar archivos
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
## 🎯 Ejemplos Completos
|
|
402
|
+
|
|
403
|
+
### API REST con Autenticación
|
|
404
|
+
|
|
405
|
+
```javascript
|
|
406
|
+
import { Nicola, Remote, Coherer, Regulator } from 'nicola-framework';
|
|
407
|
+
import User from './models/User.js';
|
|
408
|
+
|
|
409
|
+
Regulator.load();
|
|
410
|
+
|
|
411
|
+
const app = new Nicola();
|
|
412
|
+
const router = new Remote();
|
|
413
|
+
const jwt = new Coherer(process.env.JWT_SECRET);
|
|
414
|
+
|
|
415
|
+
// Middleware de autenticación
|
|
416
|
+
const authenticate = (req, res, next) => {
|
|
417
|
+
const token = req.headers.authorization?.split(' ')[1];
|
|
418
|
+
const payload = jwt.verify(token);
|
|
419
|
+
|
|
420
|
+
if (!payload) {
|
|
421
|
+
return res.status(401).json({ error: 'No autorizado' });
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
req.user = payload;
|
|
425
|
+
next();
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
// Rutas públicas
|
|
429
|
+
router.post('/register', async (req, res) => {
|
|
430
|
+
const user = await User.create(req.body);
|
|
431
|
+
const token = jwt.sign({ userId: user.id }, '7d');
|
|
432
|
+
|
|
433
|
+
res.json({ user, token });
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
router.post('/login', async (req, res) => {
|
|
437
|
+
const user = await User.where('email', req.body.email).first();
|
|
438
|
+
|
|
439
|
+
if (!user || user.password !== req.body.password) {
|
|
440
|
+
return res.status(401).json({ error: 'Credenciales inválidas' });
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const token = jwt.sign({ userId: user.id }, '7d');
|
|
444
|
+
res.json({ user, token });
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
// Rutas protegidas
|
|
448
|
+
router.get('/profile', authenticate, async (req, res) => {
|
|
449
|
+
const user = await User.find(req.user.userId);
|
|
450
|
+
res.json(user);
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
router.put('/profile', authenticate, async (req, res) => {
|
|
454
|
+
await User.where('id', req.user.userId).update(req.body);
|
|
455
|
+
res.json({ message: 'Perfil actualizado' });
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
app.use('/api', router);
|
|
459
|
+
app.listen(3000);
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
### CRUD Completo
|
|
463
|
+
|
|
464
|
+
```javascript
|
|
465
|
+
import { Nicola, Remote, Dynamo, Insulator, Shadowgraph, BlackBox } from 'nicola-framework';
|
|
466
|
+
import Post from './models/Post.js';
|
|
467
|
+
|
|
468
|
+
await Dynamo.connect({
|
|
469
|
+
dialect: 'mysql',
|
|
470
|
+
host: 'localhost',
|
|
471
|
+
database: 'blog'
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
const app = new Nicola();
|
|
475
|
+
const router = new Remote();
|
|
476
|
+
|
|
477
|
+
app.use(Shadowgraph); // Logger
|
|
478
|
+
|
|
479
|
+
const postSchema = {
|
|
480
|
+
title: { type: 'string', required: true, min: 5 },
|
|
481
|
+
content: { type: 'string', required: true },
|
|
482
|
+
published: { type: 'boolean' }
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
// List posts
|
|
486
|
+
router.get('/', async (req, res) => {
|
|
487
|
+
const posts = await Post.where('published', true).get();
|
|
488
|
+
res.json(posts);
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
// Get single post
|
|
492
|
+
router.get('/:id', async (req, res) => {
|
|
493
|
+
const post = await Post.find(req.params.id);
|
|
494
|
+
|
|
495
|
+
if (!post) {
|
|
496
|
+
return res.status(404).json({ error: 'Post no encontrado' });
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
res.json(post);
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
// Create post
|
|
503
|
+
router.post('/', Insulator(postSchema), async (req, res) => {
|
|
504
|
+
const post = await Post.create(req.body);
|
|
505
|
+
res.status(201).json(post);
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
// Update post
|
|
509
|
+
router.put('/:id', Insulator(postSchema), async (req, res) => {
|
|
510
|
+
await Post.where('id', req.params.id).update(req.body);
|
|
511
|
+
res.json({ message: 'Post actualizado' });
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
// Delete post
|
|
515
|
+
router.delete('/:id', async (req, res) => {
|
|
516
|
+
await Post.where('id', req.params.id).delete();
|
|
517
|
+
res.status(204).send();
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
app.use('/api/posts', router);
|
|
521
|
+
app.use(BlackBox); // Error handler (último)
|
|
522
|
+
|
|
523
|
+
app.listen(3000);
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
---
|
|
527
|
+
|
|
528
|
+
## 🔧 Estructura de Proyecto Recomendada
|
|
529
|
+
|
|
530
|
+
```
|
|
531
|
+
/mi-proyecto
|
|
532
|
+
├── /src
|
|
533
|
+
│ ├── /controllers # Lógica de negocio
|
|
534
|
+
│ ├── /models # Modelos Dynamo
|
|
535
|
+
│ ├── /routes # Definición de rutas
|
|
536
|
+
│ ├── /middlewares # Middlewares custom
|
|
537
|
+
│ └── /config # Configuraciones
|
|
538
|
+
├── app.js # Entry point
|
|
539
|
+
├── dev.js # Script desarrollo
|
|
540
|
+
├── .env # Variables de entorno
|
|
541
|
+
├── .env.example # Template de .env
|
|
542
|
+
└── package.json
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
---
|
|
546
|
+
|
|
547
|
+
## 🚀 Scripts NPM Recomendados
|
|
548
|
+
|
|
549
|
+
```json
|
|
550
|
+
{
|
|
551
|
+
"scripts": {
|
|
552
|
+
"start": "node app.js",
|
|
553
|
+
"dev": "node dev.js",
|
|
554
|
+
"test": "node --test"
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
561
|
+
## 🌟 Características Destacadas
|
|
562
|
+
|
|
563
|
+
### Zero Dependencies
|
|
564
|
+
A diferencia de Express o Fastify, Nicola no tiene dependencias externas (excepto chalk para logs en desarrollo). Todo está construido con módulos nativos de Node.js.
|
|
565
|
+
|
|
566
|
+
### JWT Nativo
|
|
567
|
+
Implementación propia de JWT usando el módulo `crypto` nativo, sin necesidad de jsonwebtoken.
|
|
568
|
+
|
|
569
|
+
### ORM Incluido
|
|
570
|
+
No necesitas instalar Sequelize, TypeORM o Prisma. Dynamo viene integrado con soporte para MySQL y PostgreSQL.
|
|
571
|
+
|
|
572
|
+
### Hot Reload Nativo
|
|
573
|
+
LiveCurrent detecta cambios en archivos y reinicia el servidor sin necesidad de nodemon o pm2.
|
|
574
|
+
|
|
575
|
+
### Error Handler Visual
|
|
576
|
+
BlackBox captura errores y los muestra en una interfaz web elegante con stack trace completo.
|
|
577
|
+
|
|
578
|
+
---
|
|
579
|
+
|
|
580
|
+
## 📊 Comparación con Otros Frameworks
|
|
581
|
+
|
|
582
|
+
| Feature | Nicola | Express | Fastify |
|
|
583
|
+
|---------|--------|---------|---------|
|
|
584
|
+
| Dependencies | 0 | ~50 | ~20 |
|
|
585
|
+
| Router | ✅ Incluido | ✅ | ✅ |
|
|
586
|
+
| ORM | ✅ Incluido | ❌ | ❌ |
|
|
587
|
+
| JWT | ✅ Nativo | ❌ | ❌ |
|
|
588
|
+
| Hot Reload | ✅ Nativo | ❌ | ❌ |
|
|
589
|
+
| Error UI | ✅ Visual | ❌ | ❌ |
|
|
590
|
+
| Validation | ✅ Incluido | ❌ | ✅ |
|
|
591
|
+
|
|
592
|
+
---
|
|
593
|
+
|
|
594
|
+
## 🤝 Contribuir
|
|
595
|
+
|
|
596
|
+
Las contribuciones son bienvenidas. Por favor:
|
|
597
|
+
|
|
598
|
+
1. Fork el proyecto
|
|
599
|
+
2. Crea una rama (`git checkout -b feature/amazing-feature`)
|
|
600
|
+
3. Commit tus cambios (`git commit -m 'Add amazing feature'`)
|
|
601
|
+
4. Push a la rama (`git push origin feature/amazing-feature`)
|
|
602
|
+
5. Abre un Pull Request
|
|
603
|
+
|
|
604
|
+
---
|
|
605
|
+
|
|
606
|
+
## 📝 Licencia
|
|
607
|
+
|
|
608
|
+
MIT © [Erick Mauricio Tiznado Rodriguez](https://github.com/yourusername)
|
|
609
|
+
|
|
610
|
+
---
|
|
611
|
+
|
|
612
|
+
## 🙏 Agradecimientos
|
|
613
|
+
|
|
614
|
+
Inspirado en la filosofía de Nikola Nicola: *"Si quieres encontrar los secretos del universo, piensa en términos de energía, frecuencia y vibración."*
|
|
615
|
+
|
|
616
|
+
---
|
|
617
|
+
|
|
618
|
+
## 📬 Contacto
|
|
619
|
+
|
|
620
|
+
- **NPM**: [nicola-framework](https://www.npmjs.com/package/nicola-framework)
|
|
621
|
+
- **Issues**: [GitHub Issues](https://github.com/yourusername/nicola-framework/issues)
|
|
622
|
+
|
|
623
|
+
---
|
|
624
|
+
|
|
625
|
+
<div align="center">
|
|
626
|
+
|
|
627
|
+
⚡ **Built with electricity and zero dependencies** ⚡
|
|
628
|
+
|
|
629
|
+
</div>
|
package/dev-tools/DevRunner.js
CHANGED
package/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Nicola Framework - Main Export
|
|
3
3
|
*
|
|
4
4
|
* Punto de entrada principal del framework
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
// Core
|
|
8
|
-
export { default as
|
|
8
|
+
export { default as Nicola } from './core/Core.js';
|
|
9
9
|
export { default as Remote } from './core/Remote.js';
|
|
10
10
|
|
|
11
11
|
// Middlewares
|
|
@@ -21,11 +21,10 @@ export { default as Regulator } from './security/Regulator.js';
|
|
|
21
21
|
|
|
22
22
|
// Dev Tools
|
|
23
23
|
export { default as LiveCurrent } from './dev-tools/LiveCurrent.js';
|
|
24
|
-
export { default as DevRunner } from './dev-tools/DevRunner.js';
|
|
25
24
|
|
|
26
25
|
// Database (Dynamo ORM)
|
|
27
26
|
export { default as Dynamo } from './database/index.js';
|
|
28
27
|
|
|
29
|
-
// Default export (
|
|
30
|
-
import
|
|
31
|
-
export default
|
|
28
|
+
// Default export (Nicola Core)
|
|
29
|
+
import Nicola from './core/Core.js';
|
|
30
|
+
export default Nicola;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nicola-framework",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Zero-dependency web framework for Node.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"zero-dependency",
|
|
26
26
|
"orm"
|
|
27
27
|
],
|
|
28
|
-
"author": "
|
|
28
|
+
"author": "Erick Mauricio Tiznado Rodriguez",
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"chalk": "^5.6.2"
|
package/security/Coherer.js
CHANGED