@microsoft/teams.common
Version:
<p> <a href="https://www.npmjs.com/package/@microsoft/teams.common" target="_blank"> <img src="https://img.shields.io/npm/v/@microsoft/teams.common/latest" /> </a> <a href="https://www.npmjs.com/package/@microsoft/teams.common?activeTa
294 lines (292 loc) • 8.52 kB
JavaScript
import axios, { AxiosHeaders } from 'axios';
import { ConsoleLogger } from '../logging/index.mjs';
class Client {
token;
name;
options;
log;
http;
seq = 0;
_interceptors;
_middlewares;
constructor(options = {}) {
this.options = options;
this.name = options.name || "http";
this.token = options.token;
this.log = options.logger || new ConsoleLogger(this.name);
this._interceptors = /* @__PURE__ */ new Map();
this._middlewares = /* @__PURE__ */ new Map();
this.http = axios.create({
baseURL: options.baseUrl,
timeout: options.timeout,
headers: options.headers
});
for (const interceptor of options.interceptors || []) {
this.use(interceptor);
}
for (const middleware of options.middlewares || []) {
this.use(middleware);
}
}
get interceptors() {
return Array.from(this._interceptors.values()).map((i) => i.interceptor);
}
/**
* Registered HTTP middleware in execution order.
*/
get middlewares() {
return Array.from(this._middlewares.values());
}
async get(url, config) {
return this.invokeMiddleware({
config: { ...config, method: "get", url },
log: this.log
}, 0, "method");
}
async post(url, data, config) {
return this.invokeMiddleware({
config: { ...config, method: "post", url, data },
log: this.log
}, 0, "method");
}
async put(url, data, config) {
return this.invokeMiddleware({
config: { ...config, method: "put", url, data },
log: this.log
}, 0, "method");
}
async patch(url, data, config) {
return this.invokeMiddleware({
config: { ...config, method: "patch", url, data },
log: this.log
}, 0, "method");
}
async delete(url, config) {
return this.invokeMiddleware({
config: { ...config, method: "delete", url },
log: this.log
}, 0, "method");
}
async request(config) {
return this.invokeMiddleware({
config,
log: this.log
}, 0, "request");
}
use(handler) {
if (isMiddleware(handler)) {
return this.useMiddleware(handler);
}
return this.useInterceptor(handler);
}
/**
* Eject an interceptor
*/
eject(id) {
const registry = this._interceptors.get(id);
if (!registry) {
this._middlewares.delete(id);
return;
}
if (registry.requestId !== void 0) {
this.http.interceptors.request.eject(registry.requestId);
}
if (registry.responseId !== void 0) {
this.http.interceptors.response.eject(registry.responseId);
}
this._interceptors.delete(id);
}
/**
* Clear (Eject) all interceptors
*/
clear() {
for (const id of this._interceptors.keys()) {
this.eject(id);
}
this._middlewares.clear();
}
/**
* Create a copy of the client
*/
clone(options) {
const findUA = (h) => {
if (!h) return void 0;
const key = Object.keys(h).find((k) => k.toLowerCase() === "user-agent");
return key ? String(h[key]) : void 0;
};
const parentUA = findUA(this.options.headers);
const childUA = findUA(options?.headers);
const mergedUA = parentUA && childUA ? `${childUA} ${parentUA}` : childUA || parentUA;
const headers = {
...this.options.headers,
...options?.headers
};
if (mergedUA) {
for (const key of Object.keys(headers)) {
if (key.toLowerCase() === "user-agent") {
delete headers[key];
}
}
headers["User-Agent"] = mergedUA;
}
return new Client({
...this.options,
...options,
headers,
interceptors: [
...Array.from(this._interceptors.values()).map((i) => i.interceptor)
],
middlewares: [
...this.middlewares
]
});
}
async withConfig(config = {}) {
let token = config.token || this.token;
const requestHasAuthorization = hasAuthorizationHeader(config.headers);
if (config.token) {
delete config.token;
}
if (this.options.headers) {
config.headers = {
...this.options.headers,
...headersToObject(config.headers)
};
}
if (token && !requestHasAuthorization && !hasAuthorizationHeader(config.headers)) {
if (!config.headers) {
config.headers = {};
}
if (typeof token === "function") {
token = await token(config);
}
if (token && typeof token === "object") {
token = token.toString();
}
if (!token?.toString().trim()) {
return config;
}
config.headers["Authorization"] = `Bearer ${token}`;
}
return config;
}
useMiddleware(middleware) {
const id = ++this.seq;
this._middlewares.set(id, middleware);
return id;
}
/**
* axios >= 1.19 types its verb methods as `AxiosResponseResult<T, R, D, P>`, a conditional keyed on an unexported marker symbol.
* For any concrete `R` that conditional collapses to `R`, but TypeScript cannot prove that for an unconstrained generic, so each dispatch is asserted back to `Promise<R>`.
*/
async send(config, dispatch) {
const resolvedConfig = await this.withConfig(config);
if (dispatch === "request") {
return this.http.request(resolvedConfig);
}
const method = resolvedConfig.method?.toLowerCase();
const url = resolvedConfig.url;
if (url === void 0) {
return this.http.request(resolvedConfig);
}
const transportConfig = { ...resolvedConfig };
delete transportConfig.method;
delete transportConfig.url;
switch (method) {
// get/delete carry any request body on `config.data`, so the resolved
// config is forwarded as-is. (Stripping `data` here previously dropped
// GET/DELETE request bodies that callers passed through `config`.)
case "get":
return this.http.get(url, transportConfig);
case "delete":
return this.http.delete(url, transportConfig);
// post/put/patch take the body as a positional argument, so remove it
// from the forwarded config to avoid sending it in two places.
case "post": {
const { data, ...rest } = transportConfig;
return this.http.post(url, data, rest);
}
case "put": {
const { data, ...rest } = transportConfig;
return this.http.put(url, data, rest);
}
case "patch": {
const { data, ...rest } = transportConfig;
return this.http.patch(url, data, rest);
}
default:
return this.http.request(resolvedConfig);
}
}
useInterceptor(interceptor) {
const id = ++this.seq;
let requestId = void 0;
let responseId = void 0;
if (interceptor.request) {
requestId = this.http.interceptors.request.use(
/* istanbul ignore next */
(config) => {
return interceptor.request({ config, log: this.log });
},
/* istanbul ignore next */
(error) => {
if (!interceptor.error) return error;
return interceptor.error({ error, log: this.log });
}
);
}
if (interceptor.response) {
responseId = this.http.interceptors.response.use(
/* istanbul ignore next */
(res) => {
return interceptor.response({ res, log: this.log });
},
/* istanbul ignore next */
(error) => {
if (!interceptor.error) return error;
return interceptor.error({ error, log: this.log });
}
);
}
this._interceptors.set(id, {
requestId,
responseId,
interceptor
});
return id;
}
async invokeMiddleware(context, index, dispatch) {
const middleware = this.middlewares.at(index);
if (!middleware) {
return this.send(context.config, dispatch);
}
return middleware.invoke(
context,
() => this.invokeMiddleware(context, index + 1, dispatch)
);
}
}
function isMiddleware(handler) {
return typeof handler.invoke === "function";
}
function hasAuthorizationHeader(headers) {
if (!headers) {
return false;
}
if (headers instanceof AxiosHeaders) {
return !!headers.get("Authorization") || !!headers.get("authorization");
}
return Object.keys(headers).some((key) => key.toLowerCase() === "authorization");
}
function headersToObject(headers) {
if (!headers) {
return void 0;
}
if (headers instanceof AxiosHeaders) {
return headers.toJSON();
}
return headers;
}
export { Client };
//# sourceMappingURL=client.mjs.map
//# sourceMappingURL=client.mjs.map