node-firebird 2.12.0 → 2.14.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/README.md +138 -6
- package/lib/callback.d.ts +7 -0
- package/lib/callback.js +16 -0
- package/lib/index.d.ts +10 -0
- package/lib/index.js +13 -0
- package/lib/pool-cluster.d.ts +89 -0
- package/lib/pool-cluster.js +266 -0
- package/lib/pool.js +2 -10
- package/lib/types.d.ts +38 -5
- package/lib/utils.d.ts +12 -0
- package/lib/utils.js +20 -2
- package/lib/wire/batch-stream.d.ts +26 -0
- package/lib/wire/batch-stream.js +109 -0
- package/lib/wire/codepages.d.ts +23 -0
- package/lib/wire/codepages.js +137 -0
- package/lib/wire/connection.d.ts +38 -4
- package/lib/wire/connection.js +294 -44
- package/lib/wire/database.d.ts +9 -0
- package/lib/wire/database.js +13 -6
- package/lib/wire/serialize.d.ts +2 -0
- package/lib/wire/serialize.js +10 -0
- package/lib/wire/socket.js +9 -3
- package/lib/wire/transaction.d.ts +6 -0
- package/lib/wire/transaction.js +27 -2
- package/lib/wire/xsqlvar.d.ts +56 -1
- package/lib/wire/xsqlvar.js +107 -29
- package/package.json +19 -1
- package/src/callback.ts +15 -0
- package/src/index.ts +15 -0
- package/src/pool-cluster.ts +319 -0
- package/src/pool.ts +3 -10
- package/src/types.ts +40 -5
- package/src/utils.ts +19 -1
- package/src/wire/batch-stream.ts +121 -0
- package/src/wire/codepages.ts +147 -0
- package/src/wire/connection.ts +315 -49
- package/src/wire/database.ts +15 -7
- package/src/wire/serialize.ts +11 -0
- package/src/wire/socket.ts +9 -3
- package/src/wire/transaction.ts +28 -2
- package/src/wire/xsqlvar.ts +129 -30
package/lib/wire/transaction.js
CHANGED
|
@@ -9,6 +9,7 @@ const const_1 = __importDefault(require("./const"));
|
|
|
9
9
|
const sql_template_1 = require("../sql-template");
|
|
10
10
|
const xsqlvar_1 = require("./xsqlvar");
|
|
11
11
|
const query_stream_1 = __importDefault(require("./query-stream"));
|
|
12
|
+
const batch_stream_1 = __importDefault(require("./batch-stream"));
|
|
12
13
|
/***************************************
|
|
13
14
|
*
|
|
14
15
|
* Transaction
|
|
@@ -254,7 +255,17 @@ class Transaction {
|
|
|
254
255
|
break;
|
|
255
256
|
case const_1.default.isc_info_sql_stmt_exec_procedure:
|
|
256
257
|
if (ret && ret.data && ret.data.length > 0) {
|
|
257
|
-
|
|
258
|
+
// singleton op_execute2 rows never pass through
|
|
259
|
+
// fetchAll, so their blobAsText fetches must be
|
|
260
|
+
// resolved here (issue #305: EXECUTE PROCEDURE
|
|
261
|
+
// returned text blobs as unresolved functions)
|
|
262
|
+
self.connection.resolveTextBlobs(self, ret, function (blobErr) {
|
|
263
|
+
if (blobErr) {
|
|
264
|
+
dropError(blobErr);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
deliver(ret.data[0], true);
|
|
268
|
+
});
|
|
258
269
|
break;
|
|
259
270
|
}
|
|
260
271
|
else if (statement.output.length) {
|
|
@@ -263,7 +274,13 @@ class Transaction {
|
|
|
263
274
|
dropError(err);
|
|
264
275
|
return;
|
|
265
276
|
}
|
|
266
|
-
|
|
277
|
+
self.connection.resolveTextBlobs(self, fret, function (blobErr) {
|
|
278
|
+
if (blobErr) {
|
|
279
|
+
dropError(blobErr);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
deliver(fret.data[0], false);
|
|
283
|
+
});
|
|
267
284
|
});
|
|
268
285
|
break;
|
|
269
286
|
}
|
|
@@ -344,6 +361,14 @@ class Transaction {
|
|
|
344
361
|
queryStream(query, params, options) {
|
|
345
362
|
return (0, query_stream_1.default)(this, query, params, options);
|
|
346
363
|
}
|
|
364
|
+
/**
|
|
365
|
+
* Bulk-insert Writable running inside this transaction (see
|
|
366
|
+
* Database.batchStream). The transaction is NOT committed or rolled
|
|
367
|
+
* back by the stream — settle it yourself after 'finish'/'error'.
|
|
368
|
+
*/
|
|
369
|
+
batchStream(query, options) {
|
|
370
|
+
return (0, batch_stream_1.default)(this, query, options, false);
|
|
371
|
+
}
|
|
347
372
|
query(query, params, callback, options = {}) {
|
|
348
373
|
if (params instanceof Function) {
|
|
349
374
|
callback = params;
|
package/lib/wire/xsqlvar.d.ts
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
|
+
import type { TextCodec } from './codepages';
|
|
1
2
|
import type { XdrReader, XdrWriter, BlrWriter } from './serialize';
|
|
2
3
|
import type { RecordCounts } from '../types';
|
|
4
|
+
export declare function getFirebirdCharsetWidth(charset?: string): number;
|
|
5
|
+
/**
|
|
6
|
+
* Resolve the Node.js Buffer encoding to use when decoding text from a
|
|
7
|
+
* Firebird response buffer.
|
|
8
|
+
*
|
|
9
|
+
* @param {object|null} options Connection options object (may be falsy).
|
|
10
|
+
* @returns {string} A Node.js-compatible encoding string.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveTextEncoding(options?: any): BufferEncoding;
|
|
13
|
+
/**
|
|
14
|
+
* Codec for the CONNECTION charset when it is a codepage Node cannot
|
|
15
|
+
* handle natively (WIN1251, ISO8859_7, KOI8R, …); null on the native
|
|
16
|
+
* path (UTF8/latin1/ascii) and for unknown charsets. With a codec
|
|
17
|
+
* connection charset the server transliterates all text to that
|
|
18
|
+
* codepage, so every text column, parameter, SQL string and text blob
|
|
19
|
+
* goes through the codec (issues #319/#301).
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveTextCodec(options?: any): TextCodec | null;
|
|
22
|
+
interface TextState {
|
|
23
|
+
key: string | undefined;
|
|
24
|
+
codec: TextCodec | null;
|
|
25
|
+
enc: BufferEncoding;
|
|
26
|
+
width: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Per-connection text handling, resolved once and memoized on the
|
|
30
|
+
* long-lived options object: the decode loop calls this per CELL, and
|
|
31
|
+
* recomputing uppercased names + map lookups a million times per large
|
|
32
|
+
* fetch is pure waste. Invalidated if options.encoding ever changes.
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveTextState(options?: any): TextState;
|
|
35
|
+
/**
|
|
36
|
+
* Encode text in the CONNECTION charset — the byte form the server
|
|
37
|
+
* expects for parameters, SQL statement text and text-blob content.
|
|
38
|
+
*/
|
|
39
|
+
export declare function encodeConnectionText(options: any, value: string): Buffer;
|
|
40
|
+
/**
|
|
41
|
+
* Decode connection-charset bytes to text (the read counterpart of
|
|
42
|
+
* encodeConnectionText — used for text blobs).
|
|
43
|
+
*/
|
|
44
|
+
export declare function decodeConnectionText(options: any, buffer: Buffer): string;
|
|
3
45
|
/**
|
|
4
46
|
* Common shape of all SQLVar descriptor objects. The metadata properties
|
|
5
47
|
* are populated externally (in connection.ts) from the op_prepare_statement
|
|
@@ -19,6 +61,9 @@ export declare abstract class SQLVarBase {
|
|
|
19
61
|
owner?: string;
|
|
20
62
|
charSetId?: number;
|
|
21
63
|
collationId?: number;
|
|
64
|
+
/** Original declared byte length when scaleOutputLengths widened
|
|
65
|
+
* `length` for the fetch capacity check (issue #422). */
|
|
66
|
+
nativeLength?: number;
|
|
22
67
|
abstract decode(data: XdrReader, lowerV13: boolean, options?: any): any;
|
|
23
68
|
abstract calcBlr(blr: BlrWriter): void;
|
|
24
69
|
}
|
|
@@ -278,7 +323,17 @@ export declare class SQLParamDate {
|
|
|
278
323
|
}
|
|
279
324
|
export declare class SQLParamBool {
|
|
280
325
|
value: any;
|
|
281
|
-
|
|
326
|
+
/**
|
|
327
|
+
* Encode as a real BOOLEAN (blr_bool + xdr opaque byte) instead of the
|
|
328
|
+
* legacy blr_short 0/1. Set when the DESCRIBED parameter type is
|
|
329
|
+
* SQL_BOOLEAN: Firebird refuses smallint→BOOLEAN conversion
|
|
330
|
+
* ("conversion error from string", issue #122), and conversely BOOLEAN
|
|
331
|
+
* does not convert to numbers — so smallint targets keep the legacy
|
|
332
|
+
* form for compatibility.
|
|
333
|
+
*/
|
|
334
|
+
asBoolean: boolean;
|
|
335
|
+
constructor(value: any, asBoolean?: boolean);
|
|
282
336
|
encode(data: XdrWriter): void;
|
|
283
337
|
calcBlr(blr: BlrWriter): void;
|
|
284
338
|
}
|
|
339
|
+
export {};
|
package/lib/wire/xsqlvar.js
CHANGED
|
@@ -4,6 +4,12 @@ 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.SQL_TYPE_NAMES = exports.SQLVarBase = void 0;
|
|
7
|
+
exports.getFirebirdCharsetWidth = getFirebirdCharsetWidth;
|
|
8
|
+
exports.resolveTextEncoding = resolveTextEncoding;
|
|
9
|
+
exports.resolveTextCodec = resolveTextCodec;
|
|
10
|
+
exports.resolveTextState = resolveTextState;
|
|
11
|
+
exports.encodeConnectionText = encodeConnectionText;
|
|
12
|
+
exports.decodeConnectionText = decodeConnectionText;
|
|
7
13
|
exports.computeColumnKeys = computeColumnKeys;
|
|
8
14
|
exports.camelizeKey = camelizeKey;
|
|
9
15
|
exports.resolveKeyTransform = resolveKeyTransform;
|
|
@@ -15,6 +21,7 @@ exports.parseRecordCounts = parseRecordCounts;
|
|
|
15
21
|
exports.encodeDateTimeParts = encodeDateTimeParts;
|
|
16
22
|
const const_1 = __importDefault(require("./const"));
|
|
17
23
|
const serialize_1 = require("./serialize");
|
|
24
|
+
const codepages_1 = require("./codepages");
|
|
18
25
|
/***************************************
|
|
19
26
|
*
|
|
20
27
|
* SQLVar
|
|
@@ -22,6 +29,7 @@ const serialize_1 = require("./serialize");
|
|
|
22
29
|
***************************************/
|
|
23
30
|
const ScaleDivisor = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000];
|
|
24
31
|
const DateOffset = 40587, TimeCoeff = 86400000, MsPerMinute = 60000;
|
|
32
|
+
const EMPTY_BUFFER = Buffer.alloc(0);
|
|
25
33
|
/**
|
|
26
34
|
* Maps Firebird character-set names (upper-case) to the Node.js Buffer
|
|
27
35
|
* encoding string used by Buffer.toString() / Buffer.from().
|
|
@@ -46,8 +54,16 @@ const FirebirdToNodeEncoding = Object.freeze({
|
|
|
46
54
|
const FirebirdCharsetWidths = {
|
|
47
55
|
'UTF8': 4,
|
|
48
56
|
'UNICODE_FSS': 3,
|
|
49
|
-
'SJIS'
|
|
50
|
-
|
|
57
|
+
// real Firebird names — the bare 'SJIS'/'EUCJ' keys never matched a
|
|
58
|
+
// valid encoding option and silently resolved to width 1
|
|
59
|
+
'SJIS_0208': 2,
|
|
60
|
+
'EUCJ_0208': 2,
|
|
61
|
+
'KSC_5601': 2,
|
|
62
|
+
'BIG_5': 2,
|
|
63
|
+
'GB_2312': 2,
|
|
64
|
+
'GBK': 2,
|
|
65
|
+
'CP943C': 2,
|
|
66
|
+
'GB18030': 4,
|
|
51
67
|
};
|
|
52
68
|
function getFirebirdCharsetWidth(charset) {
|
|
53
69
|
if (!charset)
|
|
@@ -68,6 +84,67 @@ function resolveTextEncoding(options) {
|
|
|
68
84
|
: const_1.default.DEFAULT_ENCODING;
|
|
69
85
|
return (FirebirdToNodeEncoding[encoding] || const_1.default.DEFAULT_ENCODING.toLowerCase());
|
|
70
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Codec for the CONNECTION charset when it is a codepage Node cannot
|
|
89
|
+
* handle natively (WIN1251, ISO8859_7, KOI8R, …); null on the native
|
|
90
|
+
* path (UTF8/latin1/ascii) and for unknown charsets. With a codec
|
|
91
|
+
* connection charset the server transliterates all text to that
|
|
92
|
+
* codepage, so every text column, parameter, SQL string and text blob
|
|
93
|
+
* goes through the codec (issues #319/#301).
|
|
94
|
+
*/
|
|
95
|
+
function resolveTextCodec(options) {
|
|
96
|
+
return resolveTextState(options).codec;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Per-connection text handling, resolved once and memoized on the
|
|
100
|
+
* long-lived options object: the decode loop calls this per CELL, and
|
|
101
|
+
* recomputing uppercased names + map lookups a million times per large
|
|
102
|
+
* fetch is pure waste. Invalidated if options.encoding ever changes.
|
|
103
|
+
*/
|
|
104
|
+
function resolveTextState(options) {
|
|
105
|
+
const key = options && options.encoding;
|
|
106
|
+
if (options && options.__textState && options.__textState.key === key) {
|
|
107
|
+
return options.__textState;
|
|
108
|
+
}
|
|
109
|
+
const encoding = (key || const_1.default.DEFAULT_ENCODING).toUpperCase();
|
|
110
|
+
const state = {
|
|
111
|
+
key,
|
|
112
|
+
codec: FirebirdToNodeEncoding[encoding] ? null : (0, codepages_1.getCodec)(encoding),
|
|
113
|
+
enc: (FirebirdToNodeEncoding[encoding] || const_1.default.DEFAULT_ENCODING.toLowerCase()),
|
|
114
|
+
width: getFirebirdCharsetWidth(encoding),
|
|
115
|
+
};
|
|
116
|
+
if (options) {
|
|
117
|
+
options.__textState = state;
|
|
118
|
+
}
|
|
119
|
+
return state;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Encode text in the CONNECTION charset — the byte form the server
|
|
123
|
+
* expects for parameters, SQL statement text and text-blob content.
|
|
124
|
+
*/
|
|
125
|
+
function encodeConnectionText(options, value) {
|
|
126
|
+
const state = resolveTextState(options);
|
|
127
|
+
if (state.codec) {
|
|
128
|
+
return state.codec.encode(value);
|
|
129
|
+
}
|
|
130
|
+
if (state.enc === 'ascii') {
|
|
131
|
+
// Node's 'ascii' encoding masks high bits (0xE4 → 'd') — replace
|
|
132
|
+
// non-ASCII with '?' instead, matching the codec policy
|
|
133
|
+
value = value.replace(/[^\x00-\x7F]/g, '?');
|
|
134
|
+
}
|
|
135
|
+
return Buffer.from(value, state.enc);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Decode connection-charset bytes to text (the read counterpart of
|
|
139
|
+
* encodeConnectionText — used for text blobs).
|
|
140
|
+
*/
|
|
141
|
+
function decodeConnectionText(options, buffer) {
|
|
142
|
+
const codec = resolveTextCodec(options);
|
|
143
|
+
if (codec) {
|
|
144
|
+
return codec.decode(buffer);
|
|
145
|
+
}
|
|
146
|
+
return buffer.toString(resolveTextEncoding(options));
|
|
147
|
+
}
|
|
71
148
|
//------------------------------------------------------
|
|
72
149
|
/**
|
|
73
150
|
* Common shape of all SQLVar descriptor objects. The metadata properties
|
|
@@ -222,7 +299,9 @@ function describeField(meta) {
|
|
|
222
299
|
typeName: exports.SQL_TYPE_NAMES[meta.type] || 'UNKNOWN',
|
|
223
300
|
subType: meta.subType,
|
|
224
301
|
scale: meta.scale,
|
|
225
|
-
|
|
302
|
+
// report the column's true declared length, not the widened fetch
|
|
303
|
+
// buffer (see scaleOutputLengths)
|
|
304
|
+
length: meta.nativeLength !== undefined ? meta.nativeLength : meta.length,
|
|
226
305
|
nullable: meta.nullable,
|
|
227
306
|
field: meta.field,
|
|
228
307
|
relation: meta.relation,
|
|
@@ -290,23 +369,12 @@ function parseRecordCounts(buffer) {
|
|
|
290
369
|
class SQLVarText extends SQLVarBase {
|
|
291
370
|
decode(data, lowerV13, options) {
|
|
292
371
|
let ret;
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const
|
|
299
|
-
const charLength = Math.floor(this.length / width);
|
|
300
|
-
if (ret.length > charLength) {
|
|
301
|
-
ret = ret.substring(0, charLength);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
else if (this.subType === 0) {
|
|
305
|
-
// without charset definition
|
|
306
|
-
ret = data.readText(this.length, textEncoding);
|
|
307
|
-
const encoding = options && options.encoding ? options.encoding : 'UTF8';
|
|
308
|
-
const width = getFirebirdCharsetWidth(encoding);
|
|
309
|
-
const charLength = Math.floor(this.length / width);
|
|
372
|
+
if (this.subType > 1 || this.subType === 0) {
|
|
373
|
+
const state = resolveTextState(options);
|
|
374
|
+
ret = state.codec
|
|
375
|
+
? state.codec.decode(data.readBuffer(this.length) || EMPTY_BUFFER)
|
|
376
|
+
: data.readText(this.length, state.enc);
|
|
377
|
+
const charLength = Math.floor(this.length / state.width);
|
|
310
378
|
if (ret.length > charLength) {
|
|
311
379
|
ret = ret.substring(0, charLength);
|
|
312
380
|
}
|
|
@@ -333,14 +401,11 @@ exports.SQLVarNull = SQLVarNull;
|
|
|
333
401
|
class SQLVarString extends SQLVarBase {
|
|
334
402
|
decode(data, lowerV13, options) {
|
|
335
403
|
let ret;
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
else if (this.subType === 0) {
|
|
342
|
-
// without charset definition
|
|
343
|
-
ret = data.readString(textEncoding);
|
|
404
|
+
if (this.subType > 1 || this.subType === 0) {
|
|
405
|
+
const state = resolveTextState(options);
|
|
406
|
+
ret = state.codec
|
|
407
|
+
? state.codec.decode(data.readArray() || EMPTY_BUFFER)
|
|
408
|
+
: data.readString(state.enc);
|
|
344
409
|
}
|
|
345
410
|
else {
|
|
346
411
|
ret = data.readBuffer();
|
|
@@ -875,10 +940,19 @@ class SQLParamDate {
|
|
|
875
940
|
exports.SQLParamDate = SQLParamDate;
|
|
876
941
|
//------------------------------------------------------
|
|
877
942
|
class SQLParamBool {
|
|
878
|
-
constructor(value) {
|
|
943
|
+
constructor(value, asBoolean = false) {
|
|
879
944
|
this.value = value;
|
|
945
|
+
this.asBoolean = asBoolean;
|
|
880
946
|
}
|
|
881
947
|
encode(data) {
|
|
948
|
+
if (this.asBoolean) {
|
|
949
|
+
// xdr_datum sends booleans as 1 opaque value byte + 3 pad bytes
|
|
950
|
+
// (NOT a big-endian int: the value byte comes FIRST — addInt(1)
|
|
951
|
+
// would decode server-side as false). Matches the batch encoder.
|
|
952
|
+
data.addBuffer(Buffer.from([this.value ? 1 : 0]));
|
|
953
|
+
data.addAlignment(1);
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
882
956
|
if (this.value != null) {
|
|
883
957
|
data.addInt(this.value ? 1 : 0);
|
|
884
958
|
}
|
|
@@ -888,6 +962,10 @@ class SQLParamBool {
|
|
|
888
962
|
}
|
|
889
963
|
}
|
|
890
964
|
calcBlr(blr) {
|
|
965
|
+
if (this.asBoolean) {
|
|
966
|
+
blr.addByte(const_1.default.blr_bool);
|
|
967
|
+
return;
|
|
968
|
+
}
|
|
891
969
|
blr.addByte(const_1.default.blr_short);
|
|
892
970
|
blr.addShort(0);
|
|
893
971
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-firebird",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.14.0",
|
|
4
4
|
"description": "Pure JavaScript and Asynchronous Firebird client for Node.js.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"firebird",
|
|
@@ -23,6 +23,24 @@
|
|
|
23
23
|
],
|
|
24
24
|
"main": "./lib/index.js",
|
|
25
25
|
"types": "./lib/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./lib/index.d.ts",
|
|
29
|
+
"import": "./lib/index.js",
|
|
30
|
+
"require": "./lib/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./lib/firebird.msg": "./lib/firebird.msg",
|
|
33
|
+
"./lib/firebird.msg.json": "./lib/firebird.msg.json",
|
|
34
|
+
"./lib/*.js": {
|
|
35
|
+
"types": "./lib/*.d.ts",
|
|
36
|
+
"default": "./lib/*.js"
|
|
37
|
+
},
|
|
38
|
+
"./lib/*": {
|
|
39
|
+
"types": "./lib/*.d.ts",
|
|
40
|
+
"default": "./lib/*.js"
|
|
41
|
+
},
|
|
42
|
+
"./package.json": "./package.json"
|
|
43
|
+
},
|
|
26
44
|
"files": [
|
|
27
45
|
"lib",
|
|
28
46
|
"src"
|
package/src/callback.ts
CHANGED
|
@@ -45,6 +45,21 @@ export function toError(err: any): Error {
|
|
|
45
45
|
* Run a callback-style operation and return a Promise for its result.
|
|
46
46
|
* Usage: fromCallback<Database>(cb => attach(options, cb))
|
|
47
47
|
*/
|
|
48
|
+
/**
|
|
49
|
+
* Run `work` with a pooled connection and always return it to its pool
|
|
50
|
+
* (detach) when the promise settles — a detach hiccup never masks the
|
|
51
|
+
* outcome of `work`. Shared by Pool.withConnection and
|
|
52
|
+
* PoolCluster.withConnection so the release semantics cannot drift.
|
|
53
|
+
*/
|
|
54
|
+
export async function withPooledConnection<T>(getAsync: () => Promise<any>, work: (db: any) => Promise<T> | T): Promise<T> {
|
|
55
|
+
const db = await getAsync();
|
|
56
|
+
try {
|
|
57
|
+
return await work(db);
|
|
58
|
+
} finally {
|
|
59
|
+
await new Promise<void>(function(resolve) { db.detach(function() { resolve(); }); });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
48
63
|
export function fromCallback<T = any>(executor: (cb: Callback<T>) => void): Promise<T> {
|
|
49
64
|
return new Promise<T>(function(resolve, reject) {
|
|
50
65
|
executor(function(err?: any, result?: T) {
|
package/src/index.ts
CHANGED
|
@@ -2,6 +2,8 @@ import Const from './wire/const';
|
|
|
2
2
|
import { doError, doCallback, fromCallback, type Callback } from './callback';
|
|
3
3
|
import Connection from './wire/connection';
|
|
4
4
|
import Pool from './pool';
|
|
5
|
+
import PoolCluster from './pool-cluster';
|
|
6
|
+
import type { PoolClusterOptions } from './pool-cluster';
|
|
5
7
|
import { escape as escapeValue } from './utils';
|
|
6
8
|
import { parseConnectionUri, parseConnectionString, normalizeOptions } from './uri';
|
|
7
9
|
import type {
|
|
@@ -194,6 +196,19 @@ export function pool(max: number, options: Options | string): ConnectionPool {
|
|
|
194
196
|
return new Pool(attach, max, Object.assign({}, normalizeOptions(options), { isPool: true }));
|
|
195
197
|
}
|
|
196
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Multi-host pooling (primaries/replicas, failover): named nodes, each
|
|
201
|
+
* backed by a regular pool, selected by glob pattern + 'rr'/'random'/
|
|
202
|
+
* 'order' selector, with connection-failure failover and error-based
|
|
203
|
+
* node offlining. See README § Multi-host pooling.
|
|
204
|
+
*/
|
|
205
|
+
export function poolCluster(options?: PoolClusterOptions): PoolCluster {
|
|
206
|
+
const normalized: PoolClusterOptions = { ...(options || {}) };
|
|
207
|
+
normalized.defaults = normalizeOptions(normalized.defaults || {});
|
|
208
|
+
return new PoolCluster(attach, normalized);
|
|
209
|
+
}
|
|
210
|
+
export type { PoolClusterOptions, ClusterSelector } from './pool-cluster';
|
|
211
|
+
|
|
197
212
|
export { parseConnectionUri, parseConnectionString };
|
|
198
213
|
export { parseNamedPlaceholders } from './named-params';
|
|
199
214
|
|