@m2k-5f/pgtx 2.1.0 → 2.3.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 (45) hide show
  1. package/README.md +66 -13
  2. package/dist/clauses/abstract.clause.js +1 -5
  3. package/dist/clauses/array.clause.js +3 -7
  4. package/dist/clauses/empty.clause.js +3 -7
  5. package/dist/clauses/exclude.clause.js +2 -6
  6. package/dist/clauses/fragment.clause.js +4 -8
  7. package/dist/clauses/iden.caluse.js +2 -6
  8. package/dist/clauses/index.js +9 -25
  9. package/dist/clauses/insert.clause.js +2 -6
  10. package/dist/clauses/literal.clause.js +2 -6
  11. package/dist/clauses/update.clause.js +2 -6
  12. package/dist/clauses/where.clause.js +2 -6
  13. package/dist/connection.d.ts +56 -10
  14. package/dist/connection.d.ts.map +1 -1
  15. package/dist/connection.js +220 -117
  16. package/dist/error.d.ts +1 -1
  17. package/dist/error.d.ts.map +1 -1
  18. package/dist/error.js +2 -6
  19. package/dist/index.js +24 -37
  20. package/dist/pool.d.ts +20 -6
  21. package/dist/pool.d.ts.map +1 -1
  22. package/dist/pool.js +40 -41
  23. package/dist/protocol/connection-request-writer.js +13 -18
  24. package/dist/protocol/connection-response-reader.d.ts +5 -0
  25. package/dist/protocol/connection-response-reader.d.ts.map +1 -1
  26. package/dist/protocol/connection-response-reader.js +11 -9
  27. package/dist/protocol/constants.d.ts +1 -0
  28. package/dist/protocol/constants.d.ts.map +1 -1
  29. package/dist/protocol/constants.js +6 -8
  30. package/dist/protocol/socket-authorization.d.ts +5 -1
  31. package/dist/protocol/socket-authorization.d.ts.map +1 -1
  32. package/dist/protocol/socket-authorization.js +38 -34
  33. package/dist/protocol/socket-connector.d.ts.map +1 -1
  34. package/dist/protocol/socket-connector.js +4 -7
  35. package/dist/query.js +2 -6
  36. package/dist/queue.js +1 -5
  37. package/dist/security/md5.js +4 -8
  38. package/dist/security/sasl.js +7 -11
  39. package/dist/transaction.d.ts +7 -5
  40. package/dist/transaction.d.ts.map +1 -1
  41. package/dist/transaction.js +18 -26
  42. package/dist/types.js +0 -2
  43. package/dist/utils/template-compiler.js +3 -6
  44. package/dist/utils/value-parser.js +2 -7
  45. package/package.json +5 -2
