refactor(backend): Types
This commit is contained in:
parent
6ad7fbf208
commit
25f9eb2af2
31 changed files with 92 additions and 86 deletions
|
@ -1,16 +1,16 @@
|
|||
import { envVars, getEnvVar } from '../util/envVars.js';
|
||||
|
||||
type FrontendIdpConfig = {
|
||||
interface FrontendIdpConfig {
|
||||
authority: string;
|
||||
clientId: string;
|
||||
scope: string;
|
||||
responseType: string;
|
||||
};
|
||||
}
|
||||
|
||||
type FrontendAuthConfig = {
|
||||
interface FrontendAuthConfig {
|
||||
student: FrontendIdpConfig;
|
||||
teacher: FrontendIdpConfig;
|
||||
};
|
||||
}
|
||||
|
||||
const SCOPE = 'openid profile email';
|
||||
const RESPONSE_TYPE = 'code';
|
||||
|
|
|
@ -13,7 +13,7 @@ function getLearningObjectIdentifierFromRequest(req: Request): LearningObjectIde
|
|||
throw new BadRequestException('HRUID is required.');
|
||||
}
|
||||
return {
|
||||
hruid: req.params.hruid as string,
|
||||
hruid: req.params.hruid,
|
||||
language: (req.query.language || getEnvVar(envVars.FallbackLanguage)) as Language,
|
||||
version: parseInt(req.query.version as string),
|
||||
};
|
||||
|
@ -24,7 +24,7 @@ function getLearningPathIdentifierFromRequest(req: Request): LearningPathIdentif
|
|||
throw new BadRequestException('HRUID is required.');
|
||||
}
|
||||
return {
|
||||
hruid: req.params.hruid as string,
|
||||
hruid: req.params.hruid,
|
||||
language: (req.query.language as Language) || FALLBACK_LANG,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ export async function deleteTeacherHandler(req: Request, res: Response): Promise
|
|||
|
||||
export async function getTeacherClassHandler(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const username = req.params.username as string;
|
||||
const username = req.params.username;
|
||||
const full = req.query.full === 'true';
|
||||
|
||||
if (!username) {
|
||||
|
@ -104,7 +104,7 @@ export async function getTeacherClassHandler(req: Request, res: Response): Promi
|
|||
|
||||
export async function getTeacherStudentHandler(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const username = req.params.username as string;
|
||||
const username = req.params.username;
|
||||
const full = req.query.full === 'true';
|
||||
|
||||
if (!username) {
|
||||
|
@ -123,7 +123,7 @@ export async function getTeacherStudentHandler(req: Request, res: Response): Pro
|
|||
|
||||
export async function getTeacherQuestionHandler(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const username = req.params.username as string;
|
||||
const username = req.params.username;
|
||||
const full = req.query.full === 'true';
|
||||
|
||||
if (!username) {
|
||||
|
|
|
@ -24,7 +24,7 @@ export async function getAllUsersHandler<T extends User>(req: Request, res: Resp
|
|||
|
||||
export async function getUserHandler<T extends User>(req: Request, res: Response, service: UserService<T>): Promise<void> {
|
||||
try {
|
||||
const username = req.params.username as string;
|
||||
const username = req.params.username;
|
||||
|
||||
if (!username) {
|
||||
res.status(400).json({ error: 'Missing required field: username' });
|
||||
|
|
|
@ -58,7 +58,7 @@ export interface EducationalGoal {
|
|||
|
||||
export interface ReturnValue {
|
||||
callback_url: string;
|
||||
callback_schema: Record<string, any>;
|
||||
callback_schema: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface LearningObjectMetadata {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/**
|
||||
* Object with information about the user who is currently logged in.
|
||||
*/
|
||||
export type AuthenticationInfo = {
|
||||
export interface AuthenticationInfo {
|
||||
accountType: 'student' | 'teacher';
|
||||
username: string;
|
||||
name?: string;
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
email?: string;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { LearningObjectProvider } from './learning-object-provider.js';
|
||||
import { FilteredLearningObject, LearningObjectIdentifier, LearningPathIdentifier } from '../../interfaces/learning-content.js';
|
||||
import { getLearningObjectRepository, getLearningPathRepository } from '../../data/repositories.js';
|
||||
import { Language } from '../../entities/content/language.js';
|
||||
import { LearningObject } from '../../entities/content/learning-object.entity.js';
|
||||
import { getUrlStringForLearningObject } from '../../util/links.js';
|
||||
import processingService from './processing/processing-service.js';
|
||||
|
@ -44,7 +43,7 @@ function convertLearningObject(learningObject: LearningObject | null): FilteredL
|
|||
async function findLearningObjectEntityById(id: LearningObjectIdentifier): Promise<LearningObject | null> {
|
||||
const learningObjectRepo = getLearningObjectRepository();
|
||||
|
||||
return learningObjectRepo.findLatestByHruidAndLanguage(id.hruid, id.language as Language);
|
||||
return learningObjectRepo.findLatestByHruidAndLanguage(id.hruid, id.language);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,7 +64,7 @@ const databaseLearningObjectProvider: LearningObjectProvider = {
|
|||
async getLearningObjectHTML(id: LearningObjectIdentifier): Promise<string | null> {
|
||||
const learningObjectRepo = getLearningObjectRepository();
|
||||
|
||||
const learningObject = await learningObjectRepo.findLatestByHruidAndLanguage(id.hruid, id.language as Language);
|
||||
const learningObject = await learningObjectRepo.findLatestByHruidAndLanguage(id.hruid, id.language);
|
||||
if (!learningObject) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import { DwengoContentType } from '../content-type.js';
|
|||
import dwengoMarkedRenderer from './dwengo-marked-renderer.js';
|
||||
import { StringProcessor } from '../string-processor.js';
|
||||
import { ProcessingError } from '../processing-error.js';
|
||||
import { YAMLException } from 'js-yaml';
|
||||
|
||||
class MarkdownProcessor extends StringProcessor {
|
||||
constructor() {
|
||||
|
@ -19,8 +20,12 @@ class MarkdownProcessor extends StringProcessor {
|
|||
marked.use({ renderer: dwengoMarkedRenderer });
|
||||
const html = marked(mdText, { async: false });
|
||||
return this.replaceLinks(html); // Replace html image links path
|
||||
} catch (e: any) {
|
||||
throw new ProcessingError(e.message);
|
||||
} catch (e: unknown) {
|
||||
if (e instanceof YAMLException) {
|
||||
throw new ProcessingError(e.message);
|
||||
}
|
||||
|
||||
throw new ProcessingError('Unknown error while processing markdown: ' + e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ const EMBEDDED_LEARNING_OBJECT_PLACEHOLDER = /<learning-object hruid="([^"]+)" l
|
|||
const LEARNING_OBJECT_DOES_NOT_EXIST = "<div class='non-existing-learning-object' />";
|
||||
|
||||
class ProcessingService {
|
||||
private processors!: Map<DwengoContentType, Processor<any>>;
|
||||
private processors!: Map<DwengoContentType, Processor<DwengoContentType>>;
|
||||
|
||||
constructor() {
|
||||
const processors = [
|
||||
|
|
|
@ -25,7 +25,7 @@ async function getLearningObjectsForNodes(nodes: LearningPathNode[]): Promise<Ma
|
|||
version: node.version,
|
||||
language: node.language,
|
||||
})
|
||||
.then((learningObject) => <[LearningPathNode, FilteredLearningObject | null]>[node, learningObject])
|
||||
.then((learningObject) => ([node, learningObject] as [LearningPathNode, FilteredLearningObject | null]))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
|
@ -27,14 +27,14 @@ export class SqliteAutoincrementSubscriber implements EventSubscriber {
|
|||
|
||||
for (const prop of Object.values(args.meta.properties)) {
|
||||
const property = prop as EntityProperty<T>;
|
||||
if (property.primary && property.autoincrement && !(args.entity as Record<string, any>)[property.name]) {
|
||||
if (property.primary && property.autoincrement && !(args.entity as Record<string, unknown>)[property.name]) {
|
||||
// Obtain and increment sequence number of this entity.
|
||||
const propertyKey = args.meta.class.name + '.' + property.name;
|
||||
const nextSeqNumber = this.sequenceNumbersForEntityType.get(propertyKey) || 0;
|
||||
this.sequenceNumbersForEntityType.set(propertyKey, nextSeqNumber + 1);
|
||||
|
||||
// Set the property accordingly.
|
||||
(args.entity as Record<string, any>)[property.name] = nextSeqNumber + 1;
|
||||
(args.entity as Record<string, unknown>)[property.name] = nextSeqNumber + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import axios, { AxiosRequestConfig } from 'axios';
|
||||
import { getLogger, Logger } from '../logging/initalize.js';
|
||||
import { LearningObjectIdentifier } from '../interfaces/learning-content.js';
|
||||
|
||||
const logger: Logger = getLogger();
|
||||
|
||||
|
@ -17,8 +18,8 @@ export async function fetchWithLogging<T>(
|
|||
url: string,
|
||||
description: string,
|
||||
options?: {
|
||||
params?: Record<string, any>;
|
||||
query?: Record<string, any>;
|
||||
params?: Record<string, unknown> | LearningObjectIdentifier;
|
||||
query?: Record<string, unknown>;
|
||||
responseType?: 'json' | 'text';
|
||||
}
|
||||
): Promise<T | null> {
|
||||
|
@ -26,18 +27,21 @@ export async function fetchWithLogging<T>(
|
|||
const config: AxiosRequestConfig = options || {};
|
||||
const response = await axios.get<T>(url, config);
|
||||
return response.data;
|
||||
} catch (error: any) {
|
||||
if (error.response) {
|
||||
if (error.response.status === 404) {
|
||||
logger.debug(`❌ ERROR: ${description} not found (404) at "${url}".`);
|
||||
} catch (error: unknown) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
if (error.response) {
|
||||
if (error.response.status === 404) {
|
||||
logger.debug(`❌ ERROR: ${description} not found (404) at "${url}".`);
|
||||
} else {
|
||||
logger.debug(
|
||||
`❌ ERROR: Failed to fetch ${description}. Status: ${error.response.status} - ${error.response.statusText} (URL: "${url}")`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
logger.debug(
|
||||
`❌ ERROR: Failed to fetch ${description}. Status: ${error.response.status} - ${error.response.statusText} (URL: "${url}")`
|
||||
);
|
||||
logger.debug(`❌ ERROR: Network or unexpected error when fetching ${description}:`, error.message);
|
||||
}
|
||||
} else {
|
||||
logger.debug(`❌ ERROR: Network or unexpected error when fetching ${description}:`, error.message);
|
||||
}
|
||||
logger.error(`❌ ERROR: Unknown error while fetching ${description}.`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ const STUDENT_IDP_PREFIX = IDP_PREFIX + 'STUDENT_';
|
|||
const TEACHER_IDP_PREFIX = IDP_PREFIX + 'TEACHER_';
|
||||
const CORS_PREFIX = PREFIX + 'CORS_';
|
||||
|
||||
type EnvVar = { key: string; required?: boolean; defaultValue?: any };
|
||||
interface EnvVar { key: string; required?: boolean; defaultValue?: number | string | boolean }
|
||||
|
||||
export const envVars: { [key: string]: EnvVar } = {
|
||||
Port: { key: PREFIX + 'PORT', defaultValue: 3000 },
|
||||
|
@ -44,7 +44,7 @@ export function getEnvVar(envVar: EnvVar): string {
|
|||
} else if (envVar.required) {
|
||||
throw new Error(`Missing environment variable: ${envVar.key}`);
|
||||
} else {
|
||||
return envVar.defaultValue || '';
|
||||
return String(envVar.defaultValue) || '';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue