anonymous-student
Version:
Anonymous student is used to retrieve and save information from our website users.
134 lines (100 loc) • 3.67 kB
text/typescript
import { ITokenBasedSessionService } from '@studyportals/student-interfaces';
import { IStudent, StudentField } from '@studyportals/studentdomain';
import config from 'config';
import { LastStateChangeHash, StudentClient } from '../interfaces/student-client';
export class StudentAPIClient implements StudentClient {
constructor(private sessionService: ITokenBasedSessionService) {
}
private requestMap: Map<StudentField, Promise<any>> = new Map<StudentField, Promise<any>>();
private get fetch(): any {
return fetch;
}
public async getData(studentFields: StudentField[]): Promise<IStudent> {
const actions = this.getActiveDataRequestsAndFieldsToRequest(studentFields);
const activeDataRequests = actions.activeDataRequests;
const studentFieldsToRequest = actions.studentFieldsToRequest;
if (studentFieldsToRequest.length > 0) {
activeDataRequests.push(this.retrieveStudentFields(studentFieldsToRequest));
}
return this.mergeStudentDataResponses(await Promise.all(activeDataRequests));
}
private async patchData(body: object): Promise<LastStateChangeHash> {
const request = await fetch(`${config.STUDENTAPI_BASE_URL}/data`, {
method: 'PATCH',
headers: {
Authorization: await this.getAccessToken(),
},
body: JSON.stringify(body),
});
if (!request.ok) {
throw new Error('Failed to patch student data');
}
const responseBody = await request.json();
return responseBody[StudentField.LAST_STATE_CHANGE_HASH];
}
public setData(studentData: IStudent): Promise<LastStateChangeHash> {
return this.patchData(studentData);
}
public async addToCollection(type: StudentField, items: any[]): Promise<string> {
return this.patchData({
[`${type}_add`]: items,
});
}
public async removeFromCollection(type: StudentField, items: any[]): Promise<string> {
return this.patchData({
[`${type}_remove`]: items,
});
}
private getActiveDataRequestsAndFieldsToRequest(studentFields: StudentField[]): { activeDataRequests: Array<Promise<IStudent>>, studentFieldsToRequest: StudentField[] } {
const activeDataRequests: Array<Promise<IStudent>> = [];
const studentFieldsToRequest: StudentField[] = [];
studentFields.forEach((field) => {
const request = this.requestMap.get(field);
if (request) {
activeDataRequests.push(request);
return;
}
studentFieldsToRequest.push(field);
});
return {activeDataRequests, studentFieldsToRequest};
}
private async retrieveStudentFields(studentFields: StudentField[]): Promise<IStudent> {
const request = this.requestStudentData(studentFields);
studentFields.forEach((field) => {
this.requestMap.set(field, request);
});
const response = await request;
studentFields.forEach((field) => {
this.requestMap.delete(field);
});
return response;
}
private mergeStudentDataResponses(responses: IStudent[]): IStudent {
let data: IStudent = {};
responses.forEach((response) => {
data = {...data, ...response};
});
return data;
}
private async requestStudentData(studentFields: StudentField[]): Promise<IStudent> {
const request = await fetch(`${config.STUDENTAPI_BASE_URL}/data?scope=${studentFields.join(',')}`, {
headers: {
Authorization: await this.getAccessToken(),
},
});
if (!request.ok) {
throw new Error('Failed to retrieve data from StudentAPI');
}
const data = await request.json();
Object.keys(data).forEach((key) => {
if (data[key] === null) {
data[key] = undefined;
}
});
return data;
}
private async getAccessToken(): Promise<string> {
const session = await this.sessionService.getSession();
return session!.getAccessToken();
}
}