UNPKG

botframework-streaming

Version:

Streaming library for the Microsoft Bot Framework

151 lines 6.54 kB
"use strict"; /** * @module botframework-streaming */ /** * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PayloadAssembler = void 0; const subscribableStream_1 = require("../subscribableStream"); const payloads_1 = require("../payloads"); const contentStream_1 = require("../contentStream"); /** * Assembles payloads for streaming library. * * @internal */ class PayloadAssembler { /** * Initializes a new instance of the [PayloadAssembler](xref:botframework-streaming.PayloadAssembler) class. * * @param streamManager The [StreamManager](xref:botframework-streaming.StreamManager) managing the stream being assembled. * @param params Parameters for a streaming assembler. */ constructor(streamManager, params) { this.streamManager = streamManager; this._byteOrderMark = 0xfeff; this._utf = 'utf8'; if (params.header) { this.id = params.header.id; this.payloadType = params.header.payloadType; this.contentLength = params.header.payloadLength; this.end = params.header.end; } else { this.id = params.id; } if (!this.id) { throw Error('An ID must be supplied when creating an assembler.'); } this._onCompleted = params.onCompleted; } /** * Retrieves the assembler's payload as a stream. * * @returns A [SubscribableStream](xref:botframework-streaming.SubscribableStream) of the assembler's payload. */ getPayloadStream() { if (!this.stream) { this.stream = this.createPayloadStream(); } return this.stream; } /** * The action the assembler executes when new bytes are received on the incoming stream. * * @param header The stream's Header. * @param stream The incoming stream being assembled. * @param _contentLength The length of the stream, if finite. */ onReceive(header, stream, _contentLength) { this.end = header.end; if (header.payloadType === payloads_1.PayloadTypes.response || header.payloadType === payloads_1.PayloadTypes.request) { this.process(stream).then().catch(); } else if (header.end) { stream.end(); } } /** * Closes the assembler. */ close() { this.streamManager.closeStream(this.id); } /** * Creates a new [SubscribableStream](xref:botframework-streaming.SubscribableStream) instance. * * @returns The new stream ready for consumption. */ createPayloadStream() { return new subscribableStream_1.SubscribableStream(); } payloadFromJson(json) { return JSON.parse(json.charCodeAt(0) === this._byteOrderMark ? json.slice(1) : json); } stripBOM(input) { return input.charCodeAt(0) === this._byteOrderMark ? input.slice(1) : input; } process(stream) { return __awaiter(this, void 0, void 0, function* () { const streamData = stream.read(stream.length); if (!streamData) { return; } const streamDataAsString = streamData.toString(this._utf); if (this.payloadType === payloads_1.PayloadTypes.request) { yield this.processRequest(streamDataAsString); } else if (this.payloadType === payloads_1.PayloadTypes.response) { yield this.processResponse(streamDataAsString); } }); } processResponse(streamDataAsString) { return __awaiter(this, void 0, void 0, function* () { const responsePayload = this.payloadFromJson(this.stripBOM(streamDataAsString)); const receiveResponse = { streams: [], statusCode: responsePayload.statusCode }; yield this.processStreams(responsePayload, receiveResponse); }); } processRequest(streamDataAsString) { return __awaiter(this, void 0, void 0, function* () { const requestPayload = this.payloadFromJson(streamDataAsString); const receiveRequest = { streams: [], path: requestPayload.path, verb: requestPayload.verb }; yield this.processStreams(requestPayload, receiveRequest); }); } processStreams(responsePayload, receiveResponse) { var _a; return __awaiter(this, void 0, void 0, function* () { (_a = responsePayload.streams) === null || _a === void 0 ? void 0 : _a.forEach((responseStream) => { var _a; // There was a bug in how streams were handled. In .NET, the StreamDescription definiton mapped the // "type" JSON property to `contentType`, but in Typescript there was no mapping. This is a workaround // to resolve this inconsistency. // // .NET code: // https://github.com/microsoft/botbuilder-dotnet/blob/a79036ddf6625ec3fd68a6f7295886eb7831bc1c/libraries/Microsoft.Bot.Streaming/Payloads/Models/StreamDescription.cs#L28-L29 const contentType = (_a = responseStream.type) !== null && _a !== void 0 ? _a : responseStream.contentType; const contentAssembler = this.streamManager.getPayloadAssembler(responseStream.id); contentAssembler.payloadType = contentType; contentAssembler.contentLength = responseStream.length; receiveResponse.streams.push(new contentStream_1.ContentStream(responseStream.id, contentAssembler)); }); yield this._onCompleted(this.id, receiveResponse); }); } } exports.PayloadAssembler = PayloadAssembler; //# sourceMappingURL=payloadAssembler.js.map