UNPKG

@cityssm/consigno-cloud-api

Version:

An unofficial wrapper around the ConsignO Cloud API.

165 lines (130 loc) 4.21 kB
import Debug from 'debug' import { type ApiFunctionTypes, apiFunctions } from './api/api.js' import { authTokenRefreshThresholdMillis, authTokenTimeoutMillis } from './constants.js' import { DEBUG_NAMESPACE } from './debug.config.js' import { type ConsignoCloudErrorJson, ConsignoCloudError } from './error.js' const debug = Debug(`${DEBUG_NAMESPACE}:index`) export type ConsignoCloudAPIBaseUrl = `https://${string}/api/v1` export interface ConsignoCloudAPIConfig { apiKey: string apiSecret: string baseUrl: ConsignoCloudAPIBaseUrl } // eslint-disable-next-line sonarjs/class-name class _ConsignoCloudAPI { readonly #baseUrl: ConsignoCloudAPIBaseUrl readonly #apiKey: string readonly #apiSecret: string #loginAs: | { password: string userName: string } | undefined #authToken: string | undefined #authTokenLastUsedMillis = 0 constructor( apiConfig: ConsignoCloudAPIConfig, loginAs?: { password: string userName: string } ) { this.#baseUrl = apiConfig.baseUrl this.#apiKey = apiConfig.apiKey this.#apiSecret = apiConfig.apiSecret Object.assign(this, apiFunctions) if (loginAs !== undefined) { this.setLoginAs(loginAs.userName, loginAs.password) } } clearAuthToken(): this { this.#authToken = undefined this.#authTokenLastUsedMillis = 0 return this } get authToken(): string | undefined { return this.#authToken } get baseUrl(): `https://${string}/api/v1` { return this.#baseUrl } updateAuthTokenLastUsedMillis(): this { this.#authTokenLastUsedMillis = Date.now() return this } /** * Authenticate as a specific user. * Note that to use this mode, the platform must be authorized to use "loginAs" functionality. * @param userName - The username of the user to impersonate. * @param password - The third-party application password for the user. * @returns this */ setLoginAs(userName: string, password: string): this { this.#loginAs = { password, userName } this.clearAuthToken() return this } /** * Clear the impersonation user. * @returns this */ clearLoginAs(): this { this.#loginAs = undefined this.clearAuthToken() return this } async ensureActiveAuthToken(forceRefresh = false): Promise<this> { if ( !forceRefresh && this.#authToken !== undefined && Date.now() - this.#authTokenLastUsedMillis < authTokenTimeoutMillis - authTokenRefreshThresholdMillis ) { return this } const headers = { 'Content-Type': 'application/json' } if (this.#loginAs !== undefined) { headers['X-Client-Id'] = this.#apiKey headers['X-Client-Secret'] = this.#apiSecret } const endpointUrl = `${this.baseUrl}/auth/login` debug('Endpoint URL:', endpointUrl) const response = await fetch(endpointUrl, { headers, method: 'POST', body: JSON.stringify({ password: this.#loginAs === undefined ? this.#apiSecret : this.#loginAs.password, username: this.#loginAs === undefined ? this.#apiKey : this.#loginAs.userName }) }) if (!response.ok) { const errorJson = (await response.json()) as ConsignoCloudErrorJson throw new ConsignoCloudError(errorJson) } this.#authToken = response.headers.get('X-Auth-Token') ?? undefined return this } } export type ConsignoCloudAPIType = ApiFunctionTypes & InstanceType<typeof _ConsignoCloudAPI> // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion export const ConsignoCloudAPI = _ConsignoCloudAPI as unknown as new ( apiConfig: ConsignoCloudAPIConfig ) => ConsignoCloudAPIType export { ConsignoCloudError, ConsignoCloudErrorCodes } from './error.js' export type { CreateWorkflowAnchor, CreateWorkflowRequest } from './api/workflows/createWorkflow.js' export { default as lookups } from './lookups.js' export { default as utilities } from './utilities.js'