monetdb 2.0.2 → 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/dist/mapi.js CHANGED
@@ -272,14 +272,18 @@ function parseTupleLine(line, types) {
272
272
  }
273
273
  class Response {
274
274
  constructor(opt = {}) {
275
- this.buff = buffer_1.Buffer.allocUnsafe(MAPI_BLOCK_SIZE).fill(0);
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;
281
+ this.headerEmitted = false;
280
282
  this.stream = opt.stream;
281
283
  this.callbacks = opt.callbacks;
282
284
  this.fileHandler = opt.fileHandler;
285
+ this.leftOver = 0;
286
+ this._str = "";
283
287
  if (opt.stream) {
284
288
  this.queryStream = new QueryStream();
285
289
  if (opt.callbacks && opt.callbacks.resolve)
@@ -287,103 +291,89 @@ class Response {
287
291
  }
288
292
  }
289
293
  append(data) {
290
- let srcStartIndx = 0;
291
- let srcEndIndx = srcStartIndx + data.length;
292
- const l = this.segments.length;
293
- let segment = (l > 0 && this.segments[l - 1]) || undefined;
294
- let bytesCopied = 0;
294
+ //let srcStartIndx = 0;
295
+ //let srcEndIndx = srcStartIndx + data.length;
295
296
  let bytesProcessed = 0;
296
- if (!this.complete()) {
297
- // check if out of space
298
- if (this.buff.length - this.offset < data.length) {
299
- const bytes = this.expand(MAPI_BLOCK_SIZE);
300
- console.log(`expanding by ${bytes} bytes!`);
301
- }
302
- if (segment === undefined || (segment && segment.isFull())) {
303
- const hdr = data.readUInt16LE(0);
304
- const last = (hdr & 1) === 1;
305
- const bytes = hdr >> 1;
306
- srcStartIndx = MAPI_HEADER_SIZE;
307
- srcEndIndx = srcStartIndx + Math.min(bytes, data.length);
308
- bytesCopied = data.copy(this.buff, this.offset, srcStartIndx, srcEndIndx);
309
- segment = new Segment(bytes, last, this.offset, bytesCopied);
310
- this.segments.push(segment);
311
- this.offset += bytesCopied;
312
- bytesProcessed = MAPI_HEADER_SIZE + bytesCopied;
313
- }
314
- else {
315
- const byteCntToRead = segment.bytes - segment.bytesOffset;
316
- srcEndIndx = srcStartIndx + byteCntToRead;
317
- bytesCopied = data.copy(this.buff, this.offset, srcStartIndx, srcEndIndx);
318
- this.offset += bytesCopied;
319
- segment.bytesOffset += bytesCopied;
320
- // console.log(`segment is full ${segment.bytesOffset === segment.bytes}`);
321
- bytesProcessed = bytesCopied;
322
- }
323
- if (this.isQueryResponse()) {
324
- const tuples = [];
325
- const firstPackage = this.parseOffset === 0;
326
- this.parseOffset += this.parse(this.toString(this.parseOffset), tuples);
327
- if (tuples.length > 0) {
328
- if (this.queryStream) {
329
- // emit header once
330
- if (firstPackage && this.result && this.result.columns) {
331
- this.queryStream.emit("header", this.result.columns);
332
- }
333
- // emit tuples
334
- this.queryStream.emit("data", tuples);
335
- }
336
- else {
337
- this.result.data = this.result.data || [];
338
- for (let t of tuples) {
339
- this.result.data.push(t);
340
- }
341
- }
342
- }
343
- }
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;
344
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}`);
345
368
  return bytesProcessed;
346
369
  }
347
370
  complete() {
348
- const l = this.segments.length;
349
- if (l > 0) {
350
- const segment = this.segments[l - 1];
351
- return segment.last && segment.isFull();
352
- }
353
- return false;
354
- }
355
- seekOffset() {
356
- const len = this.segments.length;
357
- if (len) {
358
- const last = this.segments[len - 1];
359
- if (last.isFull())
360
- return last.offset + last.bytes;
361
- return last.offset;
362
- }
363
- return 0;
364
- }
365
- expand(byteCount) {
366
- if (this.buff.length + byteCount > MAX_BUFF_SIZE &&
367
- this.fileHandler instanceof file_transfer_1.FileDownloader) {
368
- const offset = this.seekOffset();
369
- if (offset) {
370
- this.fileHandler.writeChunk(this.buff.subarray(0, offset));
371
- this.buff = this.buff.subarray(offset);
372
- this.offset -= offset;
373
- }
374
- }
375
- const buff = buffer_1.Buffer.allocUnsafe(this.buff.length + byteCount).fill(0);
376
- const bytesCopied = this.buff.copy(buff);
377
- this.buff = buff;
378
- // should be byteCount
379
- return this.buff.length - bytesCopied;
380
- }
381
- firstCharacter() {
382
- return this.buff.toString("utf8", 0, 1);
371
+ return this.last && (this.leftOver == 0);
383
372
  }
384
373
  errorMessage() {
385
- if (this.firstCharacter() === MSG_ERROR) {
386
- return this.buff.toString("utf8", 1);
374
+ const msg = this.toString();
375
+ if (msg.startsWith(MSG_ERROR)) {
376
+ return msg;
387
377
  }
388
378
  return "";
389
379
  }
@@ -391,27 +381,32 @@ class Response {
391
381
  return this.toString().startsWith(MSG_FILETRANS);
392
382
  }
393
383
  isPrompt() {
394
- // perhaps use toString
395
- return this.complete() && this.firstCharacter() === "\x00";
384
+ return this.complete() && this.toString() == MSG_PROMPT;
396
385
  }
397
386
  isRedirect() {
398
- return this.firstCharacter() === MSG_REDIRECT;
387
+ return this.toString().startsWith(MSG_REDIRECT);
399
388
  }
400
389
  isQueryResponse() {
401
390
  if (this.result && this.result.type) {
402
391
  return this.result.type.startsWith(MSG_Q);
403
392
  }
404
- return this.firstCharacter() === MSG_Q;
393
+ return this.toString().startsWith(MSG_Q);
405
394
  }
406
395
  isMsgMore() {
407
396
  // server wants more ?
408
397
  return this.toString().startsWith(MSG_MORE);
409
398
  }
410
399
  toString(start) {
411
- const res = this.buff.toString("utf8", 0, this.offset);
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");
412
407
  if (start)
413
- return res.substring(start);
414
- return res;
408
+ return this._str.substring(start);
409
+ return this._str;
415
410
  }
416
411
  settle(res) {
417
412
  if (this.settled === false && this.complete()) {
@@ -439,116 +434,113 @@ class Response {
439
434
  }
440
435
  }
441
436
  this.settled = true;
437
+ this._str = "";
438
+ this.chunks = [];
442
439
  }
443
440
  }
444
- parse(data, res) {
441
+ parseQueryResponse(data, res) {
445
442
  let offset = 0;
446
- const lines = data.split("\n").length;
447
- if (this.isQueryResponse()) {
448
- let eol = data.indexOf("\n");
449
- this.result = this.result || {};
450
- if (this.result.type === undefined &&
451
- data.startsWith(MSG_Q) &&
452
- lines > 0) {
453
- // process 1st line
454
- const line = data.substring(0, eol);
455
- this.result.type = line.substring(0, 2);
456
- const rest = line.substring(3).trim().split(" ");
457
- if (this.result.type === MSG_QTABLE) {
458
- const [id, rowCnt, columnCnt, rows, queryId, queryTime, malOptimizerTime, sqlOptimizerTime,] = rest;
459
- this.result.id = parseInt(id);
460
- this.result.rowCnt = parseInt(rowCnt);
461
- this.result.columnCnt = parseInt(columnCnt);
462
- this.result.queryId = parseInt(queryId);
463
- this.result.queryTime = parseInt(queryTime);
464
- this.result.malOptimizerTime = parseInt(malOptimizerTime);
465
- this.result.sqlOptimizerTime = parseInt(sqlOptimizerTime);
466
- }
467
- else if (this.result.type === MSG_QUPDATE) {
468
- const [affectedRowCnt, autoIncrementId, queryId, queryTime, malOptimizerTime, sqlOptimizerTime,] = rest;
469
- this.result.affectedRows = parseInt(affectedRowCnt);
470
- this.result.queryId = parseInt(queryId);
471
- this.result.queryTime = parseInt(queryTime);
472
- this.result.malOptimizerTime = parseInt(malOptimizerTime);
473
- this.result.sqlOptimizerTime = parseInt(sqlOptimizerTime);
474
- }
475
- else if (this.result.type === MSG_QSCHEMA) {
476
- const [queryTime, malOptimizerTime] = rest;
477
- this.result.queryTime = parseInt(queryTime);
478
- this.result.malOptimizerTime = parseInt(malOptimizerTime);
479
- }
480
- else if (this.result.type === MSG_QTRANS) {
481
- // skip
482
- }
483
- else if (this.result.type === MSG_QPREPARE) {
484
- const [id, rowCnt, columnCnt, rows] = rest;
485
- this.result.id = parseInt(id);
486
- this.result.rowCnt = parseInt(rowCnt);
487
- this.result.columnCnt = parseInt(columnCnt);
488
- }
489
- // end 1st line
490
- if (this.headers === undefined &&
491
- data.charAt(eol + 1) === MSG_HEADER &&
492
- lines > 5) {
493
- let headers = {};
494
- while (data.charAt(eol + 1) === MSG_HEADER) {
495
- const hs = eol + 1;
496
- eol = data.indexOf("\n", hs);
497
- headers = Object.assign(Object.assign({}, headers), parseHeaderLine(data.substring(hs, eol)));
443
+ let eol = data.indexOf("\n");
444
+ let line = eol > 0 ? data.substring(0, eol) : undefined;
445
+ while (line) {
446
+ switch (line.charAt(0)) {
447
+ case MSG_Q:
448
+ // first line
449
+ this.result = this.result || {};
450
+ this.result.type = line.substring(0, 2);
451
+ const rest = line.substring(3).trim().split(" ");
452
+ if (this.result.type === MSG_QTABLE) {
453
+ const [id, rowCnt, columnCnt, rows, queryId, queryTime, malOptimizerTime, sqlOptimizerTime,] = rest;
454
+ this.result.id = parseInt(id);
455
+ this.result.rowCnt = parseInt(rowCnt);
456
+ this.result.columnCnt = parseInt(columnCnt);
457
+ this.result.queryId = parseInt(queryId);
458
+ this.result.queryTime = parseInt(queryTime);
459
+ this.result.malOptimizerTime = parseInt(malOptimizerTime);
460
+ this.result.sqlOptimizerTime = parseInt(sqlOptimizerTime);
498
461
  }
499
- this.headers = headers;
500
- const colums = [];
501
- for (let i = 0; i < this.result.columnCnt; i++) {
502
- const table = headers.tableNames && headers.tableNames[i];
503
- const name = headers.columnNames && headers.columnNames[i];
504
- const type = headers.columnTypes && headers.columnTypes[i];
505
- colums.push({
506
- table,
507
- name,
508
- type,
509
- index: i,
510
- });
462
+ else if (this.result.type === MSG_QUPDATE) {
463
+ const [affectedRowCnt, autoIncrementId, queryId, queryTime, malOptimizerTime, sqlOptimizerTime,] = rest;
464
+ this.result.affectedRows = parseInt(affectedRowCnt);
465
+ this.result.queryId = parseInt(queryId);
466
+ this.result.queryTime = parseInt(queryTime);
467
+ this.result.malOptimizerTime = parseInt(malOptimizerTime);
468
+ this.result.sqlOptimizerTime = parseInt(sqlOptimizerTime);
511
469
  }
512
- this.result.columns = colums;
513
- }
514
- }
515
- offset = eol + 1;
516
- let ts = undefined; // tuple index
517
- if (data.startsWith(MSG_TUPLE)) {
518
- ts = 0;
519
- }
520
- else if (data.charAt(eol + 1) === MSG_TUPLE) {
521
- ts = eol + 1;
522
- eol = data.indexOf("\n", ts);
523
- }
524
- if (ts !== undefined && eol > 0) {
525
- // we have a data row
526
- do {
527
- offset = eol + 1;
528
- const tuple = parseTupleLine(data.substring(ts, eol), this.headers.columnTypes);
529
- res.push(tuple);
530
- if (data.charAt(eol + 1) === MSG_TUPLE) {
531
- ts = eol + 1;
532
- eol = data.indexOf("\n", ts);
470
+ else if (this.result.type === MSG_QSCHEMA) {
471
+ const [queryTime, malOptimizerTime] = rest;
472
+ this.result.queryTime = parseInt(queryTime);
473
+ this.result.malOptimizerTime = parseInt(malOptimizerTime);
474
+ }
475
+ else if (this.result.type === MSG_QTRANS) {
476
+ // skip
477
+ }
478
+ else if (this.result.type === MSG_QPREPARE) {
479
+ const [id, rowCnt, columnCnt, rows] = rest;
480
+ this.result.id = parseInt(id);
481
+ this.result.rowCnt = parseInt(rowCnt);
482
+ this.result.columnCnt = parseInt(columnCnt);
483
+ }
484
+ break;
485
+ case MSG_HEADER:
486
+ const header = parseHeaderLine(line);
487
+ if (this.result.headers !== undefined) {
488
+ this.result.headers = Object.assign(Object.assign({}, this.result.headers), header);
533
489
  }
534
490
  else {
535
- ts = undefined;
491
+ this.result.headers = header;
492
+ }
493
+ // if we have all headers we can compile column info
494
+ const haveAllHeaders = Boolean(this.result.headers.tableNames) &&
495
+ Boolean(this.result.headers.columnNames) &&
496
+ Boolean(this.result.headers.columnTypes);
497
+ if (this.result.columns === undefined && haveAllHeaders) {
498
+ const colums = [];
499
+ for (let i = 0; i < this.result.columnCnt; i++) {
500
+ const table = this.result.headers.tableNames[i];
501
+ const name = this.result.headers.columnNames[i];
502
+ const type = this.result.headers.columnTypes[i];
503
+ colums.push({
504
+ table,
505
+ name,
506
+ type,
507
+ index: i,
508
+ });
509
+ }
510
+ this.result.columns = colums;
536
511
  }
537
- } while (ts && eol > -1);
512
+ break;
513
+ case MSG_TUPLE:
514
+ const tuple = parseTupleLine(line, this.result.headers.columnTypes);
515
+ res.push(tuple);
516
+ break;
517
+ default:
518
+ throw TypeError(`Invalid query response line!\n${line}`);
538
519
  }
520
+ // line is processed advance offset
521
+ offset = eol + 1;
522
+ // get next line
523
+ eol = data.indexOf("\n", offset);
524
+ line = eol > 0 ? data.substring(offset, eol) : undefined;
539
525
  }
540
526
  return offset;
541
527
  }
542
- }
543
- class Segment {
544
- constructor(bytes, last, offset, bytesOffset) {
545
- this.bytes = bytes;
546
- this.last = last;
547
- this.offset = offset;
548
- this.bytesOffset = bytesOffset;
549
- }
550
- isFull() {
551
- return this.bytes === this.bytesOffset;
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
+ }
552
544
  }
553
545
  }
554
546
  class MapiConnection extends events_1.EventEmitter {
@@ -561,23 +553,12 @@ class MapiConnection extends events_1.EventEmitter {
561
553
  socket.addListener("data", this.recv.bind(this));
562
554
  socket.addListener("error", this.handleSocketError.bind(this));
563
555
  socket.addListener("timeout", this.handleTimeout.bind(this));
564
- socket.addListener("close", () => {
565
- console.log("socket close event");
566
- this.emit("end");
556
+ socket.once("end", () => {
557
+ console.log("Server has ended the connection");
567
558
  });
568
559
  return socket;
569
560
  };
570
561
  this.state = MAPI_STATE.INIT;
571
- this.socket = this.createSocket(config.timeout);
572
- // this.socket = new Socket();
573
- // if (config.timeout) this.socket.setTimeout(config.timeout);
574
- // this.socket.addListener("data", this.recv.bind(this));
575
- // this.socket.addListener("error", this.handleSocketError.bind(this));
576
- // this.socket.addListener("timeout", this.handleTimeout.bind(this));
577
- // this.socket.addListener("close", () => {
578
- // console.log("socket close event");
579
- // this.emit("end");
580
- // });
581
562
  this.redirects = 0;
582
563
  this.queue = [];
583
564
  this.database = config.database;
@@ -608,18 +589,46 @@ class MapiConnection extends events_1.EventEmitter {
608
589
  return (0, events_1.once)(this, "ready");
609
590
  }
610
591
  ready() {
611
- return this.state === MAPI_STATE.READY;
592
+ return this.socket && this.socket.writable && this.state === MAPI_STATE.READY;
612
593
  }
613
594
  disconnect() {
614
595
  return new Promise((resolve, reject) => {
615
- this.socket.end(() => {
616
- this.redirects = 0;
596
+ if (!this.socket || this.socket.destroyed) {
597
+ this.socket = null;
617
598
  this.state = MAPI_STATE.INIT;
618
- this.socket.destroy();
619
- resolve(this.state === MAPI_STATE.INIT);
620
- });
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();
621
625
  });
622
626
  }
627
+ destroy() {
628
+ if (this.socket && !this.socket.destroyed)
629
+ this.socket.destroy();
630
+ this.socket = null;
631
+ }
623
632
  login(challenge) {
624
633
  const challengeParts = challenge.split(":");
625
634
  const [salt, identity, protocol, hashes, endian, algo, opt_level] = challengeParts;
@@ -718,7 +727,8 @@ class MapiConnection extends events_1.EventEmitter {
718
727
  this.emit("error", new Error("Timeout"));
719
728
  }
720
729
  handleSocketError(err) {
721
- console.error(err);
730
+ console.error('Socket error: ', err);
731
+ this.destroy();
722
732
  }
723
733
  request(sql, stream = false) {
724
734
  return __awaiter(this, void 0, void 0, function* () {
@@ -751,8 +761,9 @@ class MapiConnection extends events_1.EventEmitter {
751
761
  recv(data) {
752
762
  let bytesLeftOver;
753
763
  let resp;
754
- // process queue left to right, find 1st uncomplete response
755
- // remove responses that are completed
764
+ // process queue left to right,
765
+ // find 1st uncomplete response
766
+ // remove complete responses
756
767
  while (this.queue.length) {
757
768
  const next = this.queue[0];
758
769
  if (next.complete() || next.settled) {
@@ -766,17 +777,23 @@ class MapiConnection extends events_1.EventEmitter {
766
777
  if (resp === undefined && this.queue.length === 0) {
767
778
  // challenge message
768
779
  // or direct call to send has being made
769
- // e.g. request api appends Response to the queue
780
+ // request api appends Response to the queue
770
781
  resp = new Response();
771
782
  this.queue.push(resp);
772
783
  }
773
- const offset = resp.append(data);
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();
774
791
  if (resp.complete())
775
792
  this.handleResponse(resp);
776
793
  bytesLeftOver = data.length - offset;
777
794
  if (bytesLeftOver) {
778
- const msg = `some ${bytesLeftOver} bytes left over!`;
779
- console.warn(msg);
795
+ //const msg = `some ${bytesLeftOver} bytes left over!`;
796
+ //console.warn(msg);
780
797
  this.recv(data.subarray(offset));
781
798
  }
782
799
  }
@@ -794,7 +811,7 @@ class MapiConnection extends events_1.EventEmitter {
794
811
  return;
795
812
  }
796
813
  if (resp.isPrompt()) {
797
- console.log("login OK");
814
+ //console.log("login OK");
798
815
  this.state = MAPI_STATE.READY;
799
816
  this.emit("ready", this.state);
800
817
  return;
@@ -802,7 +819,7 @@ class MapiConnection extends events_1.EventEmitter {
802
819
  return this.login(resp.toString());
803
820
  }
804
821
  if (resp.isFileTransfer()) {
805
- console.log("file transfer");
822
+ //console.log("file transfer");
806
823
  let fhandler;
807
824
  const msg = resp.toString(MSG_FILETRANS.length).trim();
808
825
  let mode, offset, file;
@@ -839,11 +856,17 @@ class MapiConnection extends events_1.EventEmitter {
839
856
  resp.fileHandler.ready()) {
840
857
  // end of download
841
858
  const fileHandler = resp.fileHandler;
842
- fileHandler.writeChunk(resp.buff);
859
+ const buff = buffer_1.Buffer.concat(resp.chunks);
860
+ fileHandler.writeChunk(buff);
843
861
  // we do expect a final response from server
844
862
  this.queue.push(new Response({ fileHandler }));
845
863
  return resp.settle(fileHandler.close());
846
864
  }
865
+ if (resp.isQueryResponse()) {
866
+ const data = [];
867
+ resp.parseQueryResponse(resp.toString(), data);
868
+ resp.result.data = data;
869
+ }
847
870
  resp.settle();
848
871
  }
849
872
  }