node-firebird 2.8.1 → 2.10.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 +268 -7
- package/lib/index.d.ts +17 -9
- package/lib/index.js +42 -3
- package/lib/named-params.d.ts +42 -0
- package/lib/named-params.js +133 -0
- package/lib/pool.js +1 -1
- package/lib/srp.d.ts +3 -3
- package/lib/types.d.ts +185 -25
- package/lib/uri.d.ts +57 -0
- package/lib/uri.js +193 -0
- package/lib/wire/connection.d.ts +92 -59
- package/lib/wire/connection.js +286 -55
- package/lib/wire/const.d.ts +9 -1
- package/lib/wire/const.js +21 -9
- package/lib/wire/database.d.ts +51 -26
- package/lib/wire/database.js +26 -8
- package/lib/wire/eventConnection.js +5 -3
- package/lib/wire/query-stream.d.ts +18 -0
- package/lib/wire/query-stream.js +73 -0
- package/lib/wire/serialize.d.ts +18 -2
- package/lib/wire/serialize.js +7 -0
- package/lib/wire/service.d.ts +42 -0
- package/lib/wire/service.js +145 -0
- package/lib/wire/socket.d.ts +3 -1
- package/lib/wire/socket.js +5 -2
- package/lib/wire/statement.d.ts +40 -20
- package/lib/wire/statement.js +26 -6
- package/lib/wire/transaction.d.ts +32 -18
- package/lib/wire/transaction.js +50 -8
- package/lib/wire/wire-types.d.ts +116 -0
- package/lib/wire/wire-types.js +10 -0
- package/lib/wire/xsqlvar.d.ts +18 -18
- package/package.json +1 -1
- package/src/index.ts +54 -15
- package/src/messages.ts +1 -1
- package/src/named-params.ts +145 -0
- package/src/pool.ts +1 -1
- package/src/srp.ts +6 -6
- package/src/types.ts +183 -25
- package/src/unix-crypt.ts +9 -9
- package/src/uri.ts +204 -0
- package/src/wire/connection.ts +481 -234
- package/src/wire/const.ts +21 -9
- package/src/wire/database.ts +75 -43
- package/src/wire/eventConnection.ts +8 -5
- package/src/wire/query-stream.ts +80 -0
- package/src/wire/serialize.ts +29 -0
- package/src/wire/service.ts +188 -6
- package/src/wire/socket.ts +17 -8
- package/src/wire/statement.ts +68 -31
- package/src/wire/transaction.ts +85 -33
- package/src/wire/wire-types.ts +127 -0
- package/src/wire/xsqlvar.ts +9 -7
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;
|
|
@@ -100,9 +102,22 @@ export type BatchOptions = {
|
|
|
100
102
|
chunkSize?: number;
|
|
101
103
|
};
|
|
102
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Positional query parameters (array), or — when named placeholders are
|
|
107
|
+
* enabled via the `namedPlaceholders` connection/query option — values by
|
|
108
|
+
* placeholder name.
|
|
109
|
+
*/
|
|
110
|
+
export type QueryParams = any[] | Record<string, any>;
|
|
111
|
+
|
|
103
112
|
export type QueryOptions = {
|
|
104
113
|
timeout?: number;
|
|
105
114
|
scrollable?: boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Per-query override of the `namedPlaceholders` connection option
|
|
117
|
+
* (e.g. disable it for one EXECUTE BLOCK statement whose body uses
|
|
118
|
+
* `:variable` PSQL references).
|
|
119
|
+
*/
|
|
120
|
+
namedPlaceholders?: boolean;
|
|
106
121
|
/**
|
|
107
122
|
* Abort the query when the signal fires (Firebird 2.5+ / protocol 12+).
|
|
108
123
|
* If the signal is already aborted the query is not sent at all and the
|
|
@@ -114,15 +129,32 @@ export type QueryOptions = {
|
|
|
114
129
|
signal?: AbortSignal;
|
|
115
130
|
}
|
|
116
131
|
|
|
132
|
+
export type QueryStreamOptions = QueryOptions & {
|
|
133
|
+
/**
|
|
134
|
+
* Rows buffered internally before fetching pauses (object-mode
|
|
135
|
+
* Readable highWaterMark, default 16).
|
|
136
|
+
*/
|
|
137
|
+
highWaterMark?: number;
|
|
138
|
+
/** Emit array rows instead of objects (like db.execute). */
|
|
139
|
+
asObject?: boolean;
|
|
140
|
+
}
|
|
141
|
+
|
|
117
142
|
export interface Database {
|
|
118
143
|
detach(callback?: SimpleCallback): Database;
|
|
119
144
|
transaction(options: TransactionOptions|Isolation|TransactionCallback, callback?: TransactionCallback): Database;
|
|
120
145
|
newStatement(query: string, callback: (err: Error | null, statement: Statement) => void): Database;
|
|
121
|
-
query(query: string, params:
|
|
122
|
-
execute(query: string, params:
|
|
146
|
+
query(query: string, params: QueryParams, callback: QueryCallback, options?: QueryOptions): Database;
|
|
147
|
+
execute(query: string, params: QueryParams, callback: QueryCallback, options?: QueryOptions): Database;
|
|
123
148
|
/** Bulk-execute in its own transaction, all-or-nothing (Firebird 4.0+). */
|
|
124
|
-
executeBatch(query: string, rows:
|
|
125
|
-
sequentially(query: string, params:
|
|
149
|
+
executeBatch(query: string, rows: QueryParams[], callback?: (err: any, result: BatchResult) => void, options?: BatchOptions): Database;
|
|
150
|
+
sequentially(query: string, params: QueryParams, rowCallback: SequentialCallback, callback: SimpleCallback, options?: QueryOptions | boolean): Database;
|
|
151
|
+
/**
|
|
152
|
+
* Run `query` and return an object-mode Readable emitting one row per
|
|
153
|
+
* chunk, with backpressure (fetching pauses while the buffer is full).
|
|
154
|
+
* Runs in its own transaction. Destroying the stream early aborts the
|
|
155
|
+
* fetch and releases the statement.
|
|
156
|
+
*/
|
|
157
|
+
queryStream(query: string, params?: QueryParams, options?: QueryStreamOptions): Readable;
|
|
126
158
|
drop(callback: SimpleCallback): void;
|
|
127
159
|
escape(value: any): string;
|
|
128
160
|
attachEvent(callback: any): this;
|
|
@@ -133,10 +165,10 @@ export interface Database {
|
|
|
133
165
|
|
|
134
166
|
// Promise / async-await API (see README § Promises / async–await).
|
|
135
167
|
// Result metadata is only available through the callback API.
|
|
136
|
-
queryAsync<T = any>(query: string, params?:
|
|
137
|
-
executeAsync<T = any>(query: string, params?:
|
|
138
|
-
executeBatchAsync(query: string, rows:
|
|
139
|
-
sequentiallyAsync(query: string, params:
|
|
168
|
+
queryAsync<T = any>(query: string, params?: QueryParams, options?: QueryOptions): Promise<T[]>;
|
|
169
|
+
executeAsync<T = any>(query: string, params?: QueryParams, options?: QueryOptions): Promise<T[]>;
|
|
170
|
+
executeBatchAsync(query: string, rows: QueryParams[], options?: BatchOptions): Promise<BatchResult>;
|
|
171
|
+
sequentiallyAsync(query: string, params: QueryParams | undefined, rowCallback: SequentialCallback, options?: QueryOptions | boolean): Promise<void>;
|
|
140
172
|
sequentiallyAsync(query: string, rowCallback: SequentialCallback, options?: QueryOptions | boolean): Promise<void>;
|
|
141
173
|
transactionAsync(options?: TransactionOptions | Isolation): Promise<Transaction>;
|
|
142
174
|
startTransactionAsync(options?: TransactionOptions | Isolation): Promise<Transaction>;
|
|
@@ -158,21 +190,27 @@ export interface Database {
|
|
|
158
190
|
|
|
159
191
|
export interface Transaction {
|
|
160
192
|
newStatement(query: string, callback: (err: Error | null, statement: Statement) => void): void;
|
|
161
|
-
query(query: string, params:
|
|
162
|
-
execute(query: string, params:
|
|
193
|
+
query(query: string, params: QueryParams, callback: QueryCallback, options?: QueryOptions): void;
|
|
194
|
+
execute(query: string, params: QueryParams, callback: QueryCallback, options?: QueryOptions): void;
|
|
163
195
|
/** Bulk-execute within this transaction; per-record failures do not roll back (Firebird 4.0+). */
|
|
164
|
-
executeBatch(query: string, rows:
|
|
165
|
-
sequentially(query: string, params:
|
|
196
|
+
executeBatch(query: string, rows: QueryParams[], callback?: (err: any, result: BatchResult) => void, options?: BatchOptions): void;
|
|
197
|
+
sequentially(query: string, params: QueryParams, rowCallback: SequentialCallback, callback: SimpleCallback, options?: QueryOptions | boolean): Database;
|
|
198
|
+
/**
|
|
199
|
+
* Run `query` inside this transaction and return an object-mode
|
|
200
|
+
* Readable emitting one row per chunk, with backpressure. The
|
|
201
|
+
* transaction is NOT committed when the stream ends.
|
|
202
|
+
*/
|
|
203
|
+
queryStream(query: string, params?: QueryParams, options?: QueryStreamOptions): Readable;
|
|
166
204
|
commit(callback?: SimpleCallback): void;
|
|
167
205
|
commitRetaining(callback?: SimpleCallback): void;
|
|
168
206
|
rollback(callback?: SimpleCallback): void;
|
|
169
207
|
rollbackRetaining(callback?: SimpleCallback): void;
|
|
170
208
|
|
|
171
209
|
// Promise / async-await API
|
|
172
|
-
queryAsync<T = any>(query: string, params?:
|
|
173
|
-
executeAsync<T = any>(query: string, params?:
|
|
174
|
-
executeBatchAsync(query: string, rows:
|
|
175
|
-
sequentiallyAsync(query: string, params:
|
|
210
|
+
queryAsync<T = any>(query: string, params?: QueryParams, options?: QueryOptions): Promise<T[]>;
|
|
211
|
+
executeAsync<T = any>(query: string, params?: QueryParams, options?: QueryOptions): Promise<T[]>;
|
|
212
|
+
executeBatchAsync(query: string, rows: QueryParams[], options?: BatchOptions): Promise<BatchResult>;
|
|
213
|
+
sequentiallyAsync(query: string, params: QueryParams | undefined, rowCallback: SequentialCallback, options?: QueryOptions | boolean): Promise<void>;
|
|
176
214
|
sequentiallyAsync(query: string, rowCallback: SequentialCallback, options?: QueryOptions | boolean): Promise<void>;
|
|
177
215
|
newStatementAsync(query: string): Promise<Statement>;
|
|
178
216
|
commitAsync(): Promise<void>;
|
|
@@ -185,17 +223,17 @@ export interface Statement {
|
|
|
185
223
|
close(callback?: SimpleCallback): void;
|
|
186
224
|
drop(callback?: SimpleCallback): void;
|
|
187
225
|
release(callback?: SimpleCallback): void;
|
|
188
|
-
execute(transaction: Transaction, params:
|
|
226
|
+
execute(transaction: Transaction, params: QueryParams, callback: QueryCallback, options?: QueryOptions): void;
|
|
189
227
|
fetch(transaction: Transaction, count: number, callback: QueryCallback): void;
|
|
190
228
|
fetchScroll(transaction: Transaction, direction: 'NEXT' | 'PRIOR' | 'FIRST' | 'LAST' | 'ABSOLUTE' | 'RELATIVE' | number, offset: number, count: number, callback: QueryCallback): void;
|
|
191
229
|
fetchAll(transaction: Transaction, callback: QueryCallback): void;
|
|
192
230
|
|
|
193
231
|
/** Execute this prepared statement once per row (Firebird 4.0+ batch API). */
|
|
194
|
-
executeBatch(transaction: Transaction, rows:
|
|
232
|
+
executeBatch(transaction: Transaction, rows: QueryParams[], callback?: (err: any, result: BatchResult) => void, options?: BatchOptions): void;
|
|
195
233
|
|
|
196
234
|
// Promise / async-await API
|
|
197
|
-
executeAsync(transaction: Transaction, params?:
|
|
198
|
-
executeBatchAsync(transaction: Transaction, rows:
|
|
235
|
+
executeAsync(transaction: Transaction, params?: QueryParams, options?: QueryOptions): Promise<any>;
|
|
236
|
+
executeBatchAsync(transaction: Transaction, rows: QueryParams[], options?: BatchOptions): Promise<BatchResult>;
|
|
199
237
|
fetchAsync(transaction: Transaction, count: number | 'all'): Promise<any>;
|
|
200
238
|
fetchScrollAsync(transaction: Transaction, direction: 'NEXT' | 'PRIOR' | 'FIRST' | 'LAST' | 'ABSOLUTE' | 'RELATIVE' | number, offset?: number, count?: number): Promise<any>;
|
|
201
239
|
fetchAllAsync(transaction: Transaction): Promise<any>;
|
|
@@ -266,6 +304,26 @@ export interface Options {
|
|
|
266
304
|
blobReadChunkSize?: number;
|
|
267
305
|
wireCrypt?: number; // WIRE_CRYPT_DISABLE or WIRE_CRYPT_ENABLE
|
|
268
306
|
wireCompression?: boolean;
|
|
307
|
+
/**
|
|
308
|
+
* Enable named placeholders: SQL may use `:name` markers and params may
|
|
309
|
+
* be a values-by-name object (`db.query('... WHERE id = :id', { id: 1 })`).
|
|
310
|
+
* Placeholders are rewritten client-side to positional `?` before
|
|
311
|
+
* preparing; positional arrays keep working unchanged. Off by default
|
|
312
|
+
* because `EXECUTE BLOCK` bodies use `:variable` for PSQL references —
|
|
313
|
+
* with this option on, run such statements with positional params or a
|
|
314
|
+
* per-query `namedPlaceholders: false` override.
|
|
315
|
+
*/
|
|
316
|
+
namedPlaceholders?: boolean;
|
|
317
|
+
/**
|
|
318
|
+
* TCP keepalive probing to detect dead/stale connections (same option
|
|
319
|
+
* names as mysql2). On by default; set false to disable.
|
|
320
|
+
*/
|
|
321
|
+
enableKeepAlive?: boolean;
|
|
322
|
+
/**
|
|
323
|
+
* Milliseconds a socket must be idle before the first TCP keepalive
|
|
324
|
+
* probe is sent (default 60000). Ignored when enableKeepAlive is false.
|
|
325
|
+
*/
|
|
326
|
+
keepAliveInitialDelay?: number;
|
|
269
327
|
pluginName?: string;
|
|
270
328
|
parallelWorkers?: number;
|
|
271
329
|
maxInlineBlobSize?: number;
|
|
@@ -297,11 +355,11 @@ export interface Options {
|
|
|
297
355
|
/**
|
|
298
356
|
* **Firebird 6.0+ only (Protocol 20+)**
|
|
299
357
|
*
|
|
300
|
-
* Sets the session's current schema at connection time.
|
|
301
|
-
*
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
*
|
|
358
|
+
* Sets the session's current schema at connection time. `CURRENT_SCHEMA`
|
|
359
|
+
* in Firebird is the first existing schema of the search path, so this
|
|
360
|
+
* option is implemented by putting the schema at the front of the
|
|
361
|
+
* `searchPath` sent to the server (with `PUBLIC` kept as a fallback when
|
|
362
|
+
* no explicit `searchPath` is given).
|
|
305
363
|
*
|
|
306
364
|
* Example: `defaultSchema: 'myapp'`
|
|
307
365
|
*/
|
|
@@ -323,6 +381,18 @@ export interface Options {
|
|
|
323
381
|
* (typically `PUBLIC` then `SYSTEM`).
|
|
324
382
|
*/
|
|
325
383
|
searchPath?: string | string[];
|
|
384
|
+
/**
|
|
385
|
+
* **Firebird 6.0+ only**
|
|
386
|
+
*
|
|
387
|
+
* Owner of a newly created database (`isc_dpb_owner`), allowing a
|
|
388
|
+
* superuser to create a database owned by another user
|
|
389
|
+
* ([firebird#7718](https://github.com/FirebirdSQL/firebird/issues/7718)).
|
|
390
|
+
* Only honored by `create`/`attachOrCreate` when the database is
|
|
391
|
+
* created; ignored on plain attach and by older servers.
|
|
392
|
+
*
|
|
393
|
+
* Example: `owner: 'APP_OWNER'`
|
|
394
|
+
*/
|
|
395
|
+
owner?: string;
|
|
326
396
|
/**
|
|
327
397
|
* **Firebird 6.0+ only (Protocol 20+)**
|
|
328
398
|
*
|
|
@@ -331,8 +401,58 @@ export interface Options {
|
|
|
331
401
|
* text/BLOB columns back into JavaScript objects/arrays.
|
|
332
402
|
*/
|
|
333
403
|
jsonAsObject?: boolean;
|
|
404
|
+
/**
|
|
405
|
+
* Custom type parser (mysql2-style). Called for every column value of
|
|
406
|
+
* every result row (including NULLs); whatever it returns becomes the
|
|
407
|
+
* value in the row. Call `next()` to get the value the driver would
|
|
408
|
+
* produce by default (after `blobAsText`/`jsonAsObject` are applied).
|
|
409
|
+
*
|
|
410
|
+
* ```js
|
|
411
|
+
* typeCast: (column, next) =>
|
|
412
|
+
* column.typeName === 'INT64' ? Number(next()) : next()
|
|
413
|
+
* ```
|
|
414
|
+
*
|
|
415
|
+
* Non-text BLOB columns reach the hook as the usual fetch function;
|
|
416
|
+
* text BLOBs with `blobAsText` reach it as the resolved string. The
|
|
417
|
+
* hook must be a pure function: a row can be decoded more than once
|
|
418
|
+
* when a response spans TCP packets.
|
|
419
|
+
*/
|
|
420
|
+
typeCast?: TypeCastFunction;
|
|
421
|
+
/**
|
|
422
|
+
* Per-connection LRU cache of prepared statements (like mysql2's
|
|
423
|
+
* statement cache). `db.query`/`tx.query` and friends transparently
|
|
424
|
+
* reuse the prepared handle for a repeated SQL string, skipping the
|
|
425
|
+
* prepare round-trip on hot paths. The number is the maximum of idle
|
|
426
|
+
* cached statements; least-recently-used ones are dropped over the
|
|
427
|
+
* limit. 0 / unset = disabled. Statements that failed and DDL are
|
|
428
|
+
* never cached; concurrent runs of the same SQL never share a
|
|
429
|
+
* statement (extra preparations are simply not cached).
|
|
430
|
+
*/
|
|
431
|
+
statementCacheSize?: number;
|
|
334
432
|
}
|
|
335
433
|
|
|
434
|
+
/** Column metadata passed to the {@link Options.typeCast} hook. */
|
|
435
|
+
export interface TypeCastColumn {
|
|
436
|
+
/** Firebird SQL type code (see the exported `SQL_TYPES` map). */
|
|
437
|
+
type: number;
|
|
438
|
+
/** Friendly name of the type code: 'VARYING', 'INT64', 'BLOB', ... */
|
|
439
|
+
typeName: string;
|
|
440
|
+
/** Column subtype (e.g. 1 = text for BLOBs; charset id for strings). */
|
|
441
|
+
subType?: number;
|
|
442
|
+
/** Negative decimal scale for NUMERIC/DECIMAL columns (e.g. -2). */
|
|
443
|
+
scale?: number;
|
|
444
|
+
/** Declared length in bytes. */
|
|
445
|
+
length?: number;
|
|
446
|
+
/** Column name in the table. */
|
|
447
|
+
field?: string;
|
|
448
|
+
/** Table (relation) name. */
|
|
449
|
+
relation?: string;
|
|
450
|
+
/** Alias used in the SELECT list (the row key for object rows). */
|
|
451
|
+
alias?: string;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
export type TypeCastFunction = (column: TypeCastColumn, next: () => any) => any;
|
|
455
|
+
|
|
336
456
|
export interface SvcMgrOptions extends Options {
|
|
337
457
|
manager: true; // Attach to ServiceManager
|
|
338
458
|
}
|
|
@@ -542,4 +662,42 @@ export interface ServiceManager {
|
|
|
542
662
|
hasRunningAction(options: ReadableOptions, callback: ReadableCallback): void;
|
|
543
663
|
readusers(options: ReadableOptions, callback: ReadableCallback): void;
|
|
544
664
|
readlimbo(options: ReadableOptions, callback: ReadableCallback): void;
|
|
665
|
+
|
|
666
|
+
// Promise / async-await API (see README § Promises / async–await).
|
|
667
|
+
detachAsync(force?: boolean): Promise<void>;
|
|
668
|
+
backupAsync(options: BackupOptions): Promise<NodeJS.ReadableStream>;
|
|
669
|
+
nbackupAsync(options: BackupOptions): Promise<NodeJS.ReadableStream>;
|
|
670
|
+
restoreAsync(options: RestoreOptions): Promise<NodeJS.ReadableStream>;
|
|
671
|
+
nrestoreAsync(options: NRestoreOptions): Promise<NodeJS.ReadableStream>;
|
|
672
|
+
setDialectAsync(db: string, dialect: 1 | 3): Promise<NodeJS.ReadableStream>;
|
|
673
|
+
setSweepintervalAsync(db: string, interval: number): Promise<any>;
|
|
674
|
+
setCachebufferAsync(db: string, nbpages: any): Promise<NodeJS.ReadableStream>;
|
|
675
|
+
BringOnlineAsync(db: string): Promise<NodeJS.ReadableStream>;
|
|
676
|
+
ShutdownAsync(db: string, kind: ShutdownKind, delay: number, mode?: ShutdownMode): Promise<NodeJS.ReadableStream>;
|
|
677
|
+
setShadowAsync(db: string, val: boolean): Promise<NodeJS.ReadableStream>;
|
|
678
|
+
setForcewriteAsync(db: string, val: boolean): Promise<NodeJS.ReadableStream>;
|
|
679
|
+
setReservespaceAsync(db: string, val: boolean): Promise<NodeJS.ReadableStream>;
|
|
680
|
+
setReadonlyModeAsync(db: string): Promise<NodeJS.ReadableStream>;
|
|
681
|
+
setReadwriteModeAsync(db: string): Promise<NodeJS.ReadableStream>;
|
|
682
|
+
validateAsync(options: ValidateOptions): Promise<NodeJS.ReadableStream>;
|
|
683
|
+
commitAsync(db: string, transactid: number): Promise<NodeJS.ReadableStream>;
|
|
684
|
+
rollbackAsync(db: string, transactid: number): Promise<NodeJS.ReadableStream>;
|
|
685
|
+
recoverAsync(db: string, transactid: number): Promise<NodeJS.ReadableStream>;
|
|
686
|
+
getStatsAsync(options: StatsOptions): Promise<NodeJS.ReadableStream>;
|
|
687
|
+
getLogAsync(options: ReadableOptions): Promise<NodeJS.ReadableStream>;
|
|
688
|
+
getUsersAsync(username?: string | null): Promise<ServerInfo>;
|
|
689
|
+
addUserAsync(username: string, password: string, info?: UserInfo): Promise<NodeJS.ReadableStream>;
|
|
690
|
+
editUserAsync(username: string, info: UserInfo): Promise<NodeJS.ReadableStream>;
|
|
691
|
+
removeUserAsync(username: string, rolename?: string | null): Promise<NodeJS.ReadableStream>;
|
|
692
|
+
getFbserverInfosAsync(infos?: ServerInfoReq, options?: { buffersize?: number, timeout?: number }): Promise<ServerInfo>;
|
|
693
|
+
startTraceAsync(options: TraceOptions): Promise<NodeJS.ReadableStream>;
|
|
694
|
+
suspendTraceAsync(options: TraceOptions): Promise<NodeJS.ReadableStream>;
|
|
695
|
+
resumeTraceAsync(options: TraceOptions): Promise<NodeJS.ReadableStream>;
|
|
696
|
+
stopTraceAsync(options: TraceOptions): Promise<NodeJS.ReadableStream>;
|
|
697
|
+
getTraceListAsync(options?: ReadableOptions): Promise<NodeJS.ReadableStream>;
|
|
698
|
+
readlineAsync(options?: ReadableOptions): Promise<{ result: number, line: string }>;
|
|
699
|
+
readeofAsync(options?: ReadableOptions): Promise<{ result: number, line: string }>;
|
|
700
|
+
hasRunningActionAsync(options?: ReadableOptions): Promise<any>;
|
|
701
|
+
readusersAsync(options?: ReadableOptions): Promise<any>;
|
|
702
|
+
readlimboAsync(options?: ReadableOptions): Promise<any>;
|
|
545
703
|
}
|
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;
|
package/src/uri.ts
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/***************************************
|
|
2
|
+
*
|
|
3
|
+
* Connection URI strings
|
|
4
|
+
*
|
|
5
|
+
***************************************/
|
|
6
|
+
|
|
7
|
+
import type { Options } from './types';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Option keys coerced to boolean when they arrive as URI query parameters.
|
|
11
|
+
* "1"/"true"/"yes"/"on" (case-insensitive) → true, everything else → false.
|
|
12
|
+
*/
|
|
13
|
+
const BOOLEAN_KEYS = new Set([
|
|
14
|
+
'lowercase_keys', 'blobAsText', 'wireCompression', 'manager',
|
|
15
|
+
'namedPlaceholders', 'enableKeepAlive',
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
/** Option keys coerced to number when they arrive as URI query parameters. */
|
|
19
|
+
const NUMBER_KEYS = new Set([
|
|
20
|
+
'port', 'pageSize', 'timeout', 'retryConnectionInterval',
|
|
21
|
+
'blobChunkSize', 'blobReadChunkSize', 'wireCrypt', 'parallelWorkers',
|
|
22
|
+
'maxInlineBlobSize', 'maxNegotiatedProtocols', 'connectTimeout',
|
|
23
|
+
'min', 'idleTimeoutMillis', 'keepAliveInitialDelay',
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
function coerce(key: string, value: string): any {
|
|
27
|
+
if (BOOLEAN_KEYS.has(key)) {
|
|
28
|
+
return /^(1|true|yes|on)$/i.test(value);
|
|
29
|
+
}
|
|
30
|
+
if (NUMBER_KEYS.has(key)) {
|
|
31
|
+
var n = Number(value);
|
|
32
|
+
if (Number.isNaN(n)) {
|
|
33
|
+
throw new Error('Invalid numeric value for connection URI option "' + key + '": ' + value);
|
|
34
|
+
}
|
|
35
|
+
return n;
|
|
36
|
+
}
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Parse a firebird:// connection URI into an options object.
|
|
42
|
+
*
|
|
43
|
+
* firebird://user:password@host:port/database?option=value&...
|
|
44
|
+
*
|
|
45
|
+
* The database part:
|
|
46
|
+
* firebird://host/employee → alias "employee"
|
|
47
|
+
* firebird://host//var/db/prod.fdb → absolute path "/var/db/prod.fdb"
|
|
48
|
+
* firebird://host/var/db/prod.fdb → "/var/db/prod.fdb" (a database
|
|
49
|
+
* part with slashes is a path —
|
|
50
|
+
* aliases cannot contain "/")
|
|
51
|
+
* firebird://host/C:/db/prod.fdb → Windows path "C:/db/prod.fdb"
|
|
52
|
+
*
|
|
53
|
+
* Credentials and the database path are URL-decoded, so reserved characters
|
|
54
|
+
* can be percent-encoded (e.g. p%40ss for "p@ss"). Query parameters map
|
|
55
|
+
* 1:1 to option keys and are coerced to the option's type (booleans accept
|
|
56
|
+
* 1/true/yes/on). `user` and `password` may be given as query parameters
|
|
57
|
+
* instead of in the authority.
|
|
58
|
+
*/
|
|
59
|
+
export function parseConnectionUri(uri: string): Options {
|
|
60
|
+
var url: URL;
|
|
61
|
+
try {
|
|
62
|
+
url = new URL(uri);
|
|
63
|
+
} catch (e) {
|
|
64
|
+
throw new Error('Invalid connection URI: ' + uri);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (url.protocol !== 'firebird:') {
|
|
68
|
+
throw new Error('Unsupported connection URI scheme "' + url.protocol.replace(/:$/, '') +
|
|
69
|
+
'" (expected firebird://...)');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
var options: any = {};
|
|
73
|
+
|
|
74
|
+
if (url.hostname) {
|
|
75
|
+
// URL keeps IPv6 hostnames bracketed ([::1]); net.connect wants them bare
|
|
76
|
+
options.host = url.hostname.replace(/^\[(.*)\]$/, '$1');
|
|
77
|
+
}
|
|
78
|
+
if (url.port) {
|
|
79
|
+
options.port = Number(url.port);
|
|
80
|
+
}
|
|
81
|
+
if (url.username) {
|
|
82
|
+
options.user = decodeURIComponent(url.username);
|
|
83
|
+
}
|
|
84
|
+
if (url.password) {
|
|
85
|
+
options.password = decodeURIComponent(url.password);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
var database = decodeURIComponent(url.pathname || '');
|
|
89
|
+
if (database.startsWith('/')) {
|
|
90
|
+
database = database.slice(1);
|
|
91
|
+
}
|
|
92
|
+
// A database part with path separators is a filesystem path, not an
|
|
93
|
+
// alias (aliases cannot contain "/") — restore the leading slash unless
|
|
94
|
+
// it is a Windows drive path or already absolute (double-slash form).
|
|
95
|
+
if (database.includes('/') && !database.startsWith('/') && !/^[A-Za-z]:\//.test(database)) {
|
|
96
|
+
database = '/' + database;
|
|
97
|
+
}
|
|
98
|
+
if (database) {
|
|
99
|
+
options.database = database;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
url.searchParams.forEach(function(value, key) {
|
|
103
|
+
options[key] = coerce(key, value);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
return options as Options;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Parse a traditional ("old style") Firebird connection string:
|
|
111
|
+
*
|
|
112
|
+
* [host[/port]:]{path | alias}
|
|
113
|
+
*
|
|
114
|
+
* employee → alias "employee" (default host)
|
|
115
|
+
* /var/fb/prod.fdb → local path (default host)
|
|
116
|
+
* C:\fbdata\prod.fdb → Windows path — a single character
|
|
117
|
+
* before ":" is a drive letter, not
|
|
118
|
+
* a host (same rule as Firebird)
|
|
119
|
+
* db.example.com:employee → host + alias
|
|
120
|
+
* db.example.com/3051:/var/fb/prod.fdb → host + port + path
|
|
121
|
+
* myserver:C:\fbdata\prod.fdb → host + Windows path
|
|
122
|
+
* [::1]/3050:employee → IPv6 host + port + alias
|
|
123
|
+
*
|
|
124
|
+
* Unlike firebird:// URIs, traditional strings carry no credentials or
|
|
125
|
+
* options — the driver defaults apply (SYSDBA/masterkey, port 3050).
|
|
126
|
+
* The port must be numeric; /etc/services names are not resolved.
|
|
127
|
+
*/
|
|
128
|
+
export function parseOldStyleConnectionString(str: string): Options {
|
|
129
|
+
var options: any = {};
|
|
130
|
+
var host: string | null = null;
|
|
131
|
+
var port: string | null = null;
|
|
132
|
+
var database = str;
|
|
133
|
+
|
|
134
|
+
var ipv6 = /^\[([^\]]+)\](?:\/([^:]*))?:(.*)$/.exec(str);
|
|
135
|
+
if (ipv6) {
|
|
136
|
+
host = ipv6[1];
|
|
137
|
+
port = ipv6[2] !== undefined ? ipv6[2] : null;
|
|
138
|
+
database = ipv6[3];
|
|
139
|
+
} else {
|
|
140
|
+
var colon = str.indexOf(':');
|
|
141
|
+
if (colon === 0) {
|
|
142
|
+
throw new Error('Invalid connection string (empty host): ' + str);
|
|
143
|
+
}
|
|
144
|
+
// colon === 1 → single character before ":" is a drive letter;
|
|
145
|
+
// colon === -1 → no host part. Both leave the whole string as database.
|
|
146
|
+
if (colon > 1) {
|
|
147
|
+
var hostPart = str.slice(0, colon);
|
|
148
|
+
database = str.slice(colon + 1);
|
|
149
|
+
var slash = hostPart.indexOf('/');
|
|
150
|
+
if (slash !== -1) {
|
|
151
|
+
host = hostPart.slice(0, slash);
|
|
152
|
+
port = hostPart.slice(slash + 1);
|
|
153
|
+
if (!host) {
|
|
154
|
+
throw new Error('Invalid connection string (empty host): ' + str);
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
host = hostPart;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (!database) {
|
|
163
|
+
throw new Error('Invalid connection string (empty database): ' + str);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (host) {
|
|
167
|
+
options.host = host;
|
|
168
|
+
}
|
|
169
|
+
if (port !== null) {
|
|
170
|
+
var n = Number(port);
|
|
171
|
+
if (!/^\d+$/.test(port) || n < 1 || n > 65535) {
|
|
172
|
+
throw new Error('Invalid port in connection string "' + str +
|
|
173
|
+
'" (service names are not supported — use a numeric port)');
|
|
174
|
+
}
|
|
175
|
+
options.port = n;
|
|
176
|
+
}
|
|
177
|
+
options.database = database;
|
|
178
|
+
|
|
179
|
+
return options as Options;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const URI_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*:\/\//;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Parse any connection string the driver accepts: a firebird:// URI, or a
|
|
186
|
+
* traditional [host[/port]:]database string when there is no scheme.
|
|
187
|
+
*/
|
|
188
|
+
export function parseConnectionString(str: string): Options {
|
|
189
|
+
return URI_SCHEME.test(str)
|
|
190
|
+
? parseConnectionUri(str)
|
|
191
|
+
: parseOldStyleConnectionString(str);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Accept either an options object or a connection string (firebird:// URI
|
|
196
|
+
* or traditional host[/port]:database) everywhere options are taken.
|
|
197
|
+
* Strings are parsed; objects pass through unchanged.
|
|
198
|
+
*/
|
|
199
|
+
export function normalizeOptions<T>(options: T | string): T {
|
|
200
|
+
if (typeof options === 'string') {
|
|
201
|
+
return parseConnectionString(options) as T;
|
|
202
|
+
}
|
|
203
|
+
return options;
|
|
204
|
+
}
|