2021-08-28 10:52:47 +00:00
|
|
|
import { readdir, readFile } from "fs/promises";
|
|
|
|
import { join } from "path";
|
|
|
|
import * as yaml from "js-yaml";
|
2021-08-28 18:03:38 +00:00
|
|
|
import { plainToClass } from "class-transformer";
|
|
|
|
import { validate } from "class-validator";
|
2021-08-28 10:52:47 +00:00
|
|
|
|
2021-08-28 20:08:35 +00:00
|
|
|
import { init, Page, Exercise, Grader } from "./db/page";
|
|
|
|
import { Page as PageConfig, Exercise as ExerciseConfig, Grader as GraderConfig } from "./page";
|
2021-08-28 10:52:47 +00:00
|
|
|
|
2021-08-28 18:03:38 +00:00
|
|
|
// TODO: configure this thru cmdline or something later
|
|
|
|
let materials_dir = "../material";
|
|
|
|
let db_file = "test.db";
|
|
|
|
|
|
|
|
let db;
|
2021-08-28 18:19:21 +00:00
|
|
|
let SLUG_RE = /([A-Za-z\-\_]+)/;
|
2021-08-28 18:03:38 +00:00
|
|
|
|
|
|
|
async function loadPageIntoDb(name: string): Promise<void> {
|
2021-08-28 18:19:21 +00:00
|
|
|
let slug_match = name.match(SLUG_RE);
|
|
|
|
let slug = slug_match[0];
|
|
|
|
|
|
|
|
// if this slug has already been loaded into the database, don't do anything
|
|
|
|
let hasPage = await Page.count({ where: { slug }}) > 0;
|
|
|
|
if (hasPage) { return; }
|
2021-08-28 18:03:38 +00:00
|
|
|
|
|
|
|
let path = join(materials_dir, name);
|
|
|
|
let rawData = await readFile(path, { encoding: "utf8" });
|
|
|
|
let parsedData = yaml.load(rawData);
|
2021-08-28 18:19:21 +00:00
|
|
|
let page_cfg = plainToClass(PageConfig, parsedData);
|
|
|
|
await validate(page_cfg);
|
2021-08-28 10:52:47 +00:00
|
|
|
|
2021-08-28 18:19:21 +00:00
|
|
|
// save page
|
2021-08-28 18:03:38 +00:00
|
|
|
let page = new Page({
|
2021-08-28 18:19:21 +00:00
|
|
|
slug,
|
|
|
|
title: page_cfg.title,
|
2021-08-29 06:24:18 +00:00
|
|
|
type: page_cfg.type,
|
2021-08-28 20:08:35 +00:00
|
|
|
content: page_cfg.content,
|
2021-08-28 18:03:38 +00:00
|
|
|
});
|
|
|
|
await page.save();
|
2021-08-28 18:19:21 +00:00
|
|
|
|
|
|
|
// save exercises
|
|
|
|
async function loadExerciseIntoDb(ex_cfg: ExerciseConfig): Promise<void> {
|
2021-08-28 20:08:35 +00:00
|
|
|
let exercise = new Exercise({
|
|
|
|
page_slug: slug,
|
|
|
|
name: ex_cfg.name,
|
|
|
|
});
|
|
|
|
await exercise.save();
|
|
|
|
|
|
|
|
async function loadGraderIntoDb([language, grader_cfg]: [string, GraderConfig]): Promise<void> {
|
|
|
|
let grader = new Grader({
|
|
|
|
page_slug: slug,
|
|
|
|
exercise_name: ex_cfg.name,
|
|
|
|
language,
|
|
|
|
style: grader_cfg.style,
|
|
|
|
props: grader_cfg.props,
|
|
|
|
});
|
|
|
|
await grader.save();
|
|
|
|
}
|
|
|
|
|
2021-08-29 06:24:18 +00:00
|
|
|
let graders = ex_cfg.graders;
|
|
|
|
if (graders != null) {
|
|
|
|
await Promise.all(Object.entries(graders).map(loadGraderIntoDb));
|
|
|
|
}
|
2021-08-28 18:19:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let exercises = page_cfg.exercises;
|
|
|
|
if (exercises != null) {
|
2021-08-28 20:08:35 +00:00
|
|
|
await Promise.all(exercises.map(loadExerciseIntoDb));
|
2021-08-28 18:19:21 +00:00
|
|
|
}
|
2021-08-28 18:03:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async function main() {
|
|
|
|
db = await init(db_file);
|
2021-08-28 10:52:47 +00:00
|
|
|
|
2021-08-28 18:03:38 +00:00
|
|
|
// TODO: streaming version of readdir when the folder gets big
|
2021-08-28 10:52:47 +00:00
|
|
|
let names = await readdir(materials_dir);
|
|
|
|
|
|
|
|
await Promise.all(names
|
|
|
|
.filter(name => name.toLowerCase().endsWith(".yml"))
|
2021-08-28 18:03:38 +00:00
|
|
|
.map(loadPageIntoDb)
|
2021-08-28 10:52:47 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
main();
|