monetdb 2.1.0 → 2.2.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 +1 -1
- package/dist/connection.d.ts +1 -0
- package/dist/connection.js +3 -0
- package/dist/connection.js.map +1 -1
- package/dist/mapi.d.ts +7 -13
- package/dist/mapi.js +171 -141
- package/dist/mapi.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/connection.ts +114 -110
- package/src/mapi.ts +938 -913
- package/dist/QueryStream.d.ts +0 -7
- package/dist/QueryStream.js +0 -13
- package/dist/QueryStream.js.map +0 -1
- package/dist/connections.d.ts +0 -1
- package/dist/connections.js +0 -49
- package/dist/connections.js.map +0 -1
package/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|

|
4
4
|

|
5
|
-

|
6
6
|

|
7
7
|
|
8
8
|
Node.js connector for MonetDB.
|
package/dist/connection.d.ts
CHANGED
@@ -14,6 +14,7 @@ declare class Connection extends EventEmitter {
|
|
14
14
|
close(): Promise<boolean>;
|
15
15
|
commit(): Promise<void>;
|
16
16
|
private command;
|
17
|
+
destroy(): void;
|
17
18
|
execute(sql: string, stream?: boolean): Promise<any>;
|
18
19
|
prepare(sql: string): Promise<PrepareStatement>;
|
19
20
|
setAutocommit(v: boolean): Promise<boolean>;
|
package/dist/connection.js
CHANGED
@@ -58,6 +58,9 @@ class Connection extends events_1.EventEmitter {
|
|
58
58
|
command(str) {
|
59
59
|
return this.mapi.request(str);
|
60
60
|
}
|
61
|
+
destroy() {
|
62
|
+
return this.mapi.destroy();
|
63
|
+
}
|
61
64
|
execute(sql, stream = false) {
|
62
65
|
const query = `s${sql};\n`;
|
63
66
|
if (stream && this.replySize !== -1)
|
package/dist/connection.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"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"}
|
package/dist/mapi.d.ts
CHANGED
@@ -77,24 +77,24 @@ interface ResponseOpt {
|
|
77
77
|
fileHandler?: any;
|
78
78
|
}
|
79
79
|
declare class Response {
|
80
|
+
chunks: Buffer[];
|
80
81
|
buff: Buffer;
|
81
82
|
offset: number;
|
82
83
|
parseOffset: number;
|
83
84
|
stream: boolean;
|
84
85
|
settled: boolean;
|
85
86
|
headerEmitted: boolean;
|
86
|
-
segments: Segment[];
|
87
87
|
result?: QueryResult;
|
88
88
|
callbacks: ResponseCallbacks;
|
89
89
|
queryStream?: QueryStream;
|
90
90
|
headers?: ResponseHeaders;
|
91
91
|
fileHandler: any;
|
92
|
+
last: boolean;
|
93
|
+
leftOver: number;
|
94
|
+
private _str;
|
92
95
|
constructor(opt?: ResponseOpt);
|
93
96
|
append(data: Buffer): number;
|
94
97
|
complete(): boolean;
|
95
|
-
private seekOffset;
|
96
|
-
private expand;
|
97
|
-
private firstCharacter;
|
98
98
|
errorMessage(): string;
|
99
99
|
isFileTransfer(): boolean;
|
100
100
|
isPrompt(): boolean;
|
@@ -104,14 +104,7 @@ declare class Response {
|
|
104
104
|
toString(start?: number): string;
|
105
105
|
settle(res?: Promise<any>): void;
|
106
106
|
parseQueryResponse(data: string, res: any[]): number;
|
107
|
-
|
108
|
-
declare class Segment {
|
109
|
-
offset: number;
|
110
|
-
bytes: number;
|
111
|
-
bytesOffset: number;
|
112
|
-
last: boolean;
|
113
|
-
constructor(bytes: number, last: boolean, offset: number, bytesOffset: number);
|
114
|
-
isFull(): boolean;
|
107
|
+
streamResult(): void;
|
115
108
|
}
|
116
109
|
declare class MapiConnection extends EventEmitter {
|
117
110
|
state: MAPI_STATE;
|
@@ -131,7 +124,8 @@ declare class MapiConnection extends EventEmitter {
|
|
131
124
|
private createSocket;
|
132
125
|
connect(handShakeOptions?: HandShakeOption[]): Promise<any[]>;
|
133
126
|
ready(): boolean;
|
134
|
-
disconnect(): Promise<
|
127
|
+
disconnect(): Promise<true>;
|
128
|
+
destroy(): void;
|
135
129
|
private login;
|
136
130
|
/**
|
137
131
|
* Raise exception on server by sending bad packet
|
package/dist/mapi.js
CHANGED
@@ -272,15 +272,18 @@ function parseTupleLine(line, types) {
|
|
272
272
|
}
|
273
273
|
class Response {
|
274
274
|
constructor(opt = {}) {
|
275
|
-
this.
|
275
|
+
this.chunks = [];
|
276
|
+
//this.buff = Buffer.allocUnsafe(MAPI_BLOCK_SIZE).fill(0);
|
276
277
|
this.offset = 0;
|
277
278
|
this.parseOffset = 0;
|
278
|
-
this.segments = [];
|
279
279
|
this.settled = false;
|
280
|
+
this.last = false;
|
280
281
|
this.headerEmitted = false;
|
281
282
|
this.stream = opt.stream;
|
282
283
|
this.callbacks = opt.callbacks;
|
283
284
|
this.fileHandler = opt.fileHandler;
|
285
|
+
this.leftOver = 0;
|
286
|
+
this._str = "";
|
284
287
|
if (opt.stream) {
|
285
288
|
this.queryStream = new QueryStream();
|
286
289
|
if (opt.callbacks && opt.callbacks.resolve)
|
@@ -288,106 +291,89 @@ class Response {
|
|
288
291
|
}
|
289
292
|
}
|
290
293
|
append(data) {
|
291
|
-
let srcStartIndx = 0;
|
292
|
-
let srcEndIndx = srcStartIndx + data.length;
|
293
|
-
const l = this.segments.length;
|
294
|
-
let segment = (l > 0 && this.segments[l - 1]) || undefined;
|
295
|
-
let bytesCopied = 0;
|
294
|
+
//let srcStartIndx = 0;
|
295
|
+
//let srcEndIndx = srcStartIndx + data.length;
|
296
296
|
let bytesProcessed = 0;
|
297
|
-
if (
|
298
|
-
//
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
}
|
315
|
-
else {
|
316
|
-
const byteCntToRead = segment.bytes - segment.bytesOffset;
|
317
|
-
srcEndIndx = srcStartIndx + byteCntToRead;
|
318
|
-
bytesCopied = data.copy(this.buff, this.offset, srcStartIndx, srcEndIndx);
|
319
|
-
this.offset += bytesCopied;
|
320
|
-
segment.bytesOffset += bytesCopied;
|
321
|
-
// console.log(`segment is full ${segment.bytesOffset === segment.bytes}`);
|
322
|
-
bytesProcessed = bytesCopied;
|
323
|
-
}
|
324
|
-
if (this.isQueryResponse()) {
|
325
|
-
const tuples = [];
|
326
|
-
// const firstPackage = this.parseOffset === 0;
|
327
|
-
this.parseOffset += this.parseQueryResponse(this.toString(this.parseOffset), tuples);
|
328
|
-
if (tuples.length > 0) {
|
329
|
-
if (this.queryStream) {
|
330
|
-
// emit header once
|
331
|
-
if (this.headerEmitted === false &&
|
332
|
-
this.result &&
|
333
|
-
this.result.columns) {
|
334
|
-
this.queryStream.emit("header", this.result.columns);
|
335
|
-
this.headerEmitted = true;
|
336
|
-
}
|
337
|
-
// emit tuples
|
338
|
-
this.queryStream.emit("data", tuples);
|
339
|
-
}
|
340
|
-
else {
|
341
|
-
this.result.data = this.result.data || [];
|
342
|
-
for (let t of tuples) {
|
343
|
-
this.result.data.push(t);
|
344
|
-
}
|
345
|
-
}
|
346
|
-
}
|
347
|
-
}
|
297
|
+
if (this.leftOver == 0) {
|
298
|
+
// new mapi blk, read header
|
299
|
+
const hdr = data.readUInt16LE(0);
|
300
|
+
this.last = (hdr & 1) === 1;
|
301
|
+
this.leftOver = hdr >> 1;
|
302
|
+
data = data.subarray(MAPI_HEADER_SIZE);
|
303
|
+
bytesProcessed += MAPI_HEADER_SIZE;
|
304
|
+
//bytesCopied = data.copy(
|
305
|
+
// this.buff,
|
306
|
+
// this.offset,
|
307
|
+
// srcStartIndx,
|
308
|
+
// srcEndIndx
|
309
|
+
//);
|
310
|
+
//segment = new Segment(bytes, last, this.offset, bytesCopied);
|
311
|
+
//this.segments.push(segment);
|
312
|
+
//this.offset += bytesCopied;
|
313
|
+
//bytesProcessed = MAPI_HEADER_SIZE + bytesCopied;
|
348
314
|
}
|
315
|
+
//else {
|
316
|
+
// const byteCntToRead = segment.bytes - segment.bytesOffset;
|
317
|
+
// srcEndIndx = srcStartIndx + byteCntToRead;
|
318
|
+
// bytesCopied = data.copy(
|
319
|
+
// this.buff,
|
320
|
+
// this.offset,
|
321
|
+
// srcStartIndx,
|
322
|
+
// srcEndIndx
|
323
|
+
// );
|
324
|
+
// this.offset += bytesCopied;
|
325
|
+
// segment.bytesOffset += bytesCopied;
|
326
|
+
// // console.log(`segment is full ${segment.bytesOffset === segment.bytes}`);
|
327
|
+
// bytesProcessed = bytesCopied;
|
328
|
+
//}
|
329
|
+
const bytesToRead = Math.min(data.length, this.leftOver);
|
330
|
+
//console.log(`bytesToRead ${bytesToRead}`);
|
331
|
+
if (bytesToRead > 0) {
|
332
|
+
const chunk = data.subarray(0, bytesToRead);
|
333
|
+
this.chunks.push(chunk);
|
334
|
+
this.leftOver -= bytesToRead;
|
335
|
+
bytesProcessed += bytesToRead;
|
336
|
+
}
|
337
|
+
//if (this.isQueryResponse()) {
|
338
|
+
// const tuples = [];
|
339
|
+
// // const firstPackage = this.parseOffset === 0;
|
340
|
+
// this.parseOffset += this.parseQueryResponse(
|
341
|
+
// this.toString(this.parseOffset),
|
342
|
+
// tuples
|
343
|
+
// );
|
344
|
+
// console.log("tuples");
|
345
|
+
// console.log(tuples);
|
346
|
+
// if (tuples.length > 0) {
|
347
|
+
// if (this.queryStream) {
|
348
|
+
// // emit header once
|
349
|
+
// if (
|
350
|
+
// this.headerEmitted === false &&
|
351
|
+
// this.result &&
|
352
|
+
// this.result.columns
|
353
|
+
// ) {
|
354
|
+
// this.queryStream.emit("header", this.result.columns);
|
355
|
+
// this.headerEmitted = true;
|
356
|
+
// }
|
357
|
+
// // emit tuples
|
358
|
+
// this.queryStream.emit("data", tuples);
|
359
|
+
// } else {
|
360
|
+
// this.result.data = this.result.data || [];
|
361
|
+
// for (let t of tuples) {
|
362
|
+
// this.result.data.push(t);
|
363
|
+
// }
|
364
|
+
// }
|
365
|
+
// }
|
366
|
+
//}
|
367
|
+
//console.log(`bytesProcessed ${bytesToRead}`);
|
349
368
|
return bytesProcessed;
|
350
369
|
}
|
351
370
|
complete() {
|
352
|
-
|
353
|
-
if (l > 0) {
|
354
|
-
const segment = this.segments[l - 1];
|
355
|
-
return segment.last && segment.isFull();
|
356
|
-
}
|
357
|
-
return false;
|
358
|
-
}
|
359
|
-
seekOffset() {
|
360
|
-
const len = this.segments.length;
|
361
|
-
if (len) {
|
362
|
-
const last = this.segments[len - 1];
|
363
|
-
if (last.isFull())
|
364
|
-
return last.offset + last.bytes;
|
365
|
-
return last.offset;
|
366
|
-
}
|
367
|
-
return 0;
|
368
|
-
}
|
369
|
-
expand(byteCount) {
|
370
|
-
if (this.buff.length + byteCount > MAX_BUFF_SIZE &&
|
371
|
-
this.fileHandler instanceof file_transfer_1.FileDownloader) {
|
372
|
-
const offset = this.seekOffset();
|
373
|
-
if (offset) {
|
374
|
-
this.fileHandler.writeChunk(this.buff.subarray(0, offset));
|
375
|
-
this.buff = this.buff.subarray(offset);
|
376
|
-
this.offset -= offset;
|
377
|
-
}
|
378
|
-
}
|
379
|
-
const buff = buffer_1.Buffer.allocUnsafe(this.buff.length + byteCount).fill(0);
|
380
|
-
const bytesCopied = this.buff.copy(buff);
|
381
|
-
this.buff = buff;
|
382
|
-
// should be byteCount
|
383
|
-
return this.buff.length - bytesCopied;
|
384
|
-
}
|
385
|
-
firstCharacter() {
|
386
|
-
return this.buff.toString("utf8", 0, 1);
|
371
|
+
return this.last && (this.leftOver == 0);
|
387
372
|
}
|
388
373
|
errorMessage() {
|
389
|
-
|
390
|
-
|
374
|
+
const msg = this.toString();
|
375
|
+
if (msg.startsWith(MSG_ERROR)) {
|
376
|
+
return msg;
|
391
377
|
}
|
392
378
|
return "";
|
393
379
|
}
|
@@ -395,27 +381,32 @@ class Response {
|
|
395
381
|
return this.toString().startsWith(MSG_FILETRANS);
|
396
382
|
}
|
397
383
|
isPrompt() {
|
398
|
-
|
399
|
-
return this.complete() && this.firstCharacter() === "\x00";
|
384
|
+
return this.complete() && this.toString() == MSG_PROMPT;
|
400
385
|
}
|
401
386
|
isRedirect() {
|
402
|
-
return this.
|
387
|
+
return this.toString().startsWith(MSG_REDIRECT);
|
403
388
|
}
|
404
389
|
isQueryResponse() {
|
405
390
|
if (this.result && this.result.type) {
|
406
391
|
return this.result.type.startsWith(MSG_Q);
|
407
392
|
}
|
408
|
-
return this.
|
393
|
+
return this.toString().startsWith(MSG_Q);
|
409
394
|
}
|
410
395
|
isMsgMore() {
|
411
396
|
// server wants more ?
|
412
397
|
return this.toString().startsWith(MSG_MORE);
|
413
398
|
}
|
414
399
|
toString(start) {
|
415
|
-
|
400
|
+
if (this.complete() && !this.queryStream && this._str) {
|
401
|
+
if (start)
|
402
|
+
return this._str.substring(start);
|
403
|
+
return this._str;
|
404
|
+
}
|
405
|
+
const buff = buffer_1.Buffer.concat(this.chunks);
|
406
|
+
this._str = buff.toString("utf8");
|
416
407
|
if (start)
|
417
|
-
return
|
418
|
-
return
|
408
|
+
return this._str.substring(start);
|
409
|
+
return this._str;
|
419
410
|
}
|
420
411
|
settle(res) {
|
421
412
|
if (this.settled === false && this.complete()) {
|
@@ -443,6 +434,8 @@ class Response {
|
|
443
434
|
}
|
444
435
|
}
|
445
436
|
this.settled = true;
|
437
|
+
this._str = "";
|
438
|
+
this.chunks = [];
|
446
439
|
}
|
447
440
|
}
|
448
441
|
parseQueryResponse(data, res) {
|
@@ -532,16 +525,22 @@ class Response {
|
|
532
525
|
}
|
533
526
|
return offset;
|
534
527
|
}
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
528
|
+
streamResult() {
|
529
|
+
if (this.queryStream && this.isQueryResponse()) {
|
530
|
+
const tuples = [];
|
531
|
+
this.parseOffset += this.parseQueryResponse(this.toString(this.parseOffset), tuples);
|
532
|
+
if (tuples.length > 0) {
|
533
|
+
// emit header once
|
534
|
+
if (this.headerEmitted === false &&
|
535
|
+
this.result &&
|
536
|
+
this.result.columns) {
|
537
|
+
this.queryStream.emit("header", this.result.columns);
|
538
|
+
this.headerEmitted = true;
|
539
|
+
}
|
540
|
+
// emit tuples
|
541
|
+
this.queryStream.emit("data", tuples);
|
542
|
+
}
|
543
|
+
}
|
545
544
|
}
|
546
545
|
}
|
547
546
|
class MapiConnection extends events_1.EventEmitter {
|
@@ -554,23 +553,12 @@ class MapiConnection extends events_1.EventEmitter {
|
|
554
553
|
socket.addListener("data", this.recv.bind(this));
|
555
554
|
socket.addListener("error", this.handleSocketError.bind(this));
|
556
555
|
socket.addListener("timeout", this.handleTimeout.bind(this));
|
557
|
-
socket.
|
558
|
-
console.log("
|
559
|
-
this.emit("end");
|
556
|
+
socket.once("end", () => {
|
557
|
+
console.log("Server has ended the connection");
|
560
558
|
});
|
561
559
|
return socket;
|
562
560
|
};
|
563
561
|
this.state = MAPI_STATE.INIT;
|
564
|
-
this.socket = this.createSocket(config.timeout);
|
565
|
-
// this.socket = new Socket();
|
566
|
-
// if (config.timeout) this.socket.setTimeout(config.timeout);
|
567
|
-
// this.socket.addListener("data", this.recv.bind(this));
|
568
|
-
// this.socket.addListener("error", this.handleSocketError.bind(this));
|
569
|
-
// this.socket.addListener("timeout", this.handleTimeout.bind(this));
|
570
|
-
// this.socket.addListener("close", () => {
|
571
|
-
// console.log("socket close event");
|
572
|
-
// this.emit("end");
|
573
|
-
// });
|
574
562
|
this.redirects = 0;
|
575
563
|
this.queue = [];
|
576
564
|
this.database = config.database;
|
@@ -601,18 +589,46 @@ class MapiConnection extends events_1.EventEmitter {
|
|
601
589
|
return (0, events_1.once)(this, "ready");
|
602
590
|
}
|
603
591
|
ready() {
|
604
|
-
return this.state === MAPI_STATE.READY;
|
592
|
+
return this.socket && this.socket.writable && this.state === MAPI_STATE.READY;
|
605
593
|
}
|
606
594
|
disconnect() {
|
607
595
|
return new Promise((resolve, reject) => {
|
608
|
-
this.socket.
|
609
|
-
this.
|
596
|
+
if (!this.socket || this.socket.destroyed) {
|
597
|
+
this.socket = null;
|
610
598
|
this.state = MAPI_STATE.INIT;
|
611
|
-
|
612
|
-
|
613
|
-
|
599
|
+
return resolve(true);
|
600
|
+
}
|
601
|
+
const onClose = () => {
|
602
|
+
cleanup();
|
603
|
+
this.socket = null;
|
604
|
+
this.state = MAPI_STATE.INIT;
|
605
|
+
resolve(true);
|
606
|
+
};
|
607
|
+
const onError = (err) => {
|
608
|
+
var _a;
|
609
|
+
console.error(err);
|
610
|
+
cleanup();
|
611
|
+
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.destroy(); // force cleanup
|
612
|
+
this.socket = null;
|
613
|
+
this.state = MAPI_STATE.INIT;
|
614
|
+
reject(err);
|
615
|
+
};
|
616
|
+
const cleanup = () => {
|
617
|
+
var _a, _b;
|
618
|
+
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.removeListener("close", onClose);
|
619
|
+
(_b = this.socket) === null || _b === void 0 ? void 0 : _b.removeListener("error", onError);
|
620
|
+
};
|
621
|
+
this.socket.once("close", onClose);
|
622
|
+
this.socket.once("error", onError);
|
623
|
+
// Initiate graceful shutdown
|
624
|
+
this.socket.end();
|
614
625
|
});
|
615
626
|
}
|
627
|
+
destroy() {
|
628
|
+
if (this.socket && !this.socket.destroyed)
|
629
|
+
this.socket.destroy();
|
630
|
+
this.socket = null;
|
631
|
+
}
|
616
632
|
login(challenge) {
|
617
633
|
const challengeParts = challenge.split(":");
|
618
634
|
const [salt, identity, protocol, hashes, endian, algo, opt_level] = challengeParts;
|
@@ -711,7 +727,8 @@ class MapiConnection extends events_1.EventEmitter {
|
|
711
727
|
this.emit("error", new Error("Timeout"));
|
712
728
|
}
|
713
729
|
handleSocketError(err) {
|
714
|
-
console.error(err);
|
730
|
+
console.error('Socket error: ', err);
|
731
|
+
this.destroy();
|
715
732
|
}
|
716
733
|
request(sql, stream = false) {
|
717
734
|
return __awaiter(this, void 0, void 0, function* () {
|
@@ -744,8 +761,9 @@ class MapiConnection extends events_1.EventEmitter {
|
|
744
761
|
recv(data) {
|
745
762
|
let bytesLeftOver;
|
746
763
|
let resp;
|
747
|
-
// process queue left to right,
|
748
|
-
//
|
764
|
+
// process queue left to right,
|
765
|
+
// find 1st uncomplete response
|
766
|
+
// remove complete responses
|
749
767
|
while (this.queue.length) {
|
750
768
|
const next = this.queue[0];
|
751
769
|
if (next.complete() || next.settled) {
|
@@ -759,17 +777,23 @@ class MapiConnection extends events_1.EventEmitter {
|
|
759
777
|
if (resp === undefined && this.queue.length === 0) {
|
760
778
|
// challenge message
|
761
779
|
// or direct call to send has being made
|
762
|
-
//
|
780
|
+
// request api appends Response to the queue
|
763
781
|
resp = new Response();
|
764
782
|
this.queue.push(resp);
|
765
783
|
}
|
766
|
-
|
784
|
+
let offset = 0;
|
785
|
+
let end = data.length;
|
786
|
+
do {
|
787
|
+
offset += resp.append(data.subarray(offset, end));
|
788
|
+
} while ((offset < end) && !resp.complete());
|
789
|
+
if (resp.queryStream)
|
790
|
+
resp.streamResult();
|
767
791
|
if (resp.complete())
|
768
792
|
this.handleResponse(resp);
|
769
793
|
bytesLeftOver = data.length - offset;
|
770
794
|
if (bytesLeftOver) {
|
771
|
-
const msg = `some ${bytesLeftOver} bytes left over!`;
|
772
|
-
console.warn(msg);
|
795
|
+
//const msg = `some ${bytesLeftOver} bytes left over!`;
|
796
|
+
//console.warn(msg);
|
773
797
|
this.recv(data.subarray(offset));
|
774
798
|
}
|
775
799
|
}
|
@@ -787,7 +811,7 @@ class MapiConnection extends events_1.EventEmitter {
|
|
787
811
|
return;
|
788
812
|
}
|
789
813
|
if (resp.isPrompt()) {
|
790
|
-
console.log("login OK");
|
814
|
+
//console.log("login OK");
|
791
815
|
this.state = MAPI_STATE.READY;
|
792
816
|
this.emit("ready", this.state);
|
793
817
|
return;
|
@@ -795,7 +819,7 @@ class MapiConnection extends events_1.EventEmitter {
|
|
795
819
|
return this.login(resp.toString());
|
796
820
|
}
|
797
821
|
if (resp.isFileTransfer()) {
|
798
|
-
console.log("file transfer");
|
822
|
+
//console.log("file transfer");
|
799
823
|
let fhandler;
|
800
824
|
const msg = resp.toString(MSG_FILETRANS.length).trim();
|
801
825
|
let mode, offset, file;
|
@@ -832,11 +856,17 @@ class MapiConnection extends events_1.EventEmitter {
|
|
832
856
|
resp.fileHandler.ready()) {
|
833
857
|
// end of download
|
834
858
|
const fileHandler = resp.fileHandler;
|
835
|
-
|
859
|
+
const buff = buffer_1.Buffer.concat(resp.chunks);
|
860
|
+
fileHandler.writeChunk(buff);
|
836
861
|
// we do expect a final response from server
|
837
862
|
this.queue.push(new Response({ fileHandler }));
|
838
863
|
return resp.settle(fileHandler.close());
|
839
864
|
}
|
865
|
+
if (resp.isQueryResponse()) {
|
866
|
+
const data = [];
|
867
|
+
resp.parseQueryResponse(resp.toString(), data);
|
868
|
+
resp.result.data = data;
|
869
|
+
}
|
840
870
|
resp.settle();
|
841
871
|
}
|
842
872
|
}
|