10 files + 98 − 81 Inline Compare changes Side-by-side Inline Show whitespace changes Files 10 helpers/ArchiveHelper.ts +20 −20 Original line number Diff line number Diff line Loading @@ -8,26 +8,26 @@ import zlib from 'zlib'; class ArchiveHelper { private async explore(absoluteBasePath: string, rootPath: string, pack: tar.Pack) { for ( let file of await fs.promises.readdir(rootPath) ) { if ( file === 'output.tar' ) { continue; } file = path.join(rootPath, file); const stat = await fs.promises.stat(file); for ( const file of await fs.promises.readdir(rootPath) ) { let filename = file; if ( filename !== 'output.tar' ) { filename = path.join(rootPath, filename); const stat = await fs.promises.stat(filename); if ( stat.isDirectory() ) { await this.explore(absoluteBasePath, file, pack); continue; } await this.explore(absoluteBasePath, filename, pack); } else { const entry = pack.entry({ name: file.replace(absoluteBasePath, ''), name: filename.replace(absoluteBasePath, ''), size: stat.size }, (err) => { }, err => { if ( err ) { throw err; } }); const stream = fs.createReadStream(file); stream.pipe(entry); const readStream = fs.createReadStream(filename); readStream.pipe(entry); } } } } Loading Loading @@ -55,7 +55,7 @@ class ArchiveHelper { await this.compress(folderPath, tarDataStream); data = await (new Promise((resolve) => { data = await (new Promise(resolve => { tarDataStream.on('close', () => { resolve(data); }); Loading helpers/Dojo/SharedAssignmentHelper.ts +9 −10 Original line number Diff line number Diff line Loading @@ -8,10 +8,9 @@ import Json5FileValidator from '../Json5FileValidator'; class SharedAssignmentHelper { validateDescriptionFile(filePathOrStr: string, isFile: boolean = true, version: number = 1): { content: AssignmentFile | undefined, isValid: boolean, error: string | null } { switch ( version ) { case 1: if ( version === 1 ) { return Json5FileValidator.validateFile(AssignmentFile, filePathOrStr, isFile); default: } else { return { content: undefined, isValid: false, Loading @@ -24,7 +23,7 @@ class SharedAssignmentHelper { const pipelines = await SharedGitlabManager.getRepositoryPipelines(repositoryId, 'main'); if ( pipelines.length > 0 ) { const lastPipeline = pipelines[0]; if ( lastPipeline.status != GitlabPipelineStatus.SUCCESS ) { if ( lastPipeline.status !== GitlabPipelineStatus.SUCCESS ) { return { isPublishable: false, lastPipeline : lastPipeline, Loading helpers/LazyVal.ts +5 −2 Original line number Diff line number Diff line class LazyVal<T> { private val: T | undefined = undefined; private readonly valLoader: () => Promise<T> | T; constructor(private valLoader: () => Promise<T> | T) {} constructor(valLoader: () => Promise<T> | T) { this.valLoader = valLoader; } get value(): Promise<T> { return new Promise<T>((resolve) => { return new Promise<T>(resolve => { if ( this.val === undefined ) { Promise.resolve(this.valLoader()).then((value: T) => { this.val = value; Loading helpers/Toolbox.ts +3 −2 Original line number Diff line number Diff line Loading @@ -14,8 +14,9 @@ class Toolbox { const files = await fs.readdir(dirPath); await Promise.all(files.map(async file => { if ( (await fs.stat(dirPath + '/' + file)).isDirectory() ) { arrayOfFiles = await this.getAllFiles(dirPath + '/' + file, arrayOfFiles); const filePath = path.join(dirPath, file); if ( (await fs.stat(filePath)).isDirectory() ) { arrayOfFiles = await this.getAllFiles(filePath, arrayOfFiles); } else { arrayOfFiles.push(path.join(dirPath, file)); } Loading helpers/TypeScriptExtensions.ts +1 −3 Original line number Diff line number Diff line Loading @@ -64,9 +64,7 @@ function registerStringCapitalizeName() { function registerStringConvertWithEnvVars() { String.prototype.convertWithEnvVars = function (this: string): string { return this.replace(/\${?([a-zA-Z0-9_]+)}?/g, (_match: string, p1: string) => { return process.env[p1] || ''; }); return this.replace(/\${?([a-zA-Z0-9_]+)}?/g, (_match: string, p1: string) => process.env[p1] || ''); }; } Loading helpers/recursiveFilesStats/RecursiveFilesStats.ts +24 −23 Original line number Diff line number Diff line Loading @@ -51,33 +51,37 @@ class RecursiveFilesStats { return this.getFiles(`${ path.resolve(rootPath) }/`, rootPath, options, [], callback); } private async getFiles(absoluteBasePath: string, rootPath: string, options: RecursiveReaddirFilesOptions = {}, files: IFileDirStat[] = [], callback?: Callback): Promise<IFileDirStat[]> { const { ignored, include, exclude, filter } = options; private async getFilesDirsStat(rootPath: string, options: RecursiveReaddirFilesOptions): Promise<Array<IFileDirStat>> { const filesData = await fs.promises.readdir(rootPath); const fileDir: IFileDirStat[] = filesData.map((file) => ({ name: file, path: path.join(rootPath, file) })).filter((item) => { if ( include && include.test(item.path) ) { return filesData.map(file => ({ name: file, path: path.join(rootPath, file) })).filter(item => { if ( options.include && options.include.test(item.path) ) { return true; } if ( exclude && exclude.test(item.path) ) { if ( options.exclude && options.exclude.test(item.path) ) { return false; } if ( ignored ) { return !ignored.test(item.path); if ( options.ignored ) { return !options.ignored.test(item.path); } return true; }); } private async getFiles(absoluteBasePath: string, rootPath: string, options: RecursiveReaddirFilesOptions = {}, files: IFileDirStat[] = [], callback?: Callback): Promise<IFileDirStat[]> { const fileDir: Array<IFileDirStat> = await this.getFilesDirsStat(rootPath, options); if ( callback ) { fileDir.map(async (item: IFileDirStat) => { const stat = await this.getStat(item.path, absoluteBasePath, options); fileDir.forEach(item => { this.getStat(item.path, absoluteBasePath, options).then(stat => { if ( stat.isDirectory!() ) { await this.getFiles(absoluteBasePath, item.path, options, [], callback); this.getFiles(absoluteBasePath, item.path, options, [], callback).then(); } callback(item.path, stat); }); }); } else { await Promise.all(fileDir.map(async (item: IFileDirStat) => { const stat = await this.getStat(item.path, absoluteBasePath, options); Loading @@ -89,9 +93,9 @@ class RecursiveFilesStats { } })); } return files.filter((item) => { if ( filter && typeof filter === 'function' ) { return filter(item); return files.filter(item => { if ( options.filter && typeof options.filter === 'function' ) { return options.filter(item); } return true; }); Loading Loading @@ -124,10 +128,7 @@ class RecursiveFilesStats { delete stat.ctimeMs; delete stat.birthtimeMs; delete stat.atime; //delete stat.mtime; delete stat.ctime; //delete stat.birthtime; //delete stat.mode; } return stat; Loading logging/WinstonLogger.ts +12 −8 Original line number Diff line number Diff line Loading @@ -23,7 +23,11 @@ winston.addColors(colors); const format = winston.format.combine(winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston.format(info => ({ ...info, level: info.level.toUpperCase() }))(), SharedConfig.production ? winston.format.uncolorize() : winston.format.colorize({ all: true }), winston.format.prettyPrint(), winston.format.errors({ stack: true }), winston.format.align(), winston.format.printf((info) => `[${ info.timestamp }] (${ process.pid }) ${ info.level } ${ info.message } ${ info.metadata ? `\n${ JSON.stringify(info.metadata) }` : '' } ${ info.stack ? `\n${ info.stack }` : '' } `)); }))(), SharedConfig.production ? winston.format.uncolorize() : winston.format.colorize({ all: true }), winston.format.prettyPrint(), winston.format.errors({ stack: true }), winston.format.align(), winston.format.printf(info => { const metadata = info.metadata ? `\n${ JSON.stringify(info.metadata) }` : ''; const stack = info.stack ? `\n${ info.stack }` : ''; return `[${ info.timestamp }] (${ process.pid }) ${ info.level } ${ info.message } ${ metadata } ${ stack } `; })); const commonTransportOptions = { handleRejections: true, Loading Loading @@ -54,11 +58,11 @@ if ( SharedConfig.production ) { }) ]); } const logger = winston.createLogger({ const WinstonLogger = winston.createLogger({ levels, format, transports, exitOnError: false }); export default logger; export default WinstonLogger; types/Dojo/AssignmentFile.ts +1 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ import { z } from 'zod'; const AssignmentFile = z.object({ dojoAssignmentVersion: z.number(), version : z.number(), immutable : z.array(ImmutableFileDescriptor.transform(value => value as ImmutableFileDescriptor)), immutable : z.array(ImmutableFileDescriptor), result : z.object({ container: z.string(), volume : z.string().optional() Loading types/Dojo/DojoStatusCode.ts +18 −10 Original line number Diff line number Diff line Loading @@ -7,8 +7,16 @@ enum DojoStatusCode { ASSIGNMENT_PUBLISH_PIPELINE_FAILED = 201, ASSIGNMENT_CREATION_GITLAB_ERROR = 202, ASSIGNMENT_CREATION_INTERNAL_ERROR = 203, ASSIGNMENT_EXERCISE_NOT_RELATED = 204, ASSIGNMENT_NOT_PUBLISHED = 205, EXERCISE_CORRECTION_NOT_EXIST = 206, EXERCISE_CORRECTION_ALREADY_EXIST = 207, ASSIGNMENT_NAME_CONFLICT = 208, EXERCISE_CREATION_GITLAB_ERROR = 302, EXERCISE_CREATION_INTERNAL_ERROR = 303 EXERCISE_CREATION_INTERNAL_ERROR = 303, MAX_EXERCISE_PER_ASSIGNMENT_REACHED = 304, GITLAB_TEMPLATE_NOT_FOUND = 401, GITLAB_TEMPLATE_ACCESS_UNAUTHORIZED = 402, } Loading types/Gitlab/GitlabRoute.ts +5 −2 Original line number Diff line number Diff line const projectIdRoute = '/projects/{{id}}'; enum GitlabRoute { NOTIFICATION_SETTINGS = '/notification_settings', PROFILE_GET = '/user', USERS_GET = '/users', REPOSITORY_GET = '/projects/{{id}}', REPOSITORY_CREATE = '/projects', // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values REPOSITORY_DELETE = '/projects/{{id}}', // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values REPOSITORY_EDIT = '/projects/{{id}}', REPOSITORY_DELETE = projectIdRoute, // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values REPOSITORY_EDIT = projectIdRoute, REPOSITORY_FORK = '/projects/{{id}}/fork', REPOSITORY_MEMBER_ADD = '/projects/{{id}}/members', REPOSITORY_MEMBERS_GET = '/projects/{{id}}/members/all', Loading
helpers/ArchiveHelper.ts +20 −20 Original line number Diff line number Diff line Loading @@ -8,26 +8,26 @@ import zlib from 'zlib'; class ArchiveHelper { private async explore(absoluteBasePath: string, rootPath: string, pack: tar.Pack) { for ( let file of await fs.promises.readdir(rootPath) ) { if ( file === 'output.tar' ) { continue; } file = path.join(rootPath, file); const stat = await fs.promises.stat(file); for ( const file of await fs.promises.readdir(rootPath) ) { let filename = file; if ( filename !== 'output.tar' ) { filename = path.join(rootPath, filename); const stat = await fs.promises.stat(filename); if ( stat.isDirectory() ) { await this.explore(absoluteBasePath, file, pack); continue; } await this.explore(absoluteBasePath, filename, pack); } else { const entry = pack.entry({ name: file.replace(absoluteBasePath, ''), name: filename.replace(absoluteBasePath, ''), size: stat.size }, (err) => { }, err => { if ( err ) { throw err; } }); const stream = fs.createReadStream(file); stream.pipe(entry); const readStream = fs.createReadStream(filename); readStream.pipe(entry); } } } } Loading Loading @@ -55,7 +55,7 @@ class ArchiveHelper { await this.compress(folderPath, tarDataStream); data = await (new Promise((resolve) => { data = await (new Promise(resolve => { tarDataStream.on('close', () => { resolve(data); }); Loading
helpers/Dojo/SharedAssignmentHelper.ts +9 −10 Original line number Diff line number Diff line Loading @@ -8,10 +8,9 @@ import Json5FileValidator from '../Json5FileValidator'; class SharedAssignmentHelper { validateDescriptionFile(filePathOrStr: string, isFile: boolean = true, version: number = 1): { content: AssignmentFile | undefined, isValid: boolean, error: string | null } { switch ( version ) { case 1: if ( version === 1 ) { return Json5FileValidator.validateFile(AssignmentFile, filePathOrStr, isFile); default: } else { return { content: undefined, isValid: false, Loading @@ -24,7 +23,7 @@ class SharedAssignmentHelper { const pipelines = await SharedGitlabManager.getRepositoryPipelines(repositoryId, 'main'); if ( pipelines.length > 0 ) { const lastPipeline = pipelines[0]; if ( lastPipeline.status != GitlabPipelineStatus.SUCCESS ) { if ( lastPipeline.status !== GitlabPipelineStatus.SUCCESS ) { return { isPublishable: false, lastPipeline : lastPipeline, Loading
helpers/LazyVal.ts +5 −2 Original line number Diff line number Diff line class LazyVal<T> { private val: T | undefined = undefined; private readonly valLoader: () => Promise<T> | T; constructor(private valLoader: () => Promise<T> | T) {} constructor(valLoader: () => Promise<T> | T) { this.valLoader = valLoader; } get value(): Promise<T> { return new Promise<T>((resolve) => { return new Promise<T>(resolve => { if ( this.val === undefined ) { Promise.resolve(this.valLoader()).then((value: T) => { this.val = value; Loading
helpers/Toolbox.ts +3 −2 Original line number Diff line number Diff line Loading @@ -14,8 +14,9 @@ class Toolbox { const files = await fs.readdir(dirPath); await Promise.all(files.map(async file => { if ( (await fs.stat(dirPath + '/' + file)).isDirectory() ) { arrayOfFiles = await this.getAllFiles(dirPath + '/' + file, arrayOfFiles); const filePath = path.join(dirPath, file); if ( (await fs.stat(filePath)).isDirectory() ) { arrayOfFiles = await this.getAllFiles(filePath, arrayOfFiles); } else { arrayOfFiles.push(path.join(dirPath, file)); } Loading
helpers/TypeScriptExtensions.ts +1 −3 Original line number Diff line number Diff line Loading @@ -64,9 +64,7 @@ function registerStringCapitalizeName() { function registerStringConvertWithEnvVars() { String.prototype.convertWithEnvVars = function (this: string): string { return this.replace(/\${?([a-zA-Z0-9_]+)}?/g, (_match: string, p1: string) => { return process.env[p1] || ''; }); return this.replace(/\${?([a-zA-Z0-9_]+)}?/g, (_match: string, p1: string) => process.env[p1] || ''); }; } Loading
helpers/recursiveFilesStats/RecursiveFilesStats.ts +24 −23 Original line number Diff line number Diff line Loading @@ -51,33 +51,37 @@ class RecursiveFilesStats { return this.getFiles(`${ path.resolve(rootPath) }/`, rootPath, options, [], callback); } private async getFiles(absoluteBasePath: string, rootPath: string, options: RecursiveReaddirFilesOptions = {}, files: IFileDirStat[] = [], callback?: Callback): Promise<IFileDirStat[]> { const { ignored, include, exclude, filter } = options; private async getFilesDirsStat(rootPath: string, options: RecursiveReaddirFilesOptions): Promise<Array<IFileDirStat>> { const filesData = await fs.promises.readdir(rootPath); const fileDir: IFileDirStat[] = filesData.map((file) => ({ name: file, path: path.join(rootPath, file) })).filter((item) => { if ( include && include.test(item.path) ) { return filesData.map(file => ({ name: file, path: path.join(rootPath, file) })).filter(item => { if ( options.include && options.include.test(item.path) ) { return true; } if ( exclude && exclude.test(item.path) ) { if ( options.exclude && options.exclude.test(item.path) ) { return false; } if ( ignored ) { return !ignored.test(item.path); if ( options.ignored ) { return !options.ignored.test(item.path); } return true; }); } private async getFiles(absoluteBasePath: string, rootPath: string, options: RecursiveReaddirFilesOptions = {}, files: IFileDirStat[] = [], callback?: Callback): Promise<IFileDirStat[]> { const fileDir: Array<IFileDirStat> = await this.getFilesDirsStat(rootPath, options); if ( callback ) { fileDir.map(async (item: IFileDirStat) => { const stat = await this.getStat(item.path, absoluteBasePath, options); fileDir.forEach(item => { this.getStat(item.path, absoluteBasePath, options).then(stat => { if ( stat.isDirectory!() ) { await this.getFiles(absoluteBasePath, item.path, options, [], callback); this.getFiles(absoluteBasePath, item.path, options, [], callback).then(); } callback(item.path, stat); }); }); } else { await Promise.all(fileDir.map(async (item: IFileDirStat) => { const stat = await this.getStat(item.path, absoluteBasePath, options); Loading @@ -89,9 +93,9 @@ class RecursiveFilesStats { } })); } return files.filter((item) => { if ( filter && typeof filter === 'function' ) { return filter(item); return files.filter(item => { if ( options.filter && typeof options.filter === 'function' ) { return options.filter(item); } return true; }); Loading Loading @@ -124,10 +128,7 @@ class RecursiveFilesStats { delete stat.ctimeMs; delete stat.birthtimeMs; delete stat.atime; //delete stat.mtime; delete stat.ctime; //delete stat.birthtime; //delete stat.mode; } return stat; Loading
logging/WinstonLogger.ts +12 −8 Original line number Diff line number Diff line Loading @@ -23,7 +23,11 @@ winston.addColors(colors); const format = winston.format.combine(winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston.format(info => ({ ...info, level: info.level.toUpperCase() }))(), SharedConfig.production ? winston.format.uncolorize() : winston.format.colorize({ all: true }), winston.format.prettyPrint(), winston.format.errors({ stack: true }), winston.format.align(), winston.format.printf((info) => `[${ info.timestamp }] (${ process.pid }) ${ info.level } ${ info.message } ${ info.metadata ? `\n${ JSON.stringify(info.metadata) }` : '' } ${ info.stack ? `\n${ info.stack }` : '' } `)); }))(), SharedConfig.production ? winston.format.uncolorize() : winston.format.colorize({ all: true }), winston.format.prettyPrint(), winston.format.errors({ stack: true }), winston.format.align(), winston.format.printf(info => { const metadata = info.metadata ? `\n${ JSON.stringify(info.metadata) }` : ''; const stack = info.stack ? `\n${ info.stack }` : ''; return `[${ info.timestamp }] (${ process.pid }) ${ info.level } ${ info.message } ${ metadata } ${ stack } `; })); const commonTransportOptions = { handleRejections: true, Loading Loading @@ -54,11 +58,11 @@ if ( SharedConfig.production ) { }) ]); } const logger = winston.createLogger({ const WinstonLogger = winston.createLogger({ levels, format, transports, exitOnError: false }); export default logger; export default WinstonLogger;
types/Dojo/AssignmentFile.ts +1 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ import { z } from 'zod'; const AssignmentFile = z.object({ dojoAssignmentVersion: z.number(), version : z.number(), immutable : z.array(ImmutableFileDescriptor.transform(value => value as ImmutableFileDescriptor)), immutable : z.array(ImmutableFileDescriptor), result : z.object({ container: z.string(), volume : z.string().optional() Loading
types/Dojo/DojoStatusCode.ts +18 −10 Original line number Diff line number Diff line Loading @@ -7,8 +7,16 @@ enum DojoStatusCode { ASSIGNMENT_PUBLISH_PIPELINE_FAILED = 201, ASSIGNMENT_CREATION_GITLAB_ERROR = 202, ASSIGNMENT_CREATION_INTERNAL_ERROR = 203, ASSIGNMENT_EXERCISE_NOT_RELATED = 204, ASSIGNMENT_NOT_PUBLISHED = 205, EXERCISE_CORRECTION_NOT_EXIST = 206, EXERCISE_CORRECTION_ALREADY_EXIST = 207, ASSIGNMENT_NAME_CONFLICT = 208, EXERCISE_CREATION_GITLAB_ERROR = 302, EXERCISE_CREATION_INTERNAL_ERROR = 303 EXERCISE_CREATION_INTERNAL_ERROR = 303, MAX_EXERCISE_PER_ASSIGNMENT_REACHED = 304, GITLAB_TEMPLATE_NOT_FOUND = 401, GITLAB_TEMPLATE_ACCESS_UNAUTHORIZED = 402, } Loading
types/Gitlab/GitlabRoute.ts +5 −2 Original line number Diff line number Diff line const projectIdRoute = '/projects/{{id}}'; enum GitlabRoute { NOTIFICATION_SETTINGS = '/notification_settings', PROFILE_GET = '/user', USERS_GET = '/users', REPOSITORY_GET = '/projects/{{id}}', REPOSITORY_CREATE = '/projects', // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values REPOSITORY_DELETE = '/projects/{{id}}', // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values REPOSITORY_EDIT = '/projects/{{id}}', REPOSITORY_DELETE = projectIdRoute, // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values REPOSITORY_EDIT = projectIdRoute, REPOSITORY_FORK = '/projects/{{id}}/fork', REPOSITORY_MEMBER_ADD = '/projects/{{id}}/members', REPOSITORY_MEMBERS_GET = '/projects/{{id}}/members/all', Loading