@m2k-5f/pgtx 1.4.11 → 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 (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +225 -128
  3. package/dist/clauses/array.clause.js +1 -1
  4. package/dist/clauses/empty.clause.d.ts +1 -1
  5. package/dist/clauses/empty.clause.d.ts.map +1 -1
  6. package/dist/clauses/empty.clause.js +2 -2
  7. package/dist/clauses/fragment.clause.d.ts +1 -1
  8. package/dist/clauses/fragment.clause.d.ts.map +1 -1
  9. package/dist/clauses/fragment.clause.js +3 -5
  10. package/dist/clauses/iden.caluse.d.ts +1 -1
  11. package/dist/clauses/iden.caluse.d.ts.map +1 -1
  12. package/dist/clauses/index.d.ts +10 -0
  13. package/dist/clauses/index.d.ts.map +1 -0
  14. package/dist/clauses/index.js +25 -0
  15. package/dist/clauses/insert.clause.d.ts +1 -1
  16. package/dist/clauses/insert.clause.d.ts.map +1 -1
  17. package/dist/clauses/insert.clause.js +1 -1
  18. package/dist/clauses/literal.clause.d.ts +1 -1
  19. package/dist/clauses/literal.clause.d.ts.map +1 -1
  20. package/dist/clauses/update.clause.d.ts +1 -1
  21. package/dist/clauses/update.clause.d.ts.map +1 -1
  22. package/dist/clauses/update.clause.js +1 -1
  23. package/dist/clauses/where.clause.d.ts +1 -1
  24. package/dist/clauses/where.clause.d.ts.map +1 -1
  25. package/dist/clauses/where.clause.js +1 -1
  26. package/dist/connection.d.ts +135 -31
  27. package/dist/connection.d.ts.map +1 -1
  28. package/dist/connection.js +290 -59
  29. package/dist/index.d.ts +2 -10
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +10 -18
  32. package/dist/pool.d.ts +126 -32
  33. package/dist/pool.d.ts.map +1 -1
  34. package/dist/pool.js +203 -54
  35. package/dist/protocol/connection-request-writer.d.ts +38 -0
  36. package/dist/protocol/connection-request-writer.d.ts.map +1 -0
  37. package/dist/protocol/connection-request-writer.js +175 -0
  38. package/dist/protocol/connection-response-reader.d.ts +49 -0
  39. package/dist/protocol/connection-response-reader.d.ts.map +1 -0
  40. package/dist/protocol/connection-response-reader.js +185 -0
  41. package/dist/protocol/constants.d.ts +46 -0
  42. package/dist/protocol/constants.d.ts.map +1 -0
  43. package/dist/protocol/constants.js +43 -0
  44. package/dist/protocol/socket-authorization.d.ts +11 -0
  45. package/dist/protocol/socket-authorization.d.ts.map +1 -0
  46. package/dist/protocol/socket-authorization.js +95 -0
  47. package/dist/protocol/socket-connector.d.ts +17 -0
  48. package/dist/protocol/socket-connector.d.ts.map +1 -0
  49. package/dist/protocol/socket-connector.js +48 -0
  50. package/dist/queue.d.ts +10 -0
  51. package/dist/queue.d.ts.map +1 -0
  52. package/dist/queue.js +27 -0
  53. package/dist/security/md5.d.ts +2 -0
  54. package/dist/security/md5.d.ts.map +1 -0
  55. package/dist/security/md5.js +12 -0
  56. package/dist/security/sasl.d.ts +6 -0
  57. package/dist/security/sasl.d.ts.map +1 -0
  58. package/dist/security/sasl.js +29 -0
  59. package/dist/transaction.d.ts +1 -2
  60. package/dist/transaction.d.ts.map +1 -1
  61. package/dist/transaction.js +4 -4
  62. package/dist/types.d.ts +6 -8
  63. package/dist/types.d.ts.map +1 -1
  64. package/dist/utils/template-compiler.d.ts +3 -0
  65. package/dist/utils/template-compiler.d.ts.map +1 -0
  66. package/dist/utils/template-compiler.js +64 -0
  67. package/dist/utils/value-parser.d.ts +6 -0
  68. package/dist/utils/value-parser.d.ts.map +1 -0
  69. package/dist/utils/value-parser.js +101 -0
  70. package/package.json +8 -9
@@ -0,0 +1,48 @@
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 {
6
+ constructor(_socket, _onData, _onError) {
7
+ this._socket = _socket;
8
+ this._onData = _onData;
9
+ this._onError = _onError;
10
+ this.residualBuffer = null;
11
+ this._isDestroyed = false;
12
+ _socket.on('data', buffer => {
13
+ const currentBuffer = this.residualBuffer
14
+ ? Buffer.concat([this.residualBuffer, buffer])
15
+ : buffer;
16
+ this.residualBuffer = null;
17
+ const reader = connection_response_reader_1.ConnectionResponseReader.from(currentBuffer);
18
+ while (reader.hasMore()) {
19
+ if (!reader.hasFullPacket()) {
20
+ this.residualBuffer = reader.getResidualBuffer();
21
+ return;
22
+ }
23
+ this._onData(reader.readType(), reader);
24
+ }
25
+ });
26
+ _socket.on('error', error => {
27
+ this._onError(error);
28
+ this._socket.destroy();
29
+ this._isDestroyed = true;
30
+ });
31
+ }
32
+ write(writer) {
33
+ if (this._isDestroyed)
34
+ throw new Error("SocketConnector is destroyed");
35
+ this._socket.write(writer.asBuffer());
36
+ }
37
+ unwrapSocket() {
38
+ this._socket.off('error', this._onError);
39
+ this._socket.off("data", this._onData);
40
+ return this._socket;
41
+ }
42
+ destroy() {
43
+ this._isDestroyed = true;
44
+ this._socket.destroy();
45
+ }
46
+ get isDestroyed() { return this._isDestroyed; }
47
+ }
48
+ exports.SocketConnector = SocketConnector;
@@ -0,0 +1,10 @@
1
+ export declare class Queue<T> {
2
+ private _queue;
3
+ private _pointer;
4
+ next(): void;
5
+ get(): T;
6
+ push(item: T): void;
7
+ get size(): number;
8
+ get isFree(): boolean;
9
+ }
10
+ //# sourceMappingURL=queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAAA,qBAAa,KAAK,CAAC,CAAC;IAChB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAI;IAEpB,IAAI;IAQJ,GAAG;IAIH,IAAI,CAAC,IAAI,EAAE,CAAC;IAIZ,IAAI,IAAI,WAEP;IAED,IAAI,MAAM,YAAgD;CAC7D"}
package/dist/queue.js ADDED
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Queue = void 0;
4
+ class Queue {
5
+ constructor() {
6
+ this._queue = new Array();
7
+ this._pointer = 0;
8
+ }
9
+ next() {
10
+ this._pointer++;
11
+ if (this._pointer === this._queue.length) {
12
+ this._queue = [];
13
+ this._pointer = 0;
14
+ }
15
+ }
16
+ get() {
17
+ return this._queue[this._pointer];
18
+ }
19
+ push(item) {
20
+ this._queue.push(item);
21
+ }
22
+ get size() {
23
+ return this._queue.length - this._pointer;
24
+ }
25
+ get isFree() { return this._pointer === this._queue.length; }
26
+ }
27
+ exports.Queue = Queue;
@@ -0,0 +1,2 @@
1
+ export declare const encryptMd5: (password: string, user: string, salt: Buffer) => string;
2
+ //# sourceMappingURL=md5.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"md5.d.ts","sourceRoot":"","sources":["../../src/security/md5.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,UAAU,GAAI,UAAU,MAAM,EAAE,MAAM,MAAM,EAAE,MAAM,MAAM,WAQtE,CAAA"}
@@ -0,0 +1,12 @@
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')
8
+ .update(Buffer.concat([Buffer.from(stage1), salt]))
9
+ .digest('hex');
10
+ return 'md5' + stage2;
11
+ };
12
+ exports.encryptMd5 = encryptMd5;
@@ -0,0 +1,6 @@
1
+ export declare function generateNonce(): string;
2
+ export declare function calculateScramAuth(password: string, saltBase64: string, iterations: number, authMessage: string): {
3
+ clientProof: string;
4
+ serverSignature: string;
5
+ };
6
+ //# sourceMappingURL=sasl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sasl.d.ts","sourceRoot":"","sources":["../../src/security/sasl.ts"],"names":[],"mappings":"AAGA,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAaD,wBAAgB,kBAAkB,CAC9B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GACpB;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,CAuBlD"}
@@ -0,0 +1,29 @@
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);
8
+ }
9
+ function hmac(key, data) {
10
+ return (0, crypto_1.createHmac)('sha256', key).update(data).digest();
11
+ }
12
+ function hi(password, salt, iterations) {
13
+ return (0, crypto_1.pbkdf2Sync)(password, salt, iterations, 32, 'sha256');
14
+ }
15
+ function calculateScramAuth(password, saltBase64, iterations, authMessage) {
16
+ const salt = Buffer.from(saltBase64, 'base64');
17
+ const saltedPassword = hi(password, salt, iterations);
18
+ const clientKey = hmac(saltedPassword, 'Client Key');
19
+ const storedKey = (0, crypto_1.createHash)('sha256').update(clientKey).digest();
20
+ const clientSignature = hmac(storedKey, authMessage);
21
+ const clientProofBuf = Buffer.alloc(32);
22
+ for (let i = 0; i < 32; i++) {
23
+ clientProofBuf[i] = clientKey[i] ^ clientSignature[i];
24
+ }
25
+ const clientProof = clientProofBuf.toString('base64');
26
+ const serverKey = hmac(saltedPassword, 'Server Key');
27
+ const serverSignature = hmac(serverKey, authMessage).toString('base64');
28
+ return { clientProof, serverSignature };
29
+ }
@@ -1,4 +1,3 @@
1
- import { QueryResultRow } from "pg";
2
1
  import { Connection } from "./connection";
