node-firebird 2.3.4 → 2.4.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 +544 -6
- package/lib/callback.d.ts +20 -0
- package/lib/callback.js +6 -16
- package/lib/firebird.msg.json +1370 -1370
- package/lib/gdscodes.d.ts +1519 -1520
- package/lib/gdscodes.js +5 -5
- package/lib/ieee754-decimal.d.ts +38 -0
- package/lib/ieee754-decimal.js +71 -118
- package/lib/index.d.ts +37 -338
- package/lib/index.js +97 -86
- package/lib/messages.d.ts +6 -0
- package/lib/messages.js +135 -162
- package/lib/pool.d.ts +23 -0
- package/lib/pool.js +34 -47
- package/lib/srp.d.ts +51 -0
- package/lib/srp.js +62 -72
- package/lib/types.d.ts +375 -0
- package/lib/types.js +22 -0
- package/lib/unix-crypt.d.ts +1 -0
- package/lib/unix-crypt.js +126 -152
- package/lib/utils.d.ts +16 -0
- package/lib/utils.js +24 -48
- package/lib/wire/connection.d.ts +100 -0
- package/lib/wire/connection.js +1029 -1009
- package/lib/wire/const.d.ts +567 -0
- package/lib/wire/const.js +620 -599
- package/lib/wire/database.d.ts +57 -0
- package/lib/wire/database.js +111 -108
- package/lib/wire/eventConnection.d.ts +16 -0
- package/lib/wire/eventConnection.js +29 -31
- package/lib/wire/fbEventManager.d.ts +45 -0
- package/lib/wire/fbEventManager.js +38 -57
- package/lib/wire/serialize.d.ts +97 -0
- package/lib/wire/serialize.js +42 -141
- package/lib/wire/service.d.ts +66 -0
- package/lib/wire/service.js +374 -401
- package/lib/wire/socket.d.ts +59 -0
- package/lib/wire/socket.js +79 -40
- package/lib/wire/statement.d.ts +25 -0
- package/lib/wire/statement.js +13 -9
- package/lib/wire/transaction.d.ts +21 -0
- package/lib/wire/transaction.js +33 -61
- package/lib/wire/xsqlvar.d.ts +175 -0
- package/lib/wire/xsqlvar.js +169 -269
- package/package.json +12 -4
- package/src/callback.ts +55 -0
- package/{poc/node_modules/node-firebird/lib/gdscodes.js → src/gdscodes.ts} +3 -3
- package/{poc/node_modules/node-firebird/lib/ieee754-decimal.js → src/ieee754-decimal.ts} +7 -14
- package/src/index.ts +157 -0
- package/{poc/node_modules/node-firebird/lib/messages.js → src/messages.ts} +163 -162
- package/src/pool.ts +209 -0
- package/{poc/node_modules/node-firebird/lib/srp.js → src/srp.ts} +74 -33
- package/src/types.ts +419 -0
- package/{poc/node_modules/node-firebird/lib/unix-crypt.js → src/unix-crypt.ts} +6 -12
- package/{poc/node_modules/node-firebird/lib/utils.js → src/utils.ts} +11 -20
- package/{poc/node_modules/node-firebird/lib/wire/connection.js → src/wire/connection.ts} +611 -129
- package/{poc/node_modules/node-firebird/lib/wire/const.js → src/wire/const.ts} +96 -9
- package/{poc/node_modules/node-firebird/lib/wire/database.js → src/wire/database.ts} +110 -44
- package/{poc/node_modules/node-firebird/lib/wire/eventConnection.js → src/wire/eventConnection.ts} +29 -14
- package/{poc/node_modules/node-firebird/lib/wire/fbEventManager.js → src/wire/fbEventManager.ts} +39 -30
- package/{poc/node_modules/node-firebird/lib/wire/serialize.js → src/wire/serialize.ts} +78 -59
- package/{poc/node_modules/node-firebird/lib/wire/service.js → src/wire/service.ts} +90 -88
- package/src/wire/socket.ts +262 -0
- package/src/wire/statement.ts +71 -0
- package/{poc/node_modules/node-firebird/lib/wire/transaction.js → src/wire/transaction.ts} +25 -19
- package/{poc/node_modules/node-firebird/lib/wire/xsqlvar.js → src/wire/xsqlvar.ts} +244 -143
- package/.eslintrc.json +0 -12
- package/.github/workflows/codeql.yml +0 -76
- package/.github/workflows/node.js.yml +0 -95
- package/BIGINT_MIGRATION.md +0 -374
- package/CI_DEBUGGING_GUIDE.md +0 -148
- package/ENCRYPTION_CALLBACK.md +0 -152
- package/FIREBIRD_LOG_FEATURE.md +0 -145
- package/MINIMAL_CHANGES_SUMMARY.md +0 -136
- package/PR_SUMMARY.md +0 -96
- package/ROADMAP.md +0 -223
- package/SRP_PROTOCOL.md +0 -482
- package/poc/README.md +0 -160
- package/poc/helpers.js +0 -59
- package/poc/node_modules/.package-lock.json +0 -14
- package/poc/node_modules/node-firebird/.eslintrc.json +0 -12
- package/poc/node_modules/node-firebird/.github/workflows/codeql.yml +0 -76
- package/poc/node_modules/node-firebird/.github/workflows/node.js.yml +0 -95
- package/poc/node_modules/node-firebird/BIGINT_MIGRATION.md +0 -374
- package/poc/node_modules/node-firebird/CI_DEBUGGING_GUIDE.md +0 -148
- package/poc/node_modules/node-firebird/ENCRYPTION_CALLBACK.md +0 -152
- package/poc/node_modules/node-firebird/FIREBIRD_LOG_FEATURE.md +0 -145
- package/poc/node_modules/node-firebird/LICENSE +0 -373
- package/poc/node_modules/node-firebird/MINIMAL_CHANGES_SUMMARY.md +0 -136
- package/poc/node_modules/node-firebird/PR_SUMMARY.md +0 -96
- package/poc/node_modules/node-firebird/README.md +0 -794
- package/poc/node_modules/node-firebird/ROADMAP.md +0 -223
- package/poc/node_modules/node-firebird/SRP_PROTOCOL.md +0 -482
- package/poc/node_modules/node-firebird/lib/callback.js +0 -38
- package/poc/node_modules/node-firebird/lib/gdscodes.d.ts +0 -1524
- package/poc/node_modules/node-firebird/lib/index.d.ts +0 -316
- package/poc/node_modules/node-firebird/lib/index.js +0 -128
- package/poc/node_modules/node-firebird/lib/pool.js +0 -108
- package/poc/node_modules/node-firebird/lib/wire/socket.js +0 -175
- package/poc/node_modules/node-firebird/lib/wire/statement.js +0 -48
- package/poc/node_modules/node-firebird/package.json +0 -38
- package/poc/node_modules/node-firebird/vitest.config.js +0 -24
- package/poc/package-lock.json +0 -21
- package/poc/package.json +0 -12
- package/poc/reproduce-fixed.js +0 -150
- package/poc/reproduce.js +0 -133
- package/vitest.config.js +0 -27
- /package/{poc/node_modules/node-firebird/lib → src}/firebird.msg +0 -0
- /package/{poc/node_modules/node-firebird/lib → src}/firebird.msg.json +0 -0
package/lib/srp.js
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PRIME_N = void 0;
|
|
7
|
+
exports.clientSeed = clientSeed;
|
|
8
|
+
exports.serverSeed = serverSeed;
|
|
9
|
+
exports.serverSession = serverSession;
|
|
10
|
+
exports.clientProof = clientProof;
|
|
11
|
+
exports.hexPad = hexPad;
|
|
12
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
13
|
+
const SRP_KEY_SIZE = 128, SRP_KEY_MAX = BigInt('340282366920938463463374607431768211456'), // 1 << SRP_KEY_SIZE
|
|
14
|
+
SRP_SALT_SIZE = 32;
|
|
7
15
|
const DEBUG = false;
|
|
8
16
|
const DEBUG_PRIVATE_KEY = BigInt('0x84316857F47914F838918D5C12CE3A3E7A9B2D7C9486346809E9EEFCE8DE7CD4259D8BE4FD0BCC2D259553769E078FA61EE2977025E4DA42F7FD97914D8A33723DFAFBC00770B7DA0C2E3778A05790F0C0F33C32A19ED88A12928567749021B3FD45DCD1CE259C45325067E3DDC972F87867349BA82C303CCCAA9B207218007B');
|
|
9
|
-
|
|
10
17
|
/**
|
|
11
18
|
* Prime values.
|
|
12
19
|
*
|
|
@@ -17,29 +24,32 @@ const PRIME = {
|
|
|
17
24
|
g: BigInt(2),
|
|
18
25
|
k: BigInt('1277432915985975349439481660349303019122249719989')
|
|
19
26
|
};
|
|
20
|
-
|
|
27
|
+
const kCache = {};
|
|
28
|
+
function getK(hashAlgo) {
|
|
29
|
+
if (!kCache[hashAlgo]) {
|
|
30
|
+
kCache[hashAlgo] = BigInt('0x' + getHash(hashAlgo, pad(PRIME.N), pad(PRIME.g)));
|
|
31
|
+
}
|
|
32
|
+
return kCache[hashAlgo];
|
|
33
|
+
}
|
|
21
34
|
/**
|
|
22
35
|
* Generate a client key pair.
|
|
23
36
|
*
|
|
24
37
|
* @param a BigInt Client private key.
|
|
25
38
|
* @returns {{private: BigInt, public: BigInt}}
|
|
26
39
|
*/
|
|
27
|
-
|
|
40
|
+
function clientSeed(a = toBigInt(crypto_1.default.randomBytes(SRP_KEY_SIZE)) % PRIME.N) {
|
|
28
41
|
// a must be in [0, N): clientSession() reduces the exponent (a + ux) mod N
|
|
29
42
|
// to match the Firebird engine, but A = g^a is computed from the raw a.
|
|
30
43
|
// When random a >= N (~10% of 1024-bit values), the proof diverges from
|
|
31
44
|
// the server's session key, causing sporadic auth failures.
|
|
32
45
|
var A = modPow(PRIME.g, a, PRIME.N);
|
|
33
|
-
|
|
34
46
|
dump('a', a);
|
|
35
47
|
dump('A', A);
|
|
36
|
-
|
|
37
48
|
return {
|
|
38
49
|
public: A,
|
|
39
50
|
private: a
|
|
40
51
|
};
|
|
41
52
|
}
|
|
42
|
-
|
|
43
53
|
/**
|
|
44
54
|
* Generate a server key pair.
|
|
45
55
|
*
|
|
@@ -49,24 +59,29 @@ exports.clientSeed = function(a = toBigInt(crypto.randomBytes(SRP_KEY_SIZE)) % P
|
|
|
49
59
|
* @param b BigInt Server private key.
|
|
50
60
|
* @returns {{private: BigInt, public: BigInt}}
|
|
51
61
|
*/
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
62
|
+
function serverSeed(user, password, salt, b, hashAlgo = 'sha1') {
|
|
63
|
+
if (typeof b === 'string') {
|
|
64
|
+
hashAlgo = b;
|
|
65
|
+
b = undefined;
|
|
66
|
+
}
|
|
67
|
+
const bKey = (b === undefined || b === null)
|
|
68
|
+
? toBigInt(crypto_1.default.randomBytes(SRP_KEY_SIZE))
|
|
69
|
+
: b;
|
|
70
|
+
var v = getVerifier(user, password, salt, 'sha1');
|
|
71
|
+
var gb = modPow(PRIME.g, bKey, PRIME.N);
|
|
72
|
+
var k = getK('sha1');
|
|
73
|
+
var kv = (k * v) % PRIME.N;
|
|
56
74
|
var B = (kv + gb) % PRIME.N;
|
|
57
|
-
|
|
58
75
|
dump('v', v);
|
|
59
|
-
dump('b',
|
|
60
|
-
dump('gb',
|
|
76
|
+
dump('b', bKey);
|
|
77
|
+
dump('gb', bKey);
|
|
61
78
|
dump('kv', v);
|
|
62
79
|
dump('B', B);
|
|
63
|
-
|
|
64
80
|
return {
|
|
65
81
|
public: B,
|
|
66
|
-
private:
|
|
82
|
+
private: bKey
|
|
67
83
|
};
|
|
68
84
|
}
|
|
69
|
-
|
|
70
85
|
/**
|
|
71
86
|
* Server session secret.
|
|
72
87
|
*
|
|
@@ -78,47 +93,39 @@ exports.serverSeed = function(user, password, salt, b = toBigInt(crypto.randomBy
|
|
|
78
93
|
* @param b BigInt Server private key.
|
|
79
94
|
* @returns {BigInt}
|
|
80
95
|
*/
|
|
81
|
-
|
|
82
|
-
var u = getScramble(A, B);
|
|
83
|
-
var v = getVerifier(user, password, salt);
|
|
96
|
+
function serverSession(user, password, salt, A, B, b, hashAlgo = 'sha1') {
|
|
97
|
+
var u = getScramble(A, B, 'sha1');
|
|
98
|
+
var v = getVerifier(user, password, salt, 'sha1');
|
|
84
99
|
var vu = modPow(v, u, PRIME.N);
|
|
85
100
|
var Avu = (A * vu) % PRIME.N;
|
|
86
101
|
var sessionSecret = modPow(Avu, b, PRIME.N);
|
|
87
102
|
var K = getHash('sha1', toBuffer(sessionSecret));
|
|
88
|
-
|
|
89
103
|
dump('server sessionSecret', sessionSecret);
|
|
90
104
|
dump('server K', K);
|
|
91
|
-
|
|
92
105
|
return BigInt('0x' + K);
|
|
93
|
-
}
|
|
94
|
-
|
|
106
|
+
}
|
|
107
|
+
;
|
|
95
108
|
/**
|
|
96
109
|
* M = H(H(N) xor H(g), H(I), s, A, B, K)
|
|
97
110
|
*/
|
|
98
|
-
|
|
99
|
-
var K = clientSession(user, password, salt, A, B, a);
|
|
111
|
+
function clientProof(user, password, salt, A, B, a, hashAlgo = 'sha1') {
|
|
112
|
+
var K = clientSession(user, password, salt, A, B, a, 'sha1');
|
|
100
113
|
var n1, n2;
|
|
101
|
-
|
|
102
114
|
n1 = toBigInt(getHash('sha1', toBuffer(PRIME.N)));
|
|
103
115
|
n2 = toBigInt(getHash('sha1', toBuffer(PRIME.g)));
|
|
104
|
-
|
|
105
116
|
dump('n1', n1);
|
|
106
117
|
dump('n2', n2);
|
|
107
|
-
|
|
108
118
|
n1 = modPow(n1, n2, PRIME.N);
|
|
109
119
|
n2 = toBigInt(getHash('sha1', user));
|
|
110
120
|
var M = toBigInt(getHash(hashAlgo, toBuffer(n1), toBuffer(n2), salt, toBuffer(A), toBuffer(B), toBuffer(K)));
|
|
111
|
-
|
|
112
121
|
dump('n1-2', n1);
|
|
113
122
|
dump('n2-2', n2);
|
|
114
123
|
dump('proof:M', M);
|
|
115
|
-
|
|
116
124
|
return {
|
|
117
125
|
clientSessionKey: K,
|
|
118
126
|
authData: M,
|
|
119
127
|
};
|
|
120
128
|
}
|
|
121
|
-
|
|
122
129
|
/**
|
|
123
130
|
* Pad hex string.
|
|
124
131
|
*/
|
|
@@ -126,18 +133,14 @@ function hexPad(hex) {
|
|
|
126
133
|
if (hex.length % 2 !== 0) {
|
|
127
134
|
hex = '0' + hex;
|
|
128
135
|
}
|
|
129
|
-
|
|
130
136
|
return hex;
|
|
131
137
|
}
|
|
132
|
-
exports.hexPad = hexPad;
|
|
133
|
-
|
|
134
138
|
/**
|
|
135
139
|
* The SRP prime modulus N (1024-bit, same value used by Firebird).
|
|
136
140
|
* Exported so tests and tooling can assert key-size invariants without
|
|
137
141
|
* duplicating the constant.
|
|
138
142
|
*/
|
|
139
143
|
exports.PRIME_N = PRIME.N;
|
|
140
|
-
|
|
141
144
|
/**
|
|
142
145
|
* Pad key with SRP_KEY_SIZE.
|
|
143
146
|
*
|
|
@@ -146,14 +149,16 @@ exports.PRIME_N = PRIME.N;
|
|
|
146
149
|
*/
|
|
147
150
|
function pad(n) {
|
|
148
151
|
var buff = Buffer.from(hexPad(n.toString(16)), 'hex');
|
|
149
|
-
|
|
150
152
|
if (buff.length > SRP_KEY_SIZE) {
|
|
151
153
|
buff = buff.slice(buff.length - SRP_KEY_SIZE, buff.length);
|
|
152
154
|
}
|
|
153
|
-
|
|
155
|
+
else if (buff.length < SRP_KEY_SIZE) {
|
|
156
|
+
var padded = Buffer.alloc(SRP_KEY_SIZE);
|
|
157
|
+
buff.copy(padded, SRP_KEY_SIZE - buff.length);
|
|
158
|
+
buff = padded;
|
|
159
|
+
}
|
|
154
160
|
return buff;
|
|
155
161
|
}
|
|
156
|
-
|
|
157
162
|
/**
|
|
158
163
|
* Scramble keys.
|
|
159
164
|
*
|
|
@@ -161,10 +166,9 @@ function pad(n) {
|
|
|
161
166
|
* @param B BigInt Server public key.
|
|
162
167
|
* @returns {BigInt}
|
|
163
168
|
*/
|
|
164
|
-
function getScramble(A, B) {
|
|
165
|
-
return BigInt('0x' + getHash(
|
|
169
|
+
function getScramble(A, B, hashAlgo = 'sha1') {
|
|
170
|
+
return BigInt('0x' + getHash(hashAlgo, pad(A), pad(B)));
|
|
166
171
|
}
|
|
167
|
-
|
|
168
172
|
/**
|
|
169
173
|
* Client session secret.
|
|
170
174
|
*
|
|
@@ -180,17 +184,16 @@ function getScramble(A, B) {
|
|
|
180
184
|
* @param B BigInt Server public key.
|
|
181
185
|
* @param a BigInt Client private key.
|
|
182
186
|
*/
|
|
183
|
-
function clientSession(user, password, salt, A, B, a) {
|
|
184
|
-
var u = getScramble(A, B);
|
|
185
|
-
var x = getUserHash(user, salt, password);
|
|
187
|
+
function clientSession(user, password, salt, A, B, a, hashAlgo = 'sha1') {
|
|
188
|
+
var u = getScramble(A, B, 'sha1');
|
|
189
|
+
var x = getUserHash(user, salt, password, 'sha1');
|
|
186
190
|
var gx = modPow(PRIME.g, x, PRIME.N);
|
|
187
|
-
var
|
|
191
|
+
var k = getK('sha1');
|
|
192
|
+
var kgx = (k * gx) % PRIME.N;
|
|
188
193
|
var diff = (B - kgx) % PRIME.N;
|
|
189
|
-
|
|
190
194
|
if (diff < 0n) {
|
|
191
195
|
diff = diff + PRIME.N;
|
|
192
196
|
}
|
|
193
|
-
|
|
194
197
|
// Note: While the SRP specification says exponents should not be reduced mod N,
|
|
195
198
|
// the Firebird engine implementation does reduce these exponents mod N.
|
|
196
199
|
// We must match the server's behavior for authentication to succeed.
|
|
@@ -198,7 +201,6 @@ function clientSession(user, password, salt, A, B, a) {
|
|
|
198
201
|
var aux = (a + ux) % PRIME.N;
|
|
199
202
|
var sessionSecret = modPow(diff, aux, PRIME.N);
|
|
200
203
|
var K = toBigInt(getHash('sha1', toBuffer(sessionSecret)));
|
|
201
|
-
|
|
202
204
|
dump('B', B);
|
|
203
205
|
dump('u', u);
|
|
204
206
|
dump('x', x);
|
|
@@ -209,10 +211,8 @@ function clientSession(user, password, salt, A, B, a) {
|
|
|
209
211
|
dump('aux', aux);
|
|
210
212
|
dump('sessionSecret', sessionSecret);
|
|
211
213
|
dump('sessionKey(K)', K);
|
|
212
|
-
|
|
213
214
|
return K;
|
|
214
215
|
}
|
|
215
|
-
|
|
216
216
|
/**
|
|
217
217
|
* Compute user hash.
|
|
218
218
|
*
|
|
@@ -221,13 +221,11 @@ function clientSession(user, password, salt, A, B, a) {
|
|
|
221
221
|
* @param password string Connection password.
|
|
222
222
|
* @returns {BigInt}
|
|
223
223
|
*/
|
|
224
|
-
function getUserHash(user, salt, password) {
|
|
225
|
-
var hash1 = getHash(
|
|
226
|
-
var hash2 = getHash(
|
|
227
|
-
|
|
224
|
+
function getUserHash(user, salt, password, hashAlgo = 'sha1') {
|
|
225
|
+
var hash1 = getHash(hashAlgo, user.toUpperCase(), ':', password);
|
|
226
|
+
var hash2 = getHash(hashAlgo, salt, toBuffer(hash1));
|
|
228
227
|
return toBigInt(hash2);
|
|
229
228
|
}
|
|
230
|
-
|
|
231
229
|
/**
|
|
232
230
|
* Verifier of user hash.
|
|
233
231
|
*
|
|
@@ -236,10 +234,9 @@ function getUserHash(user, salt, password) {
|
|
|
236
234
|
* @param salt BigInt Connection salt.
|
|
237
235
|
* @returns {BigInt}
|
|
238
236
|
*/
|
|
239
|
-
function getVerifier(user, password, salt) {
|
|
240
|
-
return modPow(PRIME.g, getUserHash(user, salt, password), PRIME.N);
|
|
237
|
+
function getVerifier(user, password, salt, hashAlgo = 'sha1') {
|
|
238
|
+
return modPow(PRIME.g, getUserHash(user, salt, password, hashAlgo), PRIME.N);
|
|
241
239
|
}
|
|
242
|
-
|
|
243
240
|
/**
|
|
244
241
|
* Hash data and return hex string.
|
|
245
242
|
*
|
|
@@ -248,15 +245,12 @@ function getVerifier(user, password, salt) {
|
|
|
248
245
|
* @returns {string}
|
|
249
246
|
*/
|
|
250
247
|
function getHash(algo, ...data) {
|
|
251
|
-
var hash =
|
|
252
|
-
|
|
248
|
+
var hash = crypto_1.default.createHash(algo);
|
|
253
249
|
for (var d of data) {
|
|
254
250
|
hash.update(d);
|
|
255
251
|
}
|
|
256
|
-
|
|
257
252
|
return hash.digest('hex');
|
|
258
253
|
}
|
|
259
|
-
|
|
260
254
|
/**
|
|
261
255
|
* Convert BigInt to buffer.
|
|
262
256
|
*
|
|
@@ -266,7 +260,6 @@ function getHash(algo, ...data) {
|
|
|
266
260
|
function toBuffer(bigInt) {
|
|
267
261
|
return Buffer.from(typeof bigInt === 'bigint' ? hexPad(bigInt.toString(16)) : bigInt, 'hex');
|
|
268
262
|
}
|
|
269
|
-
|
|
270
263
|
/**
|
|
271
264
|
* Convert hex buffer or string to BigInt.
|
|
272
265
|
*
|
|
@@ -276,7 +269,6 @@ function toBuffer(bigInt) {
|
|
|
276
269
|
function toBigInt(hex) {
|
|
277
270
|
return BigInt('0x' + (Buffer.isBuffer(hex) ? hex.toString('hex') : hex));
|
|
278
271
|
}
|
|
279
|
-
|
|
280
272
|
/**
|
|
281
273
|
* Dump value in debug mode.
|
|
282
274
|
*
|
|
@@ -288,11 +280,9 @@ function dump(key, value) {
|
|
|
288
280
|
if (typeof value === 'bigint') {
|
|
289
281
|
value = value.toString(16);
|
|
290
282
|
}
|
|
291
|
-
|
|
292
283
|
console.log(key + '=' + value);
|
|
293
284
|
}
|
|
294
285
|
}
|
|
295
|
-
|
|
296
286
|
/**
|
|
297
287
|
* Calculates (base ^ exp) % mod using native BigInt.
|
|
298
288
|
*/
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
export type DatabaseCallback = (err: any, db: Database) => void;
|
|
2
|
+
export type TransactionCallback = (err: any, transaction: Transaction) => void;
|
|
3
|
+
export type QueryCallback = (err: any, result: any[]) => void;
|
|
4
|
+
export type SimpleCallback = (err: any) => void;
|
|
5
|
+
export type SequentialCallback = (row: any, index: number, next?: (err?: any) => void) => void | Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Describes a single column in a prepared statement's result set or
|
|
8
|
+
* parameter list. The properties here are populated by the
|
|
9
|
+
* `isc_info_sql_*` response items returned by the Firebird server during
|
|
10
|
+
* op_prepare_statement.
|
|
11
|
+
*
|
|
12
|
+
* On Firebird 6.0+ (Protocol 20) `relationSchema` is additionally
|
|
13
|
+
* populated when the column comes from a table that lives in a
|
|
14
|
+
* named schema.
|
|
15
|
+
*/
|
|
16
|
+
export interface ColumnMetadata {
|
|
17
|
+
/** Internal Firebird SQL type code (before nullability bit is masked). */
|
|
18
|
+
type: number;
|
|
19
|
+
/** SQL sub-type (e.g. BLOB sub-type 1 = TEXT). */
|
|
20
|
+
subType: number;
|
|
21
|
+
/** Numeric scale for fixed-point types (negative, e.g. NUMERIC(9,2) → -2). */
|
|
22
|
+
scale: number;
|
|
23
|
+
/** Maximum byte length for character / binary columns. */
|
|
24
|
+
length: number;
|
|
25
|
+
/** Whether the column accepts NULL values. */
|
|
26
|
+
nullable: boolean;
|
|
27
|
+
/** Column / parameter name as declared in the DDL. */
|
|
28
|
+
field?: string;
|
|
29
|
+
/** Source relation (table / view) name. */
|
|
30
|
+
relation?: string;
|
|
31
|
+
/**
|
|
32
|
+
* **Firebird 6.0+ (Protocol 20+)**
|
|
33
|
+
* Schema that owns the source relation. `undefined` or empty string
|
|
34
|
+
* for legacy (pre-6.0) servers or columns not drawn from a named
|
|
35
|
+
* schema (e.g. computed expressions).
|
|
36
|
+
*/
|
|
37
|
+
relationSchema?: string;
|
|
38
|
+
/** Column alias as it appears in the SELECT list. */
|
|
39
|
+
alias?: string;
|
|
40
|
+
/** Alias of the source relation / sub-query. */
|
|
41
|
+
relationAlias?: string;
|
|
42
|
+
/** Owner (user) of the source relation. */
|
|
43
|
+
owner?: string;
|
|
44
|
+
/**
|
|
45
|
+
* **Firebird 6.0+ (Protocol 20+)**
|
|
46
|
+
*
|
|
47
|
+
* Character Set ID extracted from packed subType for string/character types.
|
|
48
|
+
*/
|
|
49
|
+
charSetId?: number;
|
|
50
|
+
/**
|
|
51
|
+
* **Firebird 6.0+ (Protocol 20+)**
|
|
52
|
+
*
|
|
53
|
+
* Collation ID extracted from packed subType for string/character types.
|
|
54
|
+
*/
|
|
55
|
+
collationId?: number;
|
|
56
|
+
}
|
|
57
|
+
export type Isolation = number[];
|
|
58
|
+
export type TransactionOptions = {
|
|
59
|
+
autoCommit?: boolean;
|
|
60
|
+
autoUndo?: boolean;
|
|
61
|
+
isolation?: Isolation;
|
|
62
|
+
ignoreLimbo?: boolean;
|
|
63
|
+
readOnly?: boolean;
|
|
64
|
+
wait?: boolean;
|
|
65
|
+
waitTimeout?: number;
|
|
66
|
+
};
|
|
67
|
+
export type QueryOptions = {
|
|
68
|
+
timeout?: number;
|
|
69
|
+
scrollable?: boolean;
|
|
70
|
+
};
|
|
71
|
+
export interface Database {
|
|
72
|
+
detach(callback?: SimpleCallback): Database;
|
|
73
|
+
transaction(options: TransactionOptions | Isolation | TransactionCallback, callback?: TransactionCallback): Database;
|
|
74
|
+
newStatement(query: string, callback: (err: Error | null, statement: Statement) => void): Database;
|
|
75
|
+
query(query: string, params: any[], callback: QueryCallback, options?: QueryOptions): Database;
|
|
76
|
+
execute(query: string, params: any[], callback: QueryCallback, options?: QueryOptions): Database;
|
|
77
|
+
sequentially(query: string, params: any[], rowCallback: SequentialCallback, callback: SimpleCallback, options?: QueryOptions | boolean): Database;
|
|
78
|
+
drop(callback: SimpleCallback): void;
|
|
79
|
+
escape(value: any): string;
|
|
80
|
+
attachEvent(callback: any): this;
|
|
81
|
+
createTablespace(name: string, filePath: string, callback?: QueryCallback): Database;
|
|
82
|
+
alterTablespace(name: string, filePath: string, callback?: QueryCallback): Database;
|
|
83
|
+
dropTablespace(name: string, callback?: QueryCallback): Database;
|
|
84
|
+
createSchema(schemaName: string, tablespaceName?: string | QueryCallback, callback?: QueryCallback): Database;
|
|
85
|
+
}
|
|
86
|
+
export interface Transaction {
|
|
87
|
+
newStatement(query: string, callback: (err: Error | null, statement: Statement) => void): void;
|
|
88
|
+
query(query: string, params: any[], callback: QueryCallback, options?: QueryOptions): void;
|
|
89
|
+
execute(query: string, params: any[], callback: QueryCallback, options?: QueryOptions): void;
|
|
90
|
+
sequentially(query: string, params: any[], rowCallback: SequentialCallback, callback: SimpleCallback, options?: QueryOptions | boolean): Database;
|
|
91
|
+
commit(callback?: SimpleCallback): void;
|
|
92
|
+
commitRetaining(callback?: SimpleCallback): void;
|
|
93
|
+
rollback(callback?: SimpleCallback): void;
|
|
94
|
+
rollbackRetaining(callback?: SimpleCallback): void;
|
|
95
|
+
}
|
|
96
|
+
export interface Statement {
|
|
97
|
+
close(callback?: SimpleCallback): void;
|
|
98
|
+
drop(callback?: SimpleCallback): void;
|
|
99
|
+
release(callback?: SimpleCallback): void;
|
|
100
|
+
execute(transaction: Transaction, params: any[], callback: QueryCallback, options?: QueryOptions): void;
|
|
101
|
+
fetch(transaction: Transaction, count: number, callback: QueryCallback): void;
|
|
102
|
+
fetchScroll(transaction: Transaction, direction: 'NEXT' | 'PRIOR' | 'FIRST' | 'LAST' | 'ABSOLUTE' | 'RELATIVE' | number, offset: number, count: number, callback: QueryCallback): void;
|
|
103
|
+
fetchAll(transaction: Transaction, callback: QueryCallback): void;
|
|
104
|
+
}
|
|
105
|
+
export type SupportedCharacterSet = 'NONE' | 'CP943C' | 'DOS737' | 'DOS775' | 'DOS858' | 'DOS862' | 'DOS864' | 'DOS866' | 'DOS869' | 'GB18030' | 'GBK' | 'ISO8859_1' | 'ISO8859_2' | 'ISO8859_3' | 'ISO8859_4' | 'ISO8859_5' | 'ISO8859_6' | 'ISO8859_7' | 'ISO8859_8' | 'ISO8859_9' | 'ISO8859_13' | 'KOI8R' | 'KOI8U' | 'TIS620' | 'UTF8' | 'WIN1251' | 'WIN1252' | 'WIN1253' | 'WIN1254' | 'WIN1255' | 'WIN1256' | 'WIN1257' | 'WIN1258' | 'WIN_1258';
|
|
106
|
+
export interface Options {
|
|
107
|
+
host?: string;
|
|
108
|
+
port?: number;
|
|
109
|
+
database?: string;
|
|
110
|
+
user?: string;
|
|
111
|
+
password?: string;
|
|
112
|
+
lowercase_keys?: boolean;
|
|
113
|
+
role?: string;
|
|
114
|
+
pageSize?: number;
|
|
115
|
+
retryConnectionInterval?: number;
|
|
116
|
+
encoding?: SupportedCharacterSet;
|
|
117
|
+
blobAsText?: boolean;
|
|
118
|
+
/**
|
|
119
|
+
* Segment size in bytes used when WRITING blobs (op_batch_segments).
|
|
120
|
+
* Default 1024, max 65535. Use 65535 to minimize round-trips on
|
|
121
|
+
* remote/high-latency connections.
|
|
122
|
+
*/
|
|
123
|
+
blobChunkSize?: number;
|
|
124
|
+
/**
|
|
125
|
+
* Buffer size in bytes requested per op_get_segment when READING
|
|
126
|
+
* blobs. Default 1024, max 65535. Use 65535 to minimize round-trips
|
|
127
|
+
* on remote/high-latency connections (~64x fewer round-trips).
|
|
128
|
+
*/
|
|
129
|
+
blobReadChunkSize?: number;
|
|
130
|
+
wireCrypt?: number;
|
|
131
|
+
wireCompression?: boolean;
|
|
132
|
+
pluginName?: string;
|
|
133
|
+
parallelWorkers?: number;
|
|
134
|
+
maxInlineBlobSize?: number;
|
|
135
|
+
maxNegotiatedProtocols?: number;
|
|
136
|
+
dbCryptConfig?: string;
|
|
137
|
+
/**
|
|
138
|
+
* Timeout in milliseconds for a single pool.get() attach operation.
|
|
139
|
+
* If attach() does not complete within this time the slot is freed,
|
|
140
|
+
* the caller receives an error, and any late-arriving connection is
|
|
141
|
+
* safely discarded. Set to 0 or omit to disable (default: no timeout).
|
|
142
|
+
*
|
|
143
|
+
* Recommended value: 5000–10000 ms depending on network latency and
|
|
144
|
+
* expected Firebird server response time under load.
|
|
145
|
+
*/
|
|
146
|
+
connectTimeout?: number;
|
|
147
|
+
/**
|
|
148
|
+
* **Firebird 6.0+ only (Protocol 20+)**
|
|
149
|
+
*
|
|
150
|
+
* Sets the session's current schema at connection time. Equivalent to
|
|
151
|
+
* executing `SET SCHEMA <name>` immediately after connecting.
|
|
152
|
+
*
|
|
153
|
+
* Unqualified object references (tables, procedures, etc.) that do not
|
|
154
|
+
* match any schema in the `searchPath` fall back to `PUBLIC`.
|
|
155
|
+
*
|
|
156
|
+
* Example: `defaultSchema: 'myapp'`
|
|
157
|
+
*/
|
|
158
|
+
defaultSchema?: string;
|
|
159
|
+
/**
|
|
160
|
+
* **Firebird 6.0+ only (Protocol 20+)**
|
|
161
|
+
*
|
|
162
|
+
* Comma-separated (or array of) schema names used to resolve
|
|
163
|
+
* unqualified object references, tried in order from left to right.
|
|
164
|
+
* Equivalent to PostgreSQL's `search_path`.
|
|
165
|
+
*
|
|
166
|
+
* Examples:
|
|
167
|
+
* ```ts
|
|
168
|
+
* searchPath: 'myapp,PUBLIC'
|
|
169
|
+
* searchPath: ['myapp', 'PUBLIC']
|
|
170
|
+
* ```
|
|
171
|
+
*
|
|
172
|
+
* When omitted the server uses its own configured default
|
|
173
|
+
* (typically `PUBLIC` then `SYSTEM`).
|
|
174
|
+
*/
|
|
175
|
+
searchPath?: string | string[];
|
|
176
|
+
/**
|
|
177
|
+
* **Firebird 6.0+ only (Protocol 20+)**
|
|
178
|
+
*
|
|
179
|
+
* Automatically stringifies JavaScript objects/arrays passed as query
|
|
180
|
+
* parameters to JSON strings, and automatically parses returned JSON
|
|
181
|
+
* text/BLOB columns back into JavaScript objects/arrays.
|
|
182
|
+
*/
|
|
183
|
+
jsonAsObject?: boolean;
|
|
184
|
+
}
|
|
185
|
+
export interface SvcMgrOptions extends Options {
|
|
186
|
+
manager: true;
|
|
187
|
+
}
|
|
188
|
+
export interface ConnectionPool {
|
|
189
|
+
get(callback: DatabaseCallback): void;
|
|
190
|
+
destroy(callback?: SimpleCallback): void;
|
|
191
|
+
}
|
|
192
|
+
export interface ReadableOptions {
|
|
193
|
+
optread?: 'byline' | 'buffer';
|
|
194
|
+
buffersize?: number;
|
|
195
|
+
timeout?: number;
|
|
196
|
+
}
|
|
197
|
+
export interface BackupOptions extends ReadableOptions {
|
|
198
|
+
database?: string;
|
|
199
|
+
files: string | {
|
|
200
|
+
filename: string;
|
|
201
|
+
sizefile: string;
|
|
202
|
+
}[];
|
|
203
|
+
factor?: number;
|
|
204
|
+
verbose?: boolean;
|
|
205
|
+
ignorechecksums?: boolean;
|
|
206
|
+
ignorelimbo?: boolean;
|
|
207
|
+
metadataonly?: boolean;
|
|
208
|
+
nogarbasecollect?: boolean;
|
|
209
|
+
olddescriptions?: boolean;
|
|
210
|
+
nontransportable?: boolean;
|
|
211
|
+
convert?: boolean;
|
|
212
|
+
expand?: boolean;
|
|
213
|
+
notriggers?: boolean;
|
|
214
|
+
}
|
|
215
|
+
export interface NBackupOptions extends ReadableOptions {
|
|
216
|
+
database?: string;
|
|
217
|
+
file: string;
|
|
218
|
+
level?: number;
|
|
219
|
+
notriggers?: boolean;
|
|
220
|
+
direct?: 'on' | 'off';
|
|
221
|
+
}
|
|
222
|
+
export interface RestoreOptions extends ReadableOptions {
|
|
223
|
+
database?: string;
|
|
224
|
+
files: string | string[];
|
|
225
|
+
verbose?: boolean;
|
|
226
|
+
cachebuffers?: number;
|
|
227
|
+
pagesize?: boolean;
|
|
228
|
+
readonly?: boolean;
|
|
229
|
+
deactivateindexes?: boolean;
|
|
230
|
+
noshadow?: boolean;
|
|
231
|
+
novalidity?: boolean;
|
|
232
|
+
individualcommit?: boolean;
|
|
233
|
+
replace?: boolean;
|
|
234
|
+
create?: boolean;
|
|
235
|
+
useallspace?: boolean;
|
|
236
|
+
metadataonly?: boolean;
|
|
237
|
+
fixfssdata?: string;
|
|
238
|
+
fixfssmetadata?: string;
|
|
239
|
+
}
|
|
240
|
+
export interface NRestoreOptions extends ReadableOptions {
|
|
241
|
+
database?: string;
|
|
242
|
+
files: string | string[];
|
|
243
|
+
}
|
|
244
|
+
export interface ValidateOptions extends ReadableOptions {
|
|
245
|
+
database?: string;
|
|
246
|
+
checkdb?: boolean;
|
|
247
|
+
ignorechecksums?: boolean;
|
|
248
|
+
killshadows?: boolean;
|
|
249
|
+
mend?: boolean;
|
|
250
|
+
validate?: boolean;
|
|
251
|
+
full?: boolean;
|
|
252
|
+
sweep?: boolean;
|
|
253
|
+
listlimbo?: boolean;
|
|
254
|
+
icu?: boolean;
|
|
255
|
+
}
|
|
256
|
+
export interface StatsOptions extends ReadableOptions {
|
|
257
|
+
database?: string;
|
|
258
|
+
record?: boolean;
|
|
259
|
+
nocreation?: boolean;
|
|
260
|
+
tables?: boolean;
|
|
261
|
+
pages?: boolean;
|
|
262
|
+
header?: boolean;
|
|
263
|
+
indexes?: boolean;
|
|
264
|
+
tablesystem?: boolean;
|
|
265
|
+
encryption?: boolean;
|
|
266
|
+
objects?: string;
|
|
267
|
+
}
|
|
268
|
+
export interface UserInfo {
|
|
269
|
+
userid: number;
|
|
270
|
+
groupid: number;
|
|
271
|
+
username: string;
|
|
272
|
+
firstname: string;
|
|
273
|
+
middlename: string;
|
|
274
|
+
lastname: string;
|
|
275
|
+
admin: number;
|
|
276
|
+
rolename?: string;
|
|
277
|
+
groupname?: string;
|
|
278
|
+
}
|
|
279
|
+
export interface ServerInfo {
|
|
280
|
+
result: number;
|
|
281
|
+
dbinfo?: {
|
|
282
|
+
database: any[];
|
|
283
|
+
nbattachment: number;
|
|
284
|
+
nbdatabase: number;
|
|
285
|
+
};
|
|
286
|
+
fbconfig?: any;
|
|
287
|
+
svcversion?: number;
|
|
288
|
+
fbversion?: string;
|
|
289
|
+
fbimplementation?: string;
|
|
290
|
+
fbcapatibilities: string[];
|
|
291
|
+
pathsecuritydb?: string;
|
|
292
|
+
fbenv?: string;
|
|
293
|
+
fbenvlock?: string;
|
|
294
|
+
fbenvmsg?: string;
|
|
295
|
+
limbotrans?: number[];
|
|
296
|
+
fbusers?: UserInfo[];
|
|
297
|
+
}
|
|
298
|
+
export interface ServerInfoReq {
|
|
299
|
+
dbinfo?: boolean;
|
|
300
|
+
fbconfig?: boolean;
|
|
301
|
+
svcversion?: boolean;
|
|
302
|
+
fbversion?: boolean;
|
|
303
|
+
fbimplementation?: boolean;
|
|
304
|
+
fbcapatibilities?: boolean;
|
|
305
|
+
pathsecuritydb?: boolean;
|
|
306
|
+
fbenv?: boolean;
|
|
307
|
+
fbenvlock?: boolean;
|
|
308
|
+
fbenvmsg?: boolean;
|
|
309
|
+
limbotrans?: boolean;
|
|
310
|
+
}
|
|
311
|
+
export interface TraceOptions extends ReadableOptions {
|
|
312
|
+
configfile?: string;
|
|
313
|
+
tracename?: string;
|
|
314
|
+
traceid?: number;
|
|
315
|
+
}
|
|
316
|
+
export type ServiceManagerCallback = (err: any, svc: ServiceManager) => void;
|
|
317
|
+
export type ReadableCallback = (err: any, reader: NodeJS.ReadableStream) => void;
|
|
318
|
+
export type InfoCallback = (err: any, info: ServerInfo) => void;
|
|
319
|
+
export type LineCallback = (err: any, data: {
|
|
320
|
+
result: number;
|
|
321
|
+
line: string;
|
|
322
|
+
}) => void;
|
|
323
|
+
export declare enum ShutdownMode {
|
|
324
|
+
NORMAL = 0,
|
|
325
|
+
MULTI = 1,
|
|
326
|
+
SINGLE = 2,
|
|
327
|
+
FULL = 3
|
|
328
|
+
}
|
|
329
|
+
export declare enum ShutdownKind {
|
|
330
|
+
FORCED = 0,
|
|
331
|
+
DENY_TRANSACTION = 1,
|
|
332
|
+
DENY_ATTACHMENT = 2
|
|
333
|
+
}
|
|
334
|
+
export interface ServiceManager {
|
|
335
|
+
detach(callback?: SimpleCallback, force?: boolean): void;
|
|
336
|
+
backup(options: BackupOptions, callback: ReadableCallback): void;
|
|
337
|
+
nbackup(options: BackupOptions, callback: ReadableCallback): void;
|
|
338
|
+
restore(options: RestoreOptions, callback: ReadableCallback): void;
|
|
339
|
+
nrestore(options: NRestoreOptions, callback: ReadableCallback): void;
|
|
340
|
+
setDialect(db: string, dialect: 1 | 3, callback: ReadableCallback): void;
|
|
341
|
+
setSweepinterval(db: string, interval: number, callback: Function): void;
|
|
342
|
+
setCachebuffer(db: string, nbpages: any, callback: ReadableCallback): void;
|
|
343
|
+
BringOnline(db: string, callback: ReadableCallback): void;
|
|
344
|
+
Shutdown(db: string, kind: ShutdownKind, delay: number, mode: ShutdownMode, callback: ReadableCallback): void;
|
|
345
|
+
Shutdown(db: string, kind: ShutdownKind, delay: number, callback: ReadableCallback): void;
|
|
346
|
+
setShadow(db: string, val: boolean, callback: ReadableCallback): void;
|
|
347
|
+
setForcewrite(db: string, val: boolean, callback: ReadableCallback): void;
|
|
348
|
+
setReservespace(db: string, val: boolean, callback: ReadableCallback): void;
|
|
349
|
+
setReadonlyMode(db: string, callback: ReadableCallback): void;
|
|
350
|
+
setReadwriteMode(db: string, callback: ReadableCallback): void;
|
|
351
|
+
validate(options: ValidateOptions, callback: ReadableCallback): void;
|
|
352
|
+
commit(db: string, transactid: number, callback: ReadableCallback): void;
|
|
353
|
+
rollback(db: string, transactid: number, callback: ReadableCallback): void;
|
|
354
|
+
recover(db: string, transactid: number, callback: ReadableCallback): void;
|
|
355
|
+
getStats(options: StatsOptions, callback: ReadableCallback): void;
|
|
356
|
+
getLog(options: ReadableOptions, callback: ReadableCallback): void;
|
|
357
|
+
getUsers(username: string | null, callback: InfoCallback): void;
|
|
358
|
+
addUser(username: string, password: string, info: UserInfo, callback: ReadableCallback): void;
|
|
359
|
+
editUser(username: string, info: UserInfo, callback: ReadableCallback): void;
|
|
360
|
+
removeUser(username: string, rolename: string | null, callback: ReadableCallback): void;
|
|
361
|
+
getFbserverInfos(infos: ServerInfoReq, options: {
|
|
362
|
+
buffersize?: number;
|
|
363
|
+
timeout?: number;
|
|
364
|
+
}, callback: InfoCallback): void;
|
|
365
|
+
startTrace(options: TraceOptions, callback: ReadableCallback): void;
|
|
366
|
+
suspendTrace(options: TraceOptions, callback: ReadableCallback): void;
|
|
367
|
+
resumeTrace(options: TraceOptions, callback: ReadableCallback): void;
|
|
368
|
+
stopTrace(options: TraceOptions, callback: ReadableCallback): void;
|
|
369
|
+
getTraceList(options: ReadableOptions, callback: ReadableCallback): void;
|
|
370
|
+
readline(options: ReadableOptions, callback: LineCallback): void;
|
|
371
|
+
readeof(options: ReadableOptions, callback: LineCallback): void;
|
|
372
|
+
hasRunningAction(options: ReadableOptions, callback: ReadableCallback): void;
|
|
373
|
+
readusers(options: ReadableOptions, callback: ReadableCallback): void;
|
|
374
|
+
readlimbo(options: ReadableOptions, callback: ReadableCallback): void;
|
|
375
|
+
}
|