ravendb
Version:
RavenDB client for Node.js
133 lines • 4.84 kB
JavaScript
import { EventEmitter } from "node:events";
import { ObjectKeyCaseTransformStream } from "../Mapping/Json/Streams/ObjectKeyCaseTransformStream.js";
import { pipelineAsync } from "../Utility/StreamUtil.js";
import { Transform, pipeline } from "node:stream";
import { CollectResultStream, } from "../Mapping/Json/Streams/CollectResultStream.js";
import { throwError, getError } from "../Exceptions/index.js";
import { TypeUtil } from "../Utility/TypeUtil.js";
import { StringBuilder } from "../Utility/StringBuilder.js";
import { Buffer } from "node:buffer";
import { JsonlParser } from "../ext/stream-json/jsonl/Parser.js";
export class RavenCommandResponsePipeline extends EventEmitter {
_opts;
_body = new StringBuilder();
constructor() {
super();
this._opts = {};
}
static create() {
return new RavenCommandResponsePipeline();
}
parseJsonSync() {
this._opts.jsonSync = true;
return this;
}
/**
* @param type Type of object to extract from objects stream - use Raw to skip extraction.
* @param options
*/
parseJsonlAsync(valueExtractor, options = {}) {
const transforms = options?.transforms ?? [];
const extractItemTransform = new Transform({
objectMode: true,
transform(chunk, encoding, callback) {
const value = valueExtractor(chunk["value"]);
if (!value) {
return callback();
}
callback(null, { ...chunk, value });
}
});
transforms.unshift(extractItemTransform);
this._opts.jsonlAsync = {
transforms
};
return this;
}
collectBody(callback) {
this._opts.collectBody = callback || true;
return this;
}
objectKeysTransform(optsOrTransform) {
this._opts.streamKeyCaseTransform = !optsOrTransform || typeof optsOrTransform === "function"
? { defaultTransform: optsOrTransform }
: optsOrTransform;
return this;
}
stream(src, dst, callback) {
const streams = this._buildUp(src);
if (dst) {
streams.push(dst);
}
return pipeline(...streams, TypeUtil.NOOP);
}
_appendBody(s) {
this._body.append(s.toString());
}
_buildUp(src) {
if (!src) {
throwError("MappingError", "Body stream cannot be null.");
}
const opts = this._opts;
const streams = [src];
if (opts.collectBody) {
src.on("data", (chunk) => this._appendBody(chunk));
}
if (opts.jsonlAsync) {
streams.push(new JsonlParser());
if (opts.jsonlAsync.transforms) {
streams.push(...opts.jsonlAsync.transforms);
}
}
else if (opts.jsonSync) {
const bytesChunks = [];
const parseJsonSyncTransform = new Transform({
readableObjectMode: true,
transform(chunk, enc, callback) {
bytesChunks.push(chunk);
callback();
},
flush(callback) {
let str = null;
try {
str = Buffer.concat(bytesChunks).toString("utf8");
}
catch (err) {
callback(getError("InvalidDataException", `Failed to concat / decode server response`, err));
return;
}
try {
callback(null, JSON.parse(str));
}
catch (err) {
callback(getError("InvalidOperationException", `Error parsing response: '${str}'.`, err));
}
}
});
streams.push(parseJsonSyncTransform);
}
if (opts.streamKeyCaseTransform) {
const keyCaseOpts = Object.assign({}, opts.streamKeyCaseTransform, { handlePath: false });
streams.push(new ObjectKeyCaseTransformStream(keyCaseOpts));
}
return streams;
}
async process(src) {
const streams = this._buildUp(src);
const opts = this._opts;
const collectResult = new CollectResultStream();
streams.push(collectResult);
const resultPromise = collectResult.promise;
await pipelineAsync(...streams);
const result = await resultPromise;
if (opts.collectBody) {
const body = this._body.toString();
this.emit("body", body);
if (typeof opts.collectBody === "function") {
opts.collectBody(body);
}
}
return result;
}
}
//# sourceMappingURL=RavenCommandResponsePipeline.js.map