-
Notifications
You must be signed in to change notification settings - Fork 15
/
index.js
executable file
·97 lines (84 loc) · 3.12 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#! /usr/bin/env node
import fs from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { program } from 'commander';
import { parseLearningObjectives } from './lib/learning-objectives.js';
import { parseProject } from './lib/project.js';
import { parseTopic } from './lib/topic.js';
import { parsePart } from './lib/part.js';
import { parseChallenge } from './lib/challenge.js';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const pkg = JSON.parse(await fs.readFile(path.join(__dirname, 'package.json')));
const printError = (err, opts) => {
if (!err) {
return;
}
// Only print leaf nodes (erros may contain child errors)
if (!err.errors?.length) {
if (opts.debug) {
console.error(err);
} else {
console.error(err.message);
if (err.path) {
console.error(`└── ${err.path}`);
}
}
}
err.errors?.forEach(item => printError(
Object.assign(item, { path: item.path || err.path }),
opts,
));
};
const createHandler = fn => (dir, opts) => fn(dir, opts, pkg)
.then((result) => {
if (!result) {
return;
}
console.log(JSON.stringify(result, null, 2));
})
.catch((err) => {
printError(Object.assign(err, { path: err.path || dir }), opts);
process.exit(1);
});
program.version(pkg.version, '-V');
program.command('project')
.description('Parse a project')
.argument('<dir>', 'path to project directory')
.option('--repo <string>', 'Repository')
.option('--version <string>', 'Project version')
.option(
'--lo <string>',
'Path to directory containing data.yml with reference learning objectives',
)
.option('--debug', 'Show error stack traces')
.action(createHandler(parseProject));
program.command('topic')
.description('Parse a topic')
.argument('<dir>', 'path to topic directory')
.option('--repo <string>', 'Repository')
.option('--version <string>', 'Topic version')
.option('--debug', 'Show error stack traces')
.action(createHandler(parseTopic));
program.command('part')
.description('Parse a part')
.argument('<dir>', 'path to part directory')
.option('--repo <string>', 'Repository')
.option('--version <string>', 'Part version')
.option('--debug', 'Show error stack traces')
.action(createHandler(parsePart));
program.command('challenge')
.description('Parse a challenge')
.argument('<dir>', 'path to challenge directory')
.option('--repo <string>', 'Repository')
.option('--version <string>', 'Challenge version')
.option('--debug', 'Show error stack traces')
.action(createHandler(parseChallenge));
program.command('learning-objectives')
.description('Parse learning objectives')
.argument('<dir>', 'path to learning objectives directory') // note should there be a default here?
.option('--validate', 'Validate and throw errors for objectives missing intl or without title') // question: should we have repo and version ? why?
.option('--strict', 'With validate, only throw errors if objectives are missing in all languages')
.option('--debug', 'Show error stack traces')
.action(createHandler(parseLearningObjectives));
program.parse();