@@ -1,85 +1,86 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createAuthorizedSocket = void 0;
4
- const node_net_1 = require("node:net");
5
- const sasl_1 = require("../security/sasl");
6
- const socket_connector_1 = require("./socket-connector");
7
- const constants_1 = require("./constants");
8
- const md5_1 = require("../security/md5");
9
- const createAuthorizedSocket = (writer, params) => {
10
- return new Promise((resolve, reject) => {
11
- const nonce = (0, sasl_1.generateNonce)();
1
+ import { createConnection } from "node:net";
2
+ import { calculateScramAuth, generateNonce } from "../security/sasl";
3
+ import { SocketConnector } from "./socket-connector";
4
+ import { AuthenticationCodes, ResponseTypes } from "./constants";
5
+ import { encryptMd5 } from "../security/md5";
6
+ import { PostgresError } from "../error";
7
+ import { Future } from "fluent-future";
8
+ export const ErrNonceMismatch = new PostgresError("Protocol violation: server nonce doesn't match client nonce");
9
+ export const ErrPasswordRequired = new PostgresError('The authorization method requires a password.');
10
+ export const createAuthorizedSocket = (writer, params) => {
11
+ return Future.of(new Promise((resolve, reject) => {
12
+ const nonce = generateNonce();
12
13
  let clientMessage = '';
13
14
  let serverMessage = '';
14
- const socket = (0, node_net_1.createConnection)({ host: params.host, port: params.port });
15
- const connector = new socket_connector_1.SocketConnector(socket, (type, reader) => {
15
+ const socket = createConnection({ host: params.host, port: params.port });
16
+ const connector = new SocketConnector(socket, (type, reader) => {
16
17
  writer.clear();
17
18
  switch (type) {
18
- case constants_1.ResponseTypes.Authentication: {
19
+ case ResponseTypes.Authentication: {
19
20
  switch (reader.readAuthentication()) {
20
- case constants_1.AuthenticationCodes.Ok: break;
21
- case constants_1.AuthenticationCodes.CleartextPassword: {
21
+ case AuthenticationCodes.Ok: break;
22
+ case AuthenticationCodes.CleartextPassword: {
22
23
  if (!params.password)
23
- throw new Error('The authorization method requires a password.');
24
+ throw ErrPasswordRequired;
24
25
  connector.write(writer.writePassword(params.password));
25
26
  break;
26
27
  }
27
- case constants_1.AuthenticationCodes.MD5Password: {
28
+ case AuthenticationCodes.MD5Password: {
28
29
  const salt = reader.readMD5Salt();
29
30
  if (!params.password)
30
- throw new Error('The authorization method requires a password.');
31
- const password = (0, md5_1.encryptMd5)(params.password, params.user, salt);
31
+ throw ErrPasswordRequired;
32
+ const password = encryptMd5(params.password, params.user, salt);
32
33
  connector.write(writer.writePassword(password));
33
34
  break;
34
35
  }
35
- case constants_1.AuthenticationCodes.SASL: {
36
+ case AuthenticationCodes.SASL: {
36
37
  reader.readSaslMechanisms();
37
38
  if (!params.password)
38
- throw new Error('The authorization method requires a password.');
39
+ throw ErrPasswordRequired;
39
40
  clientMessage = `n=${params.user},r=${nonce}`;
40
41
  connector.write(writer.writeSaslInitial('SCRAM-SHA-256', `n,,${clientMessage}`));
41
42
  break;
42
43
  }
43
- case constants_1.AuthenticationCodes.SASLContinue: {
44
+ case AuthenticationCodes.SASLContinue: {
44
45
  serverMessage = reader.readSaslMessage();
45
46
  if (!params.password)
46
- throw new Error('The authorization method requires a password.');
47
+ throw ErrPasswordRequired;
47
48
  const parts = Object.fromEntries(serverMessage.split(',').map(x => x.split('=')));
48
49
  const serverNonce = parts.r;
49
50
  const saltBase64 = parts.s;
50
51
  const iterations = parseInt(parts.i, 10);
51
52
  if (!serverNonce.startsWith(nonce)) {
52
53
  connector.destroy();
53
- return reject("Protocol violation: server nonce doesn't match client nonce");
54
+ return reject(ErrNonceMismatch);
54
55
  }
55
56
  const clientFinalMessageWithoutProof = `c=biws,r=${serverNonce}`;
56
57
  const authMessage = `${clientMessage},${serverMessage},${clientFinalMessageWithoutProof}`;
57
- const { clientProof } = (0, sasl_1.calculateScramAuth)(params.password, saltBase64, iterations, authMessage);
58
+ const { clientProof } = calculateScramAuth(params.password, saltBase64, iterations, authMessage);
58
59
  const clientFinalMessage = `${clientFinalMessageWithoutProof},p=${clientProof}`;
59
60
  connector.write(writer.writeSaslResponse(clientFinalMessage));
60
61
  break;
61
62
  }
62
- case constants_1.AuthenticationCodes.SASLFinal: {
63
+ case AuthenticationCodes.SASLFinal: {
63
64
  reader.readSaslMessage();
64
65
  break;
65
66
  }
66
67
  }
67
68
  break;
68
69
  }
69
- case constants_1.ResponseTypes.ParamaterStatus: {
70
+ case ResponseTypes.ParamaterStatus: {
70
71
  reader.readParameterStatus();
71
72
  break;
72
73
  }
73
- case constants_1.ResponseTypes.ErrorResponse: {
74
- const message = reader.readErrorResponse();
74
+ case ResponseTypes.ErrorResponse: {
75
+ const error = reader.readErrorResponse();
75
76
  connector.destroy();
76
- reject(message);
77
+ reject(error);
77
78
  return;
78
79
  }
79
- case constants_1.ResponseTypes.BackendKeyData: {
80
+ case ResponseTypes.BackendKeyData: {
80
81
  reader.readBackendKeyData();
81
82
  }
82
- case constants_1.ResponseTypes.ReadyForQuery: {
83
+ case ResponseTypes.ReadyForQuery: {
83
84
  reader.readReadyForQuery();
84
85
  resolve(connector.unwrapSocket());
85
86
  return;
@@ -90,6 +91,9 @@ const createAuthorizedSocket = (writer, params) => {
90
91
  });
91
92
  connector.write(writer.writeStartup(params.user, params.database));
92
93
  writer.clear();
94
+ }), error => {
95
+ if (error instanceof PostgresError)
96
+ return error;
97
+ return new PostgresError(error.message);
93
98
  });
94
99
  };
95
- exports.createAuthorizedSocket = createAuthorizedSocket;
@@ -1 +1 @@
1
- {"version":3,"file":"socket-connector.d.ts","sourceRoot":"","sources":["../../src/protocol/socket-connector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAA;AACjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAA;AAE/E,qBAAa,eAAe;IAKpB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,QAAQ;IANpB,OAAO,CAAC,cAAc,CAAsB;IAC5C,OAAO,CAAC,YAAY,CAAQ;gBAGhB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,wBAAwB,KAAK,IAAI,EACvE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI;IA4B5C,KAAK,CAAC,MAAM,EAAE,uBAAuB;IAOrC,YAAY;IAQZ,OAAO;IAMP,IAAI,WAAW,YAA6B;CAC/C"}
1
+ {"version":3,"file":"socket-connector.d.ts","sourceRoot":"","sources":["../../src/protocol/socket-connector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAA;AACjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAA;AAE/E,qBAAa,eAAe;IAKpB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,QAAQ;IANpB,OAAO,CAAC,cAAc,CAAsB;IAC5C,OAAO,CAAC,YAAY,CAAQ;gBAGhB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,wBAAwB,KAAK,IAAI,EACvE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI;IA6B5C,KAAK,CAAC,MAAM,EAAE,uBAAuB;IAOrC,YAAY;IAQZ,OAAO;IAMP,IAAI,WAAW,YAA6B;CAC/C"}
@@ -1,20 +1,18 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SocketConnector = void 0;
4
- const connection_response_reader_1 = require("../protocol/connection-response-reader");
5
- class SocketConnector {
1
+ import { ConnectionResponseReader } from '../protocol/connection-response-reader';
2
+ export class SocketConnector {
6
3
  constructor(_socket, _onData, _onError) {
7
4
  this._socket = _socket;
8
5
  this._onData = _onData;
9
6
  this._onError = _onError;
10
7
  this.residualBuffer = null;
11
8
  this._isDestroyed = false;
9
+ _socket.setKeepAlive(true, 10000);
12
10
  _socket.on('data', buffer => {
13
11
  const currentBuffer = this.residualBuffer
14
12
  ? Buffer.concat([this.residualBuffer, buffer])
15
13
  : buffer;
16
14
  this.residualBuffer = null;
17
- const reader = connection_response_reader_1.ConnectionResponseReader.from(currentBuffer);
15
+ const reader = ConnectionResponseReader.from(currentBuffer);
18
16
  while (reader.hasMore()) {
19
17
  if (!reader.hasFullPacket()) {
20
18
  this.residualBuffer = reader.getResidualBuffer();
@@ -45,4 +43,3 @@ class SocketConnector {
45
43
  }
46
44
  get isDestroyed() { return this._isDestroyed; }
47
45
  }
48
- exports.SocketConnector = SocketConnector;
package/dist/query.js CHANGED
@@ -1,14 +1,11 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Query = exports.QueryState = void 0;
4
- exports.QueryState = {
1
+ export const QueryState = {
5
2
  Parsing: 0,
6
3
  Describing: 1,
7
4
  Executing: 2,
8
5
  Completed: 3,
9
6
  Failed: 4
10
7
  };
11
- class Query {
8
+ export class Query {
12
9
  constructor(text, args, state, statementName, columns) {
13
10
  this.text = text;
14
11
  this.args = args;
@@ -25,4 +22,3 @@ class Query {
25
22
  this.state = state;
26
23
  }
27
24
  }
28
- exports.Query = Query;
package/dist/queue.js CHANGED
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Queue = void 0;
4
- class Queue {
1
+ export class Queue {
5
2
  constructor() {
6
3
  this._queue = new Array();
7
4
  this._pointer = 0;
@@ -36,4 +33,3 @@ class Queue {
36
33
  }
37
34
  get isFree() { return this._pointer >= this._queue.length; }
38
35
  }
39
- exports.Queue = Queue;
@@ -1,12 +1,8 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.encryptMd5 = void 0;
4
- const crypto_1 = require("crypto");
5
- const encryptMd5 = (password, user, salt) => {
6
- const stage1 = (0, crypto_1.createHash)('md5').update(password + user).digest('hex');
7
- const stage2 = (0, crypto_1.createHash)('md5')
1
+ import { createHash } from "crypto";
2
+ export const encryptMd5 = (password, user, salt) => {
3
+ const stage1 = createHash('md5').update(password + user).digest('hex');
4
+ const stage2 = createHash('md5')
8
5
  .update(Buffer.concat([Buffer.from(stage1), salt]))
9
6
  .digest('hex');
10
7
  return 'md5' + stage2;
11
8
  };
12
- exports.encryptMd5 = encryptMd5;
@@ -1,22 +1,18 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateNonce = generateNonce;
4
- exports.calculateScramAuth = calculateScramAuth;
5
- const crypto_1 = require("crypto");
6
- function generateNonce() {
7
- return (0, crypto_1.randomBytes)(18).toString('base64').replace(/[^a-zA-Z0-9]/g, '').substring(0, 24);
1
+ import { randomBytes, createHmac, pbkdf2Sync, createHash } from 'crypto';
2
+ export function generateNonce() {
3
+ return randomBytes(18).toString('base64').replace(/[^a-zA-Z0-9]/g, '').substring(0, 24);
8
4
  }
9
5
  function hmac(key, data) {
10
- return (0, crypto_1.createHmac)('sha256', key).update(data).digest();
6
+ return createHmac('sha256', key).update(data).digest();
11
7
  }
12
8
  function hi(password, salt, iterations) {
13
- return (0, crypto_1.pbkdf2Sync)(password, salt, iterations, 32, 'sha256');
9
+ return pbkdf2Sync(password, salt, iterations, 32, 'sha256');
14
10
  }
15
- function calculateScramAuth(password, saltBase64, iterations, authMessage) {
11
+ export function calculateScramAuth(password, saltBase64, iterations, authMessage) {
16
12
  const salt = Buffer.from(saltBase64, 'base64');
17
13
  const saltedPassword = hi(password, salt, iterations);
18
14
  const clientKey = hmac(saltedPassword, 'Client Key');
19
- const storedKey = (0, crypto_1.createHash)('sha256').update(clientKey).digest();
15
+ const storedKey = createHash('sha256').update(clientKey).digest();
20
16
  const clientSignature = hmac(storedKey, authMessage);
21
17
  const clientProofBuf = Buffer.alloc(32);
22
18
  for (let i = 0; i < 32; i++) {
@@ -1,4 +1,6 @@
1
+ import { Future } from "fluent-future";
1
2
  import { Connection } from "./connection";
3
+ import { PostgresError } from "./error";
2
4
  /**
3
5
  * Represents an active SQL transaction.
4
6
  * All queries are executed on a single dedicated connection.
@@ -15,15 +17,15 @@ export declare class Transaction {
15
17
  /**
16
18
  * Commits the current transaction.
17
19
  */
18
- commit(): Promise<void>;
20
+ commit(): Future<[], PostgresError>;
19
21
  /**
20
22
  * Rolls back the current transaction.
21
23
  */
22
- rollback(): Promise<void>;
24
+ rollback(): Future<[], PostgresError>;
23
25
  /**
24
26
  * Executes a query within the current transaction.
25
27
  */
26
- query<T extends Record<string, any>>(strings: TemplateStringsArray, ...values: any[]): Promise<T[]>;
28
+ query<T extends Record<string, any>>(strings: TemplateStringsArray, ...values: any[]): Future<T[], PostgresError>;
27
29
  /**
28
30
  * Creates a sub-transaction using PostgreSQL SAVEPOINT.
29
31
  * If the callback throws, only the actions within this savepoint are rolled back.
@@ -31,9 +33,9 @@ export declare class Transaction {
31
33
  * @example
32
34
  * await tx.savepoint('my_point', async (stx) => {
33
35
  * await stx.query`INSERT ...`;
34
- * if (error) throw new Error(); // Only this insert rolls back
36
+ * if (error) throw new Error() // Only this insert rolls back
35
37
  * });
36
38
  */
37
- savepoint(name: string, callback: (tx: Transaction) => Promise<void>): Promise<Error | null>;
39
+ savepoint<T>(name: string, callback: (tx: Transaction) => Promise<T>): Future<T, Error>;
38
40
  }
39
41
  //# sourceMappingURL=transaction.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEzC;;;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,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAKhH;;;;;;;;;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"}
1
+ {"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAE,MAAM,eAAe,CAAA;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAEvC;;;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;IACI,MAAM,IAIiC,MAAM,CAAC,EAAE,EAAE,aAAa,CAAC;IAGvE;;OAEG;IACI,QAAQ,IAI+B,MAAM,CAAC,EAAE,EAAE,aAAa,CAAC;IAGvE;;OAEG;IACI,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IAK3F;;;;;;;;;OASG;IACI,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC;CAWjG"}
@@ -1,12 +1,10 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Transaction = void 0;
4
- const clauses_1 = require("./clauses");
1
+ import { Begin, Future } from "fluent-future";
2
+ import { IdentifierClause } from "./clauses";
5
3
  /**
6
4
  * Represents an active SQL transaction.
7
5
  * All queries are executed on a single dedicated connection.
8
6
  */
9
- class Transaction {
7
+ export class Transaction {
10
8
  constructor(conn) {
11
9
  this.conn = conn;
12
10
  this.isFinished = false;
@@ -25,25 +23,25 @@ class Transaction {
25
23
  /**
26
24
  * Commits the current transaction.
27
25
  */
28
- async commit() {
26
+ commit() {
29
27
  this.checkActive();
30
- await this.conn.query `COMMIT`;
31
- this.isFinished = true;
28
+ return this.conn.query `COMMIT`
29
+ .tap(() => this.isFinished = true);
32
30
  }
33
31
  /**
34
32
  * Rolls back the current transaction.
35
33
  */
36
- async rollback() {
34
+ rollback() {
37
35
  this.checkActive();
38
- await this.conn.query `ROLLBACK`;
39
- this.isFinished = true;
36
+ return this.conn.query `ROLLBACK`
37
+ .tap(() => this.isFinished = true);
40
38
  }
41
39
  /**
42
40
  * Executes a query within the current transaction.
43
41
  */
44
- async query(strings, ...values) {
42
+ query(strings, ...values) {
45
43
  this.checkActive();
46
- return await this.conn.query(strings, ...values);
44
+ return this.conn.query(strings, ...values);
47
45
  }
48
46
  /**
49
47
  * Creates a sub-transaction using PostgreSQL SAVEPOINT.
@@ -52,21 +50,15 @@ class Transaction {
52
50
  * @example
53
51
  * await tx.savepoint('my_point', async (stx) => {
54
52
  * await stx.query`INSERT ...`;
55
- * if (error) throw new Error(); // Only this insert rolls back
53
+ * if (error) throw new Error() // Only this insert rolls back
56
54
  * });
57
55
  */
58
- async savepoint(name, callback) {
56
+ savepoint(name, callback) {
59
57
  this.checkActive();
60
- await this.conn.query `SAVEPOINT ${clauses_1.IdentifierClause.create(name)}`;
61
- try {
62
- await callback(this);
63
- await this.conn.query `RELEASE SAVEPOINT ${clauses_1.IdentifierClause.create(name)}`;
64
- return null;
65
- }
66
- catch (err) {
67
- await this.conn.query `ROLLBACK TO SAVEPOINT ${clauses_1.IdentifierClause.create(name)}`;
68
- return err instanceof Error ? err : new Error(String(err));
69
- }
58
+ return Begin()
59
+ .andThen(() => this.conn.query `SAVEPOINT ${IdentifierClause.create(name)}`)
60
+ .andThen(() => Future.of(callback(this))
61
+ .tap(() => this.conn.query `RELEASE SAVEPOINT ${IdentifierClause.create(name)}`)
62
+ .tapErr(() => this.conn.query `ROLLBACK TO SAVEPOINT ${IdentifierClause.create(name)}`));
70
63
  }
71
64
  }
72
- exports.Transaction = Transaction;
package/dist/types.js CHANGED
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,8 +1,5 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.compileSqlTemplate = compileSqlTemplate;
4
- const abstract_clause_1 = require("../clauses/abstract.clause");
5
- function compileSqlTemplate(params, argOffset = 0) {
1
+ import { Clause } from "../clauses/abstract.clause";
2
+ export function compileSqlTemplate(params, argOffset = 0) {
6
3
  const templateLength = params.templates.length;
7
4
  const query = {
8
5
  text: [],
@@ -13,7 +10,7 @@ function compileSqlTemplate(params, argOffset = 0) {
13
10
  if (index === templateLength - 1)
14
11
  return;
15
12
  const value = params.args[index];
16
- if (value instanceof abstract_clause_1.Clause) {
13
+ if (value instanceof Clause) {
17
14
  value.mapIntoQuery(query);
18
15
  }
19
16
  else {
@@ -1,7 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.setTypeParser = void 0;
4
- exports.parseRowValues = parseRowValues;
5
1
  const parsePostgresArray = (v) => {
6
2
  if (v === '{}')
7
3
  return [];
@@ -70,7 +66,7 @@ const Parsers = {
70
66
  3807: (v) => parsePostgresArray(v).map(el => JSON.parse(el)), // jsonb[]
71
67
  };
72
68
  const defaultParser = (v) => v;
73
- function parseRowValues(columns, rows) {
69
+ export function parseRowValues(columns, rows) {
74
70
  const result = [];
75
71
  const columnsLength = columns.length;
76
72
  const columnParsers = columns.map(col => Parsers[col.typeOID] || defaultParser);
@@ -95,7 +91,6 @@ function parseRowValues(columns, rows) {
95
91
  }
96
92
  return result;
97
93
  }
98
- const setTypeParser = (typeOID, parser) => {
94
+ export const setTypeParser = (typeOID, parser) => {
99
95
  Parsers[typeOID] = parser;
100
96
  };
101
- exports.setTypeParser = setTypeParser;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m2k-5f/pgtx",
3
- "version": "2.1.0",
3
+ "version": "2.3.0",
4
4
  "description": "Blazing-fast PostgreSQL driver with pipeline support.",
5
5
  "files": [
6
6
  "dist",
@@ -9,7 +9,7 @@
9
9
  "scripts": {
10
10
  "build": "tsc",
11
11
  "prepublishOnly": "npm run build",
12
- "testGitHub": "node --import tsx --test $(find tests -name '*.test.ts')",
12
+ "testGitHub": "node --import tsx --test 0 $(find tests -name '*.test.ts')",
13
13
  "test": "node --import tsx --test ./tests/*.test.ts"
14
14
  },
15
15
  "repository": {
@@ -44,5 +44,8 @@
44
44
  "pg": "^8.22.0",
45
45
  "tsx": "^4.21.0",
46
46
  "typescript": "^5.0.0"
47
+ },
48
+ "dependencies": {
49
+ "fluent-future": "^1.3.2"
47
50
  }
48
51
  }