@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.
- package/README.md +475 -0
- package/dist/components/Database.d.ts +288 -0
- package/dist/components/Database.d.ts.map +1 -0
- package/dist/components/Database.js +554 -0
- package/dist/components/Database.js.map +1 -0
- package/dist/components/Logger.d.ts +63 -0
- package/dist/components/Logger.d.ts.map +1 -0
- package/dist/components/Logger.js +147 -0
- package/dist/components/Logger.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/BulkInsertOptions.d.ts +20 -0
- package/dist/interfaces/BulkInsertOptions.d.ts.map +1 -0
- package/dist/interfaces/BulkInsertOptions.js +3 -0
- package/dist/interfaces/BulkInsertOptions.js.map +1 -0
- package/dist/interfaces/DatabaseConfig.d.ts +52 -0
- package/dist/interfaces/DatabaseConfig.d.ts.map +1 -0
- package/dist/interfaces/DatabaseConfig.js +3 -0
- package/dist/interfaces/DatabaseConfig.js.map +1 -0
- package/dist/interfaces/Dependancy.d.ts +15 -0
- package/dist/interfaces/Dependancy.d.ts.map +1 -0
- package/dist/interfaces/Dependancy.js +3 -0
- package/dist/interfaces/Dependancy.js.map +1 -0
- package/dist/interfaces/QueryList.d.ts +4 -0
- package/dist/interfaces/QueryList.d.ts.map +1 -0
- package/dist/interfaces/QueryList.js +3 -0
- package/dist/interfaces/QueryList.js.map +1 -0
- package/dist/utils/createQueries.d.ts +65 -0
- package/dist/utils/createQueries.d.ts.map +1 -0
- package/dist/utils/createQueries.js +121 -0
- package/dist/utils/createQueries.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { QueryResult } from "pg";
|
|
2
|
+
import { Dependency } from "@/interfaces/Dependancy";
|
|
3
|
+
import { DatabaseConfig } from "@/interfaces/DatabaseConfig";
|
|
4
|
+
import { BulkInsertOptions } from "@/interfaces/BulkInsertOptions";
|
|
5
|
+
import { QueryReference } from "@/utils/createQueries";
|
|
6
|
+
/**
|
|
7
|
+
* Database class implements the Singleton pattern to manage PostgreSQL connections.
|
|
8
|
+
* Provides methods for executing SQL queries, transactions and dependency handling.
|
|
9
|
+
* Supports QueryReference objects for autocomplete.
|
|
10
|
+
*
|
|
11
|
+
* @class Database
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import Database, { createQueries } from '@crane-technologies/database';
|
|
15
|
+
*
|
|
16
|
+
* const queries = createQueries({
|
|
17
|
+
* users: {
|
|
18
|
+
* getById: "SELECT * FROM users WHERE id = $1"
|
|
19
|
+
* }
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* const db = Database.getInstance(config, queries);
|
|
23
|
+
*
|
|
24
|
+
* // ✅ Con autocompletado
|
|
25
|
+
* await db.query(queries.users.getById, [123]);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
declare class Database {
|
|
29
|
+
/** Unique singleton instance */
|
|
30
|
+
private static instance;
|
|
31
|
+
/** PostgreSQL connection pool */
|
|
32
|
+
private pool;
|
|
33
|
+
/** Dictionary of predefined SQL queries (flat map) */
|
|
34
|
+
private queries;
|
|
35
|
+
/** Logger instance */
|
|
36
|
+
private logger;
|
|
37
|
+
/** Database configuration */
|
|
38
|
+
private config;
|
|
39
|
+
/**
|
|
40
|
+
* Private constructor that implements the Singleton pattern.
|
|
41
|
+
* Use getInstance() to get the Database instance.
|
|
42
|
+
*
|
|
43
|
+
* @param {DatabaseConfig} config - Database configuration
|
|
44
|
+
* @param {Record<string, string>} flatMap - Flat map of queries
|
|
45
|
+
* @private
|
|
46
|
+
*/
|
|
47
|
+
private constructor();
|
|
48
|
+
/**
|
|
49
|
+
* Initializes the PostgreSQL connection pool using provided configuration.
|
|
50
|
+
* Executed only once when creating the first singleton instance.
|
|
51
|
+
*
|
|
52
|
+
* @private
|
|
53
|
+
* @returns {void}
|
|
54
|
+
* @throws {Error} If pool initialization fails
|
|
55
|
+
*/
|
|
56
|
+
private initializePool;
|
|
57
|
+
/**
|
|
58
|
+
* Static method to get the unique Database instance (Singleton pattern).
|
|
59
|
+
* Accepts the result of createQueries() or a plain object with queries.
|
|
60
|
+
*
|
|
61
|
+
* @param {DatabaseConfig} config - Database configuration (required on first call)
|
|
62
|
+
* @param {any} queries - Result from createQueries() or plain query object
|
|
63
|
+
* @returns {Database} The unique Database instance
|
|
64
|
+
* @throws {Error} If config is not provided on first initialization
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* // With createQueries (recommended)
|
|
69
|
+
* const queries = createQueries({
|
|
70
|
+
* users: { getById: "SELECT * FROM users WHERE id = $1" }
|
|
71
|
+
* });
|
|
72
|
+
* const db = Database.getInstance(config, queries);
|
|
73
|
+
* await db.query(queries.users.getById, [123]);
|
|
74
|
+
*
|
|
75
|
+
* // With plain object (backward compatible)
|
|
76
|
+
* const db = Database.getInstance(config, {
|
|
77
|
+
* getUser: "SELECT * FROM users WHERE id = $1"
|
|
78
|
+
* });
|
|
79
|
+
* await db.query("getUser", [123]);
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
static getInstance(config: DatabaseConfig, queries?: any): Database;
|
|
83
|
+
/**
|
|
84
|
+
* Validates that the pool is active and ready to accept connections.
|
|
85
|
+
*
|
|
86
|
+
* @private
|
|
87
|
+
* @throws {Error} If pool is closed or not initialized
|
|
88
|
+
*/
|
|
89
|
+
private ensurePoolActive;
|
|
90
|
+
/**
|
|
91
|
+
* Extracts the SQL from a QueryReference or string key.
|
|
92
|
+
*
|
|
93
|
+
* @private
|
|
94
|
+
* @param query - QueryReference, string key, or raw SQL
|
|
95
|
+
* @returns The SQL query string
|
|
96
|
+
* @throws {Error} If query is not found
|
|
97
|
+
*/
|
|
98
|
+
private getQuery;
|
|
99
|
+
/**
|
|
100
|
+
* Gets the SQL query string.
|
|
101
|
+
*
|
|
102
|
+
* @private
|
|
103
|
+
* @param query - QueryReference or string
|
|
104
|
+
* @returns The SQL query string
|
|
105
|
+
*/
|
|
106
|
+
private getQueryName;
|
|
107
|
+
/**
|
|
108
|
+
* Executes a predefined SQL query using QueryReference or string key.
|
|
109
|
+
* Gets a connection from the pool, executes the query and releases the connection.
|
|
110
|
+
*
|
|
111
|
+
* @param {string | QueryReference} query - QueryReference object or query key
|
|
112
|
+
* @param {any[]} params - Optional parameters for the SQL query
|
|
113
|
+
* @returns {Promise<QueryResult>} SQL query result
|
|
114
|
+
* @throws {Error} If the query doesn't exist or execution fails
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```typescript
|
|
118
|
+
* // With QueryReference (autocomplete!)
|
|
119
|
+
* const result = await db.queryList(queries.users.getById, [123]);
|
|
120
|
+
*
|
|
121
|
+
* // With string key (backward compatible)
|
|
122
|
+
* const result = await db.queryList("users.getById", [123]);
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
queryList(query: string | QueryReference, params?: any[]): Promise<QueryResult>;
|
|
126
|
+
/**
|
|
127
|
+
* Executes a direct SQL query (raw SQL text).
|
|
128
|
+
* Useful for dynamic queries that are not predefined in the dictionary.
|
|
129
|
+
* Gets a connection from the pool, executes the query and releases the connection.
|
|
130
|
+
*
|
|
131
|
+
* @param {string} sqlText - The complete SQL text of the query to execute
|
|
132
|
+
* @param {any[]} params - Optional parameters for the SQL query
|
|
133
|
+
* @returns {Promise<QueryResult>} SQL query result
|
|
134
|
+
* @throws {Error} If query execution fails
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* const result = await db.rawQuery("SELECT COUNT(*) FROM users WHERE active = $1", [true]);
|
|
139
|
+
* const count = result.rows[0].count;
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
rawQuery(sqlText: string, params?: any[]): Promise<QueryResult>;
|
|
143
|
+
/**
|
|
144
|
+
* Performs a high-performance bulk insert using PostgreSQL's native COPY ... FROM STDIN.
|
|
145
|
+
* Accepts an array of rows and streams them as CSV to the database.
|
|
146
|
+
* This is significantly faster than multiple INSERT statements.
|
|
147
|
+
*
|
|
148
|
+
* @param {string} table - The target table name.
|
|
149
|
+
* @param {string[]} columns - Array of column names to insert into (order matters).
|
|
150
|
+
* @param {(string | number | boolean | Date | null | undefined)[][]} rows - Array of row arrays, each representing a record.
|
|
151
|
+
* @param {BulkInsertOptions} [options] - Optional CSV formatting options (delimiter, header).
|
|
152
|
+
* @returns {Promise<{ inserted: number }>} Number of rows successfully inserted.
|
|
153
|
+
* @throws {Error} If the operation fails or the pool is not active.
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```typescript
|
|
157
|
+
* await db.bulkInsert(
|
|
158
|
+
* "users",
|
|
159
|
+
* ["name", "email"],
|
|
160
|
+
* [
|
|
161
|
+
* ["Alice", "alice@email.com"],
|
|
162
|
+
* ["Bob", "bob@email.com"]
|
|
163
|
+
* ],
|
|
164
|
+
* { header: false }
|
|
165
|
+
* );
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
168
|
+
bulkInsert(table: string, columns: string[], rows: (string | number | boolean | Date | null | undefined)[][], options?: BulkInsertOptions): Promise<{
|
|
169
|
+
inserted: number;
|
|
170
|
+
}>;
|
|
171
|
+
/**
|
|
172
|
+
* Generator that yields CSV lines for bulk insert operations.
|
|
173
|
+
* Optionally includes a header row with column names.
|
|
174
|
+
* Each yielded value is a CSV-formatted string representing a row.
|
|
175
|
+
*
|
|
176
|
+
* @private
|
|
177
|
+
* @param {string[]} columns - Array of column names.
|
|
178
|
+
* @param {(string | number | boolean | Date | null | undefined)[][]} rows - Array of row arrays.
|
|
179
|
+
* @param {string} delimiter - CSV delimiter character.
|
|
180
|
+
* @param {boolean} includeHeader - Whether to include a header row.
|
|
181
|
+
* @yields {string} CSV-formatted line.
|
|
182
|
+
*/
|
|
183
|
+
private generateCsvLines;
|
|
184
|
+
/**
|
|
185
|
+
* Escapes a single value for safe inclusion in a CSV line.
|
|
186
|
+
* Handles delimiters, quotes, and line breaks according to CSV rules.
|
|
187
|
+
*
|
|
188
|
+
* @private
|
|
189
|
+
* @param {string | number | boolean | Date | null | undefined} value - The value to escape.
|
|
190
|
+
* @param {string} delimiter - The CSV delimiter character.
|
|
191
|
+
* @returns {string} The escaped CSV value.
|
|
192
|
+
*/
|
|
193
|
+
private escapeCsvValue;
|
|
194
|
+
/**
|
|
195
|
+
* Safely quotes a SQL identifier (such as a table or column name) for use in queries.
|
|
196
|
+
* Escapes any double quotes within the identifier to prevent SQL injection or syntax errors.
|
|
197
|
+
*
|
|
198
|
+
* @private
|
|
199
|
+
* @param {string} identifier - The SQL identifier to quote (e.g., table or column name).
|
|
200
|
+
* @returns {string} The quoted and escaped identifier, safe for use in SQL statements.
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* const quoted = db.quoteIdentifier('user"name');
|
|
204
|
+
* // quoted === '"user""name"'
|
|
205
|
+
*/
|
|
206
|
+
private quoteIdentifier;
|
|
207
|
+
/**
|
|
208
|
+
* Smart method that executes queries automatically detecting the type.
|
|
209
|
+
* Supports QueryReference objects (from createQueries), string keys, or raw SQL.
|
|
210
|
+
*
|
|
211
|
+
* @param {string | QueryReference} query - QueryReference, query key, or raw SQL
|
|
212
|
+
* @param {any[]} params - Optional parameters for the SQL query
|
|
213
|
+
* @returns {Promise<QueryResult>} SQL query result
|
|
214
|
+
* @throws {Error} If query execution fails
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```typescript
|
|
218
|
+
* // Using QueryReference (autocomplete!)
|
|
219
|
+
* const user = await db.query(queries.users.getById, [123]);
|
|
220
|
+
*
|
|
221
|
+
* // Using string key (backward compatible)
|
|
222
|
+
* const user = await db.query("users.getById", [123]);
|
|
223
|
+
*
|
|
224
|
+
* // Using raw SQL
|
|
225
|
+
* const products = await db.query("SELECT * FROM products WHERE price > $1", [100]);
|
|
226
|
+
* ```
|
|
227
|
+
*/
|
|
228
|
+
query(query: string | QueryReference, params?: any[]): Promise<QueryResult>;
|
|
229
|
+
/**
|
|
230
|
+
* Executes multiple SQL queries within an atomic transaction.
|
|
231
|
+
* All queries execute or fail together (ACID compliance).
|
|
232
|
+
* Supports dependencies between queries, where the result of one query
|
|
233
|
+
* can be used as a parameter in subsequent queries.
|
|
234
|
+
* Supports QueryReference objects with autocomplete.
|
|
235
|
+
*
|
|
236
|
+
* @param {(string | QueryReference)[]} queryArray - Array of QueryReferences or query keys
|
|
237
|
+
* @param {any[][]} paramsArray - Array of arrays with parameters for each query
|
|
238
|
+
* @param {Dependency[]} dependencies - Optional array of dependencies between queries
|
|
239
|
+
* @returns {Promise<QueryResult[]>} Array with the results of all queries
|
|
240
|
+
* @throws {Error} If any query fails, the entire transaction is rolled back
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* ```typescript
|
|
244
|
+
* // With QueryReference (autocomplete!)
|
|
245
|
+
* const results = await db.transaction(
|
|
246
|
+
* [queries.users.create, queries.profiles.create],
|
|
247
|
+
* [
|
|
248
|
+
* ["John", "john@email.com"],
|
|
249
|
+
* [null, "Profile description"]
|
|
250
|
+
* ],
|
|
251
|
+
* [{ sourceIndex: 0, targetIndex: 1, targetParamIndex: 0 }]
|
|
252
|
+
* );
|
|
253
|
+
*
|
|
254
|
+
* // With string keys (backward compatible)
|
|
255
|
+
* const results = await db.transaction(
|
|
256
|
+
* ["users.create", "profiles.create"],
|
|
257
|
+
* [["John", "john@email.com"], [null, "Profile description"]],
|
|
258
|
+
* [{ sourceIndex: 0, targetIndex: 1, targetParamIndex: 0 }]
|
|
259
|
+
* );
|
|
260
|
+
* ```
|
|
261
|
+
*/
|
|
262
|
+
transaction(queryArray: (string | QueryReference)[], paramsArray: any[][], dependencies?: Dependency[]): Promise<QueryResult[]>;
|
|
263
|
+
/**
|
|
264
|
+
* Closes all connections in the pool and cleans up resources.
|
|
265
|
+
* Should be called before application shutdown or when the database is no longer needed.
|
|
266
|
+
* After calling this method, the singleton instance is reset and a new one can be created.
|
|
267
|
+
*
|
|
268
|
+
* @returns {Promise<void>}
|
|
269
|
+
* @throws {Error} If there's an error closing the pool
|
|
270
|
+
*
|
|
271
|
+
* @example
|
|
272
|
+
* ```typescript
|
|
273
|
+
* process.on('SIGTERM', async () => {
|
|
274
|
+
* const db = Database.getInstance();
|
|
275
|
+
* await db.close();
|
|
276
|
+
* process.exit(0);
|
|
277
|
+
* });
|
|
278
|
+
* ```
|
|
279
|
+
*/
|
|
280
|
+
close(): Promise<void>;
|
|
281
|
+
/**
|
|
282
|
+
* Updates the log level dynamically
|
|
283
|
+
* @param level - New log level (0-3)
|
|
284
|
+
*/
|
|
285
|
+
setLogLevel(level: 0 | 1 | 2 | 3): void;
|
|
286
|
+
}
|
|
287
|
+
export default Database;
|
|
288
|
+
//# sourceMappingURL=Database.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Database.d.ts","sourceRoot":"","sources":["../../components/Database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,WAAW,EAAE,MAAM,IAAI,CAAC;AAMnD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,cAAM,QAAQ;IACZ,gCAAgC;IAChC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAW;IAElC,iCAAiC;IACjC,OAAO,CAAC,IAAI,CAAQ;IAEpB,sDAAsD;IACtD,OAAO,CAAC,OAAO,CAAY;IAE3B,sBAAsB;IACtB,OAAO,CAAC,MAAM,CAAS;IAEvB,6BAA6B;IAC7B,OAAO,CAAC,MAAM,CAAiB;IAE/B;;;;;;;OAOG;IACH,OAAO;IAOP;;;;;;;OAOG;IACH,OAAO,CAAC,cAAc;IAuBtB;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;WACW,WAAW,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,GAAG,GAAG,QAAQ;IA6B1E;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAUxB;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ;IAgChB;;;;;;OAMG;IACH,OAAO,CAAC,YAAY;IAUpB;;;;;;;;;;;;;;;;;OAiBG;IACG,SAAS,CACb,KAAK,EAAE,MAAM,GAAG,cAAc,EAC9B,MAAM,CAAC,EAAE,GAAG,EAAE,GACb,OAAO,CAAC,WAAW,CAAC;IA6BvB;;;;;;;;;;;;;;;OAeG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IA0BrE;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACG,UAAU,CACd,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,EAAE,EAC/D,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IA6ChC;;;;;;;;;;;OAWG;IACH,OAAO,CAAE,gBAAgB;IAkBzB;;;;;;;;OAQG;IACH,OAAO,CAAC,cAAc;IAgBtB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,eAAe;IAIvB;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,KAAK,CACT,KAAK,EAAE,MAAM,GAAG,cAAc,EAC9B,MAAM,CAAC,EAAE,GAAG,EAAE,GACb,OAAO,CAAC,WAAW,CAAC;IAoBvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACG,WAAW,CACf,UAAU,EAAE,CAAC,MAAM,GAAG,cAAc,CAAC,EAAE,EACvC,WAAW,EAAE,GAAG,EAAE,EAAE,EACpB,YAAY,GAAE,UAAU,EAAO,GAC9B,OAAO,CAAC,WAAW,EAAE,CAAC;IAwEzB;;;;;;;;;;;;;;;;OAgBG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAcnC;;;OAGG;IACI,WAAW,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI;CAI/C;AAED,eAAe,QAAQ,CAAC"}
|