@crane-technologies/database 3.0.0 → 3.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 +131 -128
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
# @crane-technologies/database
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
PostgreSQL database component with connection pooling, transactions, dependency management, and **TypeScript query autocomplete**.
|
|
4
4
|
|
|
5
|
-
## ✨
|
|
5
|
+
## ✨ Features
|
|
6
6
|
|
|
7
|
-
- ✅ **
|
|
8
|
-
- ✅
|
|
9
|
-
- ✅
|
|
10
|
-
- ✅
|
|
11
|
-
- ✅ Raw SQL
|
|
12
|
-
- ✅ Backward compatible
|
|
13
|
-
- ✅
|
|
14
|
-
- ✅ 100% TypeScript
|
|
7
|
+
- ✅ **Full autocomplete** with `createQueries()`
|
|
8
|
+
- ✅ Automatic connection pooling
|
|
9
|
+
- ✅ ACID transactions with query dependencies
|
|
10
|
+
- ✅ Support for flat, nested, and mixed queries
|
|
11
|
+
- ✅ Raw SQL when you need it
|
|
12
|
+
- ✅ Backward compatible with existing code
|
|
13
|
+
- ✅ Configurable logs (4 levels)
|
|
14
|
+
- ✅ 100% TypeScript with complete types
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
-
## 📦
|
|
18
|
+
## 📦 Installation
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
21
|
npm install @crane-technologies/database
|
|
@@ -23,9 +23,9 @@ npm install @crane-technologies/database
|
|
|
23
23
|
|
|
24
24
|
---
|
|
25
25
|
|
|
26
|
-
## 🚀
|
|
26
|
+
## 🚀 Quick Start
|
|
27
27
|
|
|
28
|
-
### **
|
|
28
|
+
### **With `createQueries()` (Recommended ⭐)**
|
|
29
29
|
|
|
30
30
|
```typescript
|
|
31
31
|
import Database, {
|
|
@@ -33,7 +33,7 @@ import Database, {
|
|
|
33
33
|
DatabaseConfig,
|
|
34
34
|
} from "@crane-technologies/database";
|
|
35
35
|
|
|
36
|
-
// 1.
|
|
36
|
+
// 1. Create queries with autocomplete
|
|
37
37
|
const queries = createQueries({
|
|
38
38
|
users: {
|
|
39
39
|
getById: "SELECT * FROM users WHERE id = $1",
|
|
@@ -47,7 +47,7 @@ const queries = createQueries({
|
|
|
47
47
|
},
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
-
// 2.
|
|
50
|
+
// 2. Configure database
|
|
51
51
|
const config: DatabaseConfig = {
|
|
52
52
|
connectionString: process.env.DATABASE_URL!,
|
|
53
53
|
ssl: { rejectUnauthorized: false },
|
|
@@ -55,10 +55,10 @@ const config: DatabaseConfig = {
|
|
|
55
55
|
logLevel: 2, // 0=NONE, 1=ERROR, 2=DEBUG, 3=ALL
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
-
// 3.
|
|
58
|
+
// 3. Initialize
|
|
59
59
|
const db = Database.getInstance(config, queries);
|
|
60
60
|
|
|
61
|
-
// 4.
|
|
61
|
+
// 4. Use with autocomplete! 🎉
|
|
62
62
|
const user = await db.query(queries.users.getById, [123]);
|
|
63
63
|
const newUser = await db.query(queries.users.create, [
|
|
64
64
|
"John",
|
|
@@ -69,9 +69,9 @@ const products = await db.query(queries.products.getAll);
|
|
|
69
69
|
|
|
70
70
|
---
|
|
71
71
|
|
|
72
|
-
## 📚
|
|
72
|
+
## 📚 Use Cases
|
|
73
73
|
|
|
74
|
-
### **1. Queries
|
|
74
|
+
### **1. Flat Queries (no nesting)**
|
|
75
75
|
|
|
76
76
|
```typescript
|
|
77
77
|
const queries = createQueries({
|
|
@@ -89,7 +89,7 @@ await db.query(queries.deleteUser, [456]);
|
|
|
89
89
|
|
|
90
90
|
---
|
|
91
91
|
|
|
92
|
-
### **2. Queries
|
|
92
|
+
### **2. Nested Queries (domain-organized)**
|
|
93
93
|
|
|
94
94
|
```typescript
|
|
95
95
|
const queries = createQueries({
|
|
@@ -107,22 +107,22 @@ const queries = createQueries({
|
|
|
107
107
|
|
|
108
108
|
const db = Database.getInstance(config, queries);
|
|
109
109
|
|
|
110
|
-
//
|
|
110
|
+
// Autocomplete works at all levels!
|
|
111
111
|
await db.query(queries.users.getById, [123]);
|
|
112
112
|
await db.query(queries.products.create, ["Laptop", 999.99]);
|
|
113
113
|
```
|
|
114
114
|
|
|
115
115
|
---
|
|
116
116
|
|
|
117
|
-
### **3. Queries
|
|
117
|
+
### **3. Mixed Queries (flat + nested)**
|
|
118
118
|
|
|
119
119
|
```typescript
|
|
120
120
|
const queries = createQueries({
|
|
121
|
-
//
|
|
121
|
+
// Flat queries for simple things
|
|
122
122
|
testConnection: "SELECT NOW() as time",
|
|
123
123
|
checkHealth: "SELECT 1",
|
|
124
124
|
|
|
125
|
-
//
|
|
125
|
+
// Nested queries for complex domains
|
|
126
126
|
users: {
|
|
127
127
|
getById: "SELECT * FROM users WHERE id = $1",
|
|
128
128
|
create: "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *",
|
|
@@ -134,21 +134,21 @@ const queries = createQueries({
|
|
|
134
134
|
|
|
135
135
|
const db = Database.getInstance(config, queries);
|
|
136
136
|
|
|
137
|
-
//
|
|
137
|
+
// Flat
|
|
138
138
|
await db.query(queries.testConnection);
|
|
139
139
|
await db.query(queries.checkHealth);
|
|
140
140
|
|
|
141
|
-
//
|
|
141
|
+
// Nested
|
|
142
142
|
await db.query(queries.users.getById, [123]);
|
|
143
143
|
await db.query(queries.products.getAll);
|
|
144
144
|
```
|
|
145
145
|
|
|
146
146
|
---
|
|
147
147
|
|
|
148
|
-
### **4. Raw SQL (
|
|
148
|
+
### **4. Raw SQL (when you need it)**
|
|
149
149
|
|
|
150
150
|
```typescript
|
|
151
|
-
// Raw SQL
|
|
151
|
+
// Raw SQL still works
|
|
152
152
|
const result = await db.query("SELECT COUNT(*) FROM users WHERE active = $1", [
|
|
153
153
|
true,
|
|
154
154
|
]);
|
|
@@ -157,7 +157,7 @@ const count = result.rows[0].count;
|
|
|
157
157
|
|
|
158
158
|
---
|
|
159
159
|
|
|
160
|
-
### **5.
|
|
160
|
+
### **5. Simple Transactions**
|
|
161
161
|
|
|
162
162
|
```typescript
|
|
163
163
|
const results = await db.transaction(
|
|
@@ -168,12 +168,12 @@ const results = await db.transaction(
|
|
|
168
168
|
]
|
|
169
169
|
);
|
|
170
170
|
|
|
171
|
-
console.log("
|
|
171
|
+
console.log("Users created:", results.length);
|
|
172
172
|
```
|
|
173
173
|
|
|
174
174
|
---
|
|
175
175
|
|
|
176
|
-
### **6.
|
|
176
|
+
### **6. Transactions with Dependencies**
|
|
177
177
|
|
|
178
178
|
```typescript
|
|
179
179
|
import { Dependency } from "@crane-technologies/database";
|
|
@@ -189,7 +189,7 @@ const queries = createQueries({
|
|
|
189
189
|
|
|
190
190
|
const db = Database.getInstance(config, queries);
|
|
191
191
|
|
|
192
|
-
//
|
|
192
|
+
// The user ID is automatically injected into the profile
|
|
193
193
|
const dependencies: Dependency[] = [
|
|
194
194
|
{ sourceIndex: 0, targetIndex: 1, targetParamIndex: 0 },
|
|
195
195
|
];
|
|
@@ -198,50 +198,50 @@ const results = await db.transaction(
|
|
|
198
198
|
[queries.users.create, queries.profiles.create],
|
|
199
199
|
[
|
|
200
200
|
["John", "john@email.com"],
|
|
201
|
-
[null, "John's bio"], // null
|
|
201
|
+
[null, "John's bio"], // null will be replaced by user.id
|
|
202
202
|
],
|
|
203
203
|
dependencies
|
|
204
204
|
);
|
|
205
205
|
|
|
206
|
-
console.log("
|
|
207
|
-
console.log("
|
|
206
|
+
console.log("User created:", results[0].rows[0]);
|
|
207
|
+
console.log("Profile created:", results[1].rows[0]);
|
|
208
208
|
```
|
|
209
209
|
|
|
210
210
|
---
|
|
211
211
|
|
|
212
|
-
## 📊
|
|
212
|
+
## 📊 Log Levels
|
|
213
213
|
|
|
214
214
|
```typescript
|
|
215
215
|
export type LogLevel = 0 | 1 | 2 | 3;
|
|
216
216
|
|
|
217
|
-
// 0 = NONE -
|
|
218
|
-
// 1 = ERROR -
|
|
219
|
-
// 2 = DEBUG -
|
|
220
|
-
// 3 = ALL -
|
|
217
|
+
// 0 = NONE - No logs
|
|
218
|
+
// 1 = ERROR - Only errors
|
|
219
|
+
// 2 = DEBUG - Errors + debug
|
|
220
|
+
// 3 = ALL - All logs (errors + debug + warnings + info)
|
|
221
221
|
|
|
222
222
|
const config: DatabaseConfig = {
|
|
223
223
|
connectionString: process.env.DATABASE_URL!,
|
|
224
224
|
logLevel: 2, // DEBUG
|
|
225
225
|
};
|
|
226
226
|
|
|
227
|
-
//
|
|
228
|
-
db.setLogLevel(1); //
|
|
227
|
+
// Change dynamically
|
|
228
|
+
db.setLogLevel(1); // Only errors
|
|
229
229
|
```
|
|
230
230
|
|
|
231
231
|
---
|
|
232
232
|
|
|
233
233
|
## 🔄 Backward Compatibility
|
|
234
234
|
|
|
235
|
-
|
|
235
|
+
The package is 100% compatible with existing code:
|
|
236
236
|
|
|
237
237
|
```typescript
|
|
238
|
-
// ✅
|
|
238
|
+
// ✅ Old style (still works)
|
|
239
239
|
const db = Database.getInstance(config, {
|
|
240
240
|
getUser: "SELECT * FROM users WHERE id = $1",
|
|
241
241
|
});
|
|
242
242
|
await db.query("getUser", [123]);
|
|
243
243
|
|
|
244
|
-
// ✅
|
|
244
|
+
// ✅ New style (with autocomplete)
|
|
245
245
|
const queries = createQueries({
|
|
246
246
|
users: {
|
|
247
247
|
getById: "SELECT * FROM users WHERE id = $1",
|
|
@@ -255,7 +255,7 @@ await db.query(queries.users.getById, [123]);
|
|
|
255
255
|
|
|
256
256
|
## 🛡️ TypeScript
|
|
257
257
|
|
|
258
|
-
|
|
258
|
+
The package includes complete type definitions:
|
|
259
259
|
|
|
260
260
|
```typescript
|
|
261
261
|
import {
|
|
@@ -276,15 +276,15 @@ import {
|
|
|
276
276
|
|
|
277
277
|
### `createQueries(queries)`
|
|
278
278
|
|
|
279
|
-
|
|
279
|
+
Creates a query object with autocomplete.
|
|
280
280
|
|
|
281
|
-
**
|
|
281
|
+
**Parameters:**
|
|
282
282
|
|
|
283
|
-
- `queries: Record<string, any>` -
|
|
283
|
+
- `queries: Record<string, any>` - Object with queries (flat, nested, or mixed)
|
|
284
284
|
|
|
285
|
-
**
|
|
285
|
+
**Returns:** Object with queries and internal `__flatMap`
|
|
286
286
|
|
|
287
|
-
**
|
|
287
|
+
**Example:**
|
|
288
288
|
|
|
289
289
|
```typescript
|
|
290
290
|
const queries = createQueries({
|
|
@@ -298,16 +298,16 @@ const queries = createQueries({
|
|
|
298
298
|
|
|
299
299
|
### `Database.getInstance(config, queries)`
|
|
300
300
|
|
|
301
|
-
|
|
301
|
+
Gets the singleton Database instance.
|
|
302
302
|
|
|
303
|
-
**
|
|
303
|
+
**Parameters:**
|
|
304
304
|
|
|
305
|
-
- `config: DatabaseConfig` -
|
|
306
|
-
- `queries?: any` -
|
|
305
|
+
- `config: DatabaseConfig` - Connection configuration
|
|
306
|
+
- `queries?: any` - Result of `createQueries()` or plain object
|
|
307
307
|
|
|
308
|
-
**
|
|
308
|
+
**Returns:** `Database`
|
|
309
309
|
|
|
310
|
-
**
|
|
310
|
+
**Example:**
|
|
311
311
|
|
|
312
312
|
```typescript
|
|
313
313
|
const db = Database.getInstance(config, queries);
|
|
@@ -317,22 +317,22 @@ const db = Database.getInstance(config, queries);
|
|
|
317
317
|
|
|
318
318
|
### `db.query(query, params?)`
|
|
319
319
|
|
|
320
|
-
|
|
320
|
+
Executes a query (with QueryReference, string key, or raw SQL).
|
|
321
321
|
|
|
322
|
-
**
|
|
322
|
+
**Parameters:**
|
|
323
323
|
|
|
324
|
-
- `query: string | QueryReference` - Query
|
|
325
|
-
- `params?: any[]` -
|
|
324
|
+
- `query: string | QueryReference` - Query to execute
|
|
325
|
+
- `params?: any[]` - Query parameters
|
|
326
326
|
|
|
327
|
-
**
|
|
327
|
+
**Returns:** `Promise<QueryResult>`
|
|
328
328
|
|
|
329
|
-
**
|
|
329
|
+
**Examples:**
|
|
330
330
|
|
|
331
331
|
```typescript
|
|
332
|
-
//
|
|
332
|
+
// With QueryReference
|
|
333
333
|
await db.query(queries.users.getById, [123]);
|
|
334
334
|
|
|
335
|
-
//
|
|
335
|
+
// With string key
|
|
336
336
|
await db.query("users.getById", [123]);
|
|
337
337
|
|
|
338
338
|
// Raw SQL
|
|
@@ -343,17 +343,17 @@ await db.query("SELECT * FROM users WHERE id = $1", [123]);
|
|
|
343
343
|
|
|
344
344
|
### `db.transaction(queryArray, paramsArray, dependencies?)`
|
|
345
345
|
|
|
346
|
-
|
|
346
|
+
Executes multiple queries in an atomic transaction.
|
|
347
347
|
|
|
348
|
-
**
|
|
348
|
+
**Parameters:**
|
|
349
349
|
|
|
350
|
-
- `queryArray: (string | QueryReference)[]` - Array
|
|
351
|
-
- `paramsArray: any[][]` -
|
|
352
|
-
- `dependencies?: Dependency[]` -
|
|
350
|
+
- `queryArray: (string | QueryReference)[]` - Array of queries
|
|
351
|
+
- `paramsArray: any[][]` - Parameters for each query
|
|
352
|
+
- `dependencies?: Dependency[]` - Dependencies between queries
|
|
353
353
|
|
|
354
|
-
**
|
|
354
|
+
**Returns:** `Promise<QueryResult[]>`
|
|
355
355
|
|
|
356
|
-
**
|
|
356
|
+
**Example:**
|
|
357
357
|
|
|
358
358
|
```typescript
|
|
359
359
|
await db.transaction(
|
|
@@ -370,11 +370,11 @@ await db.transaction(
|
|
|
370
370
|
|
|
371
371
|
### `db.close()`
|
|
372
372
|
|
|
373
|
-
|
|
373
|
+
Closes all pool connections.
|
|
374
374
|
|
|
375
|
-
**
|
|
375
|
+
**Returns:** `Promise<void>`
|
|
376
376
|
|
|
377
|
-
**
|
|
377
|
+
**Example:**
|
|
378
378
|
|
|
379
379
|
```typescript
|
|
380
380
|
await db.close();
|
|
@@ -384,21 +384,48 @@ await db.close();
|
|
|
384
384
|
|
|
385
385
|
### `db.setLogLevel(level)`
|
|
386
386
|
|
|
387
|
-
|
|
387
|
+
Dynamically changes the log level.
|
|
388
388
|
|
|
389
|
-
**
|
|
389
|
+
**Parameters:**
|
|
390
390
|
|
|
391
|
-
- `level: 0 | 1 | 2 | 3` -
|
|
391
|
+
- `level: 0 | 1 | 2 | 3` - New log level
|
|
392
392
|
|
|
393
|
-
**
|
|
393
|
+
**Example:**
|
|
394
394
|
|
|
395
395
|
```typescript
|
|
396
|
-
db.setLogLevel(1); //
|
|
396
|
+
db.setLogLevel(1); // Only errors
|
|
397
397
|
```
|
|
398
398
|
|
|
399
399
|
---
|
|
400
400
|
|
|
401
|
-
|
|
401
|
+
### `db.bulkInsert(table, columns, rows, options?)`
|
|
402
|
+
|
|
403
|
+
Uses `COPY … FROM STDIN` to insert many records natively.
|
|
404
|
+
|
|
405
|
+
**Parameters:**
|
|
406
|
+
|
|
407
|
+
- `table`: target table name
|
|
408
|
+
- `columns`: columns to populate (ordered)
|
|
409
|
+
- `rows`: matrix with values (each row can have `null`)
|
|
410
|
+
- `options?`: [`BulkInsertOptions`](./interfaces/BulkInsertOptions.ts) to set delimiter and add header
|
|
411
|
+
|
|
412
|
+
**Example:**
|
|
413
|
+
|
|
414
|
+
```ts
|
|
415
|
+
await db.bulkInsert(
|
|
416
|
+
"test_users",
|
|
417
|
+
["name", "email"],
|
|
418
|
+
[
|
|
419
|
+
["Bulk 1", "bulk1@example.com"],
|
|
420
|
+
["Bulk 2", "bulk2@example.com"],
|
|
421
|
+
],
|
|
422
|
+
{ header: false }
|
|
423
|
+
);
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## 🔒 Closing Connections
|
|
402
429
|
|
|
403
430
|
```typescript
|
|
404
431
|
process.on("SIGTERM", async () => {
|
|
@@ -410,66 +437,42 @@ process.on("SIGTERM", async () => {
|
|
|
410
437
|
|
|
411
438
|
---
|
|
412
439
|
|
|
413
|
-
##
|
|
414
|
-
|
|
415
|
-
```bash
|
|
416
|
-
npm test
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
---
|
|
420
|
-
|
|
421
|
-
## 📄 Licencia
|
|
440
|
+
## 📄 License
|
|
422
441
|
|
|
423
442
|
MIT
|
|
424
443
|
|
|
425
444
|
---
|
|
426
445
|
|
|
427
|
-
## 🤝
|
|
446
|
+
## 🤝 Contributing
|
|
428
447
|
|
|
429
|
-
Issues
|
|
448
|
+
Issues and Pull Requests are welcome at: https://github.com/Crane/database
|
|
430
449
|
|
|
431
450
|
---
|
|
432
451
|
|
|
433
452
|
## 📝 Changelog
|
|
434
453
|
|
|
435
|
-
###
|
|
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
|
-
---
|
|
454
|
+
### v3.0.0 (Current)
|
|
451
455
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
456
|
+
- ✨ **NEW:** `bulkInsert()` method for high-performance bulk data loading using PostgreSQL's native `COPY ... FROM STDIN`.
|
|
457
|
+
- 🚀 Bulk insert supports:
|
|
458
|
+
- Streaming large datasets as CSV directly to the database.
|
|
459
|
+
- Custom CSV delimiter and optional header row via `BulkInsertOptions`.
|
|
460
|
+
- Automatic quoting of table and column identifiers for safety.
|
|
461
|
+
- Full TypeScript typings for all parameters and options.
|
|
462
|
+
- Efficient handling of large inserts compared to multiple `INSERT` statements.
|
|
463
|
+
- 📚 Documentation and usage examples for `bulkInsert()` added.
|
|
455
464
|
|
|
456
|
-
|
|
465
|
+
### v2.0.0
|
|
457
466
|
|
|
458
|
-
-
|
|
459
|
-
-
|
|
460
|
-
-
|
|
461
|
-
-
|
|
467
|
+
- ✨ **NEW:** `createQueries()` with full autocomplete
|
|
468
|
+
- ✨ **NEW:** Support for flat, nested, and mixed queries
|
|
469
|
+
- ✨ **NEW:** `QueryReference` type for better DX
|
|
470
|
+
- ✅ Backward compatible with v1.x.x
|
|
471
|
+
- 📚 Updated documentation with examples
|
|
462
472
|
|
|
463
|
-
|
|
473
|
+
### v1.0.0
|
|
464
474
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
[
|
|
470
|
-
["Bulk 1", "bulk1@example.com"],
|
|
471
|
-
["Bulk 2", "bulk2@example.com"],
|
|
472
|
-
],
|
|
473
|
-
{ header: false }
|
|
474
|
-
);
|
|
475
|
-
```
|
|
475
|
+
- 🎉 Initial release
|
|
476
|
+
- Connection pooling
|
|
477
|
+
- Transactions with dependencies
|
|
478
|
+
- Configurable logging system
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crane-technologies/database",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "PostgreSQL database component with connection pooling, transactions, dependency management and TypeScript autocomplete",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|