@graspful/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/create-brand.d.ts +8 -0
- package/dist/commands/create-brand.d.ts.map +1 -0
- package/dist/commands/create-brand.js +121 -0
- package/dist/commands/create-brand.js.map +1 -0
- package/dist/commands/create-course.d.ts +7 -0
- package/dist/commands/create-course.d.ts.map +1 -0
- package/dist/commands/create-course.js +98 -0
- package/dist/commands/create-course.js.map +1 -0
- package/dist/commands/describe.d.ts +3 -0
- package/dist/commands/describe.d.ts.map +1 -0
- package/dist/commands/describe.js +159 -0
- package/dist/commands/describe.js.map +1 -0
- package/dist/commands/fill-concept.d.ts +3 -0
- package/dist/commands/fill-concept.d.ts.map +1 -0
- package/dist/commands/fill-concept.js +116 -0
- package/dist/commands/fill-concept.js.map +1 -0
- package/dist/commands/import.d.ts +3 -0
- package/dist/commands/import.d.ts.map +1 -0
- package/dist/commands/import.js +116 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/login.d.ts +3 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +81 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/publish.d.ts +3 -0
- package/dist/commands/publish.d.ts.map +1 -0
- package/dist/commands/publish.js +26 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/review.d.ts +3 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/review.js +421 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/commands/validate.d.ts +3 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +154 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api-client.d.ts +10 -0
- package/dist/lib/api-client.d.ts.map +1 -0
- package/dist/lib/api-client.js +54 -0
- package/dist/lib/api-client.js.map +1 -0
- package/dist/lib/auth.d.ts +10 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/auth.js +81 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/output.d.ts +6 -0
- package/dist/lib/output.d.ts.map +1 -0
- package/dist/lib/output.js +30 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/quality-gate.d.ts +21 -0
- package/dist/quality-gate.d.ts.map +1 -0
- package/dist/quality-gate.js +16 -0
- package/dist/quality-gate.js.map +1 -0
- package/dist/schemas/academy-manifest.schema.d.ts +164 -0
- package/dist/schemas/academy-manifest.schema.d.ts.map +1 -0
- package/dist/schemas/academy-manifest.schema.js +70 -0
- package/dist/schemas/academy-manifest.schema.js.map +1 -0
- package/dist/schemas/brand-yaml.schema.d.ts +652 -0
- package/dist/schemas/brand-yaml.schema.d.ts.map +1 -0
- package/dist/schemas/brand-yaml.schema.js +97 -0
- package/dist/schemas/brand-yaml.schema.js.map +1 -0
- package/dist/schemas/course-yaml.schema.d.ts +1794 -0
- package/dist/schemas/course-yaml.schema.d.ts.map +1 -0
- package/dist/schemas/course-yaml.schema.js +161 -0
- package/dist/schemas/course-yaml.schema.js.map +1 -0
- package/dist/schemas/index.d.ts +4 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +20 -0
- package/dist/schemas/index.js.map +1 -0
- package/package.json +31 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
export declare function scaffoldBrand(niche: string, options: {
|
|
3
|
+
name?: string;
|
|
4
|
+
domain?: string;
|
|
5
|
+
orgSlug?: string;
|
|
6
|
+
}): string;
|
|
7
|
+
export declare function registerCreateBrandCommand(createCmd: Command): void;
|
|
8
|
+
//# sourceMappingURL=create-brand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-brand.d.ts","sourceRoot":"","sources":["../../src/commands/create-brand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAgDlH;AAED,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,OAAO,QA0B5D"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.scaffoldBrand = scaffoldBrand;
|
|
37
|
+
exports.registerCreateBrandCommand = registerCreateBrandCommand;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const yaml = __importStar(require("js-yaml"));
|
|
40
|
+
const output_1 = require("../lib/output");
|
|
41
|
+
const NICHE_PRESETS = {
|
|
42
|
+
education: { preset: 'blue', tagline: 'Learn smarter, not harder', headline: 'Master any subject with adaptive learning' },
|
|
43
|
+
healthcare: { preset: 'emerald', tagline: 'Training that saves lives', headline: 'Adaptive healthcare education for professionals' },
|
|
44
|
+
finance: { preset: 'slate', tagline: 'Build financial expertise', headline: 'Master finance with adaptive learning' },
|
|
45
|
+
tech: { preset: 'indigo', tagline: 'Level up your skills', headline: 'Adaptive tech training that meets you where you are' },
|
|
46
|
+
legal: { preset: 'amber', tagline: 'Know the law, pass the exam', headline: 'Adaptive legal education for exam success' },
|
|
47
|
+
default: { preset: 'blue', tagline: 'Learn adaptively', headline: 'Personalized learning that works' },
|
|
48
|
+
};
|
|
49
|
+
function scaffoldBrand(niche, options) {
|
|
50
|
+
const config = NICHE_PRESETS[niche] || NICHE_PRESETS['default'];
|
|
51
|
+
const slug = (options.name || niche).toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
52
|
+
const name = options.name || `${niche.charAt(0).toUpperCase() + niche.slice(1)} Academy`;
|
|
53
|
+
const domain = options.domain || `${slug}.graspful.com`;
|
|
54
|
+
return yaml.dump({
|
|
55
|
+
brand: {
|
|
56
|
+
id: slug,
|
|
57
|
+
name,
|
|
58
|
+
domain,
|
|
59
|
+
tagline: config.tagline,
|
|
60
|
+
orgSlug: options.orgSlug || 'TODO: your-org-slug',
|
|
61
|
+
},
|
|
62
|
+
theme: {
|
|
63
|
+
preset: config.preset,
|
|
64
|
+
radius: '0.5rem',
|
|
65
|
+
},
|
|
66
|
+
landing: {
|
|
67
|
+
hero: {
|
|
68
|
+
headline: config.headline,
|
|
69
|
+
subheadline: `${name} uses adaptive learning to help you master concepts faster.`,
|
|
70
|
+
ctaText: 'Start Learning',
|
|
71
|
+
},
|
|
72
|
+
features: {
|
|
73
|
+
heading: 'Why choose us?',
|
|
74
|
+
items: [
|
|
75
|
+
{ title: 'Adaptive Learning', description: 'Content adapts to your knowledge level', icon: 'brain' },
|
|
76
|
+
{ title: 'Spaced Repetition', description: 'Review at optimal intervals for lasting memory', icon: 'clock' },
|
|
77
|
+
{ title: 'Progress Tracking', description: 'See exactly where you stand', icon: 'chart' },
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
howItWorks: {
|
|
81
|
+
heading: 'How it works',
|
|
82
|
+
items: [
|
|
83
|
+
{ title: 'Take a diagnostic', description: 'We assess what you already know' },
|
|
84
|
+
{ title: 'Learn adaptively', description: 'Focus on gaps, skip what you know' },
|
|
85
|
+
{ title: 'Master the material', description: 'Prove mastery through progressive challenges' },
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
faq: [],
|
|
89
|
+
},
|
|
90
|
+
seo: {
|
|
91
|
+
title: `${name} — Adaptive Learning`,
|
|
92
|
+
description: config.tagline,
|
|
93
|
+
keywords: [niche, 'learning', 'adaptive', 'education'],
|
|
94
|
+
},
|
|
95
|
+
}, { lineWidth: 120, noRefs: true });
|
|
96
|
+
}
|
|
97
|
+
function registerCreateBrandCommand(createCmd) {
|
|
98
|
+
createCmd
|
|
99
|
+
.command('brand')
|
|
100
|
+
.description('Generate a brand YAML scaffold')
|
|
101
|
+
.requiredOption('--niche <niche>', 'Brand niche (education, healthcare, finance, tech, legal)')
|
|
102
|
+
.option('--name <name>', 'Brand name')
|
|
103
|
+
.option('--domain <domain>', 'Custom domain')
|
|
104
|
+
.option('--org <slug>', 'Organization slug')
|
|
105
|
+
.option('-o, --output <file>', 'Output file path (defaults to stdout)')
|
|
106
|
+
.action(async (opts) => {
|
|
107
|
+
const yamlContent = scaffoldBrand(opts.niche, {
|
|
108
|
+
name: opts.name,
|
|
109
|
+
domain: opts.domain,
|
|
110
|
+
orgSlug: opts.org,
|
|
111
|
+
});
|
|
112
|
+
if (opts.output) {
|
|
113
|
+
fs.writeFileSync(opts.output, yamlContent);
|
|
114
|
+
(0, output_1.output)({ file: opts.output, niche: opts.niche }, `Brand scaffold written to ${opts.output}`);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
console.log(yamlContent);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=create-brand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-brand.js","sourceRoot":"","sources":["../../src/commands/create-brand.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
export declare function scaffoldCourse(topic: string, options: {
|
|
3
|
+
hours?: number;
|
|
4
|
+
source?: string;
|
|
5
|
+
}): string;
|
|
6
|
+
export declare function registerCreateCourseCommand(program: Command): Command;
|
|
7
|
+
//# sourceMappingURL=create-course.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-course.d.ts","sourceRoot":"","sources":["../../src/commands/create-course.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CA4BlG;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,WAgC3D"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.scaffoldCourse = scaffoldCourse;
|
|
37
|
+
exports.registerCreateCourseCommand = registerCreateCourseCommand;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const yaml = __importStar(require("js-yaml"));
|
|
40
|
+
const output_1 = require("../lib/output");
|
|
41
|
+
function scaffoldCourse(topic, options) {
|
|
42
|
+
const slug = topic.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
43
|
+
return yaml.dump({
|
|
44
|
+
course: {
|
|
45
|
+
id: slug,
|
|
46
|
+
name: topic,
|
|
47
|
+
description: `Adaptive course on ${topic}`,
|
|
48
|
+
estimatedHours: options.hours || 10,
|
|
49
|
+
version: '2026.1',
|
|
50
|
+
sourceDocument: options.source || 'TODO: Add source document',
|
|
51
|
+
},
|
|
52
|
+
sections: [
|
|
53
|
+
{ id: 'foundations', name: 'Foundations', description: 'Core concepts' },
|
|
54
|
+
{ id: 'application', name: 'Application', description: 'Applied concepts' },
|
|
55
|
+
],
|
|
56
|
+
concepts: [
|
|
57
|
+
{
|
|
58
|
+
id: `${slug}-intro`,
|
|
59
|
+
name: `Introduction to ${topic}`,
|
|
60
|
+
section: 'foundations',
|
|
61
|
+
difficulty: 2,
|
|
62
|
+
estimatedMinutes: 15,
|
|
63
|
+
tags: ['foundational'],
|
|
64
|
+
prerequisites: [],
|
|
65
|
+
knowledgePoints: [],
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
}, { lineWidth: 120, noRefs: true });
|
|
69
|
+
}
|
|
70
|
+
function registerCreateCourseCommand(program) {
|
|
71
|
+
const create = program
|
|
72
|
+
.command('create')
|
|
73
|
+
.description('Scaffold new YAML files');
|
|
74
|
+
create
|
|
75
|
+
.command('course')
|
|
76
|
+
.description('Generate a course YAML scaffold')
|
|
77
|
+
.requiredOption('--topic <topic>', 'Course topic name')
|
|
78
|
+
.option('--hours <hours>', 'Estimated course hours', '10')
|
|
79
|
+
.option('--source <source>', 'Source document reference')
|
|
80
|
+
.option('-o, --output <file>', 'Output file path (defaults to stdout)')
|
|
81
|
+
.option('--scaffold-only', 'Generate scaffold without AI enrichment', true)
|
|
82
|
+
.action(async (opts) => {
|
|
83
|
+
const yamlContent = scaffoldCourse(opts.topic, {
|
|
84
|
+
hours: parseInt(opts.hours, 10),
|
|
85
|
+
source: opts.source,
|
|
86
|
+
});
|
|
87
|
+
if (opts.output) {
|
|
88
|
+
fs.writeFileSync(opts.output, yamlContent);
|
|
89
|
+
(0, output_1.output)({ file: opts.output, topic: opts.topic }, `Scaffold written to ${opts.output}`);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
// Output raw YAML to stdout (not wrapped in JSON even in json mode for piping)
|
|
93
|
+
console.log(yamlContent);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
return create;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=create-course.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-course.js","sourceRoot":"","sources":["../../src/commands/create-course.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,wCA4BC;AAED,kEAgCC;AAlED,uCAAyB;AACzB,8CAAgC;AAChC,0CAAoD;AAEpD,SAAgB,cAAc,CAAC,KAAa,EAAE,OAA4C;IACxF,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACnF,OAAO,IAAI,CAAC,IAAI,CAAC;QACf,MAAM,EAAE;YACN,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,KAAK;YACX,WAAW,EAAE,sBAAsB,KAAK,EAAE;YAC1C,cAAc,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;YACnC,OAAO,EAAE,QAAQ;YACjB,cAAc,EAAE,OAAO,CAAC,MAAM,IAAI,2BAA2B;SAC9D;QACD,QAAQ,EAAE;YACR,EAAE,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,eAAe,EAAE;YACxE,EAAE,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,kBAAkB,EAAE;SAC5E;QACD,QAAQ,EAAE;YACR;gBACE,EAAE,EAAE,GAAG,IAAI,QAAQ;gBACnB,IAAI,EAAE,mBAAmB,KAAK,EAAE;gBAChC,OAAO,EAAE,aAAa;gBACtB,UAAU,EAAE,CAAC;gBACb,gBAAgB,EAAE,EAAE;gBACpB,IAAI,EAAE,CAAC,cAAc,CAAC;gBACtB,aAAa,EAAE,EAAE;gBACjB,eAAe,EAAE,EAAE;aACpB;SACF;KACF,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AACvC,CAAC;AAED,SAAgB,2BAA2B,CAAC,OAAgB;IAC1D,MAAM,MAAM,GAAG,OAAO;SACnB,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,yBAAyB,CAAC,CAAC;IAE1C,MAAM;SACH,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,iCAAiC,CAAC;SAC9C,cAAc,CAAC,iBAAiB,EAAE,mBAAmB,CAAC;SACtD,MAAM,CAAC,iBAAiB,EAAE,wBAAwB,EAAE,IAAI,CAAC;SACzD,MAAM,CAAC,mBAAmB,EAAE,2BAA2B,CAAC;SACxD,MAAM,CAAC,qBAAqB,EAAE,uCAAuC,CAAC;SACtE,MAAM,CAAC,iBAAiB,EAAE,yCAAyC,EAAE,IAAI,CAAC;SAC1E,MAAM,CAAC,KAAK,EAAE,IAA+F,EAAE,EAAE;QAChH,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE;YAC7C,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;YAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;YAC3C,IAAA,eAAM,EACJ,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EACxC,uBAAuB,IAAI,CAAC,MAAM,EAAE,CACrC,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,+EAA+E;YAC/E,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe.d.ts","sourceRoot":"","sources":["../../src/commands/describe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwCpC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QA6GvD"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.registerDescribeCommand = registerDescribeCommand;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const yaml = __importStar(require("js-yaml"));
|
|
39
|
+
const schemas_1 = require("../schemas");
|
|
40
|
+
const output_1 = require("../lib/output");
|
|
41
|
+
function computeGraphDepth(concepts) {
|
|
42
|
+
const graph = new Map();
|
|
43
|
+
for (const c of concepts) {
|
|
44
|
+
graph.set(c.id, c.prerequisites);
|
|
45
|
+
}
|
|
46
|
+
const memo = new Map();
|
|
47
|
+
function depth(id, visited) {
|
|
48
|
+
if (memo.has(id))
|
|
49
|
+
return memo.get(id);
|
|
50
|
+
if (visited.has(id))
|
|
51
|
+
return 0; // cycle, avoid infinite loop
|
|
52
|
+
visited.add(id);
|
|
53
|
+
const prereqs = graph.get(id) ?? [];
|
|
54
|
+
let maxPrereqDepth = 0;
|
|
55
|
+
for (const prereq of prereqs) {
|
|
56
|
+
if (graph.has(prereq)) {
|
|
57
|
+
maxPrereqDepth = Math.max(maxPrereqDepth, depth(prereq, visited));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const d = maxPrereqDepth + 1;
|
|
61
|
+
memo.set(id, d);
|
|
62
|
+
return d;
|
|
63
|
+
}
|
|
64
|
+
let maxDepth = 0;
|
|
65
|
+
for (const c of concepts) {
|
|
66
|
+
maxDepth = Math.max(maxDepth, depth(c.id, new Set()));
|
|
67
|
+
}
|
|
68
|
+
return maxDepth;
|
|
69
|
+
}
|
|
70
|
+
function registerDescribeCommand(program) {
|
|
71
|
+
program
|
|
72
|
+
.command('describe <file>')
|
|
73
|
+
.description('Show course statistics and structure summary')
|
|
74
|
+
.action(async (file) => {
|
|
75
|
+
if (!fs.existsSync(file)) {
|
|
76
|
+
(0, output_1.outputError)(`File not found: ${file}`);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
let raw;
|
|
80
|
+
try {
|
|
81
|
+
raw = yaml.load(fs.readFileSync(file, 'utf-8'));
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
85
|
+
(0, output_1.outputError)(`YAML parse error: ${msg}`);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
const result = schemas_1.CourseYamlSchema.safeParse(raw);
|
|
89
|
+
if (!result.success) {
|
|
90
|
+
(0, output_1.outputError)(`Invalid course YAML: ${result.error.issues[0]?.message ?? 'unknown error'}`);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
const data = result.data;
|
|
94
|
+
const concepts = data.concepts;
|
|
95
|
+
const sections = data.sections;
|
|
96
|
+
const authoredConcepts = concepts.filter((c) => c.knowledgePoints.length > 0);
|
|
97
|
+
const stubConcepts = concepts.filter((c) => c.knowledgePoints.length === 0);
|
|
98
|
+
const kpCount = concepts.reduce((sum, c) => sum + c.knowledgePoints.length, 0);
|
|
99
|
+
const problemCount = concepts.reduce((sum, c) => sum + c.knowledgePoints.reduce((s, kp) => s + kp.problems.length, 0), 0);
|
|
100
|
+
const graphDepth = computeGraphDepth(concepts);
|
|
101
|
+
const conceptsWithoutKps = stubConcepts.map((c) => c.id);
|
|
102
|
+
const kpsWithoutProblems = [];
|
|
103
|
+
for (const c of concepts) {
|
|
104
|
+
for (const kp of c.knowledgePoints) {
|
|
105
|
+
if (kp.problems.length === 0) {
|
|
106
|
+
kpsWithoutProblems.push(`${c.id}/${kp.id}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Section breakdown
|
|
111
|
+
const sectionBreakdown = [];
|
|
112
|
+
if (sections.length > 0) {
|
|
113
|
+
for (const section of sections) {
|
|
114
|
+
const sectionConcepts = concepts.filter((c) => c.section === section.id);
|
|
115
|
+
const sKps = sectionConcepts.reduce((sum, c) => sum + c.knowledgePoints.length, 0);
|
|
116
|
+
const sProblems = sectionConcepts.reduce((sum, c) => sum + c.knowledgePoints.reduce((s, kp) => s + kp.problems.length, 0), 0);
|
|
117
|
+
sectionBreakdown.push({ section: section.id, concepts: sectionConcepts.length, kps: sKps, problems: sProblems });
|
|
118
|
+
}
|
|
119
|
+
// Concepts without a section
|
|
120
|
+
const unsectioned = concepts.filter((c) => !c.section);
|
|
121
|
+
if (unsectioned.length > 0) {
|
|
122
|
+
const uKps = unsectioned.reduce((sum, c) => sum + c.knowledgePoints.length, 0);
|
|
123
|
+
const uProblems = unsectioned.reduce((sum, c) => sum + c.knowledgePoints.reduce((s, kp) => s + kp.problems.length, 0), 0);
|
|
124
|
+
sectionBreakdown.push({ section: '(unsectioned)', concepts: unsectioned.length, kps: uKps, problems: uProblems });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const stats = {
|
|
128
|
+
courseName: data.course.name,
|
|
129
|
+
courseId: data.course.id,
|
|
130
|
+
version: data.course.version,
|
|
131
|
+
estimatedHours: data.course.estimatedHours,
|
|
132
|
+
concepts: concepts.length,
|
|
133
|
+
authoredConcepts: authoredConcepts.length,
|
|
134
|
+
stubConcepts: stubConcepts.length,
|
|
135
|
+
knowledgePoints: kpCount,
|
|
136
|
+
problems: problemCount,
|
|
137
|
+
graphDepth,
|
|
138
|
+
conceptsWithoutKps: conceptsWithoutKps.length,
|
|
139
|
+
kpsWithoutProblems: kpsWithoutProblems.length,
|
|
140
|
+
sections: sectionBreakdown,
|
|
141
|
+
};
|
|
142
|
+
const humanLines = [
|
|
143
|
+
`Course: "${data.course.name}" (v${data.course.version})`,
|
|
144
|
+
`Concepts: ${concepts.length} (${authoredConcepts.length} authored, ${stubConcepts.length} stubs)`,
|
|
145
|
+
`KPs: ${kpCount}, Problems: ${problemCount}`,
|
|
146
|
+
`Graph depth: ${graphDepth}`,
|
|
147
|
+
`Missing: ${conceptsWithoutKps.length} concepts need KPs, ${kpsWithoutProblems.length} KPs need problems`,
|
|
148
|
+
];
|
|
149
|
+
if (sectionBreakdown.length > 0) {
|
|
150
|
+
humanLines.push('');
|
|
151
|
+
humanLines.push('Sections:');
|
|
152
|
+
for (const s of sectionBreakdown) {
|
|
153
|
+
humanLines.push(` ${s.section}: ${s.concepts} concepts, ${s.kps} KPs, ${s.problems} problems`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
(0, output_1.output)(stats, humanLines.join('\n'));
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=describe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe.js","sourceRoot":"","sources":["../../src/commands/describe.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,0DA6GC;AApJD,uCAAyB;AACzB,8CAAgC;AAChC,wCAA8C;AAE9C,0CAAoD;AAEpD,SAAS,iBAAiB,CAAC,QAAgC;IACzD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC1C,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEvC,SAAS,KAAK,CAAC,EAAU,EAAE,OAAoB;QAC7C,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC;QACvC,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC,6BAA6B;QAC5D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEhB,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;QACpC,IAAI,cAAc,GAAG,CAAC,CAAC;QACvB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACtB,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;YACpE,CAAC;QACH,CAAC;QAED,MAAM,CAAC,GAAG,cAAc,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAChB,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAgB,uBAAuB,CAAC,OAAgB;IACtD,OAAO;SACJ,OAAO,CAAC,iBAAiB,CAAC;SAC1B,WAAW,CAAC,8CAA8C,CAAC;SAC3D,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;QAC7B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,IAAA,oBAAW,EAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;YACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,GAAY,CAAC;QACjB,IAAI,CAAC;YACH,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACvD,IAAA,oBAAW,EAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;YACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,0BAAgB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,IAAA,oBAAW,EAAC,wBAAwB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,eAAe,EAAE,CAAC,CAAC;YAC1F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAE/B,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC9E,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;QAE5E,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC/E,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAClC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,EAChF,CAAC,CACF,CAAC;QAEF,MAAM,UAAU,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAE/C,MAAM,kBAAkB,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACzD,MAAM,kBAAkB,GAAa,EAAE,CAAC;QACxC,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,eAAe,EAAE,CAAC;gBACnC,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC7B,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC9C,CAAC;YACH,CAAC;QACH,CAAC;QAED,oBAAoB;QACpB,MAAM,gBAAgB,GAAgF,EAAE,CAAC;QACzG,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAC/B,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,EAAE,CAAC,CAAC;gBACzE,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;gBACnF,MAAM,SAAS,GAAG,eAAe,CAAC,MAAM,CACtC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,EAChF,CAAC,CACF,CAAC;gBACF,gBAAgB,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,eAAe,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;YACnH,CAAC;YAED,6BAA6B;YAC7B,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YACvD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3B,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;gBAC/E,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAClC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,EAChF,CAAC,CACF,CAAC;gBACF,gBAAgB,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;YACpH,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GAAG;YACZ,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI;YAC5B,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE;YACxB,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO;YAC5B,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,cAAc;YAC1C,QAAQ,EAAE,QAAQ,CAAC,MAAM;YACzB,gBAAgB,EAAE,gBAAgB,CAAC,MAAM;YACzC,YAAY,EAAE,YAAY,CAAC,MAAM;YACjC,eAAe,EAAE,OAAO;YACxB,QAAQ,EAAE,YAAY;YACtB,UAAU;YACV,kBAAkB,EAAE,kBAAkB,CAAC,MAAM;YAC7C,kBAAkB,EAAE,kBAAkB,CAAC,MAAM;YAC7C,QAAQ,EAAE,gBAAgB;SAC3B,CAAC;QAEF,MAAM,UAAU,GAAG;YACjB,YAAY,IAAI,CAAC,MAAM,CAAC,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG;YACzD,aAAa,QAAQ,CAAC,MAAM,KAAK,gBAAgB,CAAC,MAAM,cAAc,YAAY,CAAC,MAAM,SAAS;YAClG,QAAQ,OAAO,eAAe,YAAY,EAAE;YAC5C,gBAAgB,UAAU,EAAE;YAC5B,YAAY,kBAAkB,CAAC,MAAM,uBAAuB,kBAAkB,CAAC,MAAM,oBAAoB;SAC1G,CAAC;QAEF,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpB,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC7B,KAAK,MAAM,CAAC,IAAI,gBAAgB,EAAE,CAAC;gBACjC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,QAAQ,cAAc,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,QAAQ,WAAW,CAAC,CAAC;YAClG,CAAC;QACH,CAAC;QAED,IAAA,eAAM,EAAC,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fill-concept.d.ts","sourceRoot":"","sources":["../../src/commands/fill-concept.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,WA2F1D"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.registerFillConceptCommand = registerFillConceptCommand;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const yaml = __importStar(require("js-yaml"));
|
|
39
|
+
const schemas_1 = require("../schemas");
|
|
40
|
+
const output_1 = require("../lib/output");
|
|
41
|
+
function registerFillConceptCommand(program) {
|
|
42
|
+
const fill = program
|
|
43
|
+
.command('fill')
|
|
44
|
+
.description('Fill in content stubs');
|
|
45
|
+
fill
|
|
46
|
+
.command('concept <file> <conceptId>')
|
|
47
|
+
.description('Add KP stubs to a specific concept')
|
|
48
|
+
.option('--kps <count>', 'Number of KP stubs to add', '2')
|
|
49
|
+
.option('--problems <count>', 'Number of problem stubs per KP', '3')
|
|
50
|
+
.action(async (file, conceptId, opts) => {
|
|
51
|
+
if (!fs.existsSync(file)) {
|
|
52
|
+
(0, output_1.outputError)(`File not found: ${file}`);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
const content = fs.readFileSync(file, 'utf-8');
|
|
56
|
+
let raw;
|
|
57
|
+
try {
|
|
58
|
+
raw = yaml.load(content);
|
|
59
|
+
}
|
|
60
|
+
catch (e) {
|
|
61
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
62
|
+
(0, output_1.outputError)(`YAML parse error: ${msg}`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
const parsed = schemas_1.CourseYamlSchema.safeParse(raw);
|
|
66
|
+
if (!parsed.success) {
|
|
67
|
+
(0, output_1.outputError)(`Invalid course YAML: ${parsed.error.issues[0]?.message ?? 'unknown error'}`);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
const data = parsed.data;
|
|
71
|
+
const concept = data.concepts.find((c) => c.id === conceptId);
|
|
72
|
+
if (!concept) {
|
|
73
|
+
(0, output_1.outputError)(`Concept "${conceptId}" not found. Available: ${data.concepts.map((c) => c.id).join(', ')}`);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
if (concept.knowledgePoints.length > 0) {
|
|
77
|
+
(0, output_1.output)({ conceptId, existingKps: concept.knowledgePoints.length, action: 'skipped' }, `Concept "${conceptId}" already has ${concept.knowledgePoints.length} KP(s). Use --force to overwrite (not yet implemented).`);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const kpCount = parseInt(opts.kps, 10);
|
|
81
|
+
const problemsPerKp = parseInt(opts.problems, 10);
|
|
82
|
+
const newKps = [];
|
|
83
|
+
for (let i = 1; i <= kpCount; i++) {
|
|
84
|
+
const problems = [];
|
|
85
|
+
for (let j = 1; j <= problemsPerKp; j++) {
|
|
86
|
+
problems.push({
|
|
87
|
+
id: `${conceptId}-kp${i}-p${j}`,
|
|
88
|
+
type: 'multiple_choice',
|
|
89
|
+
question: `TODO: Write question ${j} for ${conceptId} KP${i}`,
|
|
90
|
+
options: ['Option A', 'Option B', 'Option C', 'Option D'],
|
|
91
|
+
correct: 0,
|
|
92
|
+
explanation: 'TODO: Explain the correct answer',
|
|
93
|
+
difficulty: Math.min(j + 1, 5),
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
newKps.push({
|
|
97
|
+
id: `${conceptId}-kp${i}`,
|
|
98
|
+
instruction: `TODO: Write instruction for ${concept.name} — knowledge point ${i}`,
|
|
99
|
+
workedExample: `TODO: Write a worked example for ${concept.name} — knowledge point ${i}`,
|
|
100
|
+
problems,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
// Rebuild the raw object to preserve structure, then replace the concept's KPs
|
|
104
|
+
const rawObj = raw;
|
|
105
|
+
const concepts = rawObj['concepts'];
|
|
106
|
+
const targetConcept = concepts.find((c) => c['id'] === conceptId);
|
|
107
|
+
if (targetConcept) {
|
|
108
|
+
targetConcept['knowledgePoints'] = newKps;
|
|
109
|
+
}
|
|
110
|
+
const updatedYaml = yaml.dump(rawObj, { lineWidth: 120, noRefs: true });
|
|
111
|
+
fs.writeFileSync(file, updatedYaml);
|
|
112
|
+
(0, output_1.output)({ conceptId, kpsAdded: kpCount, problemsPerKp, file }, `Added ${kpCount} KP stub(s) with ${problemsPerKp} problem(s) each to "${conceptId}" in ${file}`);
|
|
113
|
+
});
|
|
114
|
+
return fill;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=fill-concept.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fill-concept.js","sourceRoot":"","sources":["../../src/commands/fill-concept.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../src/commands/import.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiBpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,QAgFrD"}
|