import { init } from '../helpers' import { AuthTokenResponse, ServiceCollection, ServiceCollectionRequest } from '../models' import { GuardService } from './guard' /** * This service enables you to handle one authentication token per practice */ export class ApisPracticeManager { private practiceInstances = new Map() /** * The constructor * @param serviceCollReq the services to initialize. Only filled urls will get corresponding service to be initialized. * It will be used each time a new practices needs a `ServiceCollection` * @param getAuthTokenCbk the callback function used to get a new JWT token * @param useLocalStorage (default: false) if true store tokens into local storage (only for browsers) */ constructor( private serviceCollReq: ServiceCollectionRequest, private getAuthTokenCbk: (guard: GuardService, practiceUuid?: string) => Promise, private useLocalStorage = false ) { // The refreshInstance will be a single instance that is used to refresh the tokens of others this way it will not interfere with requests made by other services const newPracticeInstance = init(this.serviceCollReq, undefined, this.useLocalStorage) this.practiceInstances.set('refreshInstance', newPracticeInstance) } /** * This function is used to get a `ServiceCollection` associated to a practice. If missing, it will initialize a new `ServiceCollection`. * @param practiceUuid the uuid of the practice * @returns a promise holding a `ServiceCollection` */ public async get(practiceUuid?: string): Promise { const cacheKey = practiceUuid ?? 'none' const practiceInstance = this.practiceInstances.get(cacheKey) if (practiceInstance) return practiceInstance const newPracticeInstance = init(this.serviceCollReq, undefined, this.useLocalStorage) newPracticeInstance.apiService.setAuthRefreshFn(() => this.authTokenFunc(practiceUuid)) this.practiceInstances.set(cacheKey, newPracticeInstance) return newPracticeInstance } /** * Uses the refresh intance to fetch a new auth token for the given practice * @param practiceUuid the uuid of the practice or key of a specific instance * @returns a new authentication token */ public async authTokenFunc(practiceUuidOrInstanceName?: string): Promise { // fetch the refresh intance and refresh the token for another practice const newPracticeInstance = await this.get('refreshInstance'); if (newPracticeInstance.guardService) { console.log(`\x1b[36m[Auth] Refresh auth called (practiceUuid: ${practiceUuidOrInstanceName})\x1b[36m`) return await this.getAuthTokenCbk(newPracticeInstance.guardService, practiceUuidOrInstanceName) } else { throw Error('[Auth] Unable to refresh token guard service is undefined') } } }