@m2k-5f/pgtx 1.0.5 → 1.2.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 +46 -4
- package/dist/clauses/array.clause.d.ts.map +1 -1
- package/dist/clauses/array.clause.js +5 -2
- package/dist/clauses/iden.caluse.d.ts.map +1 -1
- package/dist/clauses/iden.caluse.js +3 -0
- package/dist/clauses/insert.clause.d.ts +9 -0
- package/dist/clauses/insert.clause.d.ts.map +1 -0
- package/dist/clauses/insert.clause.js +39 -0
- package/dist/clauses/literal.clause.d.ts +9 -0
- package/dist/clauses/literal.clause.d.ts.map +1 -0
- package/dist/clauses/literal.clause.js +21 -0
- package/dist/clauses/static.clause.d.ts.map +1 -1
- package/dist/clauses/static.clause.js +3 -0
- package/dist/clauses/update.clause.d.ts +2 -3
- package/dist/clauses/update.clause.d.ts.map +1 -1
- package/dist/clauses/update.clause.js +9 -9
- package/dist/connection.d.ts +1 -1
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/transaction.d.ts +1 -1
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +2 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ Experience ORM-like convenience (auto-inserts, updates, recursive fragments) wit
|
|
|
7
7
|
|
|
8
8
|
## 🔥 Why Pgtx?
|
|
9
9
|
|
|
10
|
-
* **Zero-Cost Abstraction**: Only ~2% overhead compared to raw `pg.query`.
|
|
10
|
+
* **Zero-Cost Abstraction**: Only ~2% - 0% overhead compared to raw `pg.query`.
|
|
11
11
|
* **Structural Caching**: Uses `WeakMap` to cache SQL templates. Static parts are parsed only once.
|
|
12
12
|
* **Explicit Prepared Statements**: Create and reuse prepared statements with type safety
|
|
13
13
|
* **True Recursion**: Nest `sql.fragment` anywhere. Argument numbering ($1, $2) is managed automatically across all nesting levels.
|
|
@@ -46,8 +46,8 @@ The following results were measured during sequential execution of 10,000 comple
|
|
|
46
46
|
|
|
47
47
|
| Tool | RPS | Avg. Query Time | Performance Overhead |
|
|
48
48
|
| :--- | :---: | :---: | :---: |
|
|
49
|
-
| **Native `pg.query`** | **~
|
|
50
|
-
| **Pgtx** | **~
|
|
49
|
+
| **Native `pg.query`** | **~176** | **5.696 ms** | **0% (Baseline)** |
|
|
50
|
+
| **Pgtx** | **~177** | **5.664 ms** | **-0.56%(zero-cost)** |
|
|
51
51
|
| Typical Node.js ORM | **~58** | 12.5+ ms | > 150% |
|
|
52
52
|
|
|
53
53
|
|
|
@@ -76,10 +76,14 @@ await pool.begin(async (tx) => {
|
|
|
76
76
|
await tx.query`UPDATE accounts SET balance = balance - 100 WHERE id = 1`;
|
|
77
77
|
|
|
78
78
|
// Nested transaction (Savepoint)
|
|
79
|
-
await tx.savepoint('inventory', async (stx) => {
|
|
79
|
+
let err = await tx.savepoint('inventory', async (stx) => {
|
|
80
80
|
await stx.query`UPDATE stock SET count = count - 1 WHERE item_id = ${42}`;
|
|
81
81
|
if (outOfStock) throw new Error(); // Only 'inventory' rolls back
|
|
82
82
|
});
|
|
83
|
+
if (err) {
|
|
84
|
+
// Handle error
|
|
85
|
+
// tx still active & can be commited
|
|
86
|
+
}
|
|
83
87
|
});
|
|
84
88
|
// Main transaction commits or rolls back based on callback success
|
|
85
89
|
```
|
|
@@ -139,6 +143,44 @@ await pool.query`UPDATE users SET ${sql.update(data)} WHERE id = ${1}`
|
|
|
139
143
|
// SQL: UPDATE users SET status = $1, last_login = $2 WHERE id = $3
|
|
140
144
|
```
|
|
141
145
|
|
|
146
|
+
## 🔄 Null & Undefined Handling
|
|
147
|
+
|
|
148
|
+
Pgtx treats `null` and `undefined` differently to match SQL semantics and JavaScript expectations:
|
|
149
|
+
|
|
150
|
+
| Value | In INSERT | In UPDATE | In VALUES/Parameters | In Arrays |
|
|
151
|
+
|-------|-----------|-----------|----------------------|-----------|
|
|
152
|
+
| `null` | `NULL` | `NULL` | `NULL` | `NULL` |
|
|
153
|
+
| `undefined` | `DEFAULT` | Field skipped | Error | Error |
|
|
154
|
+
|
|
155
|
+
### Examples
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
// INSERT: undefined becomes DEFAULT
|
|
159
|
+
await pool.query`
|
|
160
|
+
INSERT INTO users ${sql.insert({
|
|
161
|
+
name: 'Alice',
|
|
162
|
+
age: undefined, // -> DEFAULT
|
|
163
|
+
email: null // -> NULL
|
|
164
|
+
})}
|
|
165
|
+
`
|
|
166
|
+
// SQL: INSERT INTO users (name, age, email) VALUES ($1, DEFAULT, $2)
|
|
167
|
+
|
|
168
|
+
// UPDATE: undefined fields are skipped
|
|
169
|
+
await pool.query`
|
|
170
|
+
UPDATE users SET ${sql.update({
|
|
171
|
+
name: 'Bob',
|
|
172
|
+
age: undefined, // skipped - age remains unchanged
|
|
173
|
+
deleted_at: null // explicitly set to NULL
|
|
174
|
+
})} WHERE id = 1
|
|
175
|
+
`
|
|
176
|
+
// SQL: UPDATE users SET name = $1, deleted_at = $2 WHERE id = 1
|
|
177
|
+
|
|
178
|
+
// Arrays: undefined throw
|
|
179
|
+
sql.array([1, undefined, 3]) // ❌ TypeError(`Array item at index 1 is undefined`)
|
|
180
|
+
|
|
181
|
+
// Empty arrays throw (use [null] for NULL result)
|
|
182
|
+
sql.array([]) // ❌ Error: Array clause is empty. Use sql.array([null])...
|
|
183
|
+
```
|
|
142
184
|
|
|
143
185
|
## 🛡️ Security
|
|
144
186
|
* **SQL Injection**: Automatically uses native placeholders ($1, $2) for all values.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/array.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,qBAAa,WAAY,SAAQ,MAAM;IAE/B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,KAAK,EAAE,GAAG,EAAE,EACZ,SAAS,GAAE,MAAa;IAGpC,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB;
|
|
1
|
+
{"version":3,"file":"array.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/array.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,qBAAa,WAAY,SAAQ,MAAM;IAE/B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,KAAK,EAAE,GAAG,EAAE,EACZ,SAAS,GAAE,MAAa;IAGpC,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB;CAyBrD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,SAAS,GAAE,MAAa,GAAG,WAAW,CAE/E"}
|
|
@@ -11,9 +11,12 @@ class ArrayClause extends base_clause_1.Clause {
|
|
|
11
11
|
}
|
|
12
12
|
map(argCounter) {
|
|
13
13
|
if (this.array.length === 0)
|
|
14
|
-
|
|
14
|
+
throw new Error('Array clause is empty.\n Use sql.array([null]) if you want no results, or check your data.');
|
|
15
15
|
const args = [];
|
|
16
|
-
const text = `${this.array.map(value => {
|
|
16
|
+
const text = `${this.array.map((value, index) => {
|
|
17
|
+
if (value === undefined) {
|
|
18
|
+
throw new TypeError(`Array item at index ${index} is undefined`);
|
|
19
|
+
}
|
|
17
20
|
if (value instanceof base_clause_1.Clause) {
|
|
18
21
|
const result = value.map(argCounter);
|
|
19
22
|
args.push(...result.args);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iden.caluse.d.ts","sourceRoot":"","sources":["../../src/clauses/iden.caluse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,qBAAa,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,MAAM;IAEtD,QAAQ,CAAC,KAAK,EAAE,CAAC;gBAAR,KAAK,EAAE,CAAC;IAGZ,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB;
|
|
1
|
+
{"version":3,"file":"iden.caluse.d.ts","sourceRoot":"","sources":["../../src/clauses/iden.caluse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,qBAAa,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,MAAM;IAEtD,QAAQ,CAAC,KAAK,EAAE,CAAC;gBAAR,KAAK,EAAE,CAAC;IAGZ,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB;CASrD;AAED,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,aAAa,EAAE,CAAC,uBAE7D"}
|
|
@@ -9,6 +9,9 @@ class IdentifierClause extends base_clause_1.Clause {
|
|
|
9
9
|
this.value = value;
|
|
10
10
|
}
|
|
11
11
|
map(argCounter) {
|
|
12
|
+
if (this.value === undefined) {
|
|
13
|
+
throw new TypeError(`Query parameter undefined at position ${argCounter}`);
|
|
14
|
+
}
|
|
12
15
|
const text = `"${this.value}"`;
|
|
13
16
|
const args = [];
|
|
14
17
|
return { text, args, argCounter };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Clause } from "./base.clause";
|
|
2
|
+
import { CompiledSqlQuery } from "../utils";
|
|
3
|
+
export declare class InsertClause<T extends Record<string, any>> extends Clause {
|
|
4
|
+
readonly inserts: T[];
|
|
5
|
+
constructor(inserts: T[]);
|
|
6
|
+
map(argCounter: number): CompiledSqlQuery;
|
|
7
|
+
}
|
|
8
|
+
export declare function insertClause<T extends Record<string, any>>(...objects: NoInfer<T>[]): InsertClause<T>;
|
|
9
|
+
//# sourceMappingURL=insert.clause.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insert.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/insert.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,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;IAGhB,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB;CAgCrD;AAED,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,mBAEnF"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InsertClause = void 0;
|
|
4
|
+
exports.insertClause = insertClause;
|
|
5
|
+
const base_clause_1 = require("./base.clause");
|
|
6
|
+
class InsertClause extends base_clause_1.Clause {
|
|
7
|
+
constructor(inserts) {
|
|
8
|
+
super();
|
|
9
|
+
this.inserts = inserts;
|
|
10
|
+
}
|
|
11
|
+
map(argCounter) {
|
|
12
|
+
if (this.inserts.length === 0) {
|
|
13
|
+
throw new Error('Insert clause has no rows to insert.\n' +
|
|
14
|
+
'Provide at least one object with data.');
|
|
15
|
+
}
|
|
16
|
+
const columns = Object.keys(this.inserts[0]);
|
|
17
|
+
const columnsCount = columns.length;
|
|
18
|
+
let text = `(${columns.join(', ')}) VALUES `;
|
|
19
|
+
let args = [];
|
|
20
|
+
const valuesText = this.inserts.map(values => {
|
|
21
|
+
if (Object.keys(values).length !== columnsCount)
|
|
22
|
+
throw new Error(`
|
|
23
|
+
all rows must have the same columns
|
|
24
|
+
`);
|
|
25
|
+
return `(${Object.values(values).map(value => {
|
|
26
|
+
if (value === undefined)
|
|
27
|
+
return "DEFAULT";
|
|
28
|
+
args.push(value);
|
|
29
|
+
return `$${argCounter++}`;
|
|
30
|
+
}).join(", ")})`;
|
|
31
|
+
}).join(", ");
|
|
32
|
+
text += valuesText;
|
|
33
|
+
return { text, args, argCounter };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.InsertClause = InsertClause;
|
|
37
|
+
function insertClause(...objects) {
|
|
38
|
+
return new InsertClause(objects);
|
|
39
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Clause } from "./base.clause";
|
|
2
|
+
import { CompiledSqlQuery } from "../utils";
|
|
3
|
+
export declare class LiteralClause<T extends string> extends Clause {
|
|
4
|
+
readonly value: T;
|
|
5
|
+
constructor(value: T);
|
|
6
|
+
map(argCounter: number): CompiledSqlQuery;
|
|
7
|
+
}
|
|
8
|
+
export declare function literalClause<T extends string>(value: T): LiteralClause<T>;
|
|
9
|
+
//# sourceMappingURL=literal.clause.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"literal.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/literal.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,qBAAa,aAAa,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,MAAM;IAEnD,QAAQ,CAAC,KAAK,EAAE,CAAC;gBAAR,KAAK,EAAE,CAAC;IAKZ,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB;CAMrD;AAGD,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAE1E"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LiteralClause = void 0;
|
|
4
|
+
exports.literalClause = literalClause;
|
|
5
|
+
const base_clause_1 = require("./base.clause");
|
|
6
|
+
class LiteralClause extends base_clause_1.Clause {
|
|
7
|
+
constructor(value) {
|
|
8
|
+
super();
|
|
9
|
+
this.value = value;
|
|
10
|
+
}
|
|
11
|
+
map(argCounter) {
|
|
12
|
+
if (this.value === undefined) {
|
|
13
|
+
throw new TypeError(`Query parameter undefined at position ${argCounter}`);
|
|
14
|
+
}
|
|
15
|
+
return { text: this.value, args: [], argCounter };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.LiteralClause = LiteralClause;
|
|
19
|
+
function literalClause(value) {
|
|
20
|
+
return new LiteralClause(value);
|
|
21
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/static.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,qBAAa,YAAY,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,MAAM;IAElD,QAAQ,CAAC,KAAK,EAAE,CAAC;gBAAR,KAAK,EAAE,CAAC;IAKZ,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB;
|
|
1
|
+
{"version":3,"file":"static.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/static.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,qBAAa,YAAY,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,MAAM;IAElD,QAAQ,CAAC,KAAK,EAAE,CAAC;gBAAR,KAAK,EAAE,CAAC;IAKZ,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB;CAMrD;AAGD,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAExE"}
|
|
@@ -9,6 +9,9 @@ class StaticClause extends base_clause_1.Clause {
|
|
|
9
9
|
this.value = value;
|
|
10
10
|
}
|
|
11
11
|
map(argCounter) {
|
|
12
|
+
if (this.value === undefined) {
|
|
13
|
+
throw new TypeError(`Query parameter undefined at position ${argCounter}`);
|
|
14
|
+
}
|
|
12
15
|
return { text: this.value, args: [], argCounter };
|
|
13
16
|
}
|
|
14
17
|
}
|
|
@@ -2,9 +2,8 @@ import { Clause } from "./base.clause";
|
|
|
2
2
|
import { CompiledSqlQuery } from "../utils";
|
|
3
3
|
export declare class UpdateClause<T extends Record<string, any>> extends Clause {
|
|
4
4
|
readonly updateMap: T;
|
|
5
|
-
|
|
6
|
-
constructor(updateMap: T, columns?: (keyof T)[] | undefined);
|
|
5
|
+
constructor(updateMap: T);
|
|
7
6
|
map(argCounter: number): CompiledSqlQuery;
|
|
8
7
|
}
|
|
9
|
-
export declare function updateClause<T extends Record<string, any>>(object: T
|
|
8
|
+
export declare function updateClause<T extends Record<string, any>>(object: T): UpdateClause<T>;
|
|
10
9
|
//# sourceMappingURL=update.clause.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/update.clause.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"update.clause.d.ts","sourceRoot":"","sources":["../../src/clauses/update.clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,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;IAGhB,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB;CAcrD;AAED,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,mBAEpE"}
|
|
@@ -4,23 +4,23 @@ exports.UpdateClause = void 0;
|
|
|
4
4
|
exports.updateClause = updateClause;
|
|
5
5
|
const base_clause_1 = require("./base.clause");
|
|
6
6
|
class UpdateClause extends base_clause_1.Clause {
|
|
7
|
-
constructor(updateMap
|
|
7
|
+
constructor(updateMap) {
|
|
8
8
|
super();
|
|
9
9
|
this.updateMap = updateMap;
|
|
10
|
-
this.columns = columns;
|
|
11
10
|
}
|
|
12
11
|
map(argCounter) {
|
|
13
|
-
const columns = this.columns || Object.keys(this.updateMap);
|
|
14
12
|
const args = [];
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
const entries = Object.entries(this.updateMap).filter(([_, value]) => value !== undefined);
|
|
14
|
+
if (entries.length === 0)
|
|
15
|
+
throw new Error('Update clause has no data to update. All values are `undefined`');
|
|
16
|
+
const text = entries.map(([key, value]) => {
|
|
17
|
+
args.push(value);
|
|
18
|
+
return `${key} = $${argCounter++}`;
|
|
19
19
|
}).join(', ');
|
|
20
20
|
return { text, args, argCounter };
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
exports.UpdateClause = UpdateClause;
|
|
24
|
-
function updateClause(object
|
|
25
|
-
return new UpdateClause(object
|
|
24
|
+
function updateClause(object) {
|
|
25
|
+
return new UpdateClause(object);
|
|
26
26
|
}
|
package/dist/connection.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ export declare class Connection {
|
|
|
26
26
|
* Releases the connection back to the pool.
|
|
27
27
|
* The connection cannot be used after this call.
|
|
28
28
|
*/
|
|
29
|
-
release(): void
|
|
29
|
+
release(): Promise<void>;
|
|
30
30
|
private checkActive;
|
|
31
31
|
/**
|
|
32
32
|
* Executes a tagged SQL query using structural caching.
|
package/dist/connection.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,IAAI,CAAA;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAK3C;;;GAGG;AACH,qBAAa,UAAU;IAIf,OAAO,CAAC,QAAQ,CAAC,MAAM;IAH3B,OAAO,CAAC,UAAU,CAAiB;gBAGd,MAAM,EAAE,UAAU;IAGvC;;OAEG;IACH,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAED;;;;;;;OAOG;IACU,OAAO,CAAC,OAAO,SAAS,cAAc,GAAG,GAAG,EAAE,OAAO,SAAS,GAAG,EAAE,GAAG,GAAG,EAAE,EACpF,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GACpB,OAAO,CAAC,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAoB/C;;;OAGG;
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,IAAI,CAAA;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAK3C;;;GAGG;AACH,qBAAa,UAAU;IAIf,OAAO,CAAC,QAAQ,CAAC,MAAM;IAH3B,OAAO,CAAC,UAAU,CAAiB;gBAGd,MAAM,EAAE,UAAU;IAGvC;;OAEG;IACH,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAED;;;;;;;OAOG;IACU,OAAO,CAAC,OAAO,SAAS,cAAc,GAAG,GAAG,EAAE,OAAO,SAAS,GAAG,EAAE,GAAG,GAAG,EAAE,EACpF,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GACpB,OAAO,CAAC,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAoB/C;;;OAGG;IACU,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAMrC,OAAO,CAAC,WAAW;IAMnB;;;;;;OAMG;IACU,KAAK,CAAC,CAAC,SAAS,cAAc,GAAG,GAAG,EAAE,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAUjH;;;;;;;;OAQG;IACU,KAAK,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAmB/E"}
|
package/dist/connection.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -2,9 +2,9 @@ import { arrayClause } from "./clauses/array.clause";
|
|
|
2
2
|
import { fragmentClause } from "./clauses/fragment.clause";
|
|
3
3
|
import { identClause } from "./clauses/iden.caluse";
|
|
4
4
|
import { Pool as PgtxPool } from "./pool";
|
|
5
|
-
import {
|
|
5
|
+
import { literalClause } from "./clauses/literal.clause";
|
|
6
6
|
import { updateClause } from "./clauses/update.clause";
|
|
7
|
-
import {
|
|
7
|
+
import { insertClause } from "./clauses/insert.clause";
|
|
8
8
|
/**
|
|
9
9
|
* Core SQL tagging utility for Pgtx.
|
|
10
10
|
* Provides type-safe helpers for building dynamic queries with recursive support.
|
|
@@ -22,7 +22,7 @@ export declare const sql: {
|
|
|
22
22
|
* sql.insert([{ id: 1 }, { id: 2 }])
|
|
23
23
|
* // Result: (id) VALUES ($1), ($2)
|
|
24
24
|
*/
|
|
25
|
-
insert: typeof
|
|
25
|
+
insert: typeof insertClause;
|
|
26
26
|
/**
|
|
27
27
|
* Generates a SET clause for UPDATE queries from a JavaScript object.
|
|
28
28
|
*
|
|
@@ -51,7 +51,7 @@ export declare const sql: {
|
|
|
51
51
|
* sql.literal('DESC')
|
|
52
52
|
* // Result: DESC
|
|
53
53
|
*/
|
|
54
|
-
literal: typeof
|
|
54
|
+
literal: typeof literalClause;
|
|
55
55
|
/**
|
|
56
56
|
* Creates a reusable, recursive SQL fragment.
|
|
57
57
|
* Fragments can be nested within each other; argument numbering is handled automatically.
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD;;;GAGG;AACH,eAAO,MAAM,GAAG;IACZ;;;;;;;;;;;OAWG;;IAGH;;;;;;OAMG;;IAGH;;;;;;;;;;OAUG;;IAGH;;;;;;;OAOG;;IAGH;;;;;;;;OAQG;;IAGH;;;;;;;;;;;;;;;;;;;OAmBG;;CAEN,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,IAAI,iBAAW,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -5,9 +5,9 @@ const array_clause_1 = require("./clauses/array.clause");
|
|
|
5
5
|
const fragment_clause_1 = require("./clauses/fragment.clause");
|
|
6
6
|
const iden_caluse_1 = require("./clauses/iden.caluse");
|
|
7
7
|
const pool_1 = require("./pool");
|
|
8
|
-
const
|
|
8
|
+
const literal_clause_1 = require("./clauses/literal.clause");
|
|
9
9
|
const update_clause_1 = require("./clauses/update.clause");
|
|
10
|
-
const
|
|
10
|
+
const insert_clause_1 = require("./clauses/insert.clause");
|
|
11
11
|
/**
|
|
12
12
|
* Core SQL tagging utility for Pgtx.
|
|
13
13
|
* Provides type-safe helpers for building dynamic queries with recursive support.
|
|
@@ -25,7 +25,7 @@ exports.sql = {
|
|
|
25
25
|
* sql.insert([{ id: 1 }, { id: 2 }])
|
|
26
26
|
* // Result: (id) VALUES ($1), ($2)
|
|
27
27
|
*/
|
|
28
|
-
insert:
|
|
28
|
+
insert: insert_clause_1.insertClause,
|
|
29
29
|
/**
|
|
30
30
|
* Generates a SET clause for UPDATE queries from a JavaScript object.
|
|
31
31
|
*
|
|
@@ -54,7 +54,7 @@ exports.sql = {
|
|
|
54
54
|
* sql.literal('DESC')
|
|
55
55
|
* // Result: DESC
|
|
56
56
|
*/
|
|
57
|
-
literal:
|
|
57
|
+
literal: literal_clause_1.literalClause,
|
|
58
58
|
/**
|
|
59
59
|
* Creates a reusable, recursive SQL fragment.
|
|
60
60
|
* Fragments can be nested within each other; argument numbering is handled automatically.
|
package/dist/transaction.d.ts
CHANGED
|
@@ -35,6 +35,6 @@ export declare class Transaction {
|
|
|
35
35
|
* if (error) throw new Error(); // Only this insert rolls back
|
|
36
36
|
* });
|
|
37
37
|
*/
|
|
38
|
-
savepoint(name: string, callback: (tx: Transaction) => Promise<void>): Promise<
|
|
38
|
+
savepoint(name: string, callback: (tx: Transaction) => Promise<void>): Promise<Error | null>;
|
|
39
39
|
}
|
|
40
40
|
//# sourceMappingURL=transaction.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,IAAI,CAAA;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAIzC;;;GAGG;AACH,qBAAa,WAAW;IAIhB,QAAQ,CAAC,IAAI,EAAE,UAAU;IAH7B,OAAO,CAAC,UAAU,CAAiB;gBAGtB,IAAI,EAAE,UAAU;IAG7B;;OAEG;IACH,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAED,OAAO,CAAC,WAAW;IAMnB;;OAEG;IACU,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAOpC;;OAEG;IACU,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtC;;OAEG;IACU,KAAK,CAAC,CAAC,SAAS,cAAc,GAAG,GAAG,EAAE,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAKjH;;;;;;;;;OASG;IACU,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,IAAI,CAAA;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAIzC;;;GAGG;AACH,qBAAa,WAAW;IAIhB,QAAQ,CAAC,IAAI,EAAE,UAAU;IAH7B,OAAO,CAAC,UAAU,CAAiB;gBAGtB,IAAI,EAAE,UAAU;IAG7B;;OAEG;IACH,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAED,OAAO,CAAC,WAAW;IAMnB;;OAEG;IACU,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAOpC;;OAEG;IACU,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtC;;OAEG;IACU,KAAK,CAAC,CAAC,SAAS,cAAc,GAAG,GAAG,EAAE,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAKjH;;;;;;;;;OASG;IACU,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;CAe5G"}
|
package/dist/transaction.js
CHANGED
|
@@ -61,10 +61,11 @@ class Transaction {
|
|
|
61
61
|
try {
|
|
62
62
|
await callback(this);
|
|
63
63
|
await this.conn.query `RELEASE SAVEPOINT ${(0, iden_caluse_1.identClause)(name)}`;
|
|
64
|
+
return null;
|
|
64
65
|
}
|
|
65
66
|
catch (err) {
|
|
66
67
|
await this.conn.query `ROLLBACK TO SAVEPOINT ${(0, iden_caluse_1.identClause)(name)}`;
|
|
67
|
-
|
|
68
|
+
return err instanceof Error ? err : new Error(String(err));
|
|
68
69
|
}
|
|
69
70
|
}
|
|
70
71
|
}
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,UAAU,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,oBAAoB,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,gBAAgB,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,UAAU,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,oBAAoB,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,gBAAgB,CAgCrH"}
|
package/dist/utils.js
CHANGED
|
@@ -18,6 +18,10 @@ function compileSqlTemplate(strings, values, argCounter) {
|
|
|
18
18
|
args.push(...result.args);
|
|
19
19
|
}
|
|
20
20
|
else {
|
|
21
|
+
if (value === undefined) {
|
|
22
|
+
throw new TypeError(`Query parameter at position ${argCounter} is undefined.
|
|
23
|
+
Use null if you want NULL in SQL, or ensure the value is defined.`);
|
|
24
|
+
}
|
|
21
25
|
args.push(value);
|
|
22
26
|
text += `$${argCounter}`;
|
|
23
27
|
argCounter++;
|