UNPKG

@sqb/connect

Version:

Multi-dialect database connection framework written with TypeScript

100 lines (99 loc) 2.74 kB
import _debug from 'debug'; import { Readable } from 'stream'; const inspect = Symbol.for('nodejs.util.inspect.custom'); const debug = _debug('sqb:cursorstream'); export class CursorStream extends Readable { _cursor; _objectMode; _limit; _rowNum = -1; _eof = false; constructor(cursor, options) { super(options); this._cursor = cursor; this._objectMode = options?.objectMode; this._limit = options?.limit || Number.MAX_SAFE_INTEGER; this.on('end', () => { this.close().catch(() => false); }); cursor.once('close', () => this.emit('close')); cursor.on('error', err => this.emit('error', err)); } /** * Returns if stream is closed. */ get isClosed() { return this._cursor.isClosed; } /** * Closes stream and releases the cursor */ close() { this.pause(); this.unpipe(); return this._cursor.close(); } toString() { return '[object ' + Object.getPrototypeOf(this).constructor.name + ']'; } [inspect]() { return this.toString(); } _read() { if (this._rowNum >= this._limit) { this.pause(); this.unpipe(); this.emit('end'); return; } this._cursor .next() .then(row => { if (this._eof) return this.push(null); let buf = ''; if (this._rowNum < 0) { this._rowNum = 0; if (!this._objectMode) buf += '['; } if (!row) { this._eof = true; if (!this._objectMode) { buf += ']'; this.push(buf); } else this.push(null); return; } this._rowNum++; if (this._objectMode) this.push(row); else { if (this._rowNum > 1) buf += ','; this.push(buf + JSON.stringify(row)); } }) .catch(err => { /* istanbul ignore next */ if (typeof this.destroy == 'function') this.destroy(err); else this.emit('error', err); this.close().catch(() => 0); }); } emit(event, ...args) { try { if (event === 'error' && !this.listenerCount('error')) return false; return super.emit(event, ...args); } catch (ignored) { debug('emit-error', ignored); return false; } } }