postgrejs 3.11.1 → 3.12.1

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 (187) hide show
  1. package/connection/bind-param.d.ts +21 -0
  2. package/connection/bind-param.js +21 -0
  3. package/connection/connection.d.ts +136 -0
  4. package/connection/connection.js +132 -5
  5. package/connection/copy-stream.d.ts +2 -0
  6. package/connection/copy-stream.js +2 -0
  7. package/connection/cursor.d.ts +67 -5
  8. package/connection/cursor.js +88 -15
  9. package/connection/intl-connection.d.ts +22 -0
  10. package/connection/intl-connection.js +107 -17
  11. package/connection/large-object.d.ts +18 -0
  12. package/connection/large-object.js +17 -0
  13. package/connection/logical-replication.d.ts +15 -0
  14. package/connection/logical-replication.js +6 -0
  15. package/connection/pool.d.ts +80 -0
  16. package/connection/pool.js +82 -9
  17. package/connection/portal.d.ts +37 -0
  18. package/connection/portal.js +29 -0
  19. package/connection/prepared-statement.d.ts +109 -0
  20. package/connection/prepared-statement.js +150 -7
  21. package/constants.d.ts +18 -0
  22. package/constants.js +18 -0
  23. package/data-type-map.d.ts +38 -0
  24. package/data-type-map.js +38 -0
  25. package/data-types/bit-type.d.ts +4 -0
  26. package/data-types/bit-type.js +4 -0
  27. package/data-types/bool-type.d.ts +2 -0
  28. package/data-types/bool-type.js +2 -0
  29. package/data-types/box-type.d.ts +2 -0
  30. package/data-types/box-type.js +2 -0
  31. package/data-types/bytea-type.d.ts +2 -0
  32. package/data-types/bytea-type.js +2 -0
  33. package/data-types/char-type.d.ts +2 -0
  34. package/data-types/char-type.js +2 -0
  35. package/data-types/circle-type.d.ts +2 -0
  36. package/data-types/circle-type.js +2 -0
  37. package/data-types/date-type.d.ts +2 -0
  38. package/data-types/date-type.js +2 -0
  39. package/data-types/float4-type.d.ts +2 -0
  40. package/data-types/float4-type.js +2 -0
  41. package/data-types/float8-type.d.ts +2 -0
  42. package/data-types/float8-type.js +2 -0
  43. package/data-types/inet-type.d.ts +4 -0
  44. package/data-types/inet-type.js +4 -0
  45. package/data-types/int2-type.d.ts +2 -0
  46. package/data-types/int2-type.js +3 -1
  47. package/data-types/int2-vector-type.d.ts +2 -0
  48. package/data-types/int2-vector-type.js +2 -0
  49. package/data-types/int4-type.d.ts +2 -0
  50. package/data-types/int4-type.js +3 -1
  51. package/data-types/int8-type.d.ts +2 -0
  52. package/data-types/int8-type.js +4 -2
  53. package/data-types/interval-type.d.ts +9 -0
  54. package/data-types/interval-type.js +9 -0
  55. package/data-types/json-type.d.ts +2 -0
  56. package/data-types/json-type.js +2 -0
  57. package/data-types/jsonb-type.d.ts +2 -0
  58. package/data-types/jsonb-type.js +2 -0
  59. package/data-types/jsonpath-type.d.ts +2 -0
  60. package/data-types/jsonpath-type.js +2 -0
  61. package/data-types/line-type.d.ts +2 -0
  62. package/data-types/line-type.js +2 -0
  63. package/data-types/lseg-type.d.ts +2 -0
  64. package/data-types/lseg-type.js +2 -0
  65. package/data-types/macaddr-type.d.ts +4 -0
  66. package/data-types/macaddr-type.js +4 -0
  67. package/data-types/money-type.d.ts +1 -0
  68. package/data-types/money-type.js +17 -10
  69. package/data-types/numeric-type.d.ts +2 -0
  70. package/data-types/numeric-type.js +2 -0
  71. package/data-types/oid-type.d.ts +2 -0
  72. package/data-types/oid-type.js +3 -1
  73. package/data-types/oid-vector-type.d.ts +1 -0
  74. package/data-types/oid-vector-type.js +1 -0
  75. package/data-types/path-type.d.ts +4 -0
  76. package/data-types/path-type.js +4 -0
  77. package/data-types/pg-lsn-type.d.ts +2 -0
  78. package/data-types/pg-lsn-type.js +2 -0
  79. package/data-types/point-type.d.ts +2 -0
  80. package/data-types/point-type.js +2 -0
  81. package/data-types/range-type.d.ts +4 -0
  82. package/data-types/range-type.js +4 -0
  83. package/data-types/snapshot-type.d.ts +4 -0
  84. package/data-types/snapshot-type.js +4 -0
  85. package/data-types/tid-type.d.ts +2 -0
  86. package/data-types/tid-type.js +2 -0
  87. package/data-types/time-type.d.ts +2 -0
  88. package/data-types/time-type.js +2 -0
  89. package/data-types/timestamp-type.d.ts +2 -0
  90. package/data-types/timestamp-type.js +2 -0
  91. package/data-types/timestamptz-type.d.ts +2 -0
  92. package/data-types/timestamptz-type.js +2 -0
  93. package/data-types/timetz-type.d.ts +2 -0
  94. package/data-types/timetz-type.js +2 -0
  95. package/data-types/tsvector-type.d.ts +4 -0
  96. package/data-types/tsvector-type.js +4 -0
  97. package/data-types/uuid-type.d.ts +2 -0
  98. package/data-types/uuid-type.js +2 -0
  99. package/data-types/varchar-type.d.ts +2 -0
  100. package/data-types/varchar-type.js +2 -0
  101. package/data-types/xid-type.d.ts +6 -0
  102. package/data-types/xid-type.js +8 -1
  103. package/interfaces/command-result.d.ts +7 -0
  104. package/interfaces/copy-from-rows-options.d.ts +4 -0
  105. package/interfaces/data-mapping-options.d.ts +6 -0
  106. package/interfaces/data-type.d.ts +37 -0
  107. package/interfaces/database-connection-params.d.ts +31 -0
  108. package/interfaces/field-info.d.ts +8 -0
  109. package/interfaces/function-call-options.d.ts +1 -0
  110. package/interfaces/function-call-result.d.ts +6 -0
  111. package/interfaces/pipeline-request.d.ts +2 -0
  112. package/interfaces/query-options.d.ts +7 -0
  113. package/interfaces/query-result.d.ts +7 -0
  114. package/interfaces/script-execute-options.d.ts +4 -0
  115. package/interfaces/script-result.d.ts +1 -0
  116. package/interfaces/statement-prepare-options.d.ts +1 -0
  117. package/package.json +5 -5
  118. package/protocol/backend.d.ts +6 -0
  119. package/protocol/backend.js +35 -5
  120. package/protocol/cert-signature.d.ts +8 -0
  121. package/protocol/cert-signature.js +8 -0
  122. package/protocol/database-error.d.ts +8 -0
  123. package/protocol/database-error.js +8 -0
  124. package/protocol/frontend.d.ts +16 -0
  125. package/protocol/frontend.js +13 -6
  126. package/protocol/pg-socket.d.ts +10 -0
  127. package/protocol/pg-socket.js +14 -7
  128. package/protocol/pgoutput.d.ts +15 -0
  129. package/protocol/pgoutput.js +7 -0
  130. package/protocol/protocol.d.ts +50 -2
  131. package/protocol/protocol.js +17 -1
  132. package/protocol/sasl.d.ts +22 -0
  133. package/protocol/sasl.js +21 -0
  134. package/protocol/smart-buffer.d.ts +4 -0
  135. package/safe-event-emitter.d.ts +7 -0
  136. package/safe-event-emitter.js +7 -0
  137. package/types.d.ts +21 -0
  138. package/util/array-calculatedim.d.ts +10 -0
  139. package/util/array-calculatedim.js +10 -0
  140. package/util/assert-integer.d.ts +40 -25
  141. package/util/assert-integer.js +97 -32
  142. package/util/bigint-methods.d.ts +7 -0
  143. package/util/bigint-methods.js +9 -0
  144. package/util/config-from-env.d.ts +10 -0
  145. package/util/config-from-env.js +10 -0
  146. package/util/connection-config.d.ts +17 -0
  147. package/util/connection-config.js +17 -0
  148. package/util/copy-from-rows.d.ts +12 -0
  149. package/util/copy-from-rows.js +9 -0
  150. package/util/decimal-as-string.d.ts +6 -0
  151. package/util/decimal-as-string.js +6 -0
  152. package/util/decode-binaryarray.d.ts +9 -0
  153. package/util/decode-binaryarray.js +9 -0
  154. package/util/escape-literal.d.ts +11 -0
  155. package/util/escape-literal.js +13 -0
  156. package/util/fast-parseint.d.ts +14 -0
  157. package/util/fast-parseint.js +14 -0
  158. package/util/format-datetime.d.ts +26 -0
  159. package/util/format-datetime.js +26 -0
  160. package/util/get-parsers.d.ts +9 -0
  161. package/util/get-parsers.js +9 -0
  162. package/util/hex-text.d.ts +13 -21
  163. package/util/hex-text.js +24 -21
  164. package/util/local-date.d.ts +2 -41
  165. package/util/local-date.js +39 -41
  166. package/util/parse-array.d.ts +8 -0
  167. package/util/parse-array.js +8 -0
  168. package/util/parse-bytea.d.ts +15 -0
  169. package/util/parse-bytea.js +15 -0
  170. package/util/parse-datetime.d.ts +26 -0
  171. package/util/parse-datetime.js +26 -0
  172. package/util/parse-row.d.ts +23 -2
  173. package/util/parse-row.js +56 -36
  174. package/util/parse-time.d.ts +10 -0
  175. package/util/parse-time.js +10 -0
  176. package/util/resolve-column-formats.d.ts +1 -0
  177. package/util/row-decoder.d.ts +32 -0
  178. package/util/row-decoder.js +22 -0
  179. package/util/stringify-arrayliteral.d.ts +33 -0
  180. package/util/stringify-arrayliteral.js +242 -7
  181. package/util/stringify-for-sql.d.ts +17 -0
  182. package/util/stringify-for-sql.js +17 -0
  183. package/util/unspecified-param.d.ts +26 -2
  184. package/util/unspecified-param.js +26 -2
  185. package/util/wrap-row-description.d.ts +10 -0
  186. package/util/wrap-row-description.js +10 -0
  187. package/CHANGELOG.md +0 -1426