3
2
  /**
4
3
  * Represents an active SQL transaction.
@@ -24,7 +23,7 @@ export declare class Transaction {
24
23
  /**
25
24
  * Executes a query within the current transaction.
26
25
  */
27
- query<T extends QueryResultRow = any>(strings: TemplateStringsArray, ...values: any[]): Promise<T[]>;
26
+ query<T extends Record<string, unknown>>(strings: TemplateStringsArray, ...values: any[]): Promise<T[]>;
28
27
  /**
29
28
  * Creates a sub-transaction using PostgreSQL SAVEPOINT.
30
29
  * If the callback throws, only the actions within this savepoint are rolled back.
@@ -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;AAGzC;;;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"}
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,OAAO,CAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAKpH;;;;;;;;;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,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Transaction = void 0;
4
- const iden_caluse_1 = require("./clauses/iden.caluse");
4
+ const clauses_1 = require("./clauses");
5
5
  /**
6
6
  * Represents an active SQL transaction.
7
7
  * All queries are executed on a single dedicated connection.
@@ -57,14 +57,14 @@ class Transaction {
57
57
  */
58
58
  async savepoint(name, callback) {
59
59
  this.checkActive();
60
- await this.conn.query `SAVEPOINT ${iden_caluse_1.IdentifierClause.create(name)}`;
60
+ await this.conn.query `SAVEPOINT ${clauses_1.IdentifierClause.create(name)}`;
61
61
  try {
62
62
  await callback(this);
63
- await this.conn.query `RELEASE SAVEPOINT ${iden_caluse_1.IdentifierClause.create(name)}`;
63
+ await this.conn.query `RELEASE SAVEPOINT ${clauses_1.IdentifierClause.create(name)}`;
64
64
  return null;
65
65
  }
66
66
  catch (err) {
67
- await this.conn.query `ROLLBACK TO SAVEPOINT ${iden_caluse_1.IdentifierClause.create(name)}`;
67
+ await this.conn.query `ROLLBACK TO SAVEPOINT ${clauses_1.IdentifierClause.create(name)}`;
68
68
  return err instanceof Error ? err : new Error(String(err));
69
69
  }
70
70
  }
