@sethub/sdk
Version:
<div align="center"> <h1> SetHub SDK </h1>
204 lines (203 loc) • 10 kB
JavaScript
import { HttpClient } from './http/client';
import { sdkVersion } from './version';
import { ProjectActivity } from './services/activity/index';
import { Admin } from './services/admin/index';
import { ProjectApplication } from './services/applications/index';
import { Authentication } from './services/authentication/index';
import { ProjectInvitations } from './services/invitations/index';
import { ProjectMembers } from './services/members/index';
import { Projects } from './services/projects/index';
import { ProjectUpdateSets } from './services/update-sets/index';
import { Profiles } from './services/profiles';
export * from './services/activity/protocols/activity';
export * from './services/activity/protocols/list.protocol';
export * from './services/admin/protocols/get-overview.protocol';
export * from './services/applications/protocols/application';
export * from './services/applications/protocols/create.protocol';
export * from './services/applications/protocols/delete.protocol';
export * from './services/applications/protocols/get-details.protocol';
export * from './services/applications/protocols/list.protocol';
export * from './services/applications/protocols/update.protocol';
export * from './services/authentication/protocols/authentication';
export * from './services/authentication/protocols/sign-in-with-email-and-password.protocols';
export * from './services/authentication/protocols/sign-up.protocols';
export * from './services/invitations/protocols/invitation';
export * from './services/invitations/protocols/accept.protocol';
export * from './services/invitations/protocols/create.protocol';
export * from './services/invitations/protocols/delete.protocol';
export * from './services/invitations/protocols/list.protocol';
export * from './services/invitations/protocols/reject.protocol';
export * from './services/invitations/protocols/update-role.protocol';
export * from './services/members/protocols/member';
export * from './services/members/protocols/activate-access.protocol';
export * from './services/members/protocols/deactivate-access.protocol';
export * from './services/members/protocols/list-editors.protocol';
export * from './services/members/protocols/list.protocol';
export * from './services/members/protocols/update-role.protocol';
export * from './services/profiles/protocols/profile';
export * from './services/profiles/protocols/get-my.protocol';
export * from './services/projects/protocols/project';
export * from './services/projects/protocols/create.protocol';
export * from './services/projects/protocols/delete.protocol';
export * from './services/projects/protocols/get-details.protocol';
export * from './services/projects/protocols/list-mine.protocol';
export * from './services/projects/protocols/update.protocol';
export * from './services/update-sets/protocols/update-set';
export * from './services/update-sets/protocols/get-details.protocol';
export * from './services/update-sets/protocols/create.protocol';
export * from './services/update-sets/protocols/delete.protocol';
export * from './services/update-sets/protocols/list.protocol';
export * from './services/update-sets/protocols/update.protocol';
const AUTHENTICATION_ROUTES = [
'/v1/auth/login',
'/v1/auth/refresh',
];
export class SetHub {
constructor(options) {
this.options = options;
this.isRefreshingAccessToken = false;
this.failedRequestsQueue = [];
this.accessToken = null;
this.refreshToken = null;
this.httpClient = new HttpClient({
baseURL: options.baseURL,
requestInterceptors: [
this.setupMetaHeadersInterceptor.bind(this),
this.authenticatedRoutesInterceptor.bind(this)
],
responseInterceptors: [
this.refreshAuthenticationInterceptor.bind(this),
this.storeAuthenticationOutputInterceptor.bind(this)
]
});
this.admin = new Admin(this.httpClient);
this.authentication = new Authentication(this.httpClient);
this.projects = new Projects(this.httpClient);
this.projectActivity = new ProjectActivity(this.httpClient);
this.projectApplications = new ProjectApplication(this.httpClient);
this.projectInvitations = new ProjectInvitations(this.httpClient);
this.projectMembers = new ProjectMembers(this.httpClient);
this.projectUpdateSets = new ProjectUpdateSets(this.httpClient);
this.profiles = new Profiles(this.httpClient);
}
async setupMetaHeadersInterceptor(config) {
config.headers.set('X-Client-ID', String(this.options.client.id || "").trim() || 'unknown');
config.headers.set('X-Client-Name', String(this.options.client.name || "").trim() || 'unknown');
config.headers.set('X-Client-Version', String(this.options.client.version || "").trim() || 'unknown');
config.headers.set('X-SDK-Version', sdkVersion);
config.headers.set('X-Platform', String(this.options.platform.name || "").trim() || 'unknown');
config.headers.set('X-Platform-Version', String(this.options.platform.version || "").trim() || 'unknown');
return config;
}
async authenticatedRoutesInterceptor(config) {
const urlPathname = new URL(config.url, this.options.baseURL).pathname;
const routeRequiresAuthentication = !AUTHENTICATION_ROUTES.includes(urlPathname);
if (routeRequiresAuthentication) {
if (this.options.authenticationStore) {
const storedAuthentication = await this.options.authenticationStore.get();
if (storedAuthentication) {
this.accessToken = storedAuthentication.accessToken;
this.refreshToken = storedAuthentication.refreshToken;
}
}
if (this.accessToken) {
config.headers.set('Authorization', `Bearer ${this.accessToken}`);
}
}
if (this.options.logRequests) {
console.log(`${config.method} ${config.url} ${this.accessToken ? '(with auth)' : ''}`);
}
return config;
}
async refreshAuthenticationInterceptor(config, response) {
var _a, _b;
if (response.ok) {
if (this.options.logRequests) {
console.log(`${response.statusCode} ${JSON.stringify(response.body, null, 2)}`);
}
return response;
}
const errorResponse = response;
if (this.options.logRequests) {
console.log(`${errorResponse.statusCode} ${(_a = errorResponse.body) === null || _a === void 0 ? void 0 : _a.code}`);
}
const authenticationExpired = errorResponse.statusCode === 401
&& ((_b = errorResponse.body) === null || _b === void 0 ? void 0 : _b.code) === 'access-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) => {
this.accessToken = refreshTokenResponse.access_token;
this.refreshToken = refreshTokenResponse.refresh_token;
if (this.options.authenticationStore) {
await this.options.authenticationStore.store({
accessToken: refreshTokenResponse.access_token,
refreshToken: refreshTokenResponse.refresh_token
});
}
this.failedRequestsQueue.forEach((request) => {
request.onSuccess(refreshTokenResponse.access_token);
});
this.failedRequestsQueue = [];
})
.catch(async (refreshTokenError) => {
if (this.options.authenticationStore) {
await this.options.authenticationStore.remove();
}
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 isAuthenticationResponse = AUTHENTICATION_ROUTES.includes(config.url);
if (isAuthenticationResponse) {
const body = response.body;
if (this.options.authenticationStore) {
await this.options.authenticationStore.store({
accessToken: body.access_token,
refreshToken: body.refresh_token
});
}
this.accessToken = body.access_token;
this.refreshToken = body.refresh_token;
}
return response;
}
async refreshAccessToken() {
return this.httpClient.post('/v1/auth/refresh', { refresh_token: this.refreshToken });
}
}