@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
141 lines • 10.1 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExpressAdapter = void 0;
const http_1 = __importDefault(require("http"));
const express_1 = __importDefault(require("express"));
const teams_common_1 = require("@microsoft/teams.common");
/**
* Express adapter for HttpServer
*
* Handles Express-specific HTTP framework concerns:
* - Express app creation and middleware setup
* - Route registration via Express routing
* - Request/response data extraction and sending
* - Server lifecycle management
*/
class ExpressAdapter {
// Expose Express methods for backwards compatibility
get;
post;
patch;
put;
delete;
route;
use;
express;
server;
logger;
onError;
constructor(serverOrApp, options) {
if (serverOrApp instanceof http_1.default.Server) {
// The adapter handles all requests on this server. Use the adapter's
// methods (get, post, use, etc.) to add routes. If you need your own
// Express app, pass it in instead and manage the server yourself.
this.express = (0, express_1.default)();
this.server = serverOrApp;
this.server.on('request', this.express);
}
else if (typeof serverOrApp === 'function') {
this.express = serverOrApp;
}
else {
this.express = (0, express_1.default)();
this.server = http_1.default.createServer(this.express);
}
this.logger = options?.logger ?? new teams_common_1.ConsoleLogger('ExpressAdapter');
this.onError = options?.onError;
// Bind Express methods
this.get = this.express.get.bind(this.express);
this.post = this.express.post.bind(this.express);
this.patch = this.express.patch.bind(this.express);
this.put = this.express.put.bind(this.express);
this.delete = this.express.delete.bind(this.express);
this.route = this.express.route.bind(this.express);
this.use = this.express.use.bind(this.express);
}
/**
* Register a route handler for a given HTTP method and path
*/
registerRoute(method, path, handler) {
if (method !== 'POST') {
throw new Error(`Unsupported HTTP method: ${method}`);
}
const expressHandler = async (req, res, next) => {
try {
const response = await handler({
body: req.body,
headers: req.headers
});
res.status(response.status).send(response.body);
}
catch (err) {
next(err);
}
};
this.express.post(path, express_1.default.json(), expressHandler);
}
/**
* Start the server listening on the specified port
*/
async start(port) {
const server = this.server;
if (!server) {
throw new Error('Cannot start: server lifecycle is managed externally. Call listen() on your Express app or http.Server directly.');
}
return new Promise((resolve, reject) => {
// Handle startup errors
server.once('error', (err) => {
if (this.onError) {
this.onError(err);
}
reject(err);
});
server.listen(port, () => {
this.logger.info(`listening on port ${port} 🚀`);
// Set up persistent error listener after startup
if (this.onError) {
server.on('error', this.onError);
}
resolve();
});
});
}
/**
* Serve static files from a directory.
*
* No CORS headers are set: Teams loads tab content inside an iframe (subject
* to the page's CSP `frame-ancestors` directive), not via cross-origin
* `fetch`/XHR, so a wildcard `Access-Control-Allow-Origin` was permissive
* without a corresponding use case. Callers that need cross-origin reads of
* the served assets should layer their own CORS middleware at the consuming
* route.
*/
serveStatic(path, directory) {
this.express.use(path, express_1.default.static(directory));
}
/**
* Stop the server and close all connections
*/
async stop() {
const server = this.server;
if (!server) {
throw new Error('Cannot stop: server lifecycle is managed externally. Call close() on your Express app or http.Server directly.');
}
return new Promise((resolve, reject) => {
server.close((err) => {
if (err) {
reject(err);
}
else {
this.logger.info('server stopped');
resolve();
}
});
});
}
}
exports.ExpressAdapter = ExpressAdapter;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhwcmVzcy1hZGFwdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2h0dHAvZXhwcmVzcy1hZGFwdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLGdEQUF3QjtBQUV4QixzREFBOEI7QUFFOUIsMERBQWlFO0FBSWpFOzs7Ozs7OztHQVFHO0FBQ0gsTUFBYSxjQUFjO0lBQ3pCLHFEQUFxRDtJQUM1QyxHQUFHLENBQTZCO0lBQ2hDLElBQUksQ0FBOEI7SUFDbEMsS0FBSyxDQUErQjtJQUNwQyxHQUFHLENBQTZCO0lBQ2hDLE1BQU0sQ0FBZ0M7SUFDdEMsS0FBSyxDQUErQjtJQUNwQyxHQUFHLENBQTZCO0lBRS9CLE9BQU8sQ0FBc0I7SUFDN0IsTUFBTSxDQUFlO0lBQ3JCLE1BQU0sQ0FBVTtJQUNoQixPQUFPLENBQXdCO0lBRXpDLFlBQVksV0FBK0MsRUFBRSxPQUE4RDtRQUN6SCxJQUFJLFdBQVcsWUFBWSxjQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDdkMscUVBQXFFO1lBQ3JFLHFFQUFxRTtZQUNyRSxrRUFBa0U7WUFDbEUsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFBLGlCQUFPLEdBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsTUFBTSxHQUFHLFdBQVcsQ0FBQztZQUMxQixJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzFDLENBQUM7YUFBTSxJQUFJLE9BQU8sV0FBVyxLQUFLLFVBQVUsRUFBRSxDQUFDO1lBQzdDLElBQUksQ0FBQyxPQUFPLEdBQUcsV0FBVyxDQUFDO1FBQzdCLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFBLGlCQUFPLEdBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsTUFBTSxHQUFHLGNBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2hE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