@m2k-5f/pgtx 1.4.12 → 2.0.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 (69) hide show
  1. package/README.md +225 -128
  2. package/dist/clauses/array.clause.js +1 -1
  3. package/dist/clauses/empty.clause.d.ts +1 -1
  4. package/dist/clauses/empty.clause.d.ts.map +1 -1
  5. package/dist/clauses/empty.clause.js +2 -2
  6. package/dist/clauses/fragment.clause.d.ts +1 -1
  7. package/dist/clauses/fragment.clause.d.ts.map +1 -1
  8. package/dist/clauses/fragment.clause.js +3 -5
  9. package/dist/clauses/iden.caluse.d.ts +1 -1
  10. package/dist/clauses/iden.caluse.d.ts.map +1 -1
  11. package/dist/clauses/index.d.ts +10 -0
  12. package/dist/clauses/index.d.ts.map +1 -0
  13. package/dist/clauses/index.js +25 -0
  14. package/dist/clauses/insert.clause.d.ts +1 -1
  15. package/dist/clauses/insert.clause.d.ts.map +1 -1
  16. package/dist/clauses/insert.clause.js +1 -1
  17. package/dist/clauses/literal.clause.d.ts +1 -1
  18. package/dist/clauses/literal.clause.d.ts.map +1 -1
  19. package/dist/clauses/update.clause.d.ts +1 -1
  20. package/dist/clauses/update.clause.d.ts.map +1 -1
  21. package/dist/clauses/update.clause.js +1 -1
  22. package/dist/clauses/where.clause.d.ts +1 -1
  23. package/dist/clauses/where.clause.d.ts.map +1 -1
  24. package/dist/clauses/where.clause.js +1 -1
  25. package/dist/connection.d.ts +135 -31
  26. package/dist/connection.d.ts.map +1 -1
  27. package/dist/connection.js +290 -59
  28. package/dist/index.d.ts +2 -10
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +10 -18
  31. package/dist/pool.d.ts +126 -32
  32. package/dist/pool.d.ts.map +1 -1
  33. package/dist/pool.js +203 -54
  34. package/dist/protocol/connection-request-writer.d.ts +38 -0
  35. package/dist/protocol/connection-request-writer.d.ts.map +1 -0
  36. package/dist/protocol/connection-request-writer.js +175 -0
  37. package/dist/protocol/connection-response-reader.d.ts +49 -0
  38. package/dist/protocol/connection-response-reader.d.ts.map +1 -0
  39. package/dist/protocol/connection-response-reader.js +185 -0
  40. package/dist/protocol/constants.d.ts +46 -0
  41. package/dist/protocol/constants.d.ts.map +1 -0
  42. package/dist/protocol/constants.js +43 -0
  43. package/dist/protocol/socket-authorization.d.ts +11 -0
  44. package/dist/protocol/socket-authorization.d.ts.map +1 -0
  45. package/dist/protocol/socket-authorization.js +95 -0
  46. package/dist/protocol/socket-connector.d.ts +17 -0
  47. package/dist/protocol/socket-connector.d.ts.map +1 -0
  48. package/dist/protocol/socket-connector.js +48 -0
  49. package/dist/queue.d.ts +10 -0
  50. package/dist/queue.d.ts.map +1 -0
  51. package/dist/queue.js +27 -0
  52. package/dist/security/md5.d.ts +2 -0
  53. package/dist/security/md5.d.ts.map +1 -0
  54. package/dist/security/md5.js +12 -0
  55. package/dist/security/sasl.d.ts +6 -0
  56. package/dist/security/sasl.d.ts.map +1 -0
  57. package/dist/security/sasl.js +29 -0
  58. package/dist/transaction.d.ts +1 -2
  59. package/dist/transaction.d.ts.map +1 -1
  60. package/dist/transaction.js +4 -4
  61. package/dist/types.d.ts +6 -8
  62. package/dist/types.d.ts.map +1 -1
  63. package/dist/utils/template-compiler.d.ts +3 -0
  64. package/dist/utils/template-compiler.d.ts.map +1 -0
  65. package/dist/utils/template-compiler.js +64 -0
  66. package/dist/utils/value-parser.d.ts +6 -0
  67. package/dist/utils/value-parser.d.ts.map +1 -0
  68. package/dist/utils/value-parser.js +101 -0
  69. package/package.json +8 -9
package/README.md CHANGED
@@ -1,9 +1,10 @@
1
- ## Pgtx 🚀
1
+ ## 🚀 Pgtx
2
2
 
