@crane-technologies/database 2.1.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.
Files changed (34) hide show
  1. package/README.md +475 -0
  2. package/dist/components/Database.d.ts +288 -0
  3. package/dist/components/Database.d.ts.map +1 -0
  4. package/dist/components/Database.js +554 -0
  5. package/dist/components/Database.js.map +1 -0
  6. package/dist/components/Logger.d.ts +63 -0
  7. package/dist/components/Logger.d.ts.map +1 -0
  8. package/dist/components/Logger.js +147 -0
  9. package/dist/components/Logger.js.map +1 -0
  10. package/dist/index.d.ts +28 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +39 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/interfaces/BulkInsertOptions.d.ts +20 -0
  15. package/dist/interfaces/BulkInsertOptions.d.ts.map +1 -0
  16. package/dist/interfaces/BulkInsertOptions.js +3 -0
  17. package/dist/interfaces/BulkInsertOptions.js.map +1 -0
  18. package/dist/interfaces/DatabaseConfig.d.ts +52 -0
  19. package/dist/interfaces/DatabaseConfig.d.ts.map +1 -0
  20. package/dist/interfaces/DatabaseConfig.js +3 -0
  21. package/dist/interfaces/DatabaseConfig.js.map +1 -0
  22. package/dist/interfaces/Dependancy.d.ts +15 -0
  23. package/dist/interfaces/Dependancy.d.ts.map +1 -0
  24. package/dist/interfaces/Dependancy.js +3 -0
  25. package/dist/interfaces/Dependancy.js.map +1 -0
  26. package/dist/interfaces/QueryList.d.ts +4 -0
  27. package/dist/interfaces/QueryList.d.ts.map +1 -0
  28. package/dist/interfaces/QueryList.js +3 -0
  29. package/dist/interfaces/QueryList.js.map +1 -0
  30. package/dist/utils/createQueries.d.ts +65 -0
  31. package/dist/utils/createQueries.d.ts.map +1 -0
  32. package/dist/utils/createQueries.js +121 -0
  33. package/dist/utils/createQueries.js.map +1 -0
  34. package/package.json +61 -0
