UNPKG

@signalwire/js

Version:
151 lines (128 loc) 4.23 kB
import jwtDecode from 'jwt-decode' import { getLogger, HttpError, type UserOptions } from '@signalwire/core' import type { GetAddressResponse, GetAddressesParams, RegisterDeviceParams, UnregisterDeviceParams, RegisterDeviceResponse, GetAddressParams, GetAddressResult, GetAddressesResponse, GetAddressesResult, RegisterDeviceResult, GetSubscriberInfoResponse, GetSubscriberInfoResult, } from './interfaces' import { CreateHttpClient, createHttpClient } from './createHttpClient' import { buildPaginatedResult } from '../utils/paginatedResult' import { makeQueryParamsUrls } from '../utils/makeQueryParamsUrl' import { isGetAddressByIdParams, isGetAddressByNameParams, isGetAddressesResponse, } from './utils/typeGuard' import { HTTPClientContract } from './interfaces/httpClient' type JWTHeader = { ch?: string; typ?: string } // TODO: extends from a Base class to share from core export class HTTPClient implements HTTPClientContract { private httpClient: CreateHttpClient constructor(public options: UserOptions) { this.httpClient = createHttpClient({ baseUrl: `https://${this.httpHost}`, headers: { Authorization: `Bearer ${this.options.token}`, }, }) } get fetch(): CreateHttpClient { return this.httpClient } get httpHost() { let decodedJwt: JWTHeader = {} try { decodedJwt = jwtDecode<JWTHeader>(this.options.token, { header: true, }) } catch (e) { if (process.env.NODE_ENV !== 'production') { getLogger().debug('[JWTSession] error decoding the JWT') } } // Shouldn't this be other way around? const host = this.options.host || decodedJwt?.ch if (!host) { return 'fabric.signalwire.com' } return `fabric.${host.split('.').splice(1).join('.')}` } public async getAddress(params: GetAddressParams): Promise<GetAddressResult> { let path = '/api/fabric/addresses' if (isGetAddressByNameParams(params)) { path = `${path}?name=${params.name}` } else if (isGetAddressByIdParams(params)) { path = `${path}/${params.id}` } const { body } = await this.httpClient< GetAddressResponse | GetAddressesResponse >(path) if (isGetAddressesResponse(body)) { // FIXME until the server handles a index lookup by name we need to handle it as a search result if (!body.data[0]) throw new HttpError(404, 'Not Found') return body.data[0] } return body } public async getAddresses( params?: GetAddressesParams ): Promise<GetAddressesResult> { const { type, displayName, pageSize, sortBy, sortOrder } = params || {} let path = '/api/fabric/addresses' const queryParams = new URLSearchParams() if (type) { queryParams.append('type', type) } if (displayName) { queryParams.append('display_name', displayName) } if (pageSize) { queryParams.append('page_size', pageSize.toString()) } if (sortBy) { queryParams.append('sort_by', sortBy) } if (sortOrder) { queryParams.append('sort_order', sortOrder) } const queryUrl = makeQueryParamsUrls(path, queryParams) getLogger().debug(`[getAddresses] query URL ${queryUrl}`) const { body } = await this.httpClient<GetAddressesResponse>(queryUrl) return buildPaginatedResult(body, this.httpClient) } public async registerDevice( params: RegisterDeviceParams ): Promise<RegisterDeviceResult> { const { deviceType, deviceToken } = params const path = '/subscriber/devices' as const const { body } = await this.httpClient<RegisterDeviceResponse>(path, { method: 'POST', body: { device_type: deviceType, device_token: deviceToken, }, }) return body } public async unregisterDevice(params: UnregisterDeviceParams) { const { id } = params const path = `/subscriber/devices/${id}` as const await this.httpClient<void>(path, { method: 'DELETE', }) } public async getSubscriberInfo(): Promise<GetSubscriberInfoResult> { let path = '/api/fabric/subscriber/info' const { body } = await this.httpClient<GetSubscriberInfoResponse>(path) return body } }