package/dist/types.d.ts CHANGED
@@ -1,7 +1,3 @@
1
- import { PoolConfig as PgPoolConfig } from "pg";
2
- export type PoolConfig = PgPoolConfig & {
3
- enableLogs?: boolean;
4
- };
5
1
  export type PreparedStatement<TResult extends any, Tparams extends any[]> = {
6
2
  text: string;
7
3
  name: string;
@@ -9,17 +5,19 @@ export type PreparedStatement<TResult extends any, Tparams extends any[]> = {
9
5
  };
10
6
  export type CompiledSqlQuery = {
11
7
  text: string;
12
- args: any[];
13
- counter: number;
8
+ args: (string | null)[];
14
9
  };
15
10
  export type ClauseStrategyParams = {
16
11
  text: string[];
17
12
  args: any[];
18
- counter: number;
19
13
  };
20
14
  export type CompileSQLParams = {
21
15
  templates: TemplateStringsArray;
22
16
  args: any[];
23
- counter: number;
24
17
  };
18
+ export type ColumnDescription = {
19
+ name: string;
20
+ typeOID: number;
21
+ };
22
+ export type ValueOF<T extends Record<string, unknown>> = T[keyof T];
25
23
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,IAAI,YAAY,EAAE,MAAM,IAAI,CAAA;AAE/C,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAC,CAAA;AAE9D,MAAM,MAAM,iBAAiB,CAAC,OAAO,SAAS,GAAG,EAAE,OAAO,SAAS,GAAG,EAAE,IAAI;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;CACpD,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,OAAO,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IAC/B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,OAAO,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC3B,SAAS,EAAE,oBAAoB,CAAC;IAChC,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,OAAO,EAAE,MAAM,CAAA;CAClB,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,CAAC,OAAO,SAAS,GAAG,EAAE,OAAO,SAAS,GAAG,EAAE,IAAI;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;CACpD,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;CAC3B,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IAC/B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,GAAG,EAAE,CAAC;CACf,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC3B,SAAS,EAAE,oBAAoB,CAAC;IAChC,IAAI,EAAE,GAAG,EAAE,CAAC;CACf,CAAA;AAGD,MAAM,MAAM,iBAAiB,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAClB,CAAA;AAGD,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA"}
@@ -0,0 +1,3 @@
1
+ import { CompiledSqlQuery, CompileSQLParams } from "../types";
2
+ export declare function compileSqlTemplate(params: Readonly<CompileSQLParams>, argOffset?: number): CompiledSqlQuery;
3
+ //# sourceMappingURL=template-compiler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-compiler.d.ts","sourceRoot":"","sources":["../../src/utils/template-compiler.ts"],"names":[],"mappings":"AACA,OAAO,EAAwB,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAInF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,SAAI,GAAG,gBAAgB,CA+BtG"}
@@ -0,0 +1,64 @@
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) {
6
+ const templateLength = params.templates.length;
7
+ const query = {
8
+ text: [],
9
+ args: [],
10
+ };
11
+ params.templates.forEach((template, index) => {
12
+ query.text.push(template);
13
+ if (index === templateLength - 1)
14
+ return;
15
+ const value = params.args[index];
16
+ if (value instanceof abstract_clause_1.Clause) {
17
+ value.mapIntoQuery(query);
18
+ }
19
+ else {
20
+ if (value === undefined) {
21
+ throw new TypeError(`Query parameter at position ${query.args.length + argOffset + 1} is undefined.
22
+ Use null if you want NULL in SQL, or ensure the value is defined.`);
23
+ }
24
+ query.args.push(value);
25
+ query.text.push(`$${query.args.length + argOffset}`);
26
+ }
27
+ });
28
+ return { args: query.args.map(prepareValue), text: query.text.join('') };
29
+ }
30
+ const prepareValue = (value) => {
31
+ if (value === null || value === undefined) {
32
+ return null;
33
+ }
34
+ if (typeof value === 'object') {
35
+ if (value instanceof Date) {
36
+ return value.toISOString();
37
+ }
38
+ if (Array.isArray(value)) {
39
+ const elements = value.map(el => {
40
+ if (el === null || el === undefined)
41
+ return 'NULL';
42
+ if (typeof el === 'boolean')
43
+ return el ? 'true' : 'false';
44
+ if (typeof el === 'object') {
45
+ const res = prepareValue(el);
46
+ return `"${res?.replace(/"/g, '\\"')}"`;
47
+ }
48
+ if (typeof el === 'string') {
49
+ return `"${el.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
50
+ }
51
+ return String(el);
52
+ });
53
+ return `{${elements.join(',')}}`;
54
+ }
55
+ return prepareObject(value);
56
+ }
57
+ return value.toString();
58
+ };
59
+ const prepareObject = (obj) => {
60
+ if (obj && typeof obj.toPG === 'function') {
61
+ return JSON.stringify(obj.toPG());
62
+ }
63
+ return JSON.stringify(obj);
64
+ };
@@ -0,0 +1,6 @@
1
+ import { ColumnDescription } from "../types";
2
+ declare const Parsers: Record<number, (value: string) => unknown>;
3
+ export declare function parseRowValues(columns: ColumnDescription[], rows: (string | null)[][]): Record<string, any>;
4
+ export declare const setTypeParser: (typeOID: keyof typeof Parsers, parser: (value: string) => unknown) => void;
5
+ export {};
6
+ //# sourceMappingURL=value-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value-parser.d.ts","sourceRoot":"","sources":["../../src/utils/value-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AA+B5C,QAAA,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAkD9C,CAAA;AAMV,wBAAgB,cAAc,CAAC,OAAO,EAAE,iBAAiB,EAAE,EAAE,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CA8B3G;AAGD,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,OAAO,OAAO,EAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,SAE9F,CAAA"}
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setTypeParser = void 0;
4
+ exports.parseRowValues = parseRowValues;
5
+ const parsePostgresArray = (v) => {
6
+ if (v === '{}')
7
+ return [];
8
+ const str = v.substring(1, v.length - 1);
9
+ const matches = str.match(/"(?:\\.|[^"\\])*"|[^,]+/g);
10
+ if (!matches)
11
+ return [];
12
+ return matches.map(el => {
13
+ const trimmed = el.trim();
14
+ if (trimmed === 'NULL')
15
+ return null;
16
+ if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
17
+ return trimmed
18
+ .substring(1, trimmed.length - 1)
19
+ .replace(/\\"/g, '"')
20
+ .replace(/\\\\/g, '\\');
21
+ }
22
+ return trimmed;
23
+ });
24
+ };
25
+ const parsePoint = (v) => {
26
+ const [x, y] = v.replace(/[()]/g, '').split(',');
27
+ return { x: parseFloat(x), y: parseFloat(y) };
28
+ };
29
+ const Parsers = {
30
+ 16: (v) => v === 't', // BOOL
31
+ 21: (v) => parseInt(v, 10), // INT2 (SMALLINT)
32
+ 23: (v) => parseInt(v, 10), // INT4 (INTEGER)
33
+ 26: (v) => parseInt(v, 10), // OID
34
+ 20: (v) => parseInt(v), // INT8 (BIGINT)
35
+ 700: (v) => parseFloat(v), // FLOAT4 (REAL)
36
+ 701: (v) => parseFloat(v), // FLOAT8 (DOUBLE PRECISION)
37
+ 1700: (v) => parseFloat(v), // NUMERIC (DECIMAL)
38
+ 18: (v) => v, // CHAR
39
+ 19: (v) => v, // NAME
40
+ 25: (v) => v, // TEXT
41
+ 1042: (v) => v, // BPCHAR (CHAR(N))
42
+ 1043: (v) => v, // VARCHAR
43
+ 2950: (v) => v, // UUID
44
+ 17: (v) => Buffer.from(v.substring(2), 'hex'), // BYTEA
45
+ 1082: (v) => new Date(v), // DATE
46
+ 1114: (v) => new Date(v + 'Z'), // TIMESTAMP
47
+ 1184: (v) => new Date(v), // TIMESTAMPTZ
48
+ 1083: (v) => v, // TIME
49
+ 1266: (v) => v, // TIMETZ
50
+ 1186: (v) => v, // INTERVAL
51
+ 114: (v) => JSON.parse(v), // JSON
52
+ 3802: (v) => JSON.parse(v), // JSONB
53
+ 869: (v) => v, // INET (IP-адреса)
54
+ 650: (v) => v, // CIDR
55
+ 829: (v) => v, // MACADDR
56
+ 600: parsePoint, // POINT
57
+ 603: (v) => v.replace(/[()]/g, '') // POLYGON
58
+ .split(',')
59
+ .map(parsePoint),
60
+ 1000: (v) => parsePostgresArray(v).map(el => el === 't'),
61
+ 1005: (v) => parsePostgresArray(v).map(el => parseInt(el, 10)),
62
+ 1007: (v) => parsePostgresArray(v).map(el => parseInt(el, 10)), // int4[]
63
+ 1016: (v) => parsePostgresArray(v).map(el => BigInt(el)), // int8[]
64
+ 1021: (v) => parsePostgresArray(v).map(el => parseFloat(el)),
65
+ 1022: (v) => parsePostgresArray(v).map(el => parseFloat(el)), // float8[]
66
+ 1231: (v) => parsePostgresArray(v).map(el => parseFloat(el)), // numeric[]
67
+ 1009: (v) => parsePostgresArray(v), // text[]
68
+ 1015: (v) => parsePostgresArray(v), // varchar[]
69
+ 199: (v) => parsePostgresArray(v).map(el => JSON.parse(el)), // json[]
70
+ 3807: (v) => parsePostgresArray(v).map(el => JSON.parse(el)), // jsonb[]
71
+ };
72
+ const defaultParser = (v) => v;
73
+ function parseRowValues(columns, rows) {
74
+ const result = [];
75
+ const columnsLength = columns.length;
76
+ const columnParsers = columns.map(col => Parsers[col.typeOID] || defaultParser);
77
+ for (let r = 0; r < rows.length; r++) {
78
+ const rawRow = rows[r];
79
+ const rowObject = {};
80
+ for (let c = 0; c < columnsLength; c++) {
81
+ const val = rawRow[c];
82
+ const colName = columns[c].name;
83
+ if (val === null) {
84
+ rowObject[colName] = null;
85
+ continue;
86
+ }
87
+ try {
88
+ rowObject[colName] = columnParsers[c](val);
89
+ }
90
+ catch {
91
+ rowObject[colName] = val;
92
+ }
93
+ }
94
+ result.push(rowObject);
95
+ }
96
+ return result;
97
+ }
98
+ const setTypeParser = (typeOID, parser) => {
99
+ Parsers[typeOID] = parser;
100
+ };
101
+ exports.setTypeParser = setTypeParser;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@m2k-5f/pgtx",
3
- "version": "1.4.11",
4
- "description": "Lightweight, high-performance SQL toolkit for node-postgres",
3
+ "version": "2.0.0",
4
+ "description": "Blazing-fast PostgreSQL driver with pipeline support.",
5
5
  "files": [
6
6
  "dist",
7
7
  "README.md"
@@ -9,7 +9,8 @@
9
9
  "scripts": {
10
10
  "build": "tsc",
11
11
  "prepublishOnly": "npm run build",
12
- "test": "node --import tsx --test $(find tests -name '*.test.ts')"
12
+ "testGitHub": "node --import tsx --test $(find tests -name '*.test.ts')",
13
+ "test": "node --import tsx --test ./tests/*.test.ts"
13
14
  },
14
15
  "repository": {
15
16
  "type": "git",
@@ -18,7 +19,8 @@
18
19
  "keywords": [
19
20
  "sql",
20
21
  "postgres",
21
- "pg",
22
+ "driver",
23
+ "pipeline",
22
24
  "query-builder",
23
25
  "typescript",
24
26
  "transactions",
@@ -37,12 +39,9 @@
37
39
  "types": "./dist/index.d.ts"
38
40
  }
39
41
  },
40
- "dependencies": {
41
- "pg": "^8.11.0"
42
- },
43
42
  "devDependencies": {
44
- "@types/pg": "^8.11.0",
45
43
  "tsx": "^4.21.0",
46
- "typescript": "^5.0.0"
44
+ "typescript": "^5.0.0",
45
+ "@types/node": "^26.1.1"
47
46
  }
48
47
  }