@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
76 lines (75 loc) • 3.58 kB
TypeScript
import { Client as HttpClient, ILogger } from '@microsoft/teams.common';
import { NegotiateResult } from './types';
/**
* Dependencies for {@link negotiate}. Kept explicit so the call is unit-testable
* without a live Teams backend service endpoint.
*/
export type NegotiateDeps = {
/** Fully-resolved negotiate URL (`{base}/v3/websockets/connect`). */
readonly negotiateUrl: string;
/** The app's shared HTTP client. */
readonly client: HttpClient;
/** Acquire the Bot Framework access token, reusing the app's credentials. */
readonly getBotToken: () => Promise<string>;
/**
* Read the open, unexpired predecessor's exact ID after token acquisition.
* Omit or return `undefined`/`""` to omit the planned-refresh replacement header.
*/
readonly getConnectionIdToReplace?: () => string | undefined;
/**
* Abort the negotiate request after this many milliseconds so a hung endpoint
* can't leave the caller pending forever. Defaults to
* {@link DEFAULT_NEGOTIATE_TIMEOUT_MS}.
*/
readonly timeoutMs?: number;
readonly log?: ILogger;
};
/** Default negotiate request timeout — bounds a hung or misconfigured endpoint. */
export declare const DEFAULT_NEGOTIATE_TIMEOUT_MS = 15000;
/**
* Reject a negotiate URL that isn't HTTPS. The negotiate request carries a Bot
* Framework JWT in the `authorization` header; sending it over plaintext `http`
* would leak that token. A narrow exception is made for loopback hosts
* (`localhost`/`127.0.0.1`/`::1`) so local test endpoints still work.
*/
export declare function assertSecureNegotiateUrl(negotiateUrl: string): void;
/**
* Error thrown by {@link negotiate} when the service returns a non-2xx status.
* Carries the HTTP status and the parsed `Retry-After` (in milliseconds) when
* the service asked the caller to back off — typically on `429` or `503` — so
* the reconnect supervisor can honor it instead of using its own back-off.
* Authentication and authorization failures (`401`/`403`) are not retried;
* see {@link NegotiateError.isAuthError}.
*/
export declare class NegotiateError extends Error {
/** Service-requested delay before retrying, when supplied. */
readonly retryAfterMs?: number | undefined;
/**
* HTTP status returned by the Socket Mode negotiate endpoint. `undefined`
* when the error was constructed without a status.
*/
readonly statusCode?: number | undefined;
constructor(message: string,
/** Service-requested delay before retrying, when supplied. */
retryAfterMs?: number | undefined,
/**
* HTTP status returned by the Socket Mode negotiate endpoint. `undefined`
* when the error was constructed without a status.
*/
statusCode?: number | undefined);
/**
* `true` when negotiate was rejected with HTTP `401` or `403`. Retrying
* cannot fix these until the bot's credentials or Socket Mode access are
* corrected, so the SDK stops retrying on startup and reconnect.
*/
get isAuthError(): boolean;
}
/**
* Perform the Teams backend service Socket Mode handshake: `POST {negotiateUrl}` authenticated
* with a Bot Framework JWT minted from the bot's own credentials. Teams backend service returns
* the Azure SignalR `url` + `accessToken` to open the socket against.
*
* @throws {NegotiateError} if Teams backend service returns a non-2xx response.
* @throws if the bot token is missing (the app has no credentials configured).
*/
export declare function negotiate(deps: NegotiateDeps): Promise<NegotiateResult>;