3
3
  [![Tests](https://github.com/M2K-5F/pgtx/actions/workflows/tests.yaml/badge.svg)](https://github.com/M2K-5F/pgtx/actions/workflows/tests.yaml)
4
+ [![npm version](https://img.shields.io/npm/v/@m2k-5f/pgtx.svg)](https://www.npmjs.com/package/@m2k-5f/pgtx)
4
5
 
5
- A lightweight, **high-performance** SQL query builder for `node-postgres` (pg).
6
- Experience ORM-like convenience (auto-inserts, updates, recursive fragments) with the transparency and speed of raw SQL.
6
+ **Blazing-fast PostgreSQL driver** with pipeline support.
7
+ Zero deps, pure TypeScript.
7
8
 
8
9
  ---
9
10
 
@@ -11,92 +12,106 @@ Experience ORM-like convenience (auto-inserts, updates, recursive fragments) wit
11
12
 
12
13
  ```bash
13
14
  npm install @m2k-5f/pgtx
14
- # or
15
- yarn add @m2k-5f/pgtx
16
- # or
17
- pnpm add @m2k-5f/pgtx
18
- # or
19
- bun add @m2k-5f/pgtx
15
+ # yarn add @m2k-5f/pgtx
16
+ # pnpm add @m2k-5f/pgtx
17
+ # bun add @m2k-5f/pgtx
20
18
  ```
21
- ## 🔥 Why Pgtx?
22
19
 
23
20
  ---
24
21
 
25
- * **Zero-Cost Abstraction**: Only ~2% - 0% overhead compared to raw `pg.query`.
26
- * **Structural Caching**: Uses `WeakMap` to cache SQL templates. Static parts are parsed only once.
27
- * **Explicit Prepared Statements**: Create and reuse prepared statements with type safety
28
- * **True Recursion**: Nest `sql.fragment` anywhere. Argument numbering ($1, $2) is managed automatically across all nesting levels.
29
- * **No Magic**: You write SQL, `Pgtx` handles the tedious parts (placeholders, identifiers, bulk inserts).
30
- * **ACID Transactions**: Reliable transaction management with automatic rollback on errors.
22
+ ## Performance
31
23
 
32
- ---
24
+ **2000 concurrent UPSERT queries, 150 concurrency, connection pool:**
33
25
 
34
- ## 🚀 Quick Start
26
+ | Tool | RPS | Avg Time | Connections |
27
+ |------|-----|----------|-------------|
28
+ | **Pgtx** | **1584** | **0.631ms** | **20 (used only one)** |
29
+ | Native `pg` | 179 | 5.585ms | 20 |
35
30
 
36
- ```typescript
37
- import { sql, Pool } from "@m2k-5f/pgtx";
31
+ **9x faster**
38
32
 
39
- const pool = new Pool({ /* pg.PoolConfig */ })
40
33
 
41
- // Type-safe query with automatic placeholder ($1)
42
- const [user] = await pool.query<User>`SELECT * FROM users WHERE id = ${1}`
43
- ```
34
+ > Benchmark source available in the [repository](https://github.com/M2K-5F/pgtx).
44
35
 
45
36
  ---
46
37
 
38
+ ## ✨ Features
47
39
 
40
+ - **Pipeline queries** — 9x faster than `pg`
41
+ - **Tagged templates** — Natural SQL with type safety
42
+ - **Transactions & Savepoints** — Nested transactions with rollback
43
+ - **Bulk inserts** — Auto-extract columns from objects
44
+ - **Dynamic updates** — Generate SET clauses from objects
45
+ - **Recursive fragments** — Compose SQL like Lego
46
+ - **Prepared statements** — Pre-parse any SQL with parameters
47
+ - **Connection pool** — Auto-management connections with support for pipeline queries via the pool itself.
48
+ - **Zero dependencies** — Lightweight and blazing
48
49
 
49
- ## ⚡ Performance Benchmark
50
-
51
- The following results were measured during sequential execution of 2000 complex `UPSERT` queries.
50
+ ---
52
51
 
52
+ ## 🔥 Why Pgtx?
53
53
 
54
- | Tool | RPS | Avg. Query Time | Performance Overhead |
55
- | :--- | :---: | :---: | :---: |
56
- | **Native `pg.query`** | **~209** | **4.791ms** | **0% (Baseline)** |
57
- | **Pgtx** | **~207** | **4.827ms** | **0.76%(zero-cost)** |
58
- | Typical Node.js ORM | **~58** | 12.5+ ms | > 150% |
54
+ | Feature | Pgtx | pg | TypeORM | Prisma |
55
+ |---------|------|----|---------|--------|
56
+ | **Pipeline Queries** | | | | |
57
+ | **Tagged Templates** | | | | ❌ |
58
+ | **Transactions** | | | | |
59
+ | **Savepoints** | ✅ | ❌ | ✅ | ❌ |
60
+ | **Bulk Insert** | ✅ | ❌ | ✅ | ✅ |
61
+ | **Prepared Statements** | ✅ | ✅ | ✅ | ✅ |
62
+ | **TypeScript** | ✅ | ✅ | ✅ | ✅ |
63
+ | **Zero Dependencies** | ✅ | ❌ | ❌ | ❌ |
64
+ | **Connection Pool** | ✅ | ✅ | ✅ | ✅ |
59
65
 
66
+ ---
60
67
 
61
- ## 📖 Feature Guide
62
68
 
63
- ### 1. Recursive Fragments (sql.fragment)
64
- Combine multiple SQL pieces. Perfect for dynamic filters or subqueries.
69
+ ## 🚀 Quick Start
65
70
 
66
71
  ```typescript
67
- const filter = sql.fragment`status = ${'active'} AND age > ${21}`
68
- const roleSub = sql.fragment`(SELECT id FROM roles WHERE name = ${'admin'})`
72
+ import { sql, Pool } from "@m2k-5f/pgtx";
69
73
 
74
+ const pool = new Pool({
75
+ host: 'localhost',
76
+ user: 'postgres',
77
+ password: 'postgres',
78
+ database: 'myapp'
79
+ })
80
+
81
+ // Type-safe query
82
+ const [user] = await pool.query<User>`SELECT * FROM users WHERE id = ${1}`
83
+
84
+ // Bulk insert
70
85
  await pool.query`
71
- INSERT INTO users (name, role_id)
72
- VALUES (${'Ivan'}, (${roleSub}))
73
- WHERE ${filter}
86
+ INSERT INTO users ${sql.insert([{ name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }])}
74
87
  `
75
- // SQL: INSERT INTO users ... VALUES ($1, (SELECT id FROM roles WHERE name = $2)) WHERE status = $3 AND age > $4
88
+
89
+ // Transaction
90
+ await pool.begin(async (tx) => {
91
+ await tx.query`UPDATE accounts SET balance = balance - 100 WHERE id = ${1}`
92
+ await tx.query`UPDATE accounts SET balance = balance + 100 WHERE id = ${2}`
93
+ })
76
94
  ```
77
95
 
78
- ### 2. Transactions
79
- Automatic BEGIN, COMMIT, and ROLLBACK. Use savepoint for nested logic.
96
+ ---
97
+
98
+ ## 📖 Features
99
+
100
+ ### Transactions & Savepoints
80
101
 
81
102
  ```typescript
82
103
  await pool.begin(async (tx) => {
83
- await tx.query`UPDATE accounts SET balance = balance - 100 WHERE id = 1`;
84
-
85
- // Nested transaction (Savepoint)
86
- let err = await tx.savepoint('inventory', async (stx) => {
87
- await stx.query`UPDATE stock SET count = count - 1 WHERE item_id = ${42}`;
88
- if (outOfStock) throw new Error(); // Only 'inventory' rolls back
89
- });
90
- if (err) {
91
- // Handle error
92
- // tx still active & can be commited
93
- }
94
- });
95
- // Main transaction commits or rolls back based on callback success
104
+ await tx.query`INSERT INTO orders (user_id) VALUES (${userId})`
105
+
106
+ // err: Error | null
107
+ const err = await tx.savepoint('update_stock', async (stx) => {
108
+ await stx.query`UPDATE stock SET count = count - 1 WHERE product_id = ${productId}`
109
+ if (outOfStock) throw new Error() // Only savepoint rolls back
110
+ })
111
+ })
96
112
  ```
97
113
 
98
- ### 3. Bulk Inserts (sql.insert)
99
- Automatically extracts columns from the first object. Supports single objects and arrays.
114
+ ### Bulk Inserts
100
115
 
101
116
  ```typescript
102
117
  const users = [
@@ -104,125 +119,207 @@ const users = [
104
119
  { name: 'Bob', email: 'bob@test.com' }
105
120
  ]
106
121
 
107
- await pool.query`INSERT INTO users ${sql.insert(users)}`
108
- // SQL: INSERT INTO users (name, email) VALUES ($1, $2), ($3, $4)
109
- ```
110
- #### 3.1 UPSERT Helper (sql.excluded)
111
- Perfect for ON CONFLICT clauses to avoid re-typing column names.
112
-
113
- ```typescript
114
122
  await pool.query`
115
- INSERT INTO users ${sql.insert(data)}
116
- ON CONFLICT (id) DO UPDATE
117
- SET ${sql.excluded(['name', 'email', 'updated_at'])}
123
+ INSERT INTO users ${sql.insert(users)}
118
124
  `
119
- // SQL: ... SET name = EXCLUDED.name, email = EXCLUDED.email, updated_at = EXCLUDED.updated_at
125
+ // INSERT INTO users (name, email) VALUES ($1, $2), ($3, $4)
120
126
  ```
121
127
 
122
- ### 4. Prepared Statements
123
- Pre-parse SQL on the database server for maximum performance in hot loops.
128
+ ### Dynamic Updates
124
129
 
125
130
  ```typescript
126
- const stmt = await pool.prepare<User, [string]>("get_user_by_email", 'SELECT * FROM users WHERE email = ?')
127
- // `Pgtx` automatically maps standard `?` placeholders to native `$1, $2` indexes.
131
+ const data = { status: 'active', last_login: new Date() }
128
132
 
129
- const users = await stmt.execute('test@example.com')
130
- // Statements created via pool.prepare are lazily initialized on each connection upon first use,
131
- // gradually "warming up" the entire pool for peak performance.
133
+ await pool.query`
134
+ UPDATE users SET ${sql.update(data)} WHERE id = ${userId}
135
+ `
136
+ // UPDATE users SET status = $1, last_login = $2 WHERE id = $3
132
137
  ```
133
138
 
134
- ### 5. Smart Lists (sql.array)
135
- The ultimate tool for dynamic lists. Works for IN clauses, column lists, or joined conditions.
139
+ ### Recursive Fragments
136
140
 
137
141
  ```typescript
138
- // 1. Classic IN clause
139
- const ids = [10, 20]
140
- await pool.query`SELECT * FROM users WHERE id IN (${sql.array(ids)})`
141
- // SQL: SELECT * FROM users WHERE id IN ($1, $2)
142
-
143
- // 2. Dynamic column list
144
- const cols = [sql.ident('id'), sql.ident('name')]
145
- await pool.query`SELECT ${sql.array(cols)} FROM users`
146
- // SQL: SELECT "id", "name" FROM users
147
-
148
- // 3. Dynamic WHERE conditions
149
- const conds = [sql.fragment`active = true`, sql.fragment`age > ${18}`]
150
- await pool.query`SELECT * FROM users WHERE ${sql.array(conds, ' AND ')}`
151
- // SQL: SELECT * FROM users WHERE active = true AND age > $1
142
+ const filter = sql.fragment`status = ${'active'} AND age > ${21}`
143
+ const subquery = sql.fragment`(SELECT id FROM roles WHERE name = ${'admin'})`
144
+
145
+ await pool.query`
146
+ SELECT * FROM users
147
+ WHERE ${filter} AND role_id = (${subquery})
148
+ `
152
149
  ```
153
150
 
154
- ### 6. Dynamic Updates (sql.update)
155
- Easily generate SET clauses from plain JavaScript objects.
151
+ ### Smart Lists
156
152
 
157
153
  ```typescript
158
- const data = { status: 'pro', last_login: new Date() }
154
+ const ids = [10, 20, 30]
155
+ await pool.query`
156
+ SELECT * FROM users WHERE id IN (${sql.array(ids)})
157
+ `
158
+ // SELECT * FROM users WHERE id IN ($1, $2, $3)
159
159
 
160
- await pool.query`UPDATE users SET ${sql.update(data)} WHERE id = ${1}`
161
- // SQL: UPDATE users SET status = $1, last_login = $2 WHERE id = $3
160
+ const conditions = [
161
+ sql.fragment`status = ${'active'}`,
162
+ sql.fragment`age > ${18}`
163
+ ]
164
+ await pool.query`
165
+ SELECT * FROM users WHERE ${sql.array(conditions, ' AND ')}
166
+ `
162
167
  ```
163
168
 
164
- ### 7. Clean Filtering (sql.where)
165
- Generates AND-separated conditions from an object. Skips undefined values for easy dynamic filtering.
169
+ ### Clean WHERE Clauses
166
170
 
167
171
  ```typescript
168
- const filters = { role: 'admin', age: undefined, active: true };
169
- await pool.query`SELECT * FROM users WHERE ${sql.where(filters)}`
170
- // SQL: SELECT * FROM users WHERE role = $1 AND active = $2
172
+ const filters = { role: 'admin', age: undefined, active: true }
173
+ await pool.query`
174
+ SELECT * FROM users WHERE ${sql.where(filters)}
175
+ `
176
+ // SELECT * FROM users WHERE role = $1 AND active = $2
171
177
  ```
172
178
 
173
- ### 8. Conditional Logic (sql.empty)
174
- A safe "no-op" fragment for cleaner ternary operations in templates.
179
+ ### Conditional Logic
175
180
 
176
181
  ```typescript
177
- const search = "";
182
+ const search = ""
178
183
  await pool.query`
179
184
  SELECT * FROM posts
180
185
  ${search ? sql.fragment`WHERE title ILIKE ${search}` : sql.empty}
181
186
  `
182
- // Result if empty: SELECT * FROM posts
183
187
  ```
188
+
184
189
  ---
185
190
 
186
- ## 🔄 Null & Undefined Handling
191
+ ## 🛡️ Security
192
+
193
+ | Pattern | Protection |
194
+ |---------|------------|
195
+ | `sql.ident(name)` | Escapes identifiers: `user` → `"user"` |
196
+ | `sql.literal(value)` | Escapes string literals |
197
+ | Parameter binding | Uses native `$1, $2` placeholders |
198
+ | Template tags | Cannot be injected via user input |
199
+
200
+ ```typescript
201
+ // ✅ Safe - parameterized
202
+ await pool.query`SELECT * FROM users WHERE name = ${userInput}`
203
+
204
+ // ⚠️ Unsafe - raw interpolation (DON'T DO THIS)
205
+ await pool.query(`SELECT * FROM users WHERE name = '${userInput}'`)
187
206
 
188
- Pgtx treats `null` and `undefined` differently to match SQL semantics and JavaScript expectations:
207
+ // Safe - identifiers
208
+ await pool.query`SELECT * FROM ${sql.ident(tableName)}`
209
+ ```
210
+
211
+ ---
189
212
 
190
- | Value | In INSERT | In UPDATE | In VALUES/Parameters | In Arrays |
191
- |-------|-----------|-----------|----------------------|-----------|
213
+ ## 📊 Null & Undefined Handling
214
+
215
+ | Value | In INSERT | In UPDATE | In VALUES | In Arrays |
216
+ |-------|-----------|-----------|-----------|-----------|
192
217
  | `null` | `NULL` | `NULL` | `NULL` | `NULL` |
193
- | `undefined` | `DEFAULT` | Field skipped | Error | Error |
218
+ | `undefined` | `DEFAULT` | Skipped | `Error` | `Error` |
194
219
 
195
- ### Examples
196
220
 
197
221
  ```typescript
198
- // INSERT: undefined becomes DEFAULT
222
+ // undefined becomes DEFAULT
199
223
  await pool.query`
200
224
  INSERT INTO users ${sql.insert({
201
225
  name: 'Alice',
202
- age: undefined, // -> DEFAULT
203
- email: null // -> NULL
226
+ age: undefined, // DEFAULT
227
+ email: null // NULL
204
228
  })}
205
229
  `
206
- // SQL: INSERT INTO users (name, age, email) VALUES ($1, DEFAULT, $2)
230
+ // INSERT INTO users (name, age, email) VALUES ($1, DEFAULT, $2)
207
231
 
208
- // UPDATE: undefined fields are skipped
232
+ // undefined fields are skipped in UPDATE
209
233
  await pool.query`
210
234
  UPDATE users SET ${sql.update({
211
235
  name: 'Bob',
212
- age: undefined, // skipped - age remains unchanged
213
- deleted_at: null // explicitly set to NULL
236
+ age: undefined // Skipped - age remains unchanged
214
237
  })} WHERE id = 1
215
238
  `
216
- // SQL: UPDATE users SET name = $1, deleted_at = $2 WHERE id = 1
239
+ // UPDATE users SET name = $1 WHERE id = 1
240
+ ```
217
241
 
218
- // Arrays: undefined throw
219
- sql.array([1, undefined, 3]) // ❌ TypeError(`Array item at index 1 is undefined`)
242
+ ---
243
+
244
+ ## 🔧 API Reference
220
245
 
221
- // Empty arrays throw (use [null] for NULL result)
222
- sql.array([]) // ❌ Error: Array clause is empty. Use sql.array([null])...
246
+ ### Connection
247
+ ```typescript
248
+ class Connection {
249
+ static new(params: ConnectionParams): Promise<Connection>
250
+
251
+ query<T>(strings: TemplateStringsArray, ...values: any[]): Promise<T[]>
252
+ begin<T>(callback: (tx: Transaction) => Promise<T>): Promise<T>
253
+
254
+ get isAlive(): boolean
255
+ close(): void
256
+ }
257
+
258
+ interface ConnectionParams {
259
+ user: string
260
+ password?: string
261
+ host: string
262
+ port: number
263
+ database: string
264
+ logLevel?: 'none' | 'error' | 'notice' | 'query' // defaul: "error"
265
+ }
223
266
  ```
224
267
 
225
- ## 🛡️ Security
226
- * **SQL Injection**: Automatically uses native placeholders ($1, $2) for all values.
227
- * **Identifiers**: `sql.ident` escapes names (e.g., user -> "user") to prevent conflicts with SQL keywords and identifier injection.
228
- * **Connection Leaks**: `pool.begin` and `pool.query` use `try...finally` internally. Prepared statements created via Pool also automatically release connections.
268
+ ### Pool
269
+
270
+ ```typescript
271
+ class Pool {
272
+ constructor(config: PoolConfig)
273
+
274
+ query<T>(strings: TemplateStringsArray, ...values: any[]): Promise<T[]>
275
+ begin<T>(callback: (tx: Transaction) => Promise<T>): Promise<T>
276
+ acquire(): Promise<Connection>
277
+ release(conn: Connection): void
278
+ close(): Promise<void>
279
+
280
+ get size(): number
281
+ get total(): number
282
+ }
283
+
284
+ interface PoolConfig extends ConnectionParams {
285
+ max?: number
286
+ }
287
+ ```
288
+
289
+ ### Transaction
290
+
291
+ ```typescript
292
+ class Transaction {
293
+ query<T>(strings: TemplateStringsArray, ...values: any[]): Promise<T[]>
294
+ commit(): Promise<void>
295
+ rollback(): Promise<void>
296
+ savepoint<T>(name: string, callback: (tx: Transaction) => Promise<T>): Promise<T>
297
+
298
+ get isActive(): boolean
299
+ }
300
+ ```
301
+
302
+ ### **sql** helper
303
+ ```typescript
304
+ const sql: {
305
+ ident<T extends string>(identificator: T): IdentifierClause<T>
306
+ literal<T extends string>(value: T): LiteralClause<T>
307
+ fragment(strings: TemplateStringsArray, ...values: any[]): FragmentClause
308
+ insert<T extends Record<string, any>>(...objects: NoInfer<T>[]): InsertClause<T>
309
+ update<T extends Record<string, any>>(object: T): UpdateClause<T>
310
+ where<T extends Record<string, any>>(whereMap: T): WhereClause<T>
311
+ excluded(fields: string[]): ExcludeUpdateClause
312
+ array(array: any[], separator?: string): ArrayClause
313
+ empty: EmptyClause
314
+ }
315
+ ```
316
+
317
+ ---
318
+
319
+ ## 📝 License
320
+
321
+ MIT © [M2K-5F](https://github.com/M2K-5F)
322
+
323
+ ---
324
+
325
+ **Made with ❤️ and a bit of insanity**
@@ -25,7 +25,7 @@ class ArrayClause extends abstract_clause_1.Clause {
25
25
  }
26
26
  else {
27
27
  params.args.push(value);
28
- params.text.push(`$${params.counter++}`);
28
+ params.text.push(`$${params.args.length}`);
29
29
  }
30
30
  });
31
31
  }
@@ -1,7 +1,7 @@
1
1
  import { ClauseStrategyParams } from "../types";
2
2
  import { Clause } from "./abstract.clause";
3
3
  export declare class EmptyClause extends Clause {
4
- static new(): EmptyClause;
4
+ static create(): EmptyClause;
5
5
  mapIntoQuery(params: ClauseStrategyParams): void;
6
6
  }
7
7
  export declare const emptyClause: EmptyClause;
@@ -1 +1 @@
1
- {"version":3,"file":"empty.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/empty.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG3C,qBAAa,WAAY,SAAQ,MAAM;IACnC,MAAM,CAAC,GAAG;IAIV,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAC5C;AAED,eAAO,MAAM,WAAW,aAAoB,CAAA"}
1
+ {"version":3,"file":"empty.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/empty.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG3C,qBAAa,WAAY,SAAQ,MAAM;IACnC,MAAM,CAAC,MAAM;IAIb,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAC5C;AAED,eAAO,MAAM,WAAW,aAAuB,CAAA"}
@@ -3,10 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.emptyClause = exports.EmptyClause = void 0;
4
4
  const abstract_clause_1 = require("./abstract.clause");
5
5
  class EmptyClause extends abstract_clause_1.Clause {
6
- static new() {
6
+ static create() {
7
7
  return new EmptyClause();
8
8
  }
9
9
  mapIntoQuery(params) { }
10
10
  }
11
11
  exports.EmptyClause = EmptyClause;
12
- exports.emptyClause = EmptyClause.new();
12
+ exports.emptyClause = EmptyClause.create();
@@ -3,7 +3,7 @@ import { ClauseStrategyParams } from "../types";
3
3
  export declare class FragmentClause extends Clause {
4
4
  readonly templates: TemplateStringsArray;
5
5
  readonly args: any[];
6
- constructor(templates: TemplateStringsArray, args: any[]);
6
+ private constructor();
7
7
  static create(strings: TemplateStringsArray, ...values: any[]): FragmentClause;
8
8
  mapIntoQuery(params: ClauseStrategyParams): void;
9
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fragment.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/fragment.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAI,MAAM,mBAAmB,CAAC;AAE7C,OAAO,EAAE,oBAAoB,EAAoB,MAAM,UAAU,CAAC;AAElE,qBAAa,cAAe,SAAQ,MAAM;IAElC,QAAQ,CAAC,SAAS,EAAE,oBAAoB;IACxC,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE;gBADX,SAAS,EAAE,oBAAoB,EAC/B,IAAI,EAAE,GAAG,EAAE;IAGxB,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IAIpD,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAWrD"}
1
+ {"version":3,"file":"fragment.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/fragment.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAI,MAAM,mBAAmB,CAAC;AAE7C,OAAO,EAAE,oBAAoB,EAAoB,MAAM,UAAU,CAAC;AAElE,qBAAa,cAAe,SAAQ,MAAM;IAElC,QAAQ,CAAC,SAAS,EAAE,oBAAoB;IACxC,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE;IAFxB,OAAO;IAKP,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IAIpD,YAAY,CAAC,MAAM,EAAE,oBAAoB;CASrD"}
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FragmentClause = void 0;
4
4
  const abstract_clause_1 = require("./abstract.clause");
5
- const utils_1 = require("../utils");
5
+ const template_compiler_1 = require("../utils/template-compiler");
6
6
  class FragmentClause extends abstract_clause_1.Clause {
7
7
  constructor(templates, args) {
8
8
  super();
@@ -13,12 +13,10 @@ class FragmentClause extends abstract_clause_1.Clause {
13
13
  return new FragmentClause(strings, values);
14
14
  }
15
15
  mapIntoQuery(params) {
16
- const compiled = (0, utils_1.compileSqlTemplate)({
16
+ const compiled = (0, template_compiler_1.compileSqlTemplate)({
17
17
  args: this.args,
18
- counter: params.counter,
19
18
  templates: this.templates
20
- });
21
- params.counter = compiled.counter;
19
+ }, params.args.length);
22
20
  params.args.push(...compiled.args);
23
21
  params.text.push(compiled.text);
24
22
  }
@@ -2,7 +2,7 @@ import { ClauseStrategyParams } from "../types";
2
2
  import { Clause } from "./abstract.clause";
3
3
  export declare class IdentifierClause<T extends string> extends Clause {
4
4
  readonly value: T;
5
- constructor(value: T);
5
+ private constructor();
6
6
  static create<T extends string>(identificator: T): IdentifierClause<T>;
7
7
  mapIntoQuery(params: ClauseStrategyParams): void;
8
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"iden.caluse.d.ts","sourceRoot":"","sources":["../../src/clauses/iden.caluse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAE1C,qBAAa,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,MAAM;IAEtD,QAAQ,CAAC,KAAK,EAAE,CAAC;gBAAR,KAAK,EAAE,CAAC;IAGrB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,aAAa,EAAE,CAAC;IAMvC,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAGrD"}
1
+ {"version":3,"file":"iden.caluse.d.ts","sourceRoot":"","sources":["../../src/clauses/iden.caluse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAE1C,qBAAa,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,MAAM;IAEtD,QAAQ,CAAC,KAAK,EAAE,CAAC;IADrB,OAAO;IAIP,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,aAAa,EAAE,CAAC;IAMvC,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAGrD"}
@@ -0,0 +1,10 @@
1
+ export * from './array.clause';
2
+ export * from './empty.clause';
3
+ export * from './exclude.clause';
4
+ export * from './fragment.clause';
5
+ export * from './iden.caluse';
6
+ export * from './insert.clause';
7
+ export * from './literal.clause';
8
+ export * from './update.clause';
9
+ export * from './where.clause';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/clauses/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./array.clause"), exports);
18
+ __exportStar(require("./empty.clause"), exports);
19
+ __exportStar(require("./exclude.clause"), exports);
20
+ __exportStar(require("./fragment.clause"), exports);
21
+ __exportStar(require("./iden.caluse"), exports);
22
+ __exportStar(require("./insert.clause"), exports);
23
+ __exportStar(require("./literal.clause"), exports);
24
+ __exportStar(require("./update.clause"), exports);
25
+ __exportStar(require("./where.clause"), exports);
@@ -2,7 +2,7 @@ import { Clause } from "./abstract.clause";
2
2
  import { ClauseStrategyParams } from "../types";
3
3
  export declare class InsertClause<T extends Record<string, any>> extends Clause {
4
4
  readonly inserts: T[];
5
- constructor(inserts: T[]);
5
+ private constructor();
6
6
  static create<T extends Record<string, any>>(...objects: NoInfer<T>[]): InsertClause<T>;
7
7
  mapIntoQuery(params: ClauseStrategyParams): void;
8
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"insert.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/insert.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAEhD,qBAAa,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAE,SAAQ,MAAM;IAE/D,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE;gBAAZ,OAAO,EAAE,CAAC,EAAE;IAGzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE;IAO5D,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAyBrD"}
1
+ {"version":3,"file":"insert.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/insert.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAEhD,qBAAa,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAE,SAAQ,MAAM;IAE/D,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE;IADzB,OAAO;IAIP,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE;IAO5D,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAyBrD"}
@@ -27,7 +27,7 @@ class InsertClause extends abstract_clause_1.Clause {
27
27
  if (value === undefined)
28
28
  return "DEFAULT";
29
29
  params.args.push(value);
30
- return `$${params.counter++}`;
30
+ return `$${params.args.length}`;
31
31
  })
32
32
  .join(", ")})`);
33
33
  });
@@ -2,7 +2,7 @@ import { ClauseStrategyParams } from "../types";
2
2
  import { Clause } from "./abstract.clause";
3
3
  export declare class LiteralClause<T extends string> extends Clause {
4
4
  readonly value: T;
5
- constructor(value: T);
5
+ private constructor();
6
6
  static create<T extends string>(value: T): LiteralClause<T>;
7
7
  mapIntoQuery(params: ClauseStrategyParams): void;
8
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"literal.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/literal.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,MAAM,EAAC,MAAM,mBAAmB,CAAC;AAE1C,qBAAa,aAAa,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,MAAM;IAEnD,QAAQ,CAAC,KAAK,EAAE,CAAC;gBAAR,KAAK,EAAE,CAAC;IAKrB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;IAQlD,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAGrD"}
1
+ {"version":3,"file":"literal.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/literal.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,MAAM,EAAC,MAAM,mBAAmB,CAAC;AAE1C,qBAAa,aAAa,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,MAAM;IAEnD,QAAQ,CAAC,KAAK,EAAE,CAAC;IADrB,OAAO;IAMP,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;IAQlD,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAGrD"}
@@ -2,7 +2,7 @@ import { ClauseStrategyParams } from "../types";
2
2
  import { Clause } from "./abstract.clause";
3
3
  export declare class UpdateClause<T extends Record<string, any>> extends Clause {
4
4
  readonly updateMap: T;
5
- constructor(updateMap: T);
5
+ private constructor();
6
6
  static create<T extends Record<string, any>>(object: T): UpdateClause<T>;
7
7
  mapIntoQuery(params: ClauseStrategyParams): void;
8
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"update.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/update.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,qBAAa,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAE,SAAQ,MAAM;IAE/D,QAAQ,CAAC,SAAS,EAAE,CAAC;gBAAZ,SAAS,EAAE,CAAC;IAGzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IAI7C,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAarD"}
1
+ {"version":3,"file":"update.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/update.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,qBAAa,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAE,SAAQ,MAAM;IAE/D,QAAQ,CAAC,SAAS,EAAE,CAAC;IADzB,OAAO;IAIP,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IAI7C,YAAY,CAAC,MAAM,EAAE,oBAAoB;CAarD"}