UNPKG

@starsched/sdk

Version:

ABA clinic control and management service API SDK

190 lines (189 loc) 8.86 kB
import { HttpClient } from './http/client'; import { Accounts } from './services/account/index'; import { Appointments } from './services/appointment/index'; import { Authentication } from './services/authentication/index'; import { Companies } from './services/companies/index'; import { CompanyInvites } from './services/company-invites/index'; import { CompanyMembers } from './services/company-members/index'; import { CompanyPatients } from './services/company-patient/index'; import { CompaniesPlan } from './services/company-plan/index'; import { Companyprofessionals } from './services/company-professional/index'; import { Profiles } from './services/profiles/index'; export * from './services/account/protocols/company-sign-up-request'; export * from './services/account/protocols/finalize-company-sign-up-request.protocols'; export * from './services/account/protocols/get-company-sign-up-request.protocols'; export * from './services/account/protocols/request-company-sign-up.protocols'; export * from './services/appointment/protocols/appointment'; export * from './services/appointment/protocols/list-by-patient'; export * from './services/authentication/protocols/sign-in-with-email-and-password.protocols'; export * from './services/company-plan/protocols/company-plan'; export * from './services/company-plan/protocols/get-plan.protocols'; export * from './services/companies/protocols/company'; export * from './services/companies/protocols/create-company.protocols'; export * from './services/companies/protocols/get-my-companies.protocols'; export * from './services/companies/protocols/update-company.protocols'; export * from './services/company-invites/protocols/company-invite'; export * from './services/company-invites/protocols/create.protocols'; export * from './services/company-invites/protocols/delete.protocols'; export * from './services/company-invites/protocols/list.protocols'; export * from './services/company-invites/protocols/resend.protocols'; export * from './services/company-invites/protocols/update-role.protocols'; export * from './services/company-members/protocols/company-member'; export * from './services/company-members/protocols/list.protocols'; export * from './services/company-members/protocols/update-role.protocols'; export * from './services/company-members/protocols/update-access.protocols'; export * from './services/company-patient/protocols/company-patient'; export * from './services/company-patient/protocols/create.protocols'; export * from './services/company-patient/protocols/list.protocols'; export * from './services/company-professional/protocols/company-professional'; export * from './services/company-professional/protocols/list.protocols'; export * from './services/profiles/protocols/get-my-profile.protocols'; export * from './services/profiles/protocols/profile'; export class StarSchedAPI { options; isRefreshingAccessToken = false; failedRequestsQueue = []; accessToken = null; refreshToken = null; httpClient; authentication; profiles; accounts; companies; companiesPlan; companyMembers; companyProfessionals; companyInvites; companyPatients; appointments; constructor(options) { this.options = options; this.httpClient = new HttpClient({ baseURL: options.baseURL, requestInterceptors: [this.authenticatedRoutesInterceptor.bind(this)], responseInterceptors: [ this.refreshAuthenticationInterceptor.bind(this), this.storeAuthenticationOutputInterceptor.bind(this) ] }); this.authentication = new Authentication(this.httpClient); this.profiles = new Profiles(this.httpClient); this.accounts = new Accounts(this.httpClient); this.companies = new Companies(this.httpClient); this.companiesPlan = new CompaniesPlan(this.httpClient); this.companyMembers = new CompanyMembers(this.httpClient); this.companyProfessionals = new Companyprofessionals(this.httpClient); this.companyInvites = new CompanyInvites(this.httpClient); this.companyPatients = new CompanyPatients(this.httpClient); this.appointments = new Appointments(this.httpClient); } async authenticatedRoutesInterceptor(config) { if (this.options.logRequests) { console.log(`${config.method} ${config.url} ${this.accessToken ? '(with auth)' : ''}`); } const notAuthenticatedRoutes = [ '/v1/authentication/email', '/v1/authentication/refresh' ]; const routeRequiresAuthentication = !notAuthenticatedRoutes.includes(config.url); if (routeRequiresAuthentication) { if (this.options.authenticationStore) { const storedAuthentication = await this.options.authenticationStore.get(); if (storedAuthentication) { this.accessToken = storedAuthentication.access_token; this.refreshToken = storedAuthentication.refresh_token; } } if (this.accessToken) { config.headers.set('Authorization', `Bearer ${this.accessToken}`); } } return config; } async refreshAuthenticationInterceptor(config, response) { if (response.ok) { return response; } const errorResponse = response; const authenticationExpired = errorResponse.statusCode === 401 && errorResponse.body?.code === 'token.expired'; if (!authenticationExpired) { return response; } if (!this.refreshToken) { return response; } if (!this.isRefreshingAccessToken) { this.isRefreshingAccessToken = true; this.refreshAccessToken() .then((refreshTokenResponse) => { if (!refreshTokenResponse.ok) { throw refreshTokenResponse; } return refreshTokenResponse.body; }) .then(async (refreshTokenResponse) => { // biome-ignore lint/style/noNonNullAssertion: <explanation> const authentication = refreshTokenResponse; this.accessToken = authentication.access_token; this.refreshToken = authentication.refresh_token; if (this.options.authenticationStore) { await this.options.authenticationStore.store(authentication); } // biome-ignore lint/complexity/noForEach: <explanation> this.failedRequestsQueue.forEach((request) => { request.onSuccess(authentication.access_token); }); this.failedRequestsQueue = []; }) .catch(async (refreshTokenError) => { if (this.options.authenticationStore) { await this.options.authenticationStore.remove(); } // biome-ignore lint/complexity/noForEach: <explanation> this.failedRequestsQueue.forEach((request) => { request.onFailure(refreshTokenError); }); this.failedRequestsQueue = []; if (this.options.onLogout) { this.options.onLogout(); } }) .finally(() => { this.isRefreshingAccessToken = false; }); return new Promise((resolve, reject) => { this.failedRequestsQueue.push({ onSuccess: (updatedAccessToken) => { config.headers.set('Authorization', `Bearer ${updatedAccessToken}`); resolve(this.httpClient.request(config)); }, onFailure: reject }); }); } return errorResponse; } async storeAuthenticationOutputInterceptor(config, response) { if (!response.ok) { return response; } const authenticationRoutes = [ '/v1/authentication/email', '/v1/authentication/refresh' ]; const isAuthenticationResponse = authenticationRoutes.includes(config.url); if (isAuthenticationResponse) { const body = response.body; if (this.options.authenticationStore) { await this.options.authenticationStore.store(body); } this.accessToken = body.access_token; this.refreshToken = body.refresh_token; } return response; } async refreshAccessToken() { return this.httpClient.post('/v1/authentication/refresh', { refresh_token: this.refreshToken }); } }