@@ -9,4 +9,12 @@
9
9
  * signatureAlgorithm and signatureValue, so this skips the first and reads
10
10
  * the OID out of the second.
11
11
  */
12
+ /**
13
+ * The hash a certificate was signed with, for `tls-server-end-point`
14
+ * channel binding.
15
+ *
16
+ * @param der The server's certificate, as DER.
17
+ * @returns The Node digest name to bind with - SHA-256 where the
18
+ * signature's own hash is MD5 or SHA-1, as the RFC requires.
19
+ */
12
20
  export declare function signatureHashOfCertificate(der: Buffer): string;
@@ -79,6 +79,14 @@ const PSS_HASHES = {
79
79
  '2.16.840.1.101.3.4.2.2': 'sha384',
80
80
  '2.16.840.1.101.3.4.2.3': 'sha512',
81
81
  };
82
+ /**
83
+ * The hash a certificate was signed with, for `tls-server-end-point`
84
+ * channel binding.
85
+ *
86
+ * @param der The server's certificate, as DER.
87
+ * @returns The Node digest name to bind with - SHA-256 where the
88
+ * signature's own hash is MD5 or SHA-1, as the RFC requires.
89
+ */
82
90
  export function signatureHashOfCertificate(der) {
83
91
  let index = expectSequence(der, 0).index; // Certificate
84
92
  const tbs = readLength(der, index + 1); // tbsCertificate's own header
@@ -1,5 +1,13 @@
1
1
  import type { BatchCommandResult } from '../interfaces/batch-result.js';
2
2
  import { Protocol } from './protocol.js';
3
+ /**
4
+ * An error the server reported, with every field it sent.
5
+ *
6
+ * `code` is the five-character SQLSTATE and is the thing to branch on -
7
+ * `23505` for a unique violation, `40P01` for a deadlock - since the
8
+ * message is localized and may be reworded between releases. `detail`,
9
+ * `hint`, `position` and the rest are there when the server sent them.
10
+ */
3
11
  export declare class DatabaseError extends Error {
4
12
  /**
5
13
  * Which entry of a multi-statement submission the server rejected -
@@ -1,4 +1,12 @@
1
1
  import { Protocol } from './protocol.js';
2
+ /**
3
+ * An error the server reported, with every field it sent.
4
+ *
5
+ * `code` is the five-character SQLSTATE and is the thing to branch on -
6
+ * `23505` for a unique violation, `40P01` for a deadlock - since the
7
+ * message is localized and may be reworded between releases. `detail`,
8
+ * `hint`, `position` and the rest are there when the server sent them.
9
+ */
2
10
  export class DatabaseError extends Error {
3
11
  /**
4
12
  * Which entry of a multi-statement submission the server rejected -
@@ -4,15 +4,20 @@ import type { Maybe, OID } from '../types.js';
4
4
  import { Protocol } from './protocol.js';
5
5
  import type { SASL } from './sasl.js';
6
6
  import { type SmartBufferConfig } from './smart-buffer.js';
7
+ /** How a `Frontend` builds its messages - the buffer it writes them into. */
7
8
  export interface FrontendOptions {
9
+ /** The send buffer's own configuration. */
8
10
  buffer?: SmartBufferConfig;
9
11
  }
12
+ /** What each message the client sends is built from. */
10
13
  export declare namespace Frontend {
14
+ /** The startup packet: who is connecting, to what, and any session settings to carry with it. */
11
15
  interface StartupMessageArgs {
12
16
  user: string;
13
17
  database: string;
14
18
  [index: string]: string;
15
19
  }
20
+ /** A Bind: which statement, which portal, the parameters and the formats to read the result in. */
16
21
  interface BindMessageArgs {
17
22
  typeMap: DataTypeMap;
18
23
  statement?: string;
@@ -28,19 +33,23 @@ export declare namespace Frontend {
28
33
  */
29
34
  columnFormat?: Protocol.DataFormat | Protocol.DataFormat[];
30
35
  }
36
+ /** A Parse: the SQL, the name to give it, and any parameter types to declare. */
31
37
  interface ParseMessageArgs {
32
38
  statement?: string;
33
39
  sql: string;
34
40
  paramTypes?: Maybe<OID>[];
35
41
  }
42
+ /** A Describe: of a statement (`S`) or of a portal (`P`). */
36
43
  interface DescribeMessageArgs {
37
44
  type: 'P' | 'S';
38
45
  name?: string;
39
46
  }
47
+ /** An Execute: which portal, and how many rows to stop at. */
40
48
  interface ExecuteMessageArgs {
41
49
  portal?: string;
42
50
  fetchCount?: number;
43
51
  }
52
+ /** A Close: of a statement (`S`) or of a portal (`P`). */
44
53
  interface CloseMessageArgs {
45
54
  type: 'P' | 'S';
46
55
  name?: string;
@@ -69,6 +78,13 @@ export declare namespace Frontend {
69
78
  resultFormat?: Protocol.DataFormat;
70
79
  }
71
80
  }
81
+ /**
82
+ * Builds the client's messages, into one buffer it keeps and reuses.
83
+ *
84
+ * Each method returns the bytes of one message; the socket writes them,
85
+ * often several at a time so a statement costs one round trip rather
86
+ * than one per message.
87
+ */
72
88
  export declare class Frontend {
73
89
  private _io;
74
90
  constructor(options?: FrontendOptions);
@@ -3,7 +3,7 @@ import { DataTypeMap } from '../data-type-map.js';
3
3
  import { arrayLeaf } from '../util/array-leaf.js';
4
4
  import { encodeBinaryArray } from '../util/encode-binaryarray.js';
5
5
  import { formatDateParam } from '../util/format-datetime.js';
6
- import { stringifyArrayLiteral } from '../util/stringify-arrayliteral.js';
6
+ import { writeArrayLiteral } from '../util/stringify-arrayliteral.js';
7
7
  import { Protocol } from './protocol.js';
8
8
  import { SmartBuffer } from './smart-buffer.js';
9
9
  const DataFormat = Protocol.DataFormat;
@@ -35,6 +35,13 @@ const StaticCopyDoneBuffer = Buffer.from([
35
35
  0x00,
36
36
  0x04,
37
37
  ]);
38
+ /**
39
+ * Builds the client's messages, into one buffer it keeps and reuses.
40
+ *
41
+ * Each method returns the bytes of one message; the socket writes them,
42
+ * often several at a time so a statement costs one round trip rather
43
+ * than one per message.
44
+ */
38
45
  export class Frontend {
39
46
  _io;
40
47
  constructor(options) {
@@ -182,10 +189,10 @@ export class Frontend {
182
189
  io.buffer.writeInt32BE(io.size - dataOffset, dataOffset - 4); // Update length
183
190
  }
184
191
  else if (typeof dt.encodeText === 'function') {
185
- v = dt.elementsOID
186
- ? stringifyArrayLiteral(v, queryOptions, dt.encodeText)
187
- : dt.encodeText(v, queryOptions);
188
- io.writeLString(v, 'utf8');
192
+ if (dt.elementsOID)
193
+ writeArrayLiteral(io, v, queryOptions, dt.encodeText);
194
+ else
195
+ io.writeLString(dt.encodeText(v, queryOptions), 'utf8');
189
196
  }
190
197
  }
191
198
  else if (v instanceof Date) {
@@ -201,7 +208,7 @@ export class Frontend {
201
208
  // takes the element type from the column. `'' + v` would hand
202
209
  // it `a,b`, which is not one - the elements have to be quoted
203
210
  // and the braces written, and a nested array needs its own.
204
- io.writeLString(stringifyArrayLiteral(v, queryOptions, arrayLeaf(v) instanceof Date ? formatDateParam : undefined), 'utf8');
211
+ writeArrayLiteral(io, v, queryOptions, arrayLeaf(v) instanceof Date ? formatDateParam : undefined);
205
212
  }
206
213
  else if (Buffer.isBuffer(v)) {
207
214
  // Set param format to binary
@@ -6,10 +6,20 @@ import { SafeEventEmitter } from '../safe-event-emitter.js';
6
6
  import type { Callback, Maybe } from '../types.js';
7
7
  import { Frontend } from './frontend.js';
8
8
  import { Protocol } from './protocol.js';
9
+ /**
10
+ * What a sender registers to receive the messages its statement
11
+ * provokes, until it calls `done`.
12
+ */
9
13
  export type CaptureCallback = (code: Protocol.BackendMessageCode, msg: any, done: (err: Maybe<Error>, result?: any) => void) => void | Promise<void>;
14
+ /** A socket-level failure, with the code the platform gave it. */
10
15
  export interface SocketError extends Error {
11
16
  code: string;
12
17
  }
18
+ /**
19
+ * The connected socket: the handshake, the authentication, TLS where it
20
+ * is asked for, and a queue that pairs each response with whoever sent
21
+ * the statement that caused it.
22
+ */
13
23
  export declare class PgSocket extends SafeEventEmitter {
14
24
  options: ConnectionConfiguration;
15
25
  private _state;
@@ -15,6 +15,11 @@ import { Protocol } from './protocol.js';
15
15
  import { SASL } from './sasl.js';
16
16
  const DEFAULT_PORT_NUMBER = 5432;
17
17
  const COMMAND_RESULT_PATTERN = /^([^\d]+)(?: (\d+)(?: (\d+))?)?$/;
18
+ /**
19
+ * The connected socket: the handshake, the authentication, TLS where it
20
+ * is asked for, and a queue that pairs each response with whoever sent
21
+ * the statement that caused it.
22
+ */
18
23
  export class PgSocket extends SafeEventEmitter {
19
24
  options;
20
25
  _state = ConnectionState.CLOSED;
@@ -588,13 +593,15 @@ export class PgSocket extends SafeEventEmitter {
588
593
  this.sendQueryMessage('select pg_catalog.pg_is_in_recovery()::text as a,' +
589
594
  " current_setting('transaction_read_only') as b", (code, msg, done) => {
590
595
  if (code === Protocol.BackendMessageCode.DataRow) {
591
- // Two text columns, each length-prefixed within the row buffer.
592
- const data = msg.data;
593
- const aLen = data.readInt32BE(0);
594
- const a = data.toString('utf8', 4, 4 + aLen);
595
- const bOffset = 4 + aLen;
596
- const bLen = data.readInt32BE(bOffset);
597
- const b = data.toString('utf8', bOffset + 4, bOffset + 4 + bLen);
596
+ // Two text columns, each length-prefixed, read where the row
597
+ // already sits in the read buffer.
598
+ const buffer = msg.buffer;
599
+ const start = msg.offset;
600
+ const aLen = buffer.readInt32BE(start);
601
+ const a = buffer.toString('utf8', start + 4, start + 4 + aLen);
602
+ const bOffset = start + 4 + aLen;
603
+ const bLen = buffer.readInt32BE(bOffset);
604
+ const b = buffer.toString('utf8', bOffset + 4, bOffset + 4 + bLen);
598
605
  this._standbyState = { standby: a === 'true', readOnly: b === 'on' };
599
606
  }
600
607
  else if (code === Protocol.BackendMessageCode.ReadyForQuery) {
@@ -1,4 +1,5 @@
1
1
  import { BufferReader } from './buffer-reader.js';
2
+ /** One column of a replicated table, as the stream declared it. */
2
3
  export interface PgOutputColumn {
3
4
  name: string;
4
5
  dataTypeId: number;
@@ -6,6 +7,12 @@ export interface PgOutputColumn {
6
7
  /** Part of the replica identity, so it can identify a row on its own. */
7
8
  isKey: boolean;
8
9
  }
10
+ /**
11
+ * A replicated table, declared once and then referred to by id.
12
+ *
13
+ * The stream sends this before the first change to that table and not
14
+ * again, so a decoder has to remember it.
15
+ */
9
16
  export interface PgOutputRelation {
10
17
  relationId: number;
11
18
  schema: string;
@@ -13,6 +20,7 @@ export interface PgOutputRelation {
13
20
  replicaIdentity: string;
14
21
  columns: PgOutputColumn[];
15
22
  }
23
+ /** Any message the `pgoutput` plugin sends, decoded. */
16
24
  export type PgOutputMessage = {
17
25
  kind: 'begin';
18
26
  finalLsn: bigint;
@@ -66,6 +74,13 @@ export type PgOutputMessage = {
66
74
  * from the map entirely - which is not the same as being null.
67
75
  */
68
76
  export type TupleValues = Record<string, string | null>;
77
+ /**
78
+ * Reads the `pgoutput` logical replication stream.
79
+ *
80
+ * Keeps the relations the stream declares, so each change can be
81
+ * reported with the table and column names it belongs to rather than
82
+ * the ids the wire uses.
83
+ */
69
84
  export declare class PgOutputDecoder {
70
85
  protected readonly _relations: Map<number, PgOutputRelation>;
71
86
  decode(data: Buffer): PgOutputMessage;
@@ -10,6 +10,13 @@ import { BufferReader } from './buffer-reader.js';
10
10
  */
11
11
  /** Microseconds since 2000-01-01, which is how this protocol tells time. */
12
12
  const PG_EPOCH_MS = Date.UTC(2000, 0, 1);
13
+ /**
14
+ * Reads the `pgoutput` logical replication stream.
15
+ *
16
+ * Keeps the relations the stream declares, so each change can be
17
+ * reported with the table and column names it belongs to rather than
18
+ * the ids the wire uses.
19
+ */
13
20
  export class PgOutputDecoder {
14
21
  _relations = new Map();
15
22
  decode(data) {
@@ -1,5 +1,15 @@
1
+ /**
2
+ * The wire protocol itself: the message codes, the shapes each message
3
+ * carries, and the version numbers the handshake negotiates.
4
+ *
5
+ * These are PostgreSQL's own definitions, named as the documentation
6
+ * names them - nothing here is this client's invention, and a reader
7
+ * comparing it against the protocol pages should find the two line up.
8
+ */
1
9
  export declare namespace Protocol {
10
+ /** The protocol major version, which has been 3 since PostgreSQL 7.4. */
2
11
  const VERSION_MAJOR = 3;
12
+ /** The minor version a connection asks for by default. */
3
13
  const VERSION_MINOR = 0;
4
14
  /**
5
15
  * Minor version 3.2 (PostgreSQL 18+) differs from 3.0 only in that
@@ -11,6 +21,7 @@ export declare namespace Protocol {
11
21
  * never a connection-breaking choice, only ever a possible no-op.
12
22
  */
13
23
  const VERSION_MINOR_LONG_CANCEL_KEY = 2;
24
+ /** The first byte of each message the server sends. */
14
25
  enum BackendMessageCode {
15
26
  Authentication = 82,// R
16
27
  BackendKeyData = 75,// K
@@ -37,6 +48,7 @@ export declare namespace Protocol {
37
48
  ReadyForQuery = 90,// Z
38
49
  RowDescription = 84
39
50
  }
51
+ /** The first byte of each message the client sends. */
40
52
  enum FrontendMessageCode {
41
53
  Bind = 66,// B
42
54
  Close = 67,// C
@@ -53,6 +65,7 @@ export declare namespace Protocol {
53
65
  Sync = 83,// S
54
66
  Terminate = 88
55
67
  }
68
+ /** Which authentication the server asked for, by name rather than by its number. */
56
69
  enum AuthenticationMessageKind {
57
70
  KerberosV5 = "KerberosV5",
58
71
  CleartextPassword = "CleartextPassword",
@@ -65,48 +78,64 @@ export declare namespace Protocol {
65
78
  SASLContinue = "SASLContinue",
66
79
  SASLFinal = "SASLFinal"
67
80
  }
81
+ /** How a value travels: as the text the server prints, or in its binary form. */
68
82
  enum DataFormat {
83
+ /** The type's own text, as `::text` would render it. */
69
84
  text = 0,
85
+ /** The type's binary form - fewer bytes, and no text to parse. */
70
86
  binary = 1
71
87
  }
88
+ /** What every Authentication message carries: which kind it is. */
72
89
  interface AuthenticationRequiredMessage {
90
+ /** The authentication the server is asking for. */
73
91
  kind: AuthenticationMessageKind;
74
92
  }
93
+ /** Kerberos V5 authentication is required - not implemented by this client, nor by any modern server. */
75
94
  interface AuthenticationKerberosV5Message extends AuthenticationRequiredMessage {
76
95
  kind: AuthenticationMessageKind.KerberosV5;
77
96
  }
97
+ /** The server wants the password as it is, which only a trusted transport should be asked for. */
78
98
  interface AuthenticationCleartextPasswordMessage extends AuthenticationRequiredMessage {
79
99
  kind: AuthenticationMessageKind.CleartextPassword;
80
100
  }
101
+ /** The server wants the password MD5-hashed with the salt it sent. */
81
102
  interface AuthenticationMD5PasswordMessage extends AuthenticationRequiredMessage {
82
103
  kind: AuthenticationMessageKind.MD5Password;
83
104
  salt: Buffer;
84
105
  }
106
+ /** SCM credential authentication, which only ever applied to some unix sockets. */
85
107
  interface AuthenticationSCMCredentialMessage extends AuthenticationRequiredMessage {
86
108
  kind: AuthenticationMessageKind.SCMCredential;
87
109
  }
110
+ /** GSSAPI authentication is required. */
88
111
  interface AuthenticationGSSMessage extends AuthenticationRequiredMessage {
89
112
  kind: AuthenticationMessageKind.GSS;
90
113
  }
114
+ /** SSPI authentication is required - the Windows spelling of GSSAPI. */
91
115
  interface AuthenticationSSPIMessage extends AuthenticationRequiredMessage {
92
116
  kind: AuthenticationMessageKind.SSPI;
93
117
  }
118
+ /** One more round of GSSAPI/SSPI data. */
94
119
  interface AuthenticationGSSContinueMessage extends AuthenticationRequiredMessage {
95
120
  kind: AuthenticationMessageKind.GSSContinue;
96
121
  data: Buffer;
97
122
  }
123
+ /** SASL authentication is required; the message names which mechanisms the server offers. */
98
124
  interface AuthenticationSASLMessage extends AuthenticationRequiredMessage {
99
125
  kind: AuthenticationMessageKind.SASL;
100
126
  mechanisms: string[];
101
127
  }
128
+ /** The server's half of the SCRAM exchange in progress. */
102
129
  interface AuthenticationSASLContinueMessage extends AuthenticationRequiredMessage {
103
130
  kind: AuthenticationMessageKind.SASLContinue;
104
131
  data: string;
105
132
  }
133
+ /** The server's final SCRAM message, which proves it knew the password too. */
106
134
  interface AuthenticationSASLFinalMessage extends AuthenticationRequiredMessage {
107
135
  kind: AuthenticationMessageKind.SASLFinal;
108
136
  data: string;
109
137
  }
138
+ /** The process id and secret key a cancel request has to carry, sent once at startup. */
110
139
  interface BackendKeyDataMessage {
111
140
  processID: number;
112
141
  /**
@@ -118,25 +147,36 @@ export declare namespace Protocol {
118
147
  */
119
148
  secretKey: Buffer;
120
149
  }
150
+ /** One statement finished: its tag, and what the tag reports. */
121
151
  interface CommandCompleteMessage {
122
152
  command: string;
123
153
  oid?: number;
124
154
  rowCount?: number;
125
155
  }
156
+ /** One chunk of a copy in either direction. */
126
157
  interface CopyDataMessage {
127
158
  data: Buffer;
128
159
  }
160
+ /** A copy is starting: which format it is in, and per column. */
129
161
  interface CopyResponseMessage {
130
162
  overallFormat: DataFormat;
131
163
  columnCount: number;
132
164
  columnFormats?: DataFormat[];
133
165
  }
166
+ /** The DataRow message body, kept for its name; `DataRowMessage` is the shape actually used. */
134
167
  interface DataRow {
135
168
  }
169
+ /** One row, still as the bytes it arrived in - the values are read out of `data` by the column parsers. */
136
170
  interface DataRowMessage {
137
171
  columnCount: number;
138
- data: Buffer;
139
- }
172
+ /** The read buffer the row's values sit in. */
173
+ buffer: Buffer;
174
+ /** Where they start in it. */
175
+ offset: number;
176
+ /** How many bytes they run for. */
177
+ len: number;
178
+ }
179
+ /** An error or a notice, with every field the server chose to send. `code` is the SQLSTATE and is the part to branch on. */
140
180
  interface ErrorResponseMessage {
141
181
  severity?: string;
142
182
  code?: string;
@@ -156,15 +196,18 @@ export declare namespace Protocol {
156
196
  line?: string;
157
197
  routine?: string;
158
198
  }
199
+ /** A `NOTIFY` arriving: which channel, what payload, and which backend sent it. */
159
200
  interface NotificationResponseMessage {
160
201
  processId: number;
161
202
  channel: string;
162
203
  payload: string;
163
204
  }
205
+ /** A fast-path function's return value, undecoded - the protocol says nothing about its type. */
164
206
  interface FunctionCallResponseMessage {
165
207
  /** `null` when the function returned SQL NULL. */
166
208
  result: Buffer | null;
167
209
  }
210
+ /** The server does not speak the minor version that was asked for, and names the highest it does. */
168
211
  interface NegotiateProtocolVersionMessage {
169
212
  /** Newest minor protocol version the server supports. */
170
213
  supportedVersionMinor: number;
@@ -175,17 +218,21 @@ export declare namespace Protocol {
175
218
  */
176
219
  unrecognizedOptions: string[];
177
220
  }
221
+ /** What the server resolved each parameter of a prepared statement to. */
178
222
  interface ParameterDescriptionMessage {
179
223
  parameterCount: number;
180
224
  parameterIds: number[];
181
225
  }
226
+ /** A session setting the server reports, at startup and whenever it changes. */
182
227
  interface ParameterStatusMessage {
183
228
  name: string;
184
229
  value: string;
185
230
  }
231
+ /** The server is ready for the next statement, and says whether a transaction is open. */
186
232
  interface ReadyForQueryMessage {
187
233
  status: string;
188
234
  }
235
+ /** One column of a result, as the server describes it. */
189
236
  interface RowDescription {
190
237
  fieldName: string;
191
238
  tableId: number;
@@ -195,6 +242,7 @@ export declare namespace Protocol {
195
242
  modifier?: number;
196
243
  format: DataFormat;
197
244
  }
245
+ /** The columns a statement will return, sent before its rows. */
198
246
  interface RowDescriptionMessage {
199
247
  fields: RowDescription[];
200
248
  }
@@ -1,6 +1,16 @@
1
+ /**
2
+ * The wire protocol itself: the message codes, the shapes each message
3
+ * carries, and the version numbers the handshake negotiates.
4
+ *
5
+ * These are PostgreSQL's own definitions, named as the documentation
6
+ * names them - nothing here is this client's invention, and a reader
7
+ * comparing it against the protocol pages should find the two line up.
8
+ */
1
9
  export var Protocol;
2
10
  (function (Protocol) {
11
+ /** The protocol major version, which has been 3 since PostgreSQL 7.4. */
3
12
  Protocol.VERSION_MAJOR = 3;
13
+ /** The minor version a connection asks for by default. */
4
14
  Protocol.VERSION_MINOR = 0;
5
15
  /**
6
16
  * Minor version 3.2 (PostgreSQL 18+) differs from 3.0 only in that
@@ -12,7 +22,8 @@ export var Protocol;
12
22
  * never a connection-breaking choice, only ever a possible no-op.
13
23
  */
14
24
  Protocol.VERSION_MINOR_LONG_CANCEL_KEY = 2;
15
- // https://www.postgresql.org/docs/9.3/protocol-message-formats.html
25
+ /** The first byte of each message the server sends. */
26
+ /* https://www.postgresql.org/docs/9.3/protocol-message-formats.html */
16
27
  let BackendMessageCode;
17
28
  (function (BackendMessageCode) {
18
29
  BackendMessageCode[BackendMessageCode["Authentication"] = 82] = "Authentication";
@@ -40,6 +51,7 @@ export var Protocol;
40
51
  BackendMessageCode[BackendMessageCode["ReadyForQuery"] = 90] = "ReadyForQuery";
41
52
  BackendMessageCode[BackendMessageCode["RowDescription"] = 84] = "RowDescription";
42
53
  })(BackendMessageCode = Protocol.BackendMessageCode || (Protocol.BackendMessageCode = {}));
54
+ /** The first byte of each message the client sends. */
43
55
  let FrontendMessageCode;
44
56
  (function (FrontendMessageCode) {
45
57
  FrontendMessageCode[FrontendMessageCode["Bind"] = 66] = "Bind";
@@ -57,6 +69,7 @@ export var Protocol;
57
69
  FrontendMessageCode[FrontendMessageCode["Sync"] = 83] = "Sync";
58
70
  FrontendMessageCode[FrontendMessageCode["Terminate"] = 88] = "Terminate";
59
71
  })(FrontendMessageCode = Protocol.FrontendMessageCode || (Protocol.FrontendMessageCode = {}));
72
+ /** Which authentication the server asked for, by name rather than by its number. */
60
73
  let AuthenticationMessageKind;
61
74
  (function (AuthenticationMessageKind) {
62
75
  AuthenticationMessageKind["KerberosV5"] = "KerberosV5";
@@ -70,9 +83,12 @@ export var Protocol;
70
83
  AuthenticationMessageKind["SASLContinue"] = "SASLContinue";
71
84
  AuthenticationMessageKind["SASLFinal"] = "SASLFinal";
72
85
  })(AuthenticationMessageKind = Protocol.AuthenticationMessageKind || (Protocol.AuthenticationMessageKind = {}));
86
+ /** How a value travels: as the text the server prints, or in its binary form. */
73
87
  let DataFormat;
74
88
  (function (DataFormat) {
89
+ /** The type's own text, as `::text` would render it. */
75
90
  DataFormat[DataFormat["text"] = 0] = "text";
91
+ /** The type's binary form - fewer bytes, and no text to parse. */
76
92
  DataFormat[DataFormat["binary"] = 1] = "binary";
77
93
  })(DataFormat = Protocol.DataFormat || (Protocol.DataFormat = {}));
78
94
  })(Protocol || (Protocol = {}));
@@ -1,4 +1,9 @@
1
+ /**
2
+ * SCRAM-SHA-256, and the channel binding that ties it to the TLS
3
+ * connection underneath.
4
+ */
1
5
  export declare namespace SASL {
6
+ /** One exchange in progress: what was sent, and what is needed to check the reply. */
2
7
  interface Session {
3
8
  username: string;
4
9
  mechanism: string;
@@ -18,6 +23,23 @@ export declare namespace SASL {
18
23
  * is what tells the server a stripped -PLUS offer would be an attack.
19
24
  */
20
25
  function createSession(username: string, mechanism: string, bindingData?: Buffer, supportsBinding?: boolean): Session;
26
+ /**
27
+ * Answers the server's first SCRAM message.
28
+ *
29
+ * @param session The session started for this connection.
30
+ * @param password The password to prove knowledge of.
31
+ * @param serverData The server's message.
32
+ * @param channelBinding The binding data, when the mechanism uses it.
33
+ */
21
34
  function continueSession(session: Session, password: string, data: string): void;
35
+ /**
36
+ * Checks the server's final message, which is what proves the server
37
+ * knew the password too.
38
+ *
39
+ * @param session The session in progress.
40
+ * @param data The server's final message.
41
+ * @throws Error When the signature does not match, meaning the server
42
+ * is not the one it claims to be.
43
+ */
22
44
  function finalizeSession(session: Session, data: string): void;
23
45
  }
package/protocol/sasl.js CHANGED
@@ -1,4 +1,8 @@
1
1
  import crypto from 'crypto';
2
+ /**
3
+ * SCRAM-SHA-256, and the channel binding that ties it to the TLS
4
+ * connection underneath.
5
+ */
2
6
  export var SASL;
3
7
  (function (SASL) {
4
8
  const CLIENT_KEY = 'Client Key';
@@ -37,6 +41,14 @@ export var SASL;
37
41
  };
38
42
  }
39
43
  SASL.createSession = createSession;
44
+ /**
45
+ * Answers the server's first SCRAM message.
46
+ *
47
+ * @param session The session started for this connection.
48
+ * @param password The password to prove knowledge of.
49
+ * @param serverData The server's message.
50
+ * @param channelBinding The binding data, when the mechanism uses it.
51
+ */
40
52
  function continueSession(session, password, data) {
41
53
  const s = data.toString();
42
54
  const items = s.split(',');
@@ -91,6 +103,15 @@ export var SASL;
91
103
  clientFinalMessageWithoutProof + ',p=' + clientProof;
92
104
  }
93
105
  SASL.continueSession = continueSession;
106
+ /**
107
+ * Checks the server's final message, which is what proves the server
108
+ * knew the password too.
109
+ *
110
+ * @param session The session in progress.
111
+ * @param data The server's final message.
112
+ * @throws Error When the signature does not match, meaning the server
113
+ * is not the one it claims to be.
114
+ */
94
115
  function finalizeSession(session, data) {
95
116
  let serverSignature = '';
96
117
  const arr = data.split(',');
@@ -1,7 +1,11 @@
1
1
  import { FlexyBuffer } from 'flexy-buffer';
2
+ /** How a `SmartBuffer` grows, how far, and when it gives the pages back. */
2
3
  export interface SmartBufferConfig {
4
+ /** Bytes added at a time when it has to grow. */
3
5
  pageSize?: number;
6
+ /** The most it may ever hold. */
4
7
  maxLength?: number;
8
+ /** Idle milliseconds before the grown capacity is released. */
5
9
  houseKeepMs?: number;
6
10
  }
7
11
  /**
@@ -1,4 +1,11 @@
1
1
  import { EventEmitter } from 'events';
2
+ /**
3
+ * An `EventEmitter` whose listeners cannot take the process down.
4
+ *
5
+ * A listener that throws would otherwise escape into whatever was
6
+ * emitting - the socket's own data handler, more often than not - and
7
+ * an `error` event with nobody listening would throw by definition.
8
+ */
2
9
  export declare class SafeEventEmitter extends EventEmitter {
3
10
  emit(event: string | symbol, ...args: any[]): boolean;
4
11
  }
@@ -1,4 +1,11 @@
1
1
  import { EventEmitter } from 'events';
2
+ /**
3
+ * An `EventEmitter` whose listeners cannot take the process down.
4
+ *
5
+ * A listener that throws would otherwise escape into whatever was
6
+ * emitting - the socket's own data handler, more often than not - and
7
+ * an `error` event with nobody listening would throw by definition.
8
+ */
2
9
  export class SafeEventEmitter extends EventEmitter {
3
10
  emit(event, ...args) {
4
11
  try {