@graspful/cli 0.2.5 → 0.2.6

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.
@@ -1,8 +1,3 @@
1
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
2
  export declare function registerCreateBrandCommand(createCmd: Command): void;
8
3
  //# sourceMappingURL=create-brand.d.ts.map
@@ -1 +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;AAepC,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,CAsDlH;AAED,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,OAAO,QA2B5D"}
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;AAOpC,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,OAAO,QA4B5D"}
@@ -33,74 +33,12 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.scaffoldBrand = scaffoldBrand;
37
36
  exports.registerCreateBrandCommand = registerCreateBrandCommand;
38
37
  const fs = __importStar(require("fs"));
39
38
  const yaml = __importStar(require("js-yaml"));
39
+ const shared_1 = require("@graspful/shared");
40
40
  const output_1 = require("../lib/output");
41
41
  const analytics_1 = require("../lib/analytics");
42
- const NICHE_PRESETS = {
43
- education: { preset: 'blue', tagline: 'Learn smarter, not harder', headline: 'Master any subject with adaptive learning' },
44
- healthcare: { preset: 'emerald', tagline: 'Training that saves lives', headline: 'Adaptive healthcare education for professionals' },
45
- finance: { preset: 'slate', tagline: 'Build financial expertise', headline: 'Master finance with adaptive learning' },
46
- tech: { preset: 'indigo', tagline: 'Level up your skills', headline: 'Adaptive tech training that meets you where you are' },
47
- legal: { preset: 'amber', tagline: 'Know the law, pass the exam', headline: 'Adaptive legal education for exam success' },
48
- default: { preset: 'blue', tagline: 'Learn adaptively', headline: 'Personalized learning that works' },
49
- };
50
- function scaffoldBrand(niche, options) {
51
- const config = NICHE_PRESETS[niche] || NICHE_PRESETS['default'];
52
- const slug = (options.name || niche).toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
53
- const name = options.name || `${niche.charAt(0).toUpperCase() + niche.slice(1)} Academy`;
54
- const domain = options.domain || `${slug}.graspful.ai`;
55
- return yaml.dump({
56
- brand: {
57
- id: slug,
58
- name,
59
- domain,
60
- tagline: config.tagline,
61
- logoUrl: '/icon.svg',
62
- orgSlug: options.orgSlug || 'TODO: your-org-slug',
63
- },
64
- theme: {
65
- preset: config.preset,
66
- radius: '0.5rem',
67
- },
68
- landing: {
69
- hero: {
70
- headline: config.headline,
71
- subheadline: `${name} uses adaptive learning to help you master concepts faster.`,
72
- ctaText: 'Start Learning',
73
- },
74
- features: {
75
- heading: 'Why choose us?',
76
- items: [
77
- { title: 'Adaptive Learning', description: 'Content adapts to your knowledge level', icon: 'brain' },
78
- { title: 'Spaced Repetition', description: 'Review at optimal intervals for lasting memory', icon: 'clock' },
79
- { title: 'Progress Tracking', description: 'See exactly where you stand', icon: 'chart' },
80
- ],
81
- },
82
- howItWorks: {
83
- heading: 'How it works',
84
- items: [
85
- { title: 'Take a diagnostic', description: 'We assess what you already know' },
86
- { title: 'Learn adaptively', description: 'Focus on gaps, skip what you know' },
87
- { title: 'Master the material', description: 'Prove mastery through progressive challenges' },
88
- ],
89
- },
90
- faq: [],
91
- },
92
- pricing: {
93
- monthly: 0,
94
- currency: 'usd',
95
- trialDays: 0,
96
- },
97
- seo: {
98
- title: `${name} — Adaptive Learning`,
99
- description: config.tagline,
100
- keywords: [niche, 'learning', 'adaptive', 'education'],
101
- },
102
- }, { lineWidth: 120, noRefs: true });
103
- }
104
42
  function registerCreateBrandCommand(createCmd) {
105
43
  createCmd
106
44
  .command('brand')
@@ -111,11 +49,12 @@ function registerCreateBrandCommand(createCmd) {
111
49
  .option('--org <slug>', 'Organization slug')
112
50
  .option('-o, --output <file>', 'Output file path (defaults to stdout)')
113
51
  .action(async (opts) => {
114
- const yamlContent = scaffoldBrand(opts.niche, {
52
+ const obj = (0, shared_1.scaffoldBrandObject)(opts.niche, {
115
53
  name: opts.name,
116
54
  domain: opts.domain,
117
55
  orgSlug: opts.org,
118
56
  });
57
+ const yamlContent = yaml.dump(obj, { lineWidth: 120, noRefs: true });
119
58
  (0, analytics_1.cliCapture)('brand scaffolded', { niche: opts.niche });
120
59
  if (opts.output) {
121
60
  fs.writeFileSync(opts.output, yamlContent);
@@ -1 +1 @@
1
- {"version":3,"file":"create-brand.js","sourceRoot":"","sources":["../../src/commands/create-brand.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAeA,sCAsDC;AAED,gEA2BC;AAjGD,uCAAyB;AACzB,8CAAgC;AAChC,0CAAuC;AACvC,gDAA8C;AAE9C,MAAM,aAAa,GAA0E;IAC3F,SAAS,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,2BAA2B,EAAE,QAAQ,EAAE,2CAA2C,EAAE;IAC1H,UAAU,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,2BAA2B,EAAE,QAAQ,EAAE,iDAAiD,EAAE;IACpI,OAAO,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,2BAA2B,EAAE,QAAQ,EAAE,uCAAuC,EAAE;IACrH,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,sBAAsB,EAAE,QAAQ,EAAE,qDAAqD,EAAE;IAC5H,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,6BAA6B,EAAE,QAAQ,EAAE,2CAA2C,EAAE;IACzH,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,kCAAkC,EAAE;CACvG,CAAC;AAEF,SAAgB,aAAa,CAAC,KAAa,EAAE,OAA6D;IACxG,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,aAAa,CAAC,SAAS,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACrG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC;IACzF,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,GAAG,IAAI,cAAc,CAAC;IAEvD,OAAO,IAAI,CAAC,IAAI,CAAC;QACf,KAAK,EAAE;YACL,EAAE,EAAE,IAAI;YACR,IAAI;YACJ,MAAM;YACN,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,OAAO,EAAE,WAAW;YACpB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,qBAAqB;SAClD;QACD,KAAK,EAAE;YACL,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM,EAAE,QAAQ;SACjB;QACD,OAAO,EAAE;YACP,IAAI,EAAE;gBACJ,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,WAAW,EAAE,GAAG,IAAI,6DAA6D;gBACjF,OAAO,EAAE,gBAAgB;aAC1B;YACD,QAAQ,EAAE;gBACR,OAAO,EAAE,gBAAgB;gBACzB,KAAK,EAAE;oBACL,EAAE,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,wCAAwC,EAAE,IAAI,EAAE,OAAO,EAAE;oBACpG,EAAE,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,gDAAgD,EAAE,IAAI,EAAE,OAAO,EAAE;oBAC5G,EAAE,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,6BAA6B,EAAE,IAAI,EAAE,OAAO,EAAE;iBAC1F;aACF;YACD,UAAU,EAAE;gBACV,OAAO,EAAE,cAAc;gBACvB,KAAK,EAAE;oBACL,EAAE,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,iCAAiC,EAAE;oBAC9E,EAAE,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,mCAAmC,EAAE;oBAC/E,EAAE,KAAK,EAAE,qBAAqB,EAAE,WAAW,EAAE,8CAA8C,EAAE;iBAC9F;aACF;YACD,GAAG,EAAE,EAAE;SACR;QACD,OAAO,EAAE;YACP,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,KAAK;YACf,SAAS,EAAE,CAAC;SACb;QACD,GAAG,EAAE;YACH,KAAK,EAAE,GAAG,IAAI,sBAAsB;YACpC,WAAW,EAAE,MAAM,CAAC,OAAO;YAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,CAAC;SACvD;KACF,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AACvC,CAAC;AAED,SAAgB,0BAA0B,CAAC,SAAkB;IAC3D,SAAS;SACN,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,gCAAgC,CAAC;SAC7C,cAAc,CAAC,iBAAiB,EAAE,2DAA2D,CAAC;SAC9F,MAAM,CAAC,eAAe,EAAE,YAAY,CAAC;SACrC,MAAM,CAAC,mBAAmB,EAAE,eAAe,CAAC;SAC5C,MAAM,CAAC,cAAc,EAAE,mBAAmB,CAAC;SAC3C,MAAM,CAAC,qBAAqB,EAAE,uCAAuC,CAAC;SACtE,MAAM,CAAC,KAAK,EAAE,IAAsF,EAAE,EAAE;QACvG,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE;YAC5C,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,IAAI,CAAC,GAAG;SAClB,CAAC,CAAC;QAEH,IAAA,sBAAU,EAAC,kBAAkB,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACtD,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,6BAA6B,IAAI,CAAC,MAAM,EAAE,CAC3C,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"create-brand.js","sourceRoot":"","sources":["../../src/commands/create-brand.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,gEA4BC;AAlCD,uCAAyB;AACzB,8CAAgC;AAChC,6CAAuD;AACvD,0CAAuC;AACvC,gDAA8C;AAE9C,SAAgB,0BAA0B,CAAC,SAAkB;IAC3D,SAAS;SACN,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,gCAAgC,CAAC;SAC7C,cAAc,CAAC,iBAAiB,EAAE,2DAA2D,CAAC;SAC9F,MAAM,CAAC,eAAe,EAAE,YAAY,CAAC;SACrC,MAAM,CAAC,mBAAmB,EAAE,eAAe,CAAC;SAC5C,MAAM,CAAC,cAAc,EAAE,mBAAmB,CAAC;SAC3C,MAAM,CAAC,qBAAqB,EAAE,uCAAuC,CAAC;SACtE,MAAM,CAAC,KAAK,EAAE,IAAsF,EAAE,EAAE;QACvG,MAAM,GAAG,GAAG,IAAA,4BAAmB,EAAC,IAAI,CAAC,KAAK,EAAE;YAC1C,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,IAAI,CAAC,GAAG;SAClB,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAErE,IAAA,sBAAU,EAAC,kBAAkB,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACtD,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,6BAA6B,IAAI,CAAC,MAAM,EAAE,CAC3C,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -1,7 +1,3 @@
1
1
  import { Command } from 'commander';
2
- export declare function scaffoldCourse(topic: string, options: {
3
- hours?: number;
4
- source?: string;
5
- }): string;
6
2
  export declare function registerCreateCourseCommand(program: Command): Command;
7
3
  //# sourceMappingURL=create-course.d.ts.map
@@ -1 +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;AAMpC,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,WAkC3D"}
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;AAOpC,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,WAkC3D"}
@@ -33,41 +33,12 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.scaffoldCourse = scaffoldCourse;
37
36
  exports.registerCreateCourseCommand = registerCreateCourseCommand;
38
37
  const fs = __importStar(require("fs"));
39
38
  const yaml = __importStar(require("js-yaml"));
39
+ const shared_1 = require("@graspful/shared");
40
40
  const output_1 = require("../lib/output");
41
41
  const analytics_1 = require("../lib/analytics");
42
- function scaffoldCourse(topic, options) {
43
- const slug = topic.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
44
- return yaml.dump({
45
- course: {
46
- id: slug,
47
- name: topic,
48
- description: `Adaptive course on ${topic}`,
49
- estimatedHours: options.hours || 10,
50
- version: '2026.1',
51
- sourceDocument: options.source || 'TODO: Add source document',
52
- },
53
- sections: [
54
- { id: 'foundations', name: 'Foundations', description: 'Core concepts' },
55
- { id: 'application', name: 'Application', description: 'Applied concepts' },
56
- ],
57
- concepts: [
58
- {
59
- id: `${slug}-intro`,
60
- name: `Introduction to ${topic}`,
61
- section: 'foundations',
62
- difficulty: 2,
63
- estimatedMinutes: 15,
64
- tags: ['foundational'],
65
- prerequisites: [],
66
- knowledgePoints: [],
67
- },
68
- ],
69
- }, { lineWidth: 120, noRefs: true });
70
- }
71
42
  function registerCreateCourseCommand(program) {
72
43
  const create = program
73
44
  .command('create')
@@ -81,17 +52,17 @@ function registerCreateCourseCommand(program) {
81
52
  .option('-o, --output <file>', 'Output file path (defaults to stdout)')
82
53
  .option('--scaffold-only', 'Generate scaffold without AI enrichment', true)
83
54
  .action(async (opts) => {
84
- const yamlContent = scaffoldCourse(opts.topic, {
55
+ const obj = (0, shared_1.scaffoldCourseObject)(opts.topic, {
85
56
  hours: parseInt(opts.hours, 10),
86
57
  source: opts.source,
87
58
  });
59
+ const yamlContent = yaml.dump(obj, { lineWidth: 120, noRefs: true });
88
60
  (0, analytics_1.cliCapture)('course scaffolded', { topic: opts.topic, estimated_hours: parseInt(opts.hours, 10) });
89
61
  if (opts.output) {
90
62
  fs.writeFileSync(opts.output, yamlContent);
91
63
  (0, output_1.output)({ file: opts.output, topic: opts.topic }, `Scaffold written to ${opts.output}`);
92
64
  }
93
65
  else {
94
- // Output raw YAML to stdout (not wrapped in JSON even in json mode for piping)
95
66
  console.log(yamlContent);
96
67
  }
97
68
  });
@@ -1 +1 @@
1
- {"version":3,"file":"create-course.js","sourceRoot":"","sources":["../../src/commands/create-course.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"create-course.js","sourceRoot":"","sources":["../../src/commands/create-course.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,kEAkCC;AAxCD,uCAAyB;AACzB,8CAAgC;AAChC,6CAAwD;AACxD,0CAAuC;AACvC,gDAA8C;AAE9C,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,GAAG,GAAG,IAAA,6BAAoB,EAAC,IAAI,CAAC,KAAK,EAAE;YAC3C,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;YAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAErE,IAAA,sBAAU,EAAC,mBAAmB,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,eAAe,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;QAElG,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,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"describe.d.ts","sourceRoot":"","sources":["../../src/commands/describe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyCpC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QA8GvD"}
1
+ {"version":3,"file":"describe.d.ts","sourceRoot":"","sources":["../../src/commands/describe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QA8CvD"}
@@ -39,35 +39,6 @@ const yaml = __importStar(require("js-yaml"));
39
39
  const shared_1 = require("@graspful/shared");
40
40
  const output_1 = require("../lib/output");
41
41
  const analytics_1 = require("../lib/analytics");
42
- function computeGraphDepth(concepts) {
43
- const graph = new Map();
44
- for (const c of concepts) {
45
- graph.set(c.id, c.prerequisites);
46
- }
47
- const memo = new Map();
48
- function depth(id, visited) {
49
- if (memo.has(id))
50
- return memo.get(id);
51
- if (visited.has(id))
52
- return 0; // cycle, avoid infinite loop
53
- visited.add(id);
54
- const prereqs = graph.get(id) ?? [];
55
- let maxPrereqDepth = 0;
56
- for (const prereq of prereqs) {
57
- if (graph.has(prereq)) {
58
- maxPrereqDepth = Math.max(maxPrereqDepth, depth(prereq, visited));
59
- }
60
- }
61
- const d = maxPrereqDepth + 1;
62
- memo.set(id, d);
63
- return d;
64
- }
65
- let maxDepth = 0;
66
- for (const c of concepts) {
67
- maxDepth = Math.max(maxDepth, depth(c.id, new Set()));
68
- }
69
- return maxDepth;
70
- }
71
42
  function registerDescribeCommand(program) {
72
43
  program
73
44
  .command('describe <file>')
@@ -91,70 +62,22 @@ function registerDescribeCommand(program) {
91
62
  (0, output_1.outputError)(`Invalid course YAML: ${result.error.issues[0]?.message ?? 'unknown error'}`);
92
63
  process.exit(1);
93
64
  }
94
- const data = result.data;
95
- const concepts = data.concepts;
96
- const sections = data.sections;
97
- const authoredConcepts = concepts.filter((c) => c.knowledgePoints.length > 0);
98
- const stubConcepts = concepts.filter((c) => c.knowledgePoints.length === 0);
99
- const kpCount = concepts.reduce((sum, c) => sum + c.knowledgePoints.length, 0);
100
- const problemCount = concepts.reduce((sum, c) => sum + c.knowledgePoints.reduce((s, kp) => s + kp.problems.length, 0), 0);
101
- const graphDepth = computeGraphDepth(concepts);
102
- const conceptsWithoutKps = stubConcepts.map((c) => c.id);
103
- const kpsWithoutProblems = [];
104
- for (const c of concepts) {
105
- for (const kp of c.knowledgePoints) {
106
- if (kp.problems.length === 0) {
107
- kpsWithoutProblems.push(`${c.id}/${kp.id}`);
108
- }
109
- }
110
- }
111
- // Section breakdown
112
- const sectionBreakdown = [];
113
- if (sections.length > 0) {
114
- for (const section of sections) {
115
- const sectionConcepts = concepts.filter((c) => c.section === section.id);
116
- const sKps = sectionConcepts.reduce((sum, c) => sum + c.knowledgePoints.length, 0);
117
- const sProblems = sectionConcepts.reduce((sum, c) => sum + c.knowledgePoints.reduce((s, kp) => s + kp.problems.length, 0), 0);
118
- sectionBreakdown.push({ section: section.id, concepts: sectionConcepts.length, kps: sKps, problems: sProblems });
119
- }
120
- // Concepts without a section
121
- const unsectioned = concepts.filter((c) => !c.section);
122
- if (unsectioned.length > 0) {
123
- const uKps = unsectioned.reduce((sum, c) => sum + c.knowledgePoints.length, 0);
124
- const uProblems = unsectioned.reduce((sum, c) => sum + c.knowledgePoints.reduce((s, kp) => s + kp.problems.length, 0), 0);
125
- sectionBreakdown.push({ section: '(unsectioned)', concepts: unsectioned.length, kps: uKps, problems: uProblems });
126
- }
127
- }
128
- const stats = {
129
- courseName: data.course.name,
130
- courseId: data.course.id,
131
- version: data.course.version,
132
- estimatedHours: data.course.estimatedHours,
133
- concepts: concepts.length,
134
- authoredConcepts: authoredConcepts.length,
135
- stubConcepts: stubConcepts.length,
136
- knowledgePoints: kpCount,
137
- problems: problemCount,
138
- graphDepth,
139
- conceptsWithoutKps: conceptsWithoutKps.length,
140
- kpsWithoutProblems: kpsWithoutProblems.length,
141
- sections: sectionBreakdown,
142
- };
65
+ const stats = (0, shared_1.describeCourse)(result.data);
143
66
  const humanLines = [
144
- `Course: "${data.course.name}" (v${data.course.version})`,
145
- `Concepts: ${concepts.length} (${authoredConcepts.length} authored, ${stubConcepts.length} stubs)`,
146
- `KPs: ${kpCount}, Problems: ${problemCount}`,
147
- `Graph depth: ${graphDepth}`,
148
- `Missing: ${conceptsWithoutKps.length} concepts need KPs, ${kpsWithoutProblems.length} KPs need problems`,
67
+ `Course: "${stats.courseName}" (v${stats.version})`,
68
+ `Concepts: ${stats.concepts} (${stats.authoredConcepts} authored, ${stats.stubConcepts} stubs)`,
69
+ `KPs: ${stats.knowledgePoints}, Problems: ${stats.problems}`,
70
+ `Graph depth: ${stats.graphDepth}`,
71
+ `Missing: ${stats.conceptsWithoutKps} concepts need KPs, ${stats.kpsWithoutProblems} KPs need problems`,
149
72
  ];
150
- if (sectionBreakdown.length > 0) {
73
+ if (stats.sections.length > 0) {
151
74
  humanLines.push('');
152
75
  humanLines.push('Sections:');
153
- for (const s of sectionBreakdown) {
76
+ for (const s of stats.sections) {
154
77
  humanLines.push(` ${s.section}: ${s.concepts} concepts, ${s.kps} KPs, ${s.problems} problems`);
155
78
  }
156
79
  }
157
- (0, analytics_1.cliCapture)('course described', { concept_count: concepts.length, kp_count: kpCount, problem_count: problemCount });
80
+ (0, analytics_1.cliCapture)('course described', { concept_count: stats.concepts, kp_count: stats.knowledgePoints, problem_count: stats.problems });
158
81
  (0, output_1.output)(stats, humanLines.join('\n'));
159
82
  });
160
83
  }
@@ -1 +1 @@
1
- {"version":3,"file":"describe.js","sourceRoot":"","sources":["../../src/commands/describe.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"describe.js","sourceRoot":"","sources":["../../src/commands/describe.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,0DA8CC;AApDD,uCAAyB;AACzB,8CAAgC;AAChC,6CAAoE;AACpE,0CAAoD;AACpD,gDAA8C;AAE9C,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,yBAAgB,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,KAAK,GAAG,IAAA,uBAAc,EAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAE1C,MAAM,UAAU,GAAG;YACjB,YAAY,KAAK,CAAC,UAAU,OAAO,KAAK,CAAC,OAAO,GAAG;YACnD,aAAa,KAAK,CAAC,QAAQ,KAAK,KAAK,CAAC,gBAAgB,cAAc,KAAK,CAAC,YAAY,SAAS;YAC/F,QAAQ,KAAK,CAAC,eAAe,eAAe,KAAK,CAAC,QAAQ,EAAE;YAC5D,gBAAgB,KAAK,CAAC,UAAU,EAAE;YAClC,YAAY,KAAK,CAAC,kBAAkB,uBAAuB,KAAK,CAAC,kBAAkB,oBAAoB;SACxG,CAAC;QAEF,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpB,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC7B,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAC/B,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,sBAAU,EAAC,kBAAkB,EAAE,EAAE,aAAa,EAAE,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,eAAe,EAAE,aAAa,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QAClI,IAAA,eAAM,EAAC,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -1 +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;AAOpC,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,WA4F1D"}
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;AAOpC,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,WA+C1D"}
@@ -63,55 +63,20 @@ function registerFillConceptCommand(program) {
63
63
  (0, output_1.outputError)(`YAML parse error: ${msg}`);
64
64
  process.exit(1);
65
65
  }
66
- const parsed = shared_1.CourseYamlSchema.safeParse(raw);
67
- if (!parsed.success) {
68
- (0, output_1.outputError)(`Invalid course YAML: ${parsed.error.issues[0]?.message ?? 'unknown error'}`);
69
- process.exit(1);
70
- }
71
- const data = parsed.data;
72
- const concept = data.concepts.find((c) => c.id === conceptId);
73
- if (!concept) {
74
- (0, output_1.outputError)(`Concept "${conceptId}" not found. Available: ${data.concepts.map((c) => c.id).join(', ')}`);
75
- process.exit(1);
76
- }
77
- if (concept.knowledgePoints.length > 0) {
78
- (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).`);
79
- return;
80
- }
81
- const kpCount = parseInt(opts.kps, 10);
82
- const problemsPerKp = parseInt(opts.problems, 10);
83
- const newKps = [];
84
- for (let i = 1; i <= kpCount; i++) {
85
- const problems = [];
86
- for (let j = 1; j <= problemsPerKp; j++) {
87
- problems.push({
88
- id: `${conceptId}-kp${i}-p${j}`,
89
- type: 'multiple_choice',
90
- question: `TODO: Write question ${j} for ${conceptId} KP${i}`,
91
- options: ['Option A', 'Option B', 'Option C', 'Option D'],
92
- correct: 0,
93
- explanation: 'TODO: Explain the correct answer',
94
- difficulty: Math.min(j + 1, 5),
95
- });
96
- }
97
- newKps.push({
98
- id: `${conceptId}-kp${i}`,
99
- instruction: `TODO: Write instruction for ${concept.name} — knowledge point ${i}`,
100
- workedExample: `TODO: Write a worked example for ${concept.name} — knowledge point ${i}`,
101
- problems,
66
+ try {
67
+ const updated = (0, shared_1.fillConceptInRaw)(raw, conceptId, {
68
+ kps: parseInt(opts.kps, 10),
69
+ problemsPerKp: parseInt(opts.problems, 10),
102
70
  });
71
+ const updatedYaml = yaml.dump(updated, { lineWidth: 120, noRefs: true, schema: yaml.JSON_SCHEMA });
72
+ fs.writeFileSync(file, updatedYaml);
73
+ (0, analytics_1.cliCapture)('concept filled', { concept_id: conceptId });
74
+ (0, output_1.output)({ conceptId, kpsAdded: parseInt(opts.kps, 10), problemsPerKp: parseInt(opts.problems, 10), file }, `Added ${opts.kps} KP stub(s) with ${opts.problems} problem(s) each to "${conceptId}" in ${file}`);
103
75
  }
104
- // Rebuild the raw object to preserve structure, then replace the concept's KPs
105
- const rawObj = raw;
106
- const concepts = rawObj['concepts'];
107
- const targetConcept = concepts.find((c) => c['id'] === conceptId);
108
- if (targetConcept) {
109
- targetConcept['knowledgePoints'] = newKps;
76
+ catch (e) {
77
+ (0, output_1.outputError)(e instanceof Error ? e.message : String(e));
78
+ process.exit(1);
110
79
  }
111
- const updatedYaml = yaml.dump(rawObj, { lineWidth: 120, noRefs: true, schema: yaml.JSON_SCHEMA });
112
- fs.writeFileSync(file, updatedYaml);
113
- (0, analytics_1.cliCapture)('concept filled', { concept_id: conceptId });
114
- (0, output_1.output)({ conceptId, kpsAdded: kpCount, problemsPerKp, file }, `Added ${kpCount} KP stub(s) with ${problemsPerKp} problem(s) each to "${conceptId}" in ${file}`);
115
80
  });
116
81
  return fill;
117
82
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fill-concept.js","sourceRoot":"","sources":["../../src/commands/fill-concept.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fill-concept.js","sourceRoot":"","sources":["../../src/commands/fill-concept.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,gEA+CC;AArDD,uCAAyB;AACzB,8CAAgC;AAChC,6CAAoD;AACpD,0CAAoD;AACpD,gDAA8C;AAE9C,SAAgB,0BAA0B,CAAC,OAAgB;IACzD,MAAM,IAAI,GAAG,OAAO;SACjB,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,uBAAuB,CAAC,CAAC;IAExC,IAAI;SACD,OAAO,CAAC,4BAA4B,CAAC;SACrC,WAAW,CAAC,oCAAoC,CAAC;SACjD,MAAM,CAAC,eAAe,EAAE,2BAA2B,EAAE,GAAG,CAAC;SACzD,MAAM,CAAC,oBAAoB,EAAE,gCAAgC,EAAE,GAAG,CAAC;SACnE,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,SAAiB,EAAE,IAAuC,EAAE,EAAE;QACzF,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,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC/C,IAAI,GAAY,CAAC;QACjB,IAAI,CAAC;YACH,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3B,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,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAA,yBAAgB,EAAC,GAAG,EAAE,SAAS,EAAE;gBAC/C,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBAC3B,aAAa,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;aAC3C,CAAC,CAAC;YAEH,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;YACnG,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YAEpC,IAAA,sBAAU,EAAC,gBAAgB,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC;YACxD,IAAA,eAAM,EACJ,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,aAAa,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,EACjG,SAAS,IAAI,CAAC,GAAG,oBAAoB,IAAI,CAAC,QAAQ,wBAAwB,SAAS,QAAQ,IAAI,EAAE,CAClG,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAA,oBAAW,EAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2DpC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QAqGvD"}
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QAsCvD"}
@@ -39,52 +39,6 @@ const yaml = __importStar(require("js-yaml"));
39
39
  const shared_1 = require("@graspful/shared");
40
40
  const output_1 = require("../lib/output");
41
41
  const analytics_1 = require("../lib/analytics");
42
- function detectFileType(data) {
43
- if (typeof data !== 'object' || data === null)
44
- return null;
45
- const obj = data;
46
- if ('course' in obj)
47
- return 'course';
48
- if ('brand' in obj)
49
- return 'brand';
50
- if ('academy' in obj)
51
- return 'academy';
52
- return null;
53
- }
54
- function detectCycles(concepts) {
55
- const graph = new Map();
56
- for (const c of concepts) {
57
- graph.set(c.id, c.prerequisites);
58
- }
59
- const visited = new Set();
60
- const inStack = new Set();
61
- const cycles = [];
62
- function dfs(node, path) {
63
- if (inStack.has(node)) {
64
- const cycleStart = path.indexOf(node);
65
- const cycle = path.slice(cycleStart).concat(node);
66
- cycles.push(`Cycle: ${cycle.join(' -> ')}`);
67
- return true;
68
- }
69
- if (visited.has(node))
70
- return false;
71
- visited.add(node);
72
- inStack.add(node);
73
- path.push(node);
74
- for (const dep of graph.get(node) ?? []) {
75
- dfs(dep, path);
76
- }
77
- path.pop();
78
- inStack.delete(node);
79
- return false;
80
- }
81
- for (const id of graph.keys()) {
82
- if (!visited.has(id)) {
83
- dfs(id, []);
84
- }
85
- }
86
- return cycles;
87
- }
88
42
  function registerValidateCommand(program) {
89
43
  program
90
44
  .command('validate <file>')
@@ -103,54 +57,13 @@ function registerValidateCommand(program) {
103
57
  (0, output_1.output)({ valid: false, errors: [`YAML parse error: ${msg}`], stats: {} }, `FAIL YAML parse error: ${msg}`);
104
58
  process.exit(1);
105
59
  }
106
- const fileType = detectFileType(raw);
107
- if (!fileType) {
108
- (0, output_1.output)({ valid: false, errors: ['Could not detect file type. Expected top-level key: course, brand, or academy'], stats: {} }, 'FAIL Could not detect file type. Expected top-level key: course, brand, or academy');
109
- process.exit(1);
110
- }
111
- const schemaMap = {
112
- course: shared_1.CourseYamlSchema,
113
- brand: shared_1.BrandYamlSchema,
114
- academy: shared_1.AcademyManifestSchema,
115
- };
116
- const result = schemaMap[fileType].safeParse(raw);
117
- if (!result.success) {
118
- const errors = result.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`);
119
- (0, output_1.output)({ valid: false, fileType, errors, stats: {} }, `FAIL ${fileType} validation (${errors.length} error${errors.length === 1 ? '' : 's'}):\n${errors.map((e) => ` - ${e}`).join('\n')}`);
120
- process.exit(1);
121
- }
122
- // For courses, also check DAG
123
- const dagErrors = [];
124
- let stats = { fileType };
125
- if (fileType === 'course') {
126
- const data = result.data;
127
- const conceptIds = new Set(data.concepts.map((c) => c.id));
128
- // Check prerequisite references
129
- for (const concept of data.concepts) {
130
- for (const prereq of concept.prerequisites) {
131
- if (!conceptIds.has(prereq)) {
132
- dagErrors.push(`Concept "${concept.id}" has unknown prerequisite "${prereq}"`);
133
- }
134
- }
135
- }
136
- // Check for cycles
137
- const cycles = detectCycles(data.concepts.map((c) => ({ id: c.id, prerequisites: c.prerequisites })));
138
- dagErrors.push(...cycles);
139
- const kpCount = data.concepts.reduce((sum, c) => sum + c.knowledgePoints.length, 0);
140
- const problemCount = data.concepts.reduce((sum, c) => sum + c.knowledgePoints.reduce((s, kp) => s + kp.problems.length, 0), 0);
141
- stats = {
142
- fileType,
143
- concepts: data.concepts.length,
144
- knowledgePoints: kpCount,
145
- problems: problemCount,
146
- };
147
- }
148
- if (dagErrors.length > 0) {
149
- (0, output_1.output)({ valid: false, fileType, errors: dagErrors, stats }, `FAIL DAG validation (${dagErrors.length} error${dagErrors.length === 1 ? '' : 's'}):\n${dagErrors.map((e) => ` - ${e}`).join('\n')}`);
60
+ const result = (0, shared_1.validateParsedYaml)(raw);
61
+ if (!result.valid) {
62
+ (0, output_1.output)(result, `FAIL ${result.fileType ?? 'unknown'} validation (${result.errors.length} error${result.errors.length === 1 ? '' : 's'}):\n${result.errors.map((e) => ` - ${e}`).join('\n')}`);
150
63
  process.exit(1);
151
64
  }
152
- (0, analytics_1.cliCapture)('course validated', { valid: true, error_count: 0, file_type: fileType });
153
- (0, output_1.output)({ valid: true, fileType, errors: [], stats }, `PASS ${fileType} validation\n${Object.entries(stats).map(([k, v]) => ` ${k}: ${v}`).join('\n')}`);
65
+ (0, analytics_1.cliCapture)('course validated', { valid: true, error_count: 0, file_type: result.fileType });
66
+ (0, output_1.output)(result, `PASS ${result.fileType} validation\n${Object.entries(result.stats).map(([k, v]) => ` ${k}: ${v}`).join('\n')}`);
154
67
  });
155
68
  }
156
69
  //# sourceMappingURL=validate.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,0DAsCC;AA5CD,uCAAyB;AACzB,8CAAgC;AAChC,6CAAsD;AACtD,0CAAoD;AACpD,gDAA8C;AAE9C,SAAgB,uBAAuB,CAAC,OAAgB;IACtD,OAAO;SACJ,OAAO,CAAC,iBAAiB,CAAC;SAC1B,WAAW,CAAC,mEAAmE,CAAC;SAChF,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,eAAM,EACJ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,qBAAqB,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EACjE,2BAA2B,GAAG,EAAE,CACjC,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,IAAA,2BAAkB,EAAC,GAAG,CAAC,CAAC;QAEvC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAClB,IAAA,eAAM,EACJ,MAAM,EACN,SAAS,MAAM,CAAC,QAAQ,IAAI,SAAS,gBAAgB,MAAM,CAAC,MAAM,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAChL,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAA,sBAAU,EAAC,kBAAkB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC5F,IAAA,eAAM,EACJ,MAAM,EACN,SAAS,MAAM,CAAC,QAAQ,gBAAgB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAClH,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graspful/cli",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "Create adaptive learning courses from YAML. CLI and MCP server for AI agents.",
5
5
  "keywords": ["course", "learning", "adaptive", "mcp", "mcp-server", "ai", "ai-agent", "agent", "cli", "education", "edtech", "knowledge-graph", "spaced-repetition", "course-creation", "yaml", "adaptive-learning", "lms"],
6
6
  "repository": {
@@ -21,7 +21,7 @@
21
21
  "lint": "echo 'no lint configured yet'"
22
22
  },
23
23
  "dependencies": {
24
- "@graspful/shared": "^0.2.2",
24
+ "@graspful/shared": "^0.2.3",
25
25
  "chalk": "^5.4.0",
26
26
  "commander": "^13.0.0",
27
27
  "js-yaml": "^4.1.0",