postgrejs 2.19.0 → 2.21.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/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ # v2.21.0
2
+ [2024-09-14]
3
+
4
+ ### Changes
5
+
6
+ * Abort pending operations when the socket closes ([`705063a`](https://github.com/panates/postgrejs/commit/705063a4a15267b1ce634a32f2b997c55b6aff45))
7
+ * chore: fixed lint issues ([`f13dab2`](https://github.com/panates/postgrejs/commit/f13dab2858dac384de4c8b3c21f650995f66ff5e))
8
+ * Throw exception when trying to run query on a connection that is not yeat ready or closing/closed ([`96bd55b`](https://github.com/panates/postgrejs/commit/96bd55bc4e6bb941a2891c79f316653c8c03e1da))
9
+
10
+ # v2.20.0
11
+ [2024-09-14]
12
+
13
+ ### Changes
14
+
15
+ * chore: Typing improvements ([`adb46c3`](https://github.com/panates/postgrejs/commit/adb46c3ae486e9182aa9a979bed4848c71e69af4))
16
+ * chore: Typing improvements ([`d414463`](https://github.com/panates/postgrejs/commit/d41446345caa940294996b5662683acca12d9578))
17
+
1
18
  # v2.19.0
2
19
  [2024-08-20]
3
20
 
@@ -55,7 +55,7 @@ class IntlConnection extends safe_event_emitter_js_1.SafeEventEmitter {
55
55
  if (this.socket.state === constants_js_1.ConnectionState.READY)
56
56
  return;
57
57
  await new Promise((resolve, reject) => {
58
- const handleConnectError = err => reject(err);
58
+ const handleConnectError = (err) => reject(err);
59
59
  this.socket.once('ready', () => {
60
60
  this.socket.removeListener('error', handleConnectError);
61
61
  resolve();
@@ -198,6 +198,7 @@ class IntlConnection extends safe_event_emitter_js_1.SafeEventEmitter {
198
198
  case protocol_js_1.Protocol.BackendMessageCode.DataRow:
199
199
  {
200
200
  let row = msg.columns.map((x) => x.toString('utf8'));
201
+ // The null override assumes we can trust PG to always send the RowDescription first
201
202
  (0, parse_row_js_1.parseRow)(parsers, row, opts);
202
203
  if (opts.objectRows && current.fields)
203
204
  row = (0, convert_row_to_object_js_1.convertRowToObject)(current.fields, row);
@@ -91,7 +91,9 @@ class Portal {
91
91
  break;
92
92
  case protocol_js_1.Protocol.BackendMessageCode.DataRow:
93
93
  if (Array.isArray(this._columnFormat)) {
94
- rows.push(msg.columns.map((buf, i) => this._columnFormat[i] === protocol_js_1.Protocol.DataFormat.text ? buf.toString('utf8') : buf));
94
+ rows.push(msg.columns.map((buf, i) => this._columnFormat[i] === protocol_js_1.Protocol.DataFormat.text
95
+ ? buf.toString('utf8')
96
+ : buf));
95
97
  }
96
98
  else if (this._columnFormat === protocol_js_1.Protocol.DataFormat.binary)
97
99
  rows.push(msg.columns);
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ArrayByteaType = exports.ByteaType = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ // @ts-ignore -- no type definitions for decodeBytea
5
6
  const postgres_bytea_1 = tslib_1.__importDefault(require("postgres-bytea"));
6
7
  const constants_js_1 = require("../constants.js");
7
8
  exports.ByteaType = {
@@ -100,13 +100,17 @@ class Frontend {
100
100
  io.writeUInt16BE(params.length);
101
101
  for (let i = 0; i < params?.length; i++) {
102
102
  let v = params[i];
103
- if (v == null) {
103
+ if (v === null || v === undefined) {
104
104
  io.writeInt32BE(-1);
105
105
  continue;
106
106
  }
107
107
  const dataTypeOid = paramTypes ? paramTypes[i] : undefined;
108
108
  const dt = dataTypeOid ? args.typeMap.get(dataTypeOid) : undefined;
109
109
  if (dt) {
110
+ if (typeof dt.encodeAsNull === 'function' && dt.encodeAsNull(v, queryOptions)) {
111
+ io.writeInt32BE(-1);
112
+ continue;
113
+ }
110
114
  if (typeof dt.encodeBinary === 'function') {
111
115
  // Set param format to binary
112
116
  io.buffer.writeInt16BE(protocol_js_1.Protocol.DataFormat.binary, formatOffset + i * 2);
@@ -45,7 +45,7 @@ class PgSocket extends safe_event_emitter_js_1.SafeEventEmitter {
45
45
  this._state = constants_js_1.ConnectionState.CONNECTING;
46
46
  const options = this.options;
47
47
  const socket = (this._socket = new net_1.default.Socket());
48
- const errorHandler = err => {
48
+ const errorHandler = (err) => {
49
49
  this._state = constants_js_1.ConnectionState.CLOSED;
50
50
  this._removeListeners();
51
51
  this._reset();
@@ -154,8 +154,14 @@ class PgSocket extends safe_event_emitter_js_1.SafeEventEmitter {
154
154
  this._send(this._frontend.getSyncMessage());
155
155
  }
156
156
  capture(callback) {
157
+ if (this._state === constants_js_1.ConnectionState.CLOSING || this._state === constants_js_1.ConnectionState.CLOSED) {
158
+ return Promise.reject(new Error('Connection closed'));
159
+ }
160
+ if (this._state !== constants_js_1.ConnectionState.READY)
161
+ return Promise.reject(new Error('Connection is not ready'));
157
162
  return new Promise((resolve, reject) => {
158
163
  const done = (err, result) => {
164
+ this.removeListener('close', closeHandler);
159
165
  this.removeListener('error', errorHandler);
160
166
  this.removeListener('message', msgHandler);
161
167
  if (err)
@@ -164,14 +170,21 @@ class PgSocket extends safe_event_emitter_js_1.SafeEventEmitter {
164
170
  resolve(result);
165
171
  };
166
172
  const errorHandler = (err) => {
173
+ this.removeListener('close', closeHandler);
167
174
  this.removeListener('message', msgHandler);
168
175
  reject(err);
169
176
  };
177
+ const closeHandler = () => {
178
+ this.removeListener('error', errorHandler);
179
+ this.removeListener('message', msgHandler);
180
+ reject(new Error('Connection closed'));
181
+ };
170
182
  const msgHandler = (code, msg) => {
171
183
  const x = callback(code, msg, done);
172
184
  if (putil_promisify_1.default.isPromise(x))
173
185
  x.catch(err => done(err));
174
186
  };
187
+ this.once('close', closeHandler);
175
188
  this.once('error', errorHandler);
176
189
  this.on('message', msgHandler);
177
190
  });
@@ -86,7 +86,7 @@ var SASL;
86
86
  const hi = function (text, salt, iterations) {
87
87
  return crypto_1.default.pbkdf2Sync(text, Buffer.from(salt, 'base64'), iterations, 32, 'sha256');
88
88
  };
89
- const encode64 = str => Buffer.from(str).toString('base64');
89
+ const encode64 = (str) => Buffer.from(str).toString('base64');
90
90
  const hmac = function (key, msg) {
91
91
  return crypto_1.default.createHmac('sha256', key).update(msg).digest();
92
92
  };
@@ -0,0 +1 @@
1
+ {"root":["../../src/constants.ts","../../src/data-type-map.ts","../../src/index.ts","../../src/safe-event-emitter.ts","../../src/types.ts","../../src/connection/bind-param.ts","../../src/connection/connection.ts","../../src/connection/cursor.ts","../../src/connection/intl-connection.ts","../../src/connection/pool.ts","../../src/connection/portal.ts","../../src/connection/prepared-statement.ts","../../src/data-types/bool-type.ts","../../src/data-types/box-type.ts","../../src/data-types/bytea-type.ts","../../src/data-types/char-type.ts","../../src/data-types/circle-type.ts","../../src/data-types/date-type.ts","../../src/data-types/float4-type.ts","../../src/data-types/float8-type.ts","../../src/data-types/int2-type.ts","../../src/data-types/int2-vector-type.ts","../../src/data-types/int4-type.ts","../../src/data-types/int8-type.ts","../../src/data-types/json-type.ts","../../src/data-types/jsonb-type.ts","../../src/data-types/lseg-type.ts","../../src/data-types/numeric-type.ts","../../src/data-types/oid-type.ts","../../src/data-types/point-type.ts","../../src/data-types/time-type.ts","../../src/data-types/timestamp-type.ts","../../src/data-types/timestamptz-type.ts","../../src/data-types/uuid-type.ts","../../src/data-types/varchar-type.ts","../../src/interfaces/command-result.ts","../../src/interfaces/data-mapping-options.ts","../../src/interfaces/data-type.ts","../../src/interfaces/database-connection-params.ts","../../src/interfaces/field-info.ts","../../src/interfaces/query-options.ts","../../src/interfaces/query-result.ts","../../src/interfaces/script-execute-options.ts","../../src/interfaces/script-result.ts","../../src/interfaces/statement-prepare-options.ts","../../src/protocol/backend.ts","../../src/protocol/buffer-reader.ts","../../src/protocol/database-error.ts","../../src/protocol/frontend.ts","../../src/protocol/pg-socket.ts","../../src/protocol/protocol.ts","../../src/protocol/sasl.ts","../../src/protocol/smart-buffer.ts","../../src/util/array-calculatedim.ts","../../src/util/bigint-methods.ts","../../src/util/config-from-env.ts","../../src/util/connection-config.ts","../../src/util/convert-row-to-object.ts","../../src/util/decode-binaryarray.ts","../../src/util/encode-binaryarray.ts","../../src/util/escape-literal.ts","../../src/util/fast-parseint.ts","../../src/util/get-parsers.ts","../../src/util/parse-array.ts","../../src/util/parse-datetime.ts","../../src/util/parse-row.ts","../../src/util/parse-time.ts","../../src/util/stringify-arrayliteral.ts","../../src/util/stringify-for-sql.ts","../../src/util/wrap-row-description.ts"],"version":"5.6.2"}
@@ -51,7 +51,7 @@ export class IntlConnection extends SafeEventEmitter {
51
51
  if (this.socket.state === ConnectionState.READY)
52
52
  return;
53
53
  await new Promise((resolve, reject) => {
54
- const handleConnectError = err => reject(err);
54
+ const handleConnectError = (err) => reject(err);
55
55
  this.socket.once('ready', () => {
56
56
  this.socket.removeListener('error', handleConnectError);
57
57
  resolve();
@@ -194,6 +194,7 @@ export class IntlConnection extends SafeEventEmitter {
194
194
  case Protocol.BackendMessageCode.DataRow:
195
195
  {
196
196
  let row = msg.columns.map((x) => x.toString('utf8'));
197
+ // The null override assumes we can trust PG to always send the RowDescription first
197
198
  parseRow(parsers, row, opts);
198
199
  if (opts.objectRows && current.fields)
199
200
  row = convertRowToObject(current.fields, row);
@@ -88,7 +88,9 @@ export class Portal {
88
88
  break;
89
89
  case Protocol.BackendMessageCode.DataRow:
90
90
  if (Array.isArray(this._columnFormat)) {
91
- rows.push(msg.columns.map((buf, i) => this._columnFormat[i] === Protocol.DataFormat.text ? buf.toString('utf8') : buf));
91
+ rows.push(msg.columns.map((buf, i) => this._columnFormat[i] === Protocol.DataFormat.text
92
+ ? buf.toString('utf8')
93
+ : buf));
92
94
  }
93
95
  else if (this._columnFormat === Protocol.DataFormat.binary)
94
96
  rows.push(msg.columns);
@@ -1,3 +1,4 @@
1
+ // @ts-ignore -- no type definitions for decodeBytea
1
2
  import decodeBytea from 'postgres-bytea';
2
3
  import { DataTypeOIDs } from '../constants.js';
3
4
  export const ByteaType = {
@@ -97,13 +97,17 @@ export class Frontend {
97
97
  io.writeUInt16BE(params.length);
98
98
  for (let i = 0; i < params?.length; i++) {
99
99
  let v = params[i];
100
- if (v == null) {
100
+ if (v === null || v === undefined) {
101
101
  io.writeInt32BE(-1);
102
102
  continue;
103
103
  }
104
104
  const dataTypeOid = paramTypes ? paramTypes[i] : undefined;
105
105
  const dt = dataTypeOid ? args.typeMap.get(dataTypeOid) : undefined;
106
106
  if (dt) {
107
+ if (typeof dt.encodeAsNull === 'function' && dt.encodeAsNull(v, queryOptions)) {
108
+ io.writeInt32BE(-1);
109
+ continue;
110
+ }
107
111
  if (typeof dt.encodeBinary === 'function') {
108
112
  // Set param format to binary
109
113
  io.buffer.writeInt16BE(Protocol.DataFormat.binary, formatOffset + i * 2);
@@ -41,7 +41,7 @@ export class PgSocket extends SafeEventEmitter {
41
41
  this._state = ConnectionState.CONNECTING;
42
42
  const options = this.options;
43
43
  const socket = (this._socket = new net.Socket());
44
- const errorHandler = err => {
44
+ const errorHandler = (err) => {
45
45
  this._state = ConnectionState.CLOSED;
46
46
  this._removeListeners();
47
47
  this._reset();
@@ -150,8 +150,14 @@ export class PgSocket extends SafeEventEmitter {
150
150
  this._send(this._frontend.getSyncMessage());
151
151
  }
152
152
  capture(callback) {
153
+ if (this._state === ConnectionState.CLOSING || this._state === ConnectionState.CLOSED) {
154
+ return Promise.reject(new Error('Connection closed'));
155
+ }
156
+ if (this._state !== ConnectionState.READY)
157
+ return Promise.reject(new Error('Connection is not ready'));
153
158
  return new Promise((resolve, reject) => {
154
159
  const done = (err, result) => {
160
+ this.removeListener('close', closeHandler);
155
161
  this.removeListener('error', errorHandler);
156
162
  this.removeListener('message', msgHandler);
157
163
  if (err)
@@ -160,14 +166,21 @@ export class PgSocket extends SafeEventEmitter {
160
166
  resolve(result);
161
167
  };
162
168
  const errorHandler = (err) => {
169
+ this.removeListener('close', closeHandler);
163
170
  this.removeListener('message', msgHandler);
164
171
  reject(err);
165
172
  };
173
+ const closeHandler = () => {
174
+ this.removeListener('error', errorHandler);
175
+ this.removeListener('message', msgHandler);
176
+ reject(new Error('Connection closed'));
177
+ };
166
178
  const msgHandler = (code, msg) => {
167
179
  const x = callback(code, msg, done);
168
180
  if (promisify.isPromise(x))
169
181
  x.catch(err => done(err));
170
182
  };
183
+ this.once('close', closeHandler);
171
184
  this.once('error', errorHandler);
172
185
  this.on('message', msgHandler);
173
186
  });
@@ -82,7 +82,7 @@ export var SASL;
82
82
  const hi = function (text, salt, iterations) {
83
83
  return crypto.pbkdf2Sync(text, Buffer.from(salt, 'base64'), iterations, 32, 'sha256');
84
84
  };
85
- const encode64 = str => Buffer.from(str).toString('base64');
85
+ const encode64 = (str) => Buffer.from(str).toString('base64');
86
86
  const hmac = function (key, msg) {
87
87
  return crypto.createHmac('sha256', key).update(msg).digest();
88
88
  };
@@ -0,0 +1 @@
1
+ {"root":["../../src/constants.ts","../../src/data-type-map.ts","../../src/index.ts","../../src/safe-event-emitter.ts","../../src/types.ts","../../src/connection/bind-param.ts","../../src/connection/connection.ts","../../src/connection/cursor.ts","../../src/connection/intl-connection.ts","../../src/connection/pool.ts","../../src/connection/portal.ts","../../src/connection/prepared-statement.ts","../../src/data-types/bool-type.ts","../../src/data-types/box-type.ts","../../src/data-types/bytea-type.ts","../../src/data-types/char-type.ts","../../src/data-types/circle-type.ts","../../src/data-types/date-type.ts","../../src/data-types/float4-type.ts","../../src/data-types/float8-type.ts","../../src/data-types/int2-type.ts","../../src/data-types/int2-vector-type.ts","../../src/data-types/int4-type.ts","../../src/data-types/int8-type.ts","../../src/data-types/json-type.ts","../../src/data-types/jsonb-type.ts","../../src/data-types/lseg-type.ts","../../src/data-types/numeric-type.ts","../../src/data-types/oid-type.ts","../../src/data-types/point-type.ts","../../src/data-types/time-type.ts","../../src/data-types/timestamp-type.ts","../../src/data-types/timestamptz-type.ts","../../src/data-types/uuid-type.ts","../../src/data-types/varchar-type.ts","../../src/interfaces/command-result.ts","../../src/interfaces/data-mapping-options.ts","../../src/interfaces/data-type.ts","../../src/interfaces/database-connection-params.ts","../../src/interfaces/field-info.ts","../../src/interfaces/query-options.ts","../../src/interfaces/query-result.ts","../../src/interfaces/script-execute-options.ts","../../src/interfaces/script-result.ts","../../src/interfaces/statement-prepare-options.ts","../../src/protocol/backend.ts","../../src/protocol/buffer-reader.ts","../../src/protocol/database-error.ts","../../src/protocol/frontend.ts","../../src/protocol/pg-socket.ts","../../src/protocol/protocol.ts","../../src/protocol/sasl.ts","../../src/protocol/smart-buffer.ts","../../src/util/array-calculatedim.ts","../../src/util/bigint-methods.ts","../../src/util/config-from-env.ts","../../src/util/connection-config.ts","../../src/util/convert-row-to-object.ts","../../src/util/decode-binaryarray.ts","../../src/util/encode-binaryarray.ts","../../src/util/escape-literal.ts","../../src/util/fast-parseint.ts","../../src/util/get-parsers.ts","../../src/util/parse-array.ts","../../src/util/parse-datetime.ts","../../src/util/parse-row.ts","../../src/util/parse-time.ts","../../src/util/stringify-arrayliteral.ts","../../src/util/stringify-for-sql.ts","../../src/util/wrap-row-description.ts"],"version":"5.6.2"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "postgrejs",
3
3
  "description": "Professional PostgreSQL client NodeJS",
4
- "version": "2.19.0",
4
+ "version": "2.21.0",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
7
7
  "dependencies": {
@@ -12,7 +12,7 @@
12
12
  "putil-merge": "^3.13.0",
13
13
  "putil-promisify": "^1.10.1",
14
14
  "putil-varhelpers": "^1.6.5",
15
- "tslib": "^2.6.3"
15
+ "tslib": "^2.7.0"
16
16
  },
17
17
  "type": "module",
18
18
  "exports": {
@@ -1,12 +1,12 @@
1
1
  import { TaskQueue } from 'power-tasks';
2
2
  import { ConnectionState } from '../constants.js';
3
- import { ConnectionConfiguration } from '../interfaces/database-connection-params.js';
4
- import { ScriptExecuteOptions } from '../interfaces/script-execute-options.js';
5
- import { ScriptResult } from '../interfaces/script-result.js';
3
+ import type { ConnectionConfiguration } from '../interfaces/database-connection-params.js';
4
+ import type { ScriptExecuteOptions } from '../interfaces/script-execute-options.js';
5
+ import type { ScriptResult } from '../interfaces/script-result.js';
6
6
  import { PgSocket } from '../protocol/pg-socket.js';
7
7
  import { SafeEventEmitter } from '../safe-event-emitter.js';
8
- import { Maybe } from '../types.js';
9
- import { Connection } from './connection.js';
8
+ import type { Maybe } from '../types.js';
9
+ import type { Connection } from './connection.js';
10
10
  export declare class IntlConnection extends SafeEventEmitter {
11
11
  protected _refCount: number;
12
12
  protected _config: ConnectionConfiguration;
@@ -125,6 +125,4 @@ export declare const DataTypeOIDs: {
125
125
  _uuid: number;
126
126
  _jsonb: number;
127
127
  };
128
- export declare const DataTypeNames: {
129
- [x: number]: string;
130
- };
128
+ export declare const DataTypeNames: Record<string, string>;
@@ -1,4 +1,4 @@
1
- import type { DecodeBinaryFunction, EncodeBinaryFunction, EncodeTextFunction, OID, ParseTextFunction } from '../types.js';
1
+ import type { DecodeBinaryFunction, EncodeAsNullFunction, EncodeBinaryFunction, EncodeTextFunction, OID, ParseTextFunction } from '../types.js';
2
2
  import { EncodeCalculateDimFunction } from '../types.js';
3
3
  export interface DataType {
4
4
  oid: OID;
@@ -10,6 +10,7 @@ export interface DataType {
10
10
  isType: (v: any) => boolean;
11
11
  parseBinary: DecodeBinaryFunction;
12
12
  parseText: ParseTextFunction;
13
+ encodeAsNull?: EncodeAsNullFunction;
13
14
  encodeBinary?: EncodeBinaryFunction;
14
15
  encodeText?: EncodeTextFunction;
15
16
  encodeCalculateDim?: EncodeCalculateDimFunction;
package/types/types.d.ts CHANGED
@@ -8,6 +8,7 @@ export type Callback = (err?: Error, value?: any) => void;
8
8
  export type DecodeBinaryFunction = (buf: Buffer, options: DataMappingOptions & Record<string, any>) => any;
9
9
  export type EncodeBinaryFunction = (buf: SmartBuffer, v: any, options: DataMappingOptions) => void;
10
10
  export type EncodeCalculateDimFunction = (v: any[]) => number[];
11
+ export type EncodeAsNullFunction = (v: any, options: DataMappingOptions) => boolean;
11
12
  export type ParseTextFunction = (v: any, options: DataMappingOptions) => any;
12
13
  export type EncodeTextFunction = (v: any, options: DataMappingOptions) => string;
13
14
  export type AnyParseFunction = ParseTextFunction | DecodeBinaryFunction;