UNPKG

@i3m/cloud-vault-client

Version:
110 lines (104 loc) 4.12 kB
import { OpenApiComponents } from '@i3m/cloud-vault-server/types/openapi' import { AxiosError } from 'axios' import { } from 'eventsource' export type VaultErrorData = { // eslint-disable-line @typescript-eslint/consistent-type-definitions 'not-initialized': any 'http-connection-error': { request: { method?: string url?: string headers?: { [header: string]: string } data?: any } response?: { status?: number headers?: { [header: string]: string } data?: any } } 'http-request-canceled': { request: { method?: string url?: string headers?: { [header: string]: string } data?: any } } 'no-uploaded-storage': any 'sse-connection-error': any 'quota-exceeded': string conflict: { localTimestamp?: number // timestamp in milliseconds elapsed from EPOCH when the latest storage has been downloaded by this client remoteTimestamp?: number // timestamp in milliseconds elapsed from EPOCH when the latest storage has been uploaded by any client } unauthorized: any 'invalid-credentials': any 'weak-password': string 'invalid-timestamp': any error: Error // unknown error generated as an instance of Error unknown: any // unknown error not as an instance of Error validation: { description?: string data?: any } } export type VaultErrorName = keyof VaultErrorData export type DataForError<T extends VaultErrorName> = VaultErrorData[T] export class VaultError<T extends VaultErrorName = VaultErrorName> extends Error { data: any message: T constructor (message: T, data: DataForError<T>, options?: ErrorOptions) constructor (message: string, data?: any, options?: ErrorOptions) { super(message, options) this.name = 'VaultError' this.data = data this.message = message as T } static from (error: unknown): VaultError { if (error instanceof VaultError) { return error } if (error instanceof Object && error.constructor.name === 'Event') { // SSE problem return new VaultError('sse-connection-error', error, { cause: 'Likely issues connecting to the events endpoint of the cloud vault server' }) } if (error instanceof AxiosError) { const err = error.response?.data as OpenApiComponents.Schemas.ApiError | OpenApiComponents.Schemas.ErrorUnauthorized | OpenApiComponents.Schemas.ErrorAlreadyRegistered | OpenApiComponents.Schemas.ErrorInvalidCredentials | OpenApiComponents.Schemas.ErrorNoStorage | OpenApiComponents.Schemas.ErrorNotRegistered | OpenApiComponents.Schemas.ErrorQuotaExceeded | OpenApiComponents.Schemas.ErrorUnauthorized switch (err.name) { case 'no-storage': return new VaultError('no-uploaded-storage', undefined) case 'invalid-credentials': return new VaultError('invalid-credentials', undefined) case 'invalid-timestamp': return new VaultError('invalid-timestamp', undefined) case 'quota-exceeded': return new VaultError('quota-exceeded', err.description) case 'unauthorized': case 'not-registered': return new VaultError('unauthorized', undefined) default: break } const vaultConnError: VaultErrorData['http-connection-error'] = { request: { method: error.config?.method?.toLocaleUpperCase(), url: error.config?.url, headers: error.config?.headers, data: error.config?.data }, response: { status: error.response?.status, headers: error.response?.headers as { [key: string]: string }, data: error.response?.data } } return new VaultError('http-connection-error', vaultConnError) } if (error instanceof Error) { const vaultError = new VaultError('error', error, { cause: error.cause }) vaultError.stack = error.stack return vaultError } return new VaultError('unknown', error) } } export function checkErrorType <T extends VaultErrorName> (err: VaultError, type: T): err is VaultError<T> { return err.message === type }