ravendb
Version:
RavenDB client for Node.js
172 lines • 7.62 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SingleNodeBatchCommand = void 0;
const RavenCommand_js_1 = require("../../../Http/RavenCommand.js");
const index_js_1 = require("../../../Exceptions/index.js");
const PutAttachmentCommandData_js_1 = require("./PutAttachmentCommandData.js");
const HttpUtil_js_1 = require("../../../Utility/HttpUtil.js");
const Serializer_js_1 = require("../../../Mapping/Json/Serializer.js");
const RavenCommandResponsePipeline_js_1 = require("../../../Http/RavenCommandResponsePipeline.js");
const node_stream_1 = require("node:stream");
const TimeUtil_js_1 = require("../../../Utility/TimeUtil.js");
const PutAttachmentCommandHelper_js_1 = require("./PutAttachmentCommandHelper.js");
const TypeUtil_js_1 = require("../../../Utility/TypeUtil.js");
const ObjectUtil_js_1 = require("../../../Utility/ObjectUtil.js");
const StreamUtil_js_1 = require("../../../Utility/StreamUtil.js");
class SingleNodeBatchCommand extends RavenCommand_js_1.RavenCommand {
_supportsAtomicWrites;
_attachmentStreams;
_conventions;
_commands;
_options;
_mode;
constructor(conventions, commands, options = null, mode = null) {
super();
this._commands = commands;
this._conventions = conventions;
this._options = options;
this._mode = mode;
if (!conventions) {
(0, index_js_1.throwError)("InvalidArgumentException", "conventions cannot be null");
}
if (!commands) {
(0, index_js_1.throwError)("InvalidArgumentException", "commands cannot be null");
}
for (const command of this._commands) {
if (command instanceof PutAttachmentCommandData_js_1.PutAttachmentCommandData) {
const putAttachmentCommandData = command;
if (!this._attachmentStreams) {
this._attachmentStreams = new Set();
}
const { attStream } = putAttachmentCommandData;
if (this._attachmentStreams.has(attStream)) {
PutAttachmentCommandHelper_js_1.PutAttachmentCommandHelper.throwStreamWasAlreadyUsed();
}
else {
this._attachmentStreams.add(attStream);
}
}
}
}
async send(agent, requestOptions) {
const { body } = requestOptions;
if (body instanceof FormData) {
const attachments = [...this._attachmentStreams]
.map(attStream => {
return {
body: attStream,
headers: {
"Command-Type": "AttachmentStream"
}
};
});
for (let i = 0; i < attachments.length; i++) {
const part = attachments[i].body;
const payload = part instanceof node_stream_1.Readable ? await (0, StreamUtil_js_1.readToBuffer)(part) : part;
body.append("attachment_" + i, payload);
}
}
return super.send(agent, requestOptions);
}
createRequest(node) {
const uri = node.url + "/databases/" + node.database + "/bulk_docs";
const headers = HttpUtil_js_1.HeadersBuilder.create().typeAppJson().build();
if (TypeUtil_js_1.TypeUtil.isNullOrUndefined(this._supportsAtomicWrites)) {
this._supportsAtomicWrites = node.supportsAtomicClusterWrites;
}
const commandsArray = this._commands.map(x => {
const serialized = x.serialize(this._conventions);
if (!this._supportsAtomicWrites) {
delete serialized["OriginalChangeVector"];
}
return serialized;
});
const body = Serializer_js_1.JsonSerializer.getDefault().serialize({
Commands: commandsArray,
TransactionMode: this._mode === "ClusterWide" ? "ClusterWide" : undefined
});
const queryString = this._appendOptions();
const request = {
method: "POST",
uri: uri + queryString,
};
if (this._attachmentStreams && this._attachmentStreams.size > 0) {
// NOTE: payload is created in send method in async fashion - to support conversion from readable to buffers
// strip out content type, see: https://stackoverflow.com/questions/39280438/fetch-missing-boundary-in-multipart-form-data-post
if (request.headers && "Content-Type" in request.headers) {
const { "Content-Type": contentType, ...restHeaders } = request.headers;
request.headers = restHeaders;
}
const multipart = new FormData();
multipart.append("main", new Blob([body], { type: "application/json" }));
request.body = multipart;
}
else {
request.body = body;
request.headers = headers;
}
return request;
}
async setResponseAsync(bodyStream, fromCache) {
if (!bodyStream) {
(0, index_js_1.throwError)("InvalidOperationException", "Got null response from the server after doing a batch,"
+ " something is very wrong. Probably a garbled response.");
}
let body = null;
this.result = await RavenCommandResponsePipeline_js_1.RavenCommandResponsePipeline.create()
.collectBody(_ => body = _)
.parseJsonSync()
.objectKeysTransform({
defaultTransform: ObjectUtil_js_1.ObjectUtil.camel,
ignoreKeys: [/^@/],
ignorePaths: [/results\.\[\]\.modifiedDocument\./i],
})
.process(bodyStream);
return body;
}
_appendOptions() {
if (!this._options) {
return "?";
}
return SingleNodeBatchCommand.appendOptions(this._options.indexOptions, this._options.replicationOptions, this._options.shardedOptions);
}
static appendOptions(indexOptions, replicationOptions, shardedOptions) {
let result = "?";
if (replicationOptions) {
result += `&waitForReplicasTimeout=${TimeUtil_js_1.TimeUtil.millisToTimeSpan(replicationOptions.timeout)}`;
result += "&throwOnTimeoutInWaitForReplicas=" + (replicationOptions.throwOnTimeout ? "true" : "false");
result += "&numberOfReplicasToWaitFor=";
result += replicationOptions.majority ? "majority" : replicationOptions.replicas;
}
if (indexOptions) {
result += "&waitForIndexesTimeout=";
result += TimeUtil_js_1.TimeUtil.millisToTimeSpan(indexOptions.timeout);
if (indexOptions.throwOnTimeout) {
result += "&waitForIndexThrow=true";
}
else {
result += "&waitForIndexThrow=false";
}
if (indexOptions.indexes) {
for (const specificIndex of indexOptions.indexes) {
result += "&waitForSpecificIndex=" + encodeURIComponent(specificIndex);
}
}
}
if (shardedOptions) {
if (shardedOptions.batchBehavior !== "Default") {
result += "&shardedBatchBehavior=" + shardedOptions.batchBehavior;
}
}
return result;
}
get isReadRequest() {
return false;
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
dispose() {
// empty
}
}
exports.SingleNodeBatchCommand = SingleNodeBatchCommand;
//# sourceMappingURL=SingleNodeBatchCommand.js.map