package/README.md ADDED
@@ -0,0 +1,475 @@
1
+ # @crane-technologies/database
2
+
3
+ Componente de base de datos PostgreSQL con connection pooling, transacciones, gestión de dependencias y **autocompletado de queries con TypeScript**.
4
+
5
+ ## ✨ Características
6
+
7
+ - ✅ **Autocompletado completo** con `createQueries()`
8
+ - ✅ Connection pooling automático
9
+ - ✅ Transacciones ACID con dependencias entre queries
10
+ - ✅ Soporte para queries planas, anidadas y mixtas
11
+ - ✅ Raw SQL cuando lo necesites
12
+ - ✅ Backward compatible con código existente
13
+ - ✅ Logs configurables (4 niveles)
14
+ - ✅ 100% TypeScript con tipos completos
15
+
16
+ ---
17
+
18
+ ## 📦 Instalación
19
+
20
+ ```bash
21
+ npm install @crane-technologies/database
22
+ ```
23
+
24
+ ---
25
+
26
+ ## 🚀 Inicio Rápido
27
+
28
+ ### **Con `createQueries()` (Recomendado ⭐)**
29
+
30
+ ```typescript
31
+ import Database, {
32
+ createQueries,
33
+ DatabaseConfig,
34
+ } from "@crane-technologies/database";
35
+
36
+ // 1. Crear queries con autocompletado
37
+ const queries = createQueries({
38
+ users: {
39
+ getById: "SELECT * FROM users WHERE id = $1",
40
+ create: "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *",
41
+ update: "UPDATE users SET name = $1 WHERE id = $2 RETURNING *",
42
+ delete: "DELETE FROM users WHERE id = $1",
43
+ },
44
+ products: {
45
+ getAll: "SELECT * FROM products",
46
+ getById: "SELECT * FROM products WHERE id = $1",
47
+ },
48
+ });
49
+
50
+ // 2. Configurar base de datos
51
+ const config: DatabaseConfig = {
52
+ connectionString: process.env.DATABASE_URL!,
53
+ ssl: { rejectUnauthorized: false },
54
+ max: 10,
55
+ logLevel: 2, // 0=NONE, 1=ERROR, 2=DEBUG, 3=ALL
56
+ };
57
+
58
+ // 3. Inicializar
59
+ const db = Database.getInstance(config, queries);
60
+
61
+ // 4. Usar con autocompletado! 🎉
62
+ const user = await db.query(queries.users.getById, [123]);
63
+ const newUser = await db.query(queries.users.create, [
64
+ "John",
65
+ "john@email.com",
66
+ ]);
67
+ const products = await db.query(queries.products.getAll);
68
+ ```
69
+
70
+ ---
71
+
72
+ ## 📚 Casos de Uso
73
+
74
+ ### **1. Queries Planas (sin anidación)**
75
+
76
+ ```typescript
77
+ const queries = createQueries({
78
+ getUser: "SELECT * FROM users WHERE id = $1",
79
+ createUser: "INSERT INTO users (name) VALUES ($1) RETURNING *",
80
+ deleteUser: "DELETE FROM users WHERE id = $1",
81
+ });
82
+
83
+ const db = Database.getInstance(config, queries);
84
+
85
+ await db.query(queries.getUser, [123]);
86
+ await db.query(queries.createUser, ["Alice"]);
87
+ await db.query(queries.deleteUser, [456]);
88
+ ```
89
+
90
+ ---
91
+
92
+ ### **2. Queries Anidadas (organizadas por dominio)**
93
+
94
+ ```typescript
95
+ const queries = createQueries({
96
+ users: {
97
+ getById: "SELECT * FROM users WHERE id = $1",
98
+ create: "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *",
99
+ update: "UPDATE users SET name = $1 WHERE id = $2 RETURNING *",
100
+ },
101
+ products: {
102
+ getAll: "SELECT * FROM products",
103
+ getById: "SELECT * FROM products WHERE id = $1",
104
+ create: "INSERT INTO products (name, price) VALUES ($1, $2) RETURNING *",
105
+ },
106
+ });
107
+
108
+ const db = Database.getInstance(config, queries);
109
+
110
+ // Autocompletado funciona en todos los niveles!
111
+ await db.query(queries.users.getById, [123]);
112
+ await db.query(queries.products.create, ["Laptop", 999.99]);
113
+ ```
114
+
115
+ ---
116
+
117
+ ### **3. Queries Mixtas (planas + anidadas)**
118
+
119
+ ```typescript
120
+ const queries = createQueries({
121
+ // Queries planas para cosas simples
122
+ testConnection: "SELECT NOW() as time",
123
+ checkHealth: "SELECT 1",
124
+
125
+ // Queries anidadas para dominios complejos
126
+ users: {
127
+ getById: "SELECT * FROM users WHERE id = $1",
128
+ create: "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *",
129
+ },
130
+ products: {
131
+ getAll: "SELECT * FROM products",
132
+ },
133
+ });
134
+
135
+ const db = Database.getInstance(config, queries);
136
+
137
+ // Planas
138
+ await db.query(queries.testConnection);
139
+ await db.query(queries.checkHealth);
140
+
141
+ // Anidadas
142
+ await db.query(queries.users.getById, [123]);
143
+ await db.query(queries.products.getAll);
144
+ ```
145
+
146
+ ---
147
+
148
+ ### **4. Raw SQL (cuando lo necesites)**
149
+
150
+ ```typescript
151
+ // Raw SQL sigue funcionando
152
+ const result = await db.query("SELECT COUNT(*) FROM users WHERE active = $1", [
153
+ true,
154
+ ]);
155
+ const count = result.rows[0].count;
156
+ ```
157
+
158
+ ---
159
+
160
+ ### **5. Transacciones Simples**
161
+
162
+ ```typescript
163
+ const results = await db.transaction(
164
+ [queries.users.create, queries.users.create],
165
+ [
166
+ ["Alice", "alice@email.com"],
167
+ ["Bob", "bob@email.com"],
168
+ ]
169
+ );
170
+
171
+ console.log("Usuarios creados:", results.length);
172
+ ```
173
+
174
+ ---
175
+
176
+ ### **6. Transacciones con Dependencias**
177
+
178
+ ```typescript
179
+ import { Dependency } from "@crane-technologies/database";
180
+
181
+ const queries = createQueries({
182
+ users: {
183
+ create: "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *",
184
+ },
185
+ profiles: {
186
+ create: "INSERT INTO profiles (user_id, bio) VALUES ($1, $2) RETURNING *",
187
+ },
188
+ });
189
+
190
+ const db = Database.getInstance(config, queries);
191
+
192
+ // El ID del usuario se inyecta automáticamente en el perfil
193
+ const dependencies: Dependency[] = [
194
+ { sourceIndex: 0, targetIndex: 1, targetParamIndex: 0 },
195
+ ];
196
+
197
+ const results = await db.transaction(
198
+ [queries.users.create, queries.profiles.create],
199
+ [
200
+ ["John", "john@email.com"],
201
+ [null, "John's bio"], // null será reemplazado por user.id
202
+ ],
203
+ dependencies
204
+ );
205
+
206
+ console.log("Usuario creado:", results[0].rows[0]);
207
+ console.log("Perfil creado:", results[1].rows[0]);
208
+ ```
209
+
210
+ ---
211
+
212
+ ## 📊 Niveles de Log
213
+
214
+ ```typescript
215
+ export type LogLevel = 0 | 1 | 2 | 3;
216
+
217
+ // 0 = NONE - Sin logs
218
+ // 1 = ERROR - Solo errores
219
+ // 2 = DEBUG - Errores + debug
220
+ // 3 = ALL - Todos los logs (errores + debug + warnings + info)
221
+
222
+ const config: DatabaseConfig = {
223
+ connectionString: process.env.DATABASE_URL!,
224
+ logLevel: 2, // DEBUG
225
+ };
226
+
227
+ // Cambiar dinámicamente
228
+ db.setLogLevel(1); // Solo errores
229
+ ```
230
+
231
+ ---
232
+
233
+ ## 🔄 Backward Compatibility
234
+
235
+ El paquete es 100% compatible con código existente:
236
+
237
+ ```typescript
238
+ // ✅ Forma antigua (sigue funcionando)
239
+ const db = Database.getInstance(config, {
240
+ getUser: "SELECT * FROM users WHERE id = $1",
241
+ });
242
+ await db.query("getUser", [123]);
243
+
244
+ // ✅ Forma nueva (con autocompletado)
245
+ const queries = createQueries({
246
+ users: {
247
+ getById: "SELECT * FROM users WHERE id = $1",
248
+ },
249
+ });
250
+ const db = Database.getInstance(config, queries);
251
+ await db.query(queries.users.getById, [123]);
252
+ ```
253
+
254
+ ---
255
+
256
+ ## 🛡️ TypeScript
257
+
258
+ El paquete incluye definiciones de tipos completas:
259
+
260
+ ```typescript
261
+ import {
262
+ Database,
263
+ createQueries,
264
+ QueryReference,
265
+ DatabaseConfig,
266
+ Dependency,
267
+ Logger,
268
+ LogLevel,
269
+ QueryList,
270
+ } from "@crane-technologies/database";
271
+ ```
272
+
273
+ ---
274
+
275
+ ## 📚 API Reference
276
+
277
+ ### `createQueries(queries)`
278
+
279
+ Crea un objeto de queries con autocompletado.
280
+
281
+ **Parámetros:**
282
+
283
+ - `queries: Record<string, any>` - Objeto con queries (planas, anidadas o mixtas)
284
+
285
+ **Retorna:** Objeto con queries y `__flatMap` interno
286
+
287
+ **Ejemplo:**
288
+
289
+ ```typescript
290
+ const queries = createQueries({
291
+ users: {
292
+ getById: "SELECT * FROM users WHERE id = $1",
293
+ },
294
+ });
295
+ ```
296
+
297
+ ---
298
+
299
+ ### `Database.getInstance(config, queries)`
300
+
301
+ Obtiene la instancia singleton de Database.
302
+
303
+ **Parámetros:**
304
+
305
+ - `config: DatabaseConfig` - Configuración de conexión
306
+ - `queries?: any` - Resultado de `createQueries()` o objeto plano
307
+
308
+ **Retorna:** `Database`
309
+
310
+ **Ejemplo:**
311
+
312
+ ```typescript
313
+ const db = Database.getInstance(config, queries);
314
+ ```
315
+
316
+ ---
317
+
318
+ ### `db.query(query, params?)`
319
+
320
+ Ejecuta una query (con QueryReference, string key o raw SQL).
321
+
322
+ **Parámetros:**
323
+
324
+ - `query: string | QueryReference` - Query a ejecutar
325
+ - `params?: any[]` - Parámetros de la query
326
+
327
+ **Retorna:** `Promise<QueryResult>`
328
+
329
+ **Ejemplos:**
330
+
331
+ ```typescript
332
+ // Con QueryReference
333
+ await db.query(queries.users.getById, [123]);
334
+
335
+ // Con string key
336
+ await db.query("users.getById", [123]);
337
+
338
+ // Raw SQL
339
+ await db.query("SELECT * FROM users WHERE id = $1", [123]);
340
+ ```
341
+
342
+ ---
343
+
344
+ ### `db.transaction(queryArray, paramsArray, dependencies?)`
345
+
346
+ Ejecuta múltiples queries en una transacción atómica.
347
+
348
+ **Parámetros:**
349
+
350
+ - `queryArray: (string | QueryReference)[]` - Array de queries
351
+ - `paramsArray: any[][]` - Parámetros para cada query
352
+ - `dependencies?: Dependency[]` - Dependencias entre queries
353
+
354
+ **Retorna:** `Promise<QueryResult[]>`
355
+
356
+ **Ejemplo:**
357
+
358
+ ```typescript
359
+ await db.transaction(
360
+ [queries.users.create, queries.profiles.create],
361
+ [
362
+ ["John", "john@email.com"],
363
+ [null, "Bio"],
364
+ ],
365
+ [{ sourceIndex: 0, targetIndex: 1, targetParamIndex: 0 }]
366
+ );
367
+ ```
368
+
369
+ ---
370
+
371
+ ### `db.close()`
372
+
373
+ Cierra todas las conexiones del pool.
374
+
375
+ **Retorna:** `Promise<void>`
376
+
377
+ **Ejemplo:**
378
+
379
+ ```typescript
380
+ await db.close();
381
+ ```
382
+
383
+ ---
384
+
385
+ ### `db.setLogLevel(level)`
386
+
387
+ Cambia el nivel de log dinámicamente.
388
+
389
+ **Parámetros:**
390
+
391
+ - `level: 0 | 1 | 2 | 3` - Nuevo nivel de log
392
+
393
+ **Ejemplo:**
394
+
395
+ ```typescript
396
+ db.setLogLevel(1); // Solo errores
397
+ ```
398
+
399
+ ---
400
+
401
+ ## 🔒 Cerrar Conexiones
402
+
403
+ ```typescript
404
+ process.on("SIGTERM", async () => {
405
+ const db = Database.getInstance(config);
406
+ await db.close();
407
+ process.exit(0);
408
+ });
409
+ ```
410
+
411
+ ---
412
+
413
+ ## 🧪 Testing
414
+
415
+ ```bash
416
+ npm test
417
+ ```
418
+
419
+ ---
420
+
421
+ ## 📄 Licencia
422
+
423
+ MIT
424
+
425
+ ---
426
+
427
+ ## 🤝 Contribuir
428
+
429
+ Issues y Pull Requests son bienvenidos en: https://github.com/Crane/database
430
+
431
+ ---
432
+
433
+ ## 📝 Changelog
434
+
435
+ ### v2.0.0 (Actual)
436
+
437
+ - ✨ **NEW:** `createQueries()` con autocompletado completo
438
+ - ✨ **NEW:** Soporte para queries planas, anidadas y mixtas
439
+ - ✨ **NEW:** `QueryReference` type para mejor DX
440
+ - ✅ Backward compatible con v1.x.x
441
+ - 📚 Documentación actualizada con ejemplos
442
+
443
+ ### v1.0.0
444
+
445
+ - 🎉 Release inicial
446
+ - Connection pooling
447
+ - Transacciones con dependencias
448
+ - Sistema de logs configurable
449
+
450
+ ---
451
+
452
+ ### `db.bulkInsert(table, columns, rows, options?)`
453
+
454
+ Usa `COPY … FROM STDIN` para insertar muchos registros de forma nativa.
455
+
456
+ **Parámetros:**
457
+
458
+ - `table`: nombre de la tabla destino
459
+ - `columns`: columnas que se van a poblar (ordenadas)
460
+ - `rows`: matriz con los valores (cada fila puede tener `null`)
461
+ - `options?`: [`BulkInsertOptions`](./interfaces/BulkInsertOptions.ts) para delimitar y agregar cabecera
462
+
463
+ **Ejemplo:**
464
+
465
+ ```ts
466
+ await db.bulkInsert(
467
+ "test_users",
468
+ ["name", "email"],
469
+ [
470
+ ["Bulk 1", "bulk1@example.com"],
471
+ ["Bulk 2", "bulk2@example.com"],
472
+ ],
473
+ { header: false }
474
+ );
475
+ ```