collabSupport/scripts/lib/webexTokenClient.js
jmcqueen 860615cb89 Add bulk MPP web access enablement script for store desk phones.
Includes telephony pagination helpers and a token-based Webex client for dry-run/execute runs across Store locations.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-31 16:35:58 -04:00

57 lines
1.8 KiB
JavaScript

// scripts/lib/webexTokenClient.js
//
// Lightweight Webex REST client for one-off scripts that accept an
// external bearer token (personal admin token) instead of the bot's
// service-app OAuth flow.
import axios from 'axios';
const DEFAULT_BASE_URL = process.env.WEBEX_BASE_URL || 'https://webexapis.com/v1';
/**
* @param {string} accessToken
* @param {object} [opts]
* @param {string} [opts.baseUrl]
* @returns {{ request: Function, requestRaw: Function }}
*/
export function createTokenClient(accessToken, { baseUrl = DEFAULT_BASE_URL } = {}) {
const token = String(accessToken || '').trim();
if (!token) {
throw new Error('createTokenClient: access token is required');
}
const base = baseUrl.replace(/\/$/, '');
async function requestRaw(method, endpointOrUrl, data = null, params = null) {
const isAbsolute = /^https?:\/\//i.test(endpointOrUrl);
const url = isAbsolute ? endpointOrUrl : `${base}/${endpointOrUrl.replace(/^\//, '')}`;
const response = await axios({
method,
url,
headers: { Authorization: `Bearer ${token}` },
data,
params: isAbsolute ? undefined : params,
validateStatus: () => true,
});
if (response.status >= 200 && response.status < 300) {
return { data: response.data, headers: response.headers, status: response.status };
}
const err = new Error(
response.data?.message
|| response.data?.errors?.[0]?.description
|| `Webex API ${method} ${endpointOrUrl} failed with HTTP ${response.status}`,
);
err.response = response;
throw err;
}
async function request(method, endpointOrUrl, data = null, params = null) {
const { data: body } = await requestRaw(method, endpointOrUrl, data, params);
return body;
}
return { request, requestRaw };
}