node-firebird 2.9.0 → 2.11.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 (50) hide show
  1. package/README.md +211 -6
  2. package/lib/index.d.ts +5 -0
  3. package/lib/index.js +32 -1
  4. package/lib/pool.js +1 -1
  5. package/lib/srp.d.ts +3 -3
  6. package/lib/types.d.ts +165 -5
  7. package/lib/uri.js +2 -2
  8. package/lib/wire/connection.d.ts +92 -59
  9. package/lib/wire/connection.js +279 -58
  10. package/lib/wire/const.d.ts +9 -1
  11. package/lib/wire/const.js +23 -9
  12. package/lib/wire/database.d.ts +51 -26
  13. package/lib/wire/database.js +53 -20
  14. package/lib/wire/eventConnection.js +5 -3
  15. package/lib/wire/query-stream.d.ts +18 -0
  16. package/lib/wire/query-stream.js +73 -0
  17. package/lib/wire/serialize.d.ts +20 -2
  18. package/lib/wire/serialize.js +7 -0
  19. package/lib/wire/service.d.ts +42 -0
  20. package/lib/wire/service.js +145 -0
  21. package/lib/wire/socket.d.ts +3 -1
  22. package/lib/wire/socket.js +5 -2
  23. package/lib/wire/statement.d.ts +31 -19
  24. package/lib/wire/statement.js +1 -5
  25. package/lib/wire/transaction.d.ts +30 -18
  26. package/lib/wire/transaction.js +23 -4
  27. package/lib/wire/wire-types.d.ts +116 -0
  28. package/lib/wire/wire-types.js +10 -0
  29. package/lib/wire/xsqlvar.d.ts +57 -18
  30. package/lib/wire/xsqlvar.js +59 -0
  31. package/package.json +1 -1
  32. package/src/index.ts +36 -4
  33. package/src/messages.ts +1 -1
  34. package/src/pool.ts +1 -1
  35. package/src/srp.ts +6 -6
  36. package/src/types.ts +162 -5
  37. package/src/unix-crypt.ts +9 -9
  38. package/src/uri.ts +2 -2
  39. package/src/wire/connection.ts +475 -234
  40. package/src/wire/const.ts +23 -9
  41. package/src/wire/database.ts +101 -54
  42. package/src/wire/eventConnection.ts +8 -5
  43. package/src/wire/query-stream.ts +80 -0
  44. package/src/wire/serialize.ts +31 -0
  45. package/src/wire/service.ts +188 -6
  46. package/src/wire/socket.ts +17 -8
  47. package/src/wire/statement.ts +37 -29
  48. package/src/wire/transaction.ts +57 -32
  49. package/src/wire/wire-types.ts +127 -0
  50. package/src/wire/xsqlvar.ts +85 -7
@@ -21,21 +21,60 @@ export declare abstract class SQLVarBase {
21
21
  abstract decode(data: XdrReader, lowerV13: boolean, options?: any): any;
22
22
  abstract calcBlr(blr: BlrWriter): void;
23
23
  }
24
+ /** Effective object-row key(s) of one output column (see computeColumnKeys). */
25
+ export interface ColumnKey {
26
+ /** Top-level table key when nestTables === true; undefined otherwise. */
27
+ table?: string;
28
+ /** Property key: the column alias, or 'table<sep>alias' in separator mode. */
29
+ key: string;
30
+ }
31
+ /**
32
+ * Compute the object-row property keys for a statement's output columns,
33
+ * honouring the nestTables and lowercase_keys options. The table qualifier
34
+ * is the query's relation alias when one is used (relationAlias, requested
35
+ * via isc_info_sql_relation_alias), the relation name otherwise, so
36
+ * self-joins nest under their query aliases. Expression columns (no source
37
+ * relation) qualify as '' exactly like mysql2: they nest under the '' key,
38
+ * and in separator mode become '<sep>alias' — always prefixing keeps
39
+ * qualified keys collision-free (a bare expression alias could otherwise
40
+ * collide with a real column's 'table<sep>column' key). Used by the fetch
41
+ * decoder and by fetchBlobSyncRow, which must agree on where each column
42
+ * landed in the row.
43
+ */
44
+ export declare function computeColumnKeys(output: SQLVarBase[], nestTables: boolean | string | undefined, lowercaseKeys: boolean | undefined): ColumnKey[];
45
+ /**
46
+ * Resolve the effective nestTables value: the per-query option wins over
47
+ * the connection option. The decoder and fetchBlobSyncRow both use this —
48
+ * they must agree on whether nesting is active or blob cells are looked
49
+ * up in the wrong place.
50
+ */
51
+ export declare function resolveNestTables(queryOptions: {
52
+ nestTables?: boolean | string;
53
+ } | undefined, connectionOptions: {
54
+ nestTables?: boolean | string;
55
+ } | undefined): boolean | string | undefined;
56
+ /**
57
+ * The object a column's value lives in: the row itself, or — when the
58
+ * column carries a nestTables table qualifier — the row's per-table
59
+ * sub-object, created on first use. Every site that reads or writes a
60
+ * cell by ColumnKey must resolve it through here.
61
+ */
62
+ export declare function nestCell(row: any, table: string | undefined): any;
24
63
  export declare class SQLVarText extends SQLVarBase {
25
- decode(data: XdrReader, lowerV13: boolean, options?: any): any;
64
+ decode(data: XdrReader, lowerV13: boolean, options?: any): string | Buffer<ArrayBufferLike> | null | undefined;
26
65
  calcBlr(blr: BlrWriter): void;
27
66
  }
28
67
  export declare class SQLVarNull extends SQLVarText {
29
68
  }
30
69
  export declare class SQLVarString extends SQLVarBase {
31
- decode(data: XdrReader, lowerV13: boolean, options?: any): any;
70
+ decode(data: XdrReader, lowerV13: boolean, options?: any): string | Buffer<ArrayBufferLike> | null | undefined;
32
71
  calcBlr(blr: BlrWriter): void;
33
72
  }
34
73
  export declare class SQLVarQuad extends SQLVarBase {
35
74
  decode(data: XdrReader, lowerV13: boolean): {
36
75
  low: number;
37
76
  high: number;
38
- };
77
+ } | null;
39
78
  calcBlr(blr: BlrWriter): void;
40
79
  }
41
80
  export declare class SQLVarBlob extends SQLVarQuad {
@@ -45,66 +84,66 @@ export declare class SQLVarArray extends SQLVarQuad {
45
84
  calcBlr(blr: BlrWriter): void;
46
85
  }
47
86
  export declare class SQLVarInt extends SQLVarBase {
48
- decode(data: XdrReader, lowerV13: boolean): number;
87
+ decode(data: XdrReader, lowerV13: boolean): number | null;
49
88
  calcBlr(blr: BlrWriter): void;
50
89
  }
51
90
  export declare class SQLVarShort extends SQLVarInt {
52
91
  calcBlr(blr: BlrWriter): void;
53
92
  }
54
93
  export declare class SQLVarInt64 extends SQLVarBase {
55
- decode(data: XdrReader, lowerV13: boolean): number;
94
+ decode(data: XdrReader, lowerV13: boolean): number | null;
56
95
  calcBlr(blr: BlrWriter): void;
57
96
  }
58
97
  export declare class SQLVarInt128 extends SQLVarBase {
59
- decode(data: XdrReader, lowerV13: boolean): string | number;
98
+ decode(data: XdrReader, lowerV13: boolean): string | number | null;
60
99
  calcBlr(blr: BlrWriter): void;
61
100
  }
62
101
  export declare class SQLVarDecFloat16 extends SQLVarBase {
63
- decode(data: XdrReader, lowerV13: boolean): string | number;
102
+ decode(data: XdrReader, lowerV13: boolean): string | number | null;
64
103
  calcBlr(blr: BlrWriter): void;
65
104
  }
66
105
  export declare class SQLVarDecFloat34 extends SQLVarBase {
67
- decode(data: XdrReader, lowerV13: boolean): string | number;
106
+ decode(data: XdrReader, lowerV13: boolean): string | number | null;
68
107
  calcBlr(blr: BlrWriter): void;
69
108
  }
70
109
  export declare class SQLVarFloat extends SQLVarBase {
71
- decode(data: XdrReader, lowerV13: boolean): number;
110
+ decode(data: XdrReader, lowerV13: boolean): number | null;
72
111
  calcBlr(blr: BlrWriter): void;
73
112
  }
74
113
  export declare class SQLVarDouble extends SQLVarBase {
75
- decode(data: XdrReader, lowerV13: boolean): number;
114
+ decode(data: XdrReader, lowerV13: boolean): number | null;
76
115
  calcBlr(blr: BlrWriter): void;
77
116
  }
78
117
  export declare class SQLVarDate extends SQLVarBase {
79
- decode(data: XdrReader, lowerV13: boolean): Date;
118
+ decode(data: XdrReader, lowerV13: boolean): Date | null;
80
119
  calcBlr(blr: BlrWriter): void;
81
120
  }
82
121
  export declare class SQLVarTime extends SQLVarBase {
83
- decode(data: XdrReader, lowerV13: boolean): Date;
122
+ decode(data: XdrReader, lowerV13: boolean): Date | null;
84
123
  calcBlr(blr: BlrWriter): void;
85
124
  }
86
125
  export declare class SQLVarTimeStamp extends SQLVarBase {
87
- decode(data: XdrReader, lowerV13: boolean): Date;
126
+ decode(data: XdrReader, lowerV13: boolean): Date | null;
88
127
  calcBlr(blr: BlrWriter): void;
89
128
  }
90
129
  export declare class SQLVarTimeTz extends SQLVarBase {
91
- decode(data: XdrReader, lowerV13: boolean): Date;
130
+ decode(data: XdrReader, lowerV13: boolean): Date | null;
92
131
  calcBlr(blr: BlrWriter): void;
93
132
  }
94
133
  export declare class SQLVarTimeTzEx extends SQLVarTimeTz {
95
- decode(data: XdrReader, lowerV13: boolean): Date;
134
+ decode(data: XdrReader, lowerV13: boolean): Date | null;
96
135
  calcBlr(blr: BlrWriter): void;
97
136
  }
98
137
  export declare class SQLVarTimeStampTz extends SQLVarBase {
99
- decode(data: XdrReader, lowerV13: boolean): Date;
138
+ decode(data: XdrReader, lowerV13: boolean): Date | null;
100
139
  calcBlr(blr: BlrWriter): void;
101
140
  }
102
141
  export declare class SQLVarTimeStampTzEx extends SQLVarTimeStampTz {
103
- decode(data: XdrReader, lowerV13: boolean): Date;
142
+ decode(data: XdrReader, lowerV13: boolean): Date | null;
104
143
  calcBlr(blr: BlrWriter): void;
105
144
  }
106
145
  export declare class SQLVarBoolean extends SQLVarBase {
107
- decode(data: XdrReader, lowerV13: boolean): boolean;
146
+ decode(data: XdrReader, lowerV13: boolean): boolean | null;
108
147
  calcBlr(blr: BlrWriter): void;
109
148
  }
110
149
  export declare class SQLParamInt {
@@ -4,6 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.SQLParamBool = exports.SQLParamDate = exports.SQLParamQuad = exports.SQLParamBuffer = exports.SQLParamString = exports.SQLParamDouble = exports.SQLParamDecFloat34 = exports.SQLParamDecFloat16 = exports.SQLParamInt128 = exports.SQLParamInt64 = exports.SQLParamInt = exports.SQLVarBoolean = exports.SQLVarTimeStampTzEx = exports.SQLVarTimeStampTz = exports.SQLVarTimeTzEx = exports.SQLVarTimeTz = exports.SQLVarTimeStamp = exports.SQLVarTime = exports.SQLVarDate = exports.SQLVarDouble = exports.SQLVarFloat = exports.SQLVarDecFloat34 = exports.SQLVarDecFloat16 = exports.SQLVarInt128 = exports.SQLVarInt64 = exports.SQLVarShort = exports.SQLVarInt = exports.SQLVarArray = exports.SQLVarBlob = exports.SQLVarQuad = exports.SQLVarString = exports.SQLVarNull = exports.SQLVarText = exports.SQLVarBase = void 0;
7
+ exports.computeColumnKeys = computeColumnKeys;
8
+ exports.resolveNestTables = resolveNestTables;
9
+ exports.nestCell = nestCell;
7
10
  exports.encodeDateTimeParts = encodeDateTimeParts;
8
11
  const const_1 = __importDefault(require("./const"));
9
12
  /***************************************
@@ -68,6 +71,62 @@ function resolveTextEncoding(options) {
68
71
  class SQLVarBase {
69
72
  }
70
73
  exports.SQLVarBase = SQLVarBase;
74
+ /**
75
+ * Compute the object-row property keys for a statement's output columns,
76
+ * honouring the nestTables and lowercase_keys options. The table qualifier
77
+ * is the query's relation alias when one is used (relationAlias, requested
78
+ * via isc_info_sql_relation_alias), the relation name otherwise, so
79
+ * self-joins nest under their query aliases. Expression columns (no source
80
+ * relation) qualify as '' exactly like mysql2: they nest under the '' key,
81
+ * and in separator mode become '<sep>alias' — always prefixing keeps
82
+ * qualified keys collision-free (a bare expression alias could otherwise
83
+ * collide with a real column's 'table<sep>column' key). Used by the fetch
84
+ * decoder and by fetchBlobSyncRow, which must agree on where each column
85
+ * landed in the row.
86
+ */
87
+ function computeColumnKeys(output, nestTables, lowercaseKeys) {
88
+ return output.map((column) => {
89
+ let key = column.alias || '';
90
+ if (lowercaseKeys) {
91
+ key = key.toLowerCase();
92
+ }
93
+ if (nestTables !== true && typeof nestTables !== 'string') {
94
+ return { key };
95
+ }
96
+ let table = column.relationAlias || column.relation || '';
97
+ if (lowercaseKeys) {
98
+ table = table.toLowerCase();
99
+ }
100
+ if (nestTables === true) {
101
+ return { table, key };
102
+ }
103
+ return { key: table + nestTables + key };
104
+ });
105
+ }
106
+ /**
107
+ * Resolve the effective nestTables value: the per-query option wins over
108
+ * the connection option. The decoder and fetchBlobSyncRow both use this —
109
+ * they must agree on whether nesting is active or blob cells are looked
110
+ * up in the wrong place.
111
+ */
112
+ function resolveNestTables(queryOptions, connectionOptions) {
113
+ if (queryOptions && queryOptions.nestTables !== undefined) {
114
+ return queryOptions.nestTables;
115
+ }
116
+ return connectionOptions && connectionOptions.nestTables;
117
+ }
118
+ /**
119
+ * The object a column's value lives in: the row itself, or — when the
120
+ * column carries a nestTables table qualifier — the row's per-table
121
+ * sub-object, created on first use. Every site that reads or writes a
122
+ * cell by ColumnKey must resolve it through here.
123
+ */
124
+ function nestCell(row, table) {
125
+ if (table === undefined) {
126
+ return row;
127
+ }
128
+ return row[table] || (row[table] = {});
129
+ }
71
130
  //------------------------------------------------------
72
131
  class SQLVarText extends SQLVarBase {
73
132
  decode(data, lowerV13, options) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-firebird",
3
- "version": "2.9.0",
3
+ "version": "2.11.0",
4
4
  "description": "Pure JavaScript and Asynchronous Firebird client for Node.js.",
5
5
  "keywords": [
6
6
  "firebird",
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import Const from './wire/const';
2
- import { doError, doCallback, fromCallback } from './callback';
2
+ import { doError, doCallback, fromCallback, type Callback } from './callback';
3
3
  import Connection from './wire/connection';
4
4
  import Pool from './pool';
5
5
  import { escape as escapeValue } from './utils';
@@ -48,6 +48,36 @@ export const ISOLATION_READ_COMMITTED_READ_ONLY: number[] = Const.ISOLATION_READ
48
48
 
49
49
  export const escape = escapeValue;
50
50
 
51
+ /**
52
+ * Firebird SQL type codes, as seen in `column.type` inside a `typeCast`
53
+ * hook (each code also has a friendly `column.typeName`).
54
+ */
55
+ export const SQL_TYPES: Readonly<Record<string, number>> = Object.freeze({
56
+ SQL_TEXT: Const.SQL_TEXT,
57
+ SQL_VARYING: Const.SQL_VARYING,
58
+ SQL_SHORT: Const.SQL_SHORT,
59
+ SQL_LONG: Const.SQL_LONG,
60
+ SQL_FLOAT: Const.SQL_FLOAT,
61
+ SQL_DOUBLE: Const.SQL_DOUBLE,
62
+ SQL_D_FLOAT: Const.SQL_D_FLOAT,
63
+ SQL_TIMESTAMP: Const.SQL_TIMESTAMP,
64
+ SQL_BLOB: Const.SQL_BLOB,
65
+ SQL_ARRAY: Const.SQL_ARRAY,
66
+ SQL_QUAD: Const.SQL_QUAD,
67
+ SQL_TYPE_TIME: Const.SQL_TYPE_TIME,
68
+ SQL_TYPE_DATE: Const.SQL_TYPE_DATE,
69
+ SQL_INT64: Const.SQL_INT64,
70
+ SQL_INT128: Const.SQL_INT128,
71
+ SQL_TIMESTAMP_TZ: Const.SQL_TIMESTAMP_TZ,
72
+ SQL_TIMESTAMP_TZ_EX: Const.SQL_TIMESTAMP_TZ_EX,
73
+ SQL_TIME_TZ: Const.SQL_TIME_TZ,
74
+ SQL_TIME_TZ_EX: Const.SQL_TIME_TZ_EX,
75
+ SQL_DEC16: Const.SQL_DEC16,
76
+ SQL_DEC34: Const.SQL_DEC34,
77
+ SQL_BOOLEAN: Const.SQL_BOOLEAN,
78
+ SQL_NULL: Const.SQL_NULL,
79
+ });
80
+
51
81
  /**
52
82
  * The most recent Connection created by attach()/create()/attachOrCreate().
53
83
  * Kept for backwards compatibility with the previous CommonJS module where
@@ -114,7 +144,7 @@ export function create(options: Options | string, callback: DatabaseCallback): v
114
144
  return;
115
145
  }
116
146
 
117
- cnx.createDatabase(options, callback);
147
+ cnx.createDatabase(options, callback as any);
118
148
  });
119
149
  }, options);
120
150
  }
@@ -146,11 +176,13 @@ export function attachOrCreate(options: Options | string, callback: DatabaseCall
146
176
  if (!err) {
147
177
  if (self.db)
148
178
  self.db.emit('connect', ret);
149
- doCallback(ret, callback);
179
+ // DatabaseCallback stays permissive (db non-optional) for
180
+ // API users; internally the error path passes no db
181
+ doCallback(ret, callback as Callback<Database>);
150
182
  return;
151
183
  }
152
184
 
153
- cnx.createDatabase(options, callback);
185
+ cnx.createDatabase(options, callback as any);
154
186
  });
155
187
  });
156
188
 
package/src/messages.ts CHANGED
@@ -138,7 +138,7 @@ export const lookupMessages = function(status: FbStatusItem[], messageFile: stri
138
138
  buffer = Buffer.alloc(bucket_size);
139
139
 
140
140
  var i = 0;
141
- var text;
141
+ var text: string | undefined;
142
142
 
143
143
  function loop() {
144
144
  lookup(status[i], function(line) {
package/src/pool.ts CHANGED
@@ -161,7 +161,7 @@ class Pool extends Events.EventEmitter {
161
161
  if ((self.dbinuse + self._creating) >= self.max)
162
162
  return self;
163
163
 
164
- var cb = self.pending.shift();
164
+ const cb = self.pending.shift();
165
165
  if (!cb)
166
166
  return self;
167
167
  if (self.pooldb.length) {
package/src/srp.ts CHANGED
@@ -67,7 +67,7 @@ export function clientSeed(a: bigint = toBigInt(crypto.randomBytes(SRP_KEY_SIZE)
67
67
  * @param b BigInt Server private key.
68
68
  * @returns {{private: BigInt, public: BigInt}}
69
69
  */
70
- export function serverSeed(user: string, password: string, salt: Buffer, b?: bigint | string, hashAlgo: string = 'sha1'): KeyPair {
70
+ export function serverSeed(user: string, password: string, salt: Buffer | string, b?: bigint | string, hashAlgo: string = 'sha1'): KeyPair {
71
71
  if (typeof b === 'string') {
72
72
  hashAlgo = b;
73
73
  b = undefined;
@@ -104,7 +104,7 @@ export function serverSeed(user: string, password: string, salt: Buffer, b?: big
104
104
  * @param b BigInt Server private key.
105
105
  * @returns {BigInt}
106
106
  */
107
- export function serverSession(user: string, password: string, salt: Buffer, A: bigint, B: bigint, b: bigint, hashAlgo: string = 'sha1'): bigint {
107
+ export function serverSession(user: string, password: string, salt: Buffer | string, A: bigint, B: bigint, b: bigint, hashAlgo: string = 'sha1'): bigint {
108
108
  var u = getScramble(A, B, 'sha1');
109
109
  var v = getVerifier(user, password, salt, 'sha1');
110
110
  var vu = modPow(v, u, PRIME.N);
@@ -121,7 +121,7 @@ export function serverSession(user: string, password: string, salt: Buffer, A: b
121
121
  /**
122
122
  * M = H(H(N) xor H(g), H(I), s, A, B, K)
123
123
  */
124
- export function clientProof(user: string, password: string, salt: Buffer, A: bigint, B: bigint, a: bigint, hashAlgo: string = 'sha1'): ClientProof {
124
+ export function clientProof(user: string, password: string, salt: Buffer | string, A: bigint, B: bigint, a: bigint, hashAlgo: string = 'sha1'): ClientProof {
125
125
  var K = clientSession(user, password, salt, A, B, a, 'sha1');
126
126
  var n1, n2;
127
127
 
@@ -222,7 +222,7 @@ function getScramble(A: bigint, B: bigint, hashAlgo: string = 'sha1'): bigint {
222
222
  * @returns Buffer The raw session-key digest (fixed length, may start
223
223
  * with a zero byte — significant for the proof).
224
224
  */
225
- function clientSession(user: string, password: string, salt: Buffer, A: bigint, B: bigint, a: bigint, hashAlgo: string = 'sha1'): Buffer {
225
+ function clientSession(user: string, password: string, salt: Buffer | string, A: bigint, B: bigint, a: bigint, hashAlgo: string = 'sha1'): Buffer {
226
226
  var u = getScramble(A, B, 'sha1');
227
227
  var x = getUserHash(user, salt, password, 'sha1');
228
228
  var gx = modPow(PRIME.g, x, PRIME.N);
@@ -264,7 +264,7 @@ function clientSession(user: string, password: string, salt: Buffer, A: bigint,
264
264
  * @param password string Connection password.
265
265
  * @returns {BigInt}
266
266
  */
267
- function getUserHash(user: string, salt: Buffer, password: string, hashAlgo: string = 'sha1'): bigint {
267
+ function getUserHash(user: string, salt: Buffer | string, password: string, hashAlgo: string = 'sha1'): bigint {
268
268
  var hash1 = getHash(hashAlgo, user.toUpperCase(), ':', password);
269
269
  var hash2 = getHash(hashAlgo, salt, toBuffer(hash1));
270
270
 
@@ -279,7 +279,7 @@ function getUserHash(user: string, salt: Buffer, password: string, hashAlgo: str
279
279
  * @param salt BigInt Connection salt.
280
280
  * @returns {BigInt}
281
281
  */
282
- function getVerifier(user: string, password: string, salt: Buffer, hashAlgo: string = 'sha1'): bigint {
282
+ function getVerifier(user: string, password: string, salt: Buffer | string, hashAlgo: string = 'sha1'): bigint {
283
283
  return modPow(PRIME.g, getUserHash(user, salt, password, hashAlgo), PRIME.N);
284
284
  }
285
285
 
package/src/types.ts CHANGED
@@ -5,6 +5,8 @@
5
5
  // They now live in the TypeScript source tree and are compiled into the
6
6
  // published declaration files.
7
7
 
8
+ import type { Readable } from 'stream';
9
+
8
10
  export type DatabaseCallback = (err: any, db: Database) => void;
9
11
  export type TransactionCallback = (err: any, transaction: Transaction) => void;
10
12
  export type QueryCallback = (err: any, result: any[]) => void;
@@ -125,6 +127,28 @@ export type QueryOptions = {
125
127
  * it cancels whatever is currently executing on the connection.
126
128
  */
127
129
  signal?: AbortSignal;
130
+ /**
131
+ * Per-query override of the `nestTables` connection option (mysql2
132
+ * semantics). `true` nests each object row by source table:
133
+ * `row[table][column]` — the table key is the query's relation alias
134
+ * when one is used (`FROM emp e` → `row.E`), the table name otherwise,
135
+ * and `''` for expression columns. A string separator flattens keys
136
+ * instead: `nestTables: '_'` → `row.EMP_NAME`; expression columns get
137
+ * the bare separator prefix (`row._ANSWER`, as in mysql2). Keys honour
138
+ * `lowercase_keys`. Object rows only — `db.execute` array rows are
139
+ * unaffected.
140
+ */
141
+ nestTables?: boolean | string;
142
+ }
143
+
144
+ export type QueryStreamOptions = QueryOptions & {
145
+ /**
146
+ * Rows buffered internally before fetching pauses (object-mode
147
+ * Readable highWaterMark, default 16).
148
+ */
149
+ highWaterMark?: number;
150
+ /** Emit array rows instead of objects (like db.execute). */
151
+ asObject?: boolean;
128
152
  }
129
153
 
130
154
  export interface Database {
@@ -136,6 +160,13 @@ export interface Database {
136
160
  /** Bulk-execute in its own transaction, all-or-nothing (Firebird 4.0+). */
137
161
  executeBatch(query: string, rows: QueryParams[], callback?: (err: any, result: BatchResult) => void, options?: BatchOptions): Database;
138
162
  sequentially(query: string, params: QueryParams, rowCallback: SequentialCallback, callback: SimpleCallback, options?: QueryOptions | boolean): Database;
163
+ /**
164
+ * Run `query` and return an object-mode Readable emitting one row per
165
+ * chunk, with backpressure (fetching pauses while the buffer is full).
166
+ * Runs in its own transaction. Destroying the stream early aborts the
167
+ * fetch and releases the statement.
168
+ */
169
+ queryStream(query: string, params?: QueryParams, options?: QueryStreamOptions): Readable;
139
170
  drop(callback: SimpleCallback): void;
140
171
  escape(value: any): string;
141
172
  attachEvent(callback: any): this;
@@ -176,6 +207,12 @@ export interface Transaction {
176
207
  /** Bulk-execute within this transaction; per-record failures do not roll back (Firebird 4.0+). */
177
208
  executeBatch(query: string, rows: QueryParams[], callback?: (err: any, result: BatchResult) => void, options?: BatchOptions): void;
178
209
  sequentially(query: string, params: QueryParams, rowCallback: SequentialCallback, callback: SimpleCallback, options?: QueryOptions | boolean): Database;
210
+ /**
211
+ * Run `query` inside this transaction and return an object-mode
212
+ * Readable emitting one row per chunk, with backpressure. The
213
+ * transaction is NOT committed when the stream ends.
214
+ */
215
+ queryStream(query: string, params?: QueryParams, options?: QueryStreamOptions): Readable;
179
216
  commit(callback?: SimpleCallback): void;
180
217
  commitRetaining(callback?: SimpleCallback): void;
181
218
  rollback(callback?: SimpleCallback): void;
@@ -289,6 +326,26 @@ export interface Options {
289
326
  * per-query `namedPlaceholders: false` override.
290
327
  */
291
328
  namedPlaceholders?: boolean;
329
+ /**
330
+ * Qualify object-row keys by source table (same option as mysql2), so
331
+ * JOINed columns with the same name stop overwriting each other:
332
+ * `true` nests each row as `row[table][column]`; a string separator
333
+ * flattens to `row['table' + sep + 'column']`. See
334
+ * `QueryOptions.nestTables` for the exact key rules. Applies wherever
335
+ * object rows are produced (query / sequentially / queryStream);
336
+ * array rows (execute) are unaffected. Overridable per query.
337
+ */
338
+ nestTables?: boolean | string;
339
+ /**
340
+ * TCP keepalive probing to detect dead/stale connections (same option
341
+ * names as mysql2). On by default; set false to disable.
342
+ */
343
+ enableKeepAlive?: boolean;
344
+ /**
345
+ * Milliseconds a socket must be idle before the first TCP keepalive
346
+ * probe is sent (default 60000). Ignored when enableKeepAlive is false.
347
+ */
348
+ keepAliveInitialDelay?: number;
292
349
  pluginName?: string;
293
350
  parallelWorkers?: number;
294
351
  maxInlineBlobSize?: number;
@@ -320,11 +377,11 @@ export interface Options {
320
377
  /**
321
378
  * **Firebird 6.0+ only (Protocol 20+)**
322
379
  *
323
- * Sets the session's current schema at connection time. Equivalent to
324
- * executing `SET SCHEMA <name>` immediately after connecting.
325
- *
326
- * Unqualified object references (tables, procedures, etc.) that do not
327
- * match any schema in the `searchPath` fall back to `PUBLIC`.
380
+ * Sets the session's current schema at connection time. `CURRENT_SCHEMA`
381
+ * in Firebird is the first existing schema of the search path, so this
382
+ * option is implemented by putting the schema at the front of the
383
+ * `searchPath` sent to the server (with `PUBLIC` kept as a fallback when
384
+ * no explicit `searchPath` is given).
328
385
  *
329
386
  * Example: `defaultSchema: 'myapp'`
330
387
  */
@@ -346,6 +403,18 @@ export interface Options {
346
403
  * (typically `PUBLIC` then `SYSTEM`).
347
404
  */
348
405
  searchPath?: string | string[];
406
+ /**
407
+ * **Firebird 6.0+ only**
408
+ *
409
+ * Owner of a newly created database (`isc_dpb_owner`), allowing a
410
+ * superuser to create a database owned by another user
411
+ * ([firebird#7718](https://github.com/FirebirdSQL/firebird/issues/7718)).
412
+ * Only honored by `create`/`attachOrCreate` when the database is
413
+ * created; ignored on plain attach and by older servers.
414
+ *
415
+ * Example: `owner: 'APP_OWNER'`
416
+ */
417
+ owner?: string;
349
418
  /**
350
419
  * **Firebird 6.0+ only (Protocol 20+)**
351
420
  *
@@ -354,8 +423,58 @@ export interface Options {
354
423
  * text/BLOB columns back into JavaScript objects/arrays.
355
424
  */
356
425
  jsonAsObject?: boolean;
426
+ /**
427
+ * Custom type parser (mysql2-style). Called for every column value of
428
+ * every result row (including NULLs); whatever it returns becomes the
429
+ * value in the row. Call `next()` to get the value the driver would
430
+ * produce by default (after `blobAsText`/`jsonAsObject` are applied).
431
+ *
432
+ * ```js
433
+ * typeCast: (column, next) =>
434
+ * column.typeName === 'INT64' ? Number(next()) : next()
435
+ * ```
436
+ *
437
+ * Non-text BLOB columns reach the hook as the usual fetch function;
438
+ * text BLOBs with `blobAsText` reach it as the resolved string. The
439
+ * hook must be a pure function: a row can be decoded more than once
440
+ * when a response spans TCP packets.
441
+ */
442
+ typeCast?: TypeCastFunction;
443
+ /**
444
+ * Per-connection LRU cache of prepared statements (like mysql2's
445
+ * statement cache). `db.query`/`tx.query` and friends transparently
446
+ * reuse the prepared handle for a repeated SQL string, skipping the
447
+ * prepare round-trip on hot paths. The number is the maximum of idle
448
+ * cached statements; least-recently-used ones are dropped over the
449
+ * limit. 0 / unset = disabled. Statements that failed and DDL are
450
+ * never cached; concurrent runs of the same SQL never share a
451
+ * statement (extra preparations are simply not cached).
452
+ */
453
+ statementCacheSize?: number;
357
454
  }
358
455
 
456
+ /** Column metadata passed to the {@link Options.typeCast} hook. */
457
+ export interface TypeCastColumn {
458
+ /** Firebird SQL type code (see the exported `SQL_TYPES` map). */
459
+ type: number;
460
+ /** Friendly name of the type code: 'VARYING', 'INT64', 'BLOB', ... */
461
+ typeName: string;
462
+ /** Column subtype (e.g. 1 = text for BLOBs; charset id for strings). */
463
+ subType?: number;
464
+ /** Negative decimal scale for NUMERIC/DECIMAL columns (e.g. -2). */
465
+ scale?: number;
466
+ /** Declared length in bytes. */
467
+ length?: number;
468
+ /** Column name in the table. */
469
+ field?: string;
470
+ /** Table (relation) name. */
471
+ relation?: string;
472
+ /** Alias used in the SELECT list (the row key for object rows). */
473
+ alias?: string;
474
+ }
475
+
476
+ export type TypeCastFunction = (column: TypeCastColumn, next: () => any) => any;
477
+
359
478
  export interface SvcMgrOptions extends Options {
360
479
  manager: true; // Attach to ServiceManager
361
480
  }
@@ -565,4 +684,42 @@ export interface ServiceManager {
565
684
  hasRunningAction(options: ReadableOptions, callback: ReadableCallback): void;
566
685
  readusers(options: ReadableOptions, callback: ReadableCallback): void;
567
686
  readlimbo(options: ReadableOptions, callback: ReadableCallback): void;
687
+
688
+ // Promise / async-await API (see README § Promises / async–await).
689
+ detachAsync(force?: boolean): Promise<void>;
690
+ backupAsync(options: BackupOptions): Promise<NodeJS.ReadableStream>;
691
+ nbackupAsync(options: BackupOptions): Promise<NodeJS.ReadableStream>;
692
+ restoreAsync(options: RestoreOptions): Promise<NodeJS.ReadableStream>;
693
+ nrestoreAsync(options: NRestoreOptions): Promise<NodeJS.ReadableStream>;
694
+ setDialectAsync(db: string, dialect: 1 | 3): Promise<NodeJS.ReadableStream>;
695
+ setSweepintervalAsync(db: string, interval: number): Promise<any>;
696
+ setCachebufferAsync(db: string, nbpages: any): Promise<NodeJS.ReadableStream>;
697
+ BringOnlineAsync(db: string): Promise<NodeJS.ReadableStream>;
698
+ ShutdownAsync(db: string, kind: ShutdownKind, delay: number, mode?: ShutdownMode): Promise<NodeJS.ReadableStream>;
699
+ setShadowAsync(db: string, val: boolean): Promise<NodeJS.ReadableStream>;
700
+ setForcewriteAsync(db: string, val: boolean): Promise<NodeJS.ReadableStream>;
701
+ setReservespaceAsync(db: string, val: boolean): Promise<NodeJS.ReadableStream>;
702
+ setReadonlyModeAsync(db: string): Promise<NodeJS.ReadableStream>;
703
+ setReadwriteModeAsync(db: string): Promise<NodeJS.ReadableStream>;
704
+ validateAsync(options: ValidateOptions): Promise<NodeJS.ReadableStream>;
705
+ commitAsync(db: string, transactid: number): Promise<NodeJS.ReadableStream>;
706
+ rollbackAsync(db: string, transactid: number): Promise<NodeJS.ReadableStream>;
707
+ recoverAsync(db: string, transactid: number): Promise<NodeJS.ReadableStream>;
708
+ getStatsAsync(options: StatsOptions): Promise<NodeJS.ReadableStream>;
709
+ getLogAsync(options: ReadableOptions): Promise<NodeJS.ReadableStream>;
710
+ getUsersAsync(username?: string | null): Promise<ServerInfo>;
711
+ addUserAsync(username: string, password: string, info?: UserInfo): Promise<NodeJS.ReadableStream>;
712
+ editUserAsync(username: string, info: UserInfo): Promise<NodeJS.ReadableStream>;
713
+ removeUserAsync(username: string, rolename?: string | null): Promise<NodeJS.ReadableStream>;
714
+ getFbserverInfosAsync(infos?: ServerInfoReq, options?: { buffersize?: number, timeout?: number }): Promise<ServerInfo>;
715
+ startTraceAsync(options: TraceOptions): Promise<NodeJS.ReadableStream>;
716
+ suspendTraceAsync(options: TraceOptions): Promise<NodeJS.ReadableStream>;
717
+ resumeTraceAsync(options: TraceOptions): Promise<NodeJS.ReadableStream>;
718
+ stopTraceAsync(options: TraceOptions): Promise<NodeJS.ReadableStream>;
719
+ getTraceListAsync(options?: ReadableOptions): Promise<NodeJS.ReadableStream>;
720
+ readlineAsync(options?: ReadableOptions): Promise<{ result: number, line: string }>;
721
+ readeofAsync(options?: ReadableOptions): Promise<{ result: number, line: string }>;
722
+ hasRunningActionAsync(options?: ReadableOptions): Promise<any>;
723
+ readusersAsync(options?: ReadableOptions): Promise<any>;
724
+ readlimboAsync(options?: ReadableOptions): Promise<any>;
568
725
  }
package/src/unix-crypt.ts CHANGED
@@ -152,25 +152,25 @@ var SPTRANS=
152
152
  0x8200020, 32768, 0x208020 ]
153
153
  ];
154
154
 
155
- function hPermOp(a, n, m) {
155
+ function hPermOp(a: number, n: number, m: number) {
156
156
  var t = (a << 16 - n ^ a) & m;
157
157
  a = a ^ t ^ t >>> 16 - n;
158
158
  return a;
159
159
  }
160
160
 
161
- function intToFourBytes(iValue, b, offset) {
161
+ function intToFourBytes(iValue: number, b: Buffer, offset: number) {
162
162
  b[offset++] = iValue & 0xff;
163
163
  b[offset++] = iValue >>> 8 & 0xff;
164
164
  b[offset++] = iValue >>> 16 & 0xff;
165
165
  b[offset++] = iValue >>> 24 & 0xff;
166
166
  }
167
167
 
168
- function byteToUnsigned(b) {
168
+ function byteToUnsigned(b: number) {
169
169
  var value = b;
170
170
  return value < 0 ? value + 256 : value;
171
171
  }
172
172
 
173
- function fourBytesToInt(b, offset) {
173
+ function fourBytesToInt(b: Buffer, offset: number) {
174
174
  var value = byteToUnsigned(b[offset++]);
175
175
  value |= byteToUnsigned(b[offset++]) << 8;
176
176
  value |= byteToUnsigned(b[offset++]) << 16;
@@ -178,7 +178,7 @@ function fourBytesToInt(b, offset) {
178
178
  return value;
179
179
  }
180
180
 
181
- function permOp(a, b, n, m, results) {
181
+ function permOp(a: number, b: number, n: number, m: number, results: number[]) {
182
182
  var t = (a >>> n ^ b) & m;
183
183
  a ^= t << n;
184
184
  b ^= t;
@@ -186,8 +186,8 @@ function permOp(a, b, n, m, results) {
186
186
  results[1] = b;
187
187
  }
188
188
 
189
- function desSetKey(key) {
190
- var schedule = [];
189
+ function desSetKey(key: Buffer) {
190
+ var schedule: number[] = [];
191
191
  var c = fourBytesToInt(key, 0);
192
192
  var d = fourBytesToInt(key, 4);
193
193
  var results = [0, 0];
@@ -232,7 +232,7 @@ function desSetKey(key) {
232
232
  return schedule;
233
233
  }
234
234
 
235
- function dEncrypt(el, r, s, e0, e1, sArr) {
235
+ function dEncrypt(el: number, r: number, s: number, e0: number, e1: number, sArr: number[]) {
236
236
  var v = r ^ r >>> 16;
237
237
  var u = v & e0;
238
238
  v &= e1;
@@ -245,7 +245,7 @@ function dEncrypt(el, r, s, e0, e1, sArr) {
245
245
  return el;
246
246
  }
247
247
 
248
- function body(schedule, eSwap0, eSwap1) {
248
+ function body(schedule: number[], eSwap0: number, eSwap1: number) {
249
249
  var left = 0;
250
250
  var right = 0;
251
251
  var t = 0;