UNPKG

@microsoft/teams.apps

Version:

<p> <a href="https://www.npmjs.com/package/@microsoft/teams.apps" target="_blank"> <img src="https://img.shields.io/npm/v/@microsoft/teams.apps/latest" /> </a> <a href="https://www.npmjs.com/package/@microsoft/teams.apps?activeTab=code

118 lines • 7.57 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.readField = readField; exports.isActivityShaped = isActivityShaped; exports.readEnvelopeActivity = readEnvelopeActivity; exports.isInvokeEnvelope = isInvokeEnvelope; exports.replyFrameBase = replyFrameBase; exports.buildInvokeReplyFrame = buildInvokeReplyFrame; exports.buildAckReplyFrame = buildAckReplyFrame; const types_1 = require("./types"); /** * Read a field from a Teams backend service-serialized object case-insensitively. Teams backend service may encode * frames with either camelCase or PascalCase depending on the hub protocol, so * every envelope read goes through this to stay robust to casing changes. */ function readField(obj, name) { if (obj == null || typeof obj !== 'object') return undefined; const record = obj; if (record[name] !== undefined) return record[name]; const cap = name.charAt(0).toUpperCase() + name.slice(1); return record[cap]; } /** * Whether a value is shaped like a Bot Framework {@link Activity}: a non-null, * non-array object carrying a string `type`. Used to reject a malformed * `payload` so it can't be returned as a bogus activity or suppress a valid * `activity` alias on the same envelope. */ function isActivityShaped(value) { return (value != null && typeof value === 'object' && !Array.isArray(value) && typeof value.type === 'string'); } /** * Extract the Bot Framework {@link Activity} from an inbound envelope. Teams backend service * carries it under `payload` (or `activity` on some builds). Each candidate is * validated with {@link isActivityShaped}, so a malformed `payload` falls * through to the `activity` alias instead of masking it. */ function readEnvelopeActivity(env) { const payload = readField(env, 'payload'); if (isActivityShaped(payload)) return payload; const activity = readField(env, 'activity'); if (isActivityShaped(activity)) return activity; return undefined; } /** * Whether an envelope represents an invoke activity — which expects a full * result over client results — versus a one-way activity, which expects a * post-handler delivery acknowledgement. * * Classification is by activity type only: an envelope is an invoke when its * `type` is `"invoke"`, falling back to the embedded activity's own `type` when * the envelope carries none. `ackRequired` is a delivery concern (whether the * caller wants a delivery ack) and deliberately does not affect this shape — an * invoke must still return its status/body even when an ack was also requested, * otherwise the invoke result would be silently dropped. */ function isInvokeEnvelope(env) { const type = String(readField(env, 'type') ?? '').toLowerCase(); if (type === 'invoke') return true; if (type) return false; // No envelope-level type: fall back to the embedded activity type. const activity = readEnvelopeActivity(env); return String(activity?.type ?? '').toLowerCase() === 'invoke'; } /** * Resolve the common reply-frame fields for an inbound envelope. * @param botKey the bot's client id, echoed back for Teams backend service routing/validation. */ function replyFrameBase(env, botKey) { return { envelopeId: readField(env, 'envelopeId'), botKey, recvAt: Date.now(), }; } /** * Build the reply frame for an invoke activity from the pipeline's processed * result. The invoke status/body are returned to Teams backend service over client results. */ function buildInvokeReplyFrame(base, response) { return { protocolVersion: types_1.SOCKET_MODE_PROTOCOL_VERSION, envelopeId: base.envelopeId, botKey: base.botKey, status: response.status ?? 200, body: response.body, recvAt: base.recvAt, ts: Date.now(), }; } /** * Build the post-handler acknowledgement frame for a one-way activity. Emitted * only after the handler pipeline has run, so it doubles as a "processed" * signal — any content reply the handler produced was already sent over HTTP. * * @param status delivery status to report; defaults to 200. Passing the * processed result's status lets a failed handler surface as a non-200 ack. */ function buildAckReplyFrame(base, status = 200) { return { protocolVersion: types_1.SOCKET_MODE_PROTOCOL_VERSION, envelopeId: base.envelopeId, botKey: base.botKey, status, recvAt: base.recvAt, ts: Date.now(), }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW52ZWxvcGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc29ja2V0LW1vZGUvZW52ZWxvcGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFhQSw4QkFNQztBQVFELDRDQU9DO0FBUUQsb0RBTUM7QUFjRCw0Q0FPQztBQWdCRCx3Q0FNQztBQWtCRCxzREFVQztBQVVELGdEQVNDO0FBeElELG1DQUlpQjtBQUVqQjs7OztHQUlHO0FBQ0gsU0FBZ0IsU0FBUyxDQUFjLEdBQVksRUFBRSxJQUFZO0lBQy9ELElBQUksR0FBRyxJQUFJLElBQUksSUFBSSxPQUFPLEdBQUcsS0FBSyxRQUFRO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFDN0QsTUFBTSxNQUFNLEdBQUcsR0FBOEIsQ0FBQztJQUM5QyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxTQUFTO1FBQUUsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFNLENBQUM7SUFDekQsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3pELE9BQU8sTUFBTSxDQUFDLEdBQUcsQ0FBa0IsQ0FBQztBQUN0QyxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixnQkFBZ0IsQ0FBQyxLQUFjO0lBQzdDLE9BQU8sQ0FDTCxLQUFLLElBQUksSUFBSTtRQUNiLE9BQU8sS0FBSyxLQUFLLFFBQVE7UUFDekIsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQztRQUNyQixPQUFRLEtBQTRCLENBQUMsSUFBSSxLQUFLLFFBQVEsQ0FDdkQsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQWdCLG9CQUFvQixDQUFDLEdBQTJCO0lBQzlELE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FBQyxHQUFHLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDMUMsSUFBSSxnQkFBZ0IsQ0FBQyxPQUFPLENBQUM7UUFBRSxPQUFPLE9BQU8sQ0FBQztJQUM5QyxNQUFNLFFBQVEsR0FBRyxTQUFTLENBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQzVDLElBQUksZ0JBQWdCLENBQUMsUUFBUSxDQUFDO1FBQUUsT0FBTyxRQUFRLENBQUM7SUFDaEQsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQztBQUVEOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsU0FBZ0IsZ0JBQWdCLENBQUMsR0FBMkI7SUFDMUQsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDaEUsSUFBSSxJQUFJLEtBQUssUUFBUTtRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ25DLElBQUksSUFBSTtRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ3ZCLG1FQUFtRTtJQUNuRSxNQUFNLFFBQVEsR0FBRyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMzQyxPQUFPLE1BQU0sQ0FBQyxRQUFRLEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxLQUFLLFFBQVEsQ0FBQztBQUNqRSxDQUFDO0FBWUQ7OztHQUdHO0FBQ0gsU0FBZ0IsY0FBYyxDQUFDLEdBQTJCLEVBQUUsTUFBZTtJQUN6RSxPQUFPO1FBQ0wsVUFBVSxFQUFFLFNBQVMsQ0FBUyxHQUFHLEVBQUUsWUFBWSxDQUFDO1FBQ2hELE1BQU07UUFDTixNQUFNLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTtLQUNuQixDQUFDO0FBQ0osQ0FBQztBQWNEOzs7R0FHRztBQUNILFNBQWdCLHFCQUFxQixDQUFDLElBQW9CLEVBQUUsUUFBcUI7SUFDL0UsT0FBTztRQUNMLGVBQWUsRUFBRSxvQ0FBNEI7UUFDN0MsVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVO1FBQzNCLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTTtRQUNuQixNQUFNLEVBQUUsUUFBUSxDQUFDLE1BQU0sSUFBSSxHQUFHO1FBQzlCLElBQUksRUFBRSxRQUFRLENBQUMsSUFBSTtRQUNuQixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07UUFDbkIsRUFBRSxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUU7S0FDZixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxTQUFnQixrQkFBa0IsQ0FBQyxJQUFvQixFQUFFLFNBQWlCLEdBQUc7SUFDM0UsT0FBTztRQUNMLGVBQWUsRUFBRSxvQ0FBNEI7UUFDN0MsVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVO1FBQzNCLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTTtRQUNuQixNQUFNO1FBQ04sTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO1FBQ25CLEVBQUUsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFO0tBQ2YsQ0FBQztBQUNKLENBQUMifQ==