@lessonkit/lxpack 1.5.0 → 1.7.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/README.md +15 -1
- package/block-tree.v1.json +40 -0
- package/dist/bridge.cjs +81 -22
- package/dist/bridge.d.cts +34 -4
- package/dist/bridge.d.ts +34 -4
- package/dist/bridge.js +78 -23
- package/dist/index.cjs +1479 -187
- package/dist/index.d.cts +212 -2
- package/dist/index.d.ts +212 -2
- package/dist/index.js +1481 -199
- package/lessonkit-manifest.v1.json +75 -5
- package/lkcourse-format.v1.json +21 -0
- package/package.json +17 -11
package/dist/index.d.cts
CHANGED
|
@@ -53,8 +53,31 @@ type FindMultipleHotspotsAssessmentDescriptor = {
|
|
|
53
53
|
correctTargetIds: string[];
|
|
54
54
|
passingScore?: number;
|
|
55
55
|
};
|
|
56
|
+
type SortParagraphsAssessmentDescriptor = {
|
|
57
|
+
kind: "sortParagraphs";
|
|
58
|
+
checkId: CheckId;
|
|
59
|
+
question: string;
|
|
60
|
+
paragraphs: string[];
|
|
61
|
+
correctOrder: number[];
|
|
62
|
+
passingScore?: number;
|
|
63
|
+
};
|
|
64
|
+
type GuessTheAnswerAssessmentDescriptor = {
|
|
65
|
+
kind: "guessTheAnswer";
|
|
66
|
+
checkId: CheckId;
|
|
67
|
+
question: string;
|
|
68
|
+
answer: string;
|
|
69
|
+
passingScore?: number;
|
|
70
|
+
};
|
|
71
|
+
type MultimediaChoiceAssessmentDescriptor = {
|
|
72
|
+
kind: "multimediaChoice";
|
|
73
|
+
checkId: CheckId;
|
|
74
|
+
question: string;
|
|
75
|
+
choices: string[];
|
|
76
|
+
answer: string;
|
|
77
|
+
passingScore?: number;
|
|
78
|
+
};
|
|
56
79
|
/** Discriminated assessment entries in lessonkit.json (defaults to MCQ when kind omitted). */
|
|
57
|
-
type AssessmentDescriptor = McqAssessmentDescriptor | TrueFalseAssessmentDescriptor | FillInBlanksAssessmentDescriptor | FindHotspotAssessmentDescriptor | FindMultipleHotspotsAssessmentDescriptor;
|
|
80
|
+
type AssessmentDescriptor = McqAssessmentDescriptor | TrueFalseAssessmentDescriptor | FillInBlanksAssessmentDescriptor | FindHotspotAssessmentDescriptor | FindMultipleHotspotsAssessmentDescriptor | SortParagraphsAssessmentDescriptor | GuessTheAnswerAssessmentDescriptor | MultimediaChoiceAssessmentDescriptor;
|
|
58
81
|
type LessonkitCourseDescriptor = {
|
|
59
82
|
courseId: CourseId;
|
|
60
83
|
title: string;
|
|
@@ -127,6 +150,8 @@ type ProjectPathsInput = {
|
|
|
127
150
|
lxpackOutDir?: string;
|
|
128
151
|
outputBaseDir?: string;
|
|
129
152
|
};
|
|
153
|
+
/** Validate lessonkit.json `name` for safe default export/archive paths. */
|
|
154
|
+
declare function validateManifestName(name: string): string | null;
|
|
130
155
|
/** Validate lessonkit.json paths.* entries stay under projectRoot. */
|
|
131
156
|
declare function validateProjectPaths(projectRoot: string, paths: ProjectPathsInput): DescriptorValidationIssue[];
|
|
132
157
|
/**
|
|
@@ -155,15 +180,30 @@ type SpaLessonEntry = {
|
|
|
155
180
|
path: string;
|
|
156
181
|
};
|
|
157
182
|
declare function resolveSpaLessons(descriptor: LessonkitCourseDescriptor): SpaLessonEntry[];
|
|
183
|
+
/**
|
|
184
|
+
* Convert a `lessonkit.json` course descriptor to portable interchange JSON for `.lkcourse`.
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* ```ts
|
|
188
|
+
* import { descriptorToInterchange } from "@lessonkit/lxpack";
|
|
189
|
+
*
|
|
190
|
+
* const interchange = descriptorToInterchange(manifest.course);
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
158
193
|
declare function descriptorToInterchange(descriptor: LessonkitCourseDescriptor): LessonkitInterchangeV1;
|
|
159
194
|
|
|
160
195
|
type LxpackInjectedAssessment = {
|
|
161
196
|
id: string;
|
|
162
197
|
title?: string;
|
|
163
198
|
passingScore: number;
|
|
199
|
+
maxAttempts?: number;
|
|
200
|
+
shuffleChoices?: boolean;
|
|
201
|
+
showFeedback?: "never" | "immediate" | "end";
|
|
164
202
|
questions: Array<{
|
|
165
203
|
id: string;
|
|
166
204
|
prompt: string;
|
|
205
|
+
explanation?: string;
|
|
206
|
+
selectionMode?: "single" | "multiple";
|
|
167
207
|
choices: Array<{
|
|
168
208
|
id: string;
|
|
169
209
|
text: string;
|
|
@@ -199,6 +239,18 @@ type WriteLxpackProjectResult = {
|
|
|
199
239
|
};
|
|
200
240
|
/**
|
|
201
241
|
* Materialize an LXPack project tree from a LessonKit descriptor (delegates to LXPack 0.6+).
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```ts
|
|
245
|
+
* import { writeLxpackProject } from "@lessonkit/lxpack";
|
|
246
|
+
*
|
|
247
|
+
* await writeLxpackProject({
|
|
248
|
+
* descriptor: courseFromLessonkitJson,
|
|
249
|
+
* outDir: ".lxpack/course",
|
|
250
|
+
* spaDistDir: "dist",
|
|
251
|
+
* projectRoot: process.cwd(),
|
|
252
|
+
* });
|
|
253
|
+
* ```
|
|
202
254
|
*/
|
|
203
255
|
declare function writeLxpackProject(options: WriteLxpackProjectOptions): Promise<WriteLxpackProjectResult>;
|
|
204
256
|
|
|
@@ -225,6 +277,9 @@ type BuildStagingPackageResult = {
|
|
|
225
277
|
}>;
|
|
226
278
|
outputPath?: string;
|
|
227
279
|
outputDir?: string;
|
|
280
|
+
/** Absolute project-root output path when `output` was explicitly requested. */
|
|
281
|
+
requestedOutputPath?: string;
|
|
282
|
+
requestedOutputDir?: string;
|
|
228
283
|
} | {
|
|
229
284
|
ok: false;
|
|
230
285
|
stagingDir: string;
|
|
@@ -260,6 +315,8 @@ type PackageLessonkitCourseOptions = WriteLxpackProjectOptions & {
|
|
|
260
315
|
outputBaseDir?: string;
|
|
261
316
|
/** Treat React parity warnings as packaging errors. */
|
|
262
317
|
strictParity?: boolean;
|
|
318
|
+
/** Treat LXPack build warnings as packaging errors. */
|
|
319
|
+
strictBuild?: boolean;
|
|
263
320
|
};
|
|
264
321
|
type PackageLessonkitCourseResult = {
|
|
265
322
|
ok: true;
|
|
@@ -282,12 +339,43 @@ type PackageLessonkitCourseResult = {
|
|
|
282
339
|
severity?: string;
|
|
283
340
|
}>;
|
|
284
341
|
};
|
|
342
|
+
/**
|
|
343
|
+
* Validate an on-disk LXPack course directory before packaging.
|
|
344
|
+
*
|
|
345
|
+
* @example
|
|
346
|
+
* ```ts
|
|
347
|
+
* import { validateLessonkitProject } from "@lessonkit/lxpack";
|
|
348
|
+
*
|
|
349
|
+
* const result = await validateLessonkitProject({
|
|
350
|
+
* courseDir: ".lxpack/course",
|
|
351
|
+
* target: "scorm12",
|
|
352
|
+
* });
|
|
353
|
+
* ```
|
|
354
|
+
*/
|
|
285
355
|
declare function validateLessonkitProject(options: ValidateLessonkitProjectOptions): Promise<ValidateCourseResult>;
|
|
286
356
|
declare function buildLessonkitProject(options: BuildLessonkitProjectOptions): Promise<BuildCourseResult>;
|
|
287
357
|
|
|
288
358
|
/**
|
|
289
359
|
* Package a built SPA into SCORM, xAPI, cmi5, or standalone LMS artifacts.
|
|
290
360
|
* Prefer `lessonkit package --target …` in course projects; call directly for custom pipelines.
|
|
361
|
+
*
|
|
362
|
+
* @example
|
|
363
|
+
* ```ts
|
|
364
|
+
* import { packageLessonkitCourse } from "@lessonkit/lxpack";
|
|
365
|
+
*
|
|
366
|
+
* const result = await packageLessonkitCourse({
|
|
367
|
+
* descriptor: manifest.course,
|
|
368
|
+
* outDir: ".lxpack/course",
|
|
369
|
+
* spaDistDir: "dist",
|
|
370
|
+
* projectRoot: process.cwd(),
|
|
371
|
+
* target: "scorm12",
|
|
372
|
+
* strictBuild: true,
|
|
373
|
+
* });
|
|
374
|
+
* if (!result.ok) console.error(result.issues);
|
|
375
|
+
* ```
|
|
376
|
+
*
|
|
377
|
+
* @remarks Returns `{ ok: false, issues }` (does not throw) for manifest parity failures,
|
|
378
|
+
* missing `dist/`, LXPack validation errors, or `strictBuild` / `strictParity` warnings.
|
|
291
379
|
*/
|
|
292
380
|
declare function packageLessonkitCourse(options: PackageLessonkitCourseOptions): Promise<PackageLessonkitCourseResult>;
|
|
293
381
|
|
|
@@ -311,6 +399,11 @@ declare function validatePackageInputs(options: Pick<PackageLessonkitCourseOptio
|
|
|
311
399
|
}): ValidatePackageInputsResult;
|
|
312
400
|
declare function remapArtifactPaths(stagingRoot: string, outDir: string, artifactPath: string | undefined): string | undefined;
|
|
313
401
|
|
|
402
|
+
/**
|
|
403
|
+
* Reject symlinks and paths escaping dist roots before packaging LMS artifacts.
|
|
404
|
+
*/
|
|
405
|
+
declare function assertSpaDistContentsSafe(spaDirs: Record<string, string>, projectRoot?: string): Promise<void>;
|
|
406
|
+
|
|
314
407
|
type LessonkitManifestPaths = {
|
|
315
408
|
spaDistDir: string;
|
|
316
409
|
lxpackOutDir: string;
|
|
@@ -340,4 +433,121 @@ type ParseManifestResult = {
|
|
|
340
433
|
declare function parseLessonkitManifest(raw: unknown, label?: string, projectRoot?: string): ParseManifestResult;
|
|
341
434
|
declare function loadLessonkitManifestFromFile(readJson: () => Promise<unknown>, label?: string, projectRoot?: string): Promise<ParseManifestResult>;
|
|
342
435
|
|
|
343
|
-
|
|
436
|
+
type LkcourseEnvelopeV1 = {
|
|
437
|
+
format: "lkcourse";
|
|
438
|
+
schemaVersion: 1;
|
|
439
|
+
lessonkitVersion: string;
|
|
440
|
+
exportedAt: string;
|
|
441
|
+
sourceManifest: LessonkitManifest;
|
|
442
|
+
entries: string[];
|
|
443
|
+
};
|
|
444
|
+
type BlockTreeNodeV1 = {
|
|
445
|
+
type: string;
|
|
446
|
+
rawTag?: string;
|
|
447
|
+
courseId?: string;
|
|
448
|
+
lessonId?: string;
|
|
449
|
+
checkId?: string;
|
|
450
|
+
blockId?: string;
|
|
451
|
+
nodeId?: string;
|
|
452
|
+
children?: BlockTreeNodeV1[];
|
|
453
|
+
};
|
|
454
|
+
type BlockTreeV1 = {
|
|
455
|
+
schemaVersion: 1;
|
|
456
|
+
sources: string[];
|
|
457
|
+
blocks: BlockTreeNodeV1[];
|
|
458
|
+
};
|
|
459
|
+
type LkcourseValidationIssue = {
|
|
460
|
+
path: string;
|
|
461
|
+
message: string;
|
|
462
|
+
};
|
|
463
|
+
type ExportLkcourseOptions = {
|
|
464
|
+
projectRoot: string;
|
|
465
|
+
manifest: LessonkitManifest;
|
|
466
|
+
outPath?: string;
|
|
467
|
+
includeBlockTree?: boolean;
|
|
468
|
+
lessonkitVersion?: string;
|
|
469
|
+
};
|
|
470
|
+
type ExportLkcourseResult = {
|
|
471
|
+
ok: true;
|
|
472
|
+
archivePath: string;
|
|
473
|
+
fileCount: number;
|
|
474
|
+
includeBlockTree: boolean;
|
|
475
|
+
} | {
|
|
476
|
+
ok: false;
|
|
477
|
+
issues: LkcourseValidationIssue[];
|
|
478
|
+
};
|
|
479
|
+
type ValidateLkcourseResult = {
|
|
480
|
+
ok: true;
|
|
481
|
+
envelope: LkcourseEnvelopeV1;
|
|
482
|
+
interchange: LessonkitInterchangeV1;
|
|
483
|
+
} | {
|
|
484
|
+
ok: false;
|
|
485
|
+
issues: LkcourseValidationIssue[];
|
|
486
|
+
};
|
|
487
|
+
type ImportLkcourseOptions = {
|
|
488
|
+
archivePath: string;
|
|
489
|
+
targetDir: string;
|
|
490
|
+
};
|
|
491
|
+
type ImportLkcourseResult = {
|
|
492
|
+
ok: true;
|
|
493
|
+
targetDir: string;
|
|
494
|
+
manifest: LessonkitManifest;
|
|
495
|
+
interchange: LessonkitInterchangeV1;
|
|
496
|
+
fileCount: number;
|
|
497
|
+
} | {
|
|
498
|
+
ok: false;
|
|
499
|
+
issues: LkcourseValidationIssue[];
|
|
500
|
+
};
|
|
501
|
+
type ExtractBlockTreeOptions = {
|
|
502
|
+
projectRoot: string;
|
|
503
|
+
blockTypes?: string[];
|
|
504
|
+
appSources?: string[];
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
type ParseEnvelopeResult = {
|
|
508
|
+
ok: true;
|
|
509
|
+
envelope: LkcourseEnvelopeV1;
|
|
510
|
+
} | {
|
|
511
|
+
ok: false;
|
|
512
|
+
issues: LkcourseValidationIssue[];
|
|
513
|
+
};
|
|
514
|
+
declare function parseLkcourseEnvelope(raw: unknown, label?: string): ParseEnvelopeResult;
|
|
515
|
+
|
|
516
|
+
declare function extractBlockTree(options: ExtractBlockTreeOptions): BlockTreeV1;
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Build a portable `.lkcourse` zip (manifest envelope + interchange + dist).
|
|
520
|
+
* Prefer `lessonkit export` in course projects.
|
|
521
|
+
*
|
|
522
|
+
* @example
|
|
523
|
+
* ```ts
|
|
524
|
+
* import { exportLkcourse } from "@lessonkit/lxpack";
|
|
525
|
+
*
|
|
526
|
+
* const result = await exportLkcourse({
|
|
527
|
+
* projectRoot: "/path/to/course",
|
|
528
|
+
* manifest: parsedLessonkitJson,
|
|
529
|
+
* archivePath: "handoff.lkcourse",
|
|
530
|
+
* });
|
|
531
|
+
* ```
|
|
532
|
+
*/
|
|
533
|
+
declare function exportLkcourse(options: ExportLkcourseOptions): Promise<ExportLkcourseResult>;
|
|
534
|
+
|
|
535
|
+
declare function validateLkcourseArchiveEntries(entries: Map<string, Uint8Array>, _archiveLabel: string): ValidateLkcourseResult;
|
|
536
|
+
declare function validateLkcourse(archivePath: string): ValidateLkcourseResult;
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Extract a `.lkcourse` archive into a project directory (manifest + dist tree).
|
|
540
|
+
*
|
|
541
|
+
* @example
|
|
542
|
+
* ```ts
|
|
543
|
+
* import { importLkcourse } from "@lessonkit/lxpack";
|
|
544
|
+
*
|
|
545
|
+
* const result = await importLkcourse({
|
|
546
|
+
* archivePath: "handoff.lkcourse",
|
|
547
|
+
* targetDir: "/path/to/dest",
|
|
548
|
+
* });
|
|
549
|
+
* ```
|
|
550
|
+
*/
|
|
551
|
+
declare function importLkcourse(options: ImportLkcourseOptions): Promise<ImportLkcourseResult>;
|
|
552
|
+
|
|
553
|
+
export { type AssessmentDescriptor, type BlockTreeNodeV1, type BlockTreeV1, type BuildLessonkitProjectOptions, type BuildStagingPackageOptions, type BuildStagingPackageResult, type DescriptorValidationIssue, type DescriptorValidationResult, type ExportLkcourseOptions, type ExportLkcourseResult, type ExtractBlockTreeOptions, type FillInBlanksAssessmentDescriptor, type ImportLkcourseOptions, type ImportLkcourseResult, type LessonDescriptor, type LessonkitCourseDescriptor, type LessonkitExportTarget, type LessonkitManifest, type LessonkitManifestPaths, type LkcourseEnvelopeV1, type LkcourseValidationIssue, type LxpackInjectedAssessment, type LxpackRuntimeTheme, type ManifestParseIssue, type MappedLessonkitIds, type McqAssessmentDescriptor, type PackageLessonkitCourseOptions, type PackageLessonkitCourseResult, type PackageValidationIssue, type ParseManifestResult, type ProjectPathsInput, type ReactParityIssue, type SpaLayout, type SpaLessonEntry, type TrueFalseAssessmentDescriptor, type ValidateLessonkitProjectOptions, type ValidateLkcourseResult, type ValidatePackageInputsResult, type ValidationIssue, type WriteLxpackProjectOptions, type WriteLxpackProjectResult, assertSpaDistContentsSafe, assessmentDescriptorToLxpack, buildLessonkitProject, buildStagingPackage, descriptorToInterchange, ensureOutDirParent, escapeShellText, exportLkcourse, extractAssessments, extractBlockTree, importLkcourse, loadLessonkitManifestFromFile, mapLessonkitIds, packageLessonkitCourse, parseLessonkitManifest, parseLkcourseEnvelope, promoteStagingToOutDir, remapArtifactPaths, resolveSafePackageOutputOverride, resolveSpaLessons, themeToLxpackRuntime, validateDescriptor, validateDescriptorForTarget, validateLessonkitProject, validateLkcourse, validateLkcourseArchiveEntries, validateManifestName, validatePackageInputs, validateProjectPaths, validateReactManifestParity, writeLxpackProject };
|
package/dist/index.d.ts
CHANGED
|
@@ -53,8 +53,31 @@ type FindMultipleHotspotsAssessmentDescriptor = {
|
|
|
53
53
|
correctTargetIds: string[];
|
|
54
54
|
passingScore?: number;
|
|
55
55
|
};
|
|
56
|
+
type SortParagraphsAssessmentDescriptor = {
|
|
57
|
+
kind: "sortParagraphs";
|
|
58
|
+
checkId: CheckId;
|
|
59
|
+
question: string;
|
|
60
|
+
paragraphs: string[];
|
|
61
|
+
correctOrder: number[];
|
|
62
|
+
passingScore?: number;
|
|
63
|
+
};
|
|
64
|
+
type GuessTheAnswerAssessmentDescriptor = {
|
|
65
|
+
kind: "guessTheAnswer";
|
|
66
|
+
checkId: CheckId;
|
|
67
|
+
question: string;
|
|
68
|
+
answer: string;
|
|
69
|
+
passingScore?: number;
|
|
70
|
+
};
|
|
71
|
+
type MultimediaChoiceAssessmentDescriptor = {
|
|
72
|
+
kind: "multimediaChoice";
|
|
73
|
+
checkId: CheckId;
|
|
74
|
+
question: string;
|
|
75
|
+
choices: string[];
|
|
76
|
+
answer: string;
|
|
77
|
+
passingScore?: number;
|
|
78
|
+
};
|
|
56
79
|
/** Discriminated assessment entries in lessonkit.json (defaults to MCQ when kind omitted). */
|
|
57
|
-
type AssessmentDescriptor = McqAssessmentDescriptor | TrueFalseAssessmentDescriptor | FillInBlanksAssessmentDescriptor | FindHotspotAssessmentDescriptor | FindMultipleHotspotsAssessmentDescriptor;
|
|
80
|
+
type AssessmentDescriptor = McqAssessmentDescriptor | TrueFalseAssessmentDescriptor | FillInBlanksAssessmentDescriptor | FindHotspotAssessmentDescriptor | FindMultipleHotspotsAssessmentDescriptor | SortParagraphsAssessmentDescriptor | GuessTheAnswerAssessmentDescriptor | MultimediaChoiceAssessmentDescriptor;
|
|
58
81
|
type LessonkitCourseDescriptor = {
|
|
59
82
|
courseId: CourseId;
|
|
60
83
|
title: string;
|
|
@@ -127,6 +150,8 @@ type ProjectPathsInput = {
|
|
|
127
150
|
lxpackOutDir?: string;
|
|
128
151
|
outputBaseDir?: string;
|
|
129
152
|
};
|
|
153
|
+
/** Validate lessonkit.json `name` for safe default export/archive paths. */
|
|
154
|
+
declare function validateManifestName(name: string): string | null;
|
|
130
155
|
/** Validate lessonkit.json paths.* entries stay under projectRoot. */
|
|
131
156
|
declare function validateProjectPaths(projectRoot: string, paths: ProjectPathsInput): DescriptorValidationIssue[];
|
|
132
157
|
/**
|
|
@@ -155,15 +180,30 @@ type SpaLessonEntry = {
|
|
|
155
180
|
path: string;
|
|
156
181
|
};
|
|
157
182
|
declare function resolveSpaLessons(descriptor: LessonkitCourseDescriptor): SpaLessonEntry[];
|
|
183
|
+
/**
|
|
184
|
+
* Convert a `lessonkit.json` course descriptor to portable interchange JSON for `.lkcourse`.
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* ```ts
|
|
188
|
+
* import { descriptorToInterchange } from "@lessonkit/lxpack";
|
|
189
|
+
*
|
|
190
|
+
* const interchange = descriptorToInterchange(manifest.course);
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
158
193
|
declare function descriptorToInterchange(descriptor: LessonkitCourseDescriptor): LessonkitInterchangeV1;
|
|
159
194
|
|
|
160
195
|
type LxpackInjectedAssessment = {
|
|
161
196
|
id: string;
|
|
162
197
|
title?: string;
|
|
163
198
|
passingScore: number;
|
|
199
|
+
maxAttempts?: number;
|
|
200
|
+
shuffleChoices?: boolean;
|
|
201
|
+
showFeedback?: "never" | "immediate" | "end";
|
|
164
202
|
questions: Array<{
|
|
165
203
|
id: string;
|
|
166
204
|
prompt: string;
|
|
205
|
+
explanation?: string;
|
|
206
|
+
selectionMode?: "single" | "multiple";
|
|
167
207
|
choices: Array<{
|
|
168
208
|
id: string;
|
|
169
209
|
text: string;
|
|
@@ -199,6 +239,18 @@ type WriteLxpackProjectResult = {
|
|
|
199
239
|
};
|
|
200
240
|
/**
|
|
201
241
|
* Materialize an LXPack project tree from a LessonKit descriptor (delegates to LXPack 0.6+).
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```ts
|
|
245
|
+
* import { writeLxpackProject } from "@lessonkit/lxpack";
|
|
246
|
+
*
|
|
247
|
+
* await writeLxpackProject({
|
|
248
|
+
* descriptor: courseFromLessonkitJson,
|
|
249
|
+
* outDir: ".lxpack/course",
|
|
250
|
+
* spaDistDir: "dist",
|
|
251
|
+
* projectRoot: process.cwd(),
|
|
252
|
+
* });
|
|
253
|
+
* ```
|
|
202
254
|
*/
|
|
203
255
|
declare function writeLxpackProject(options: WriteLxpackProjectOptions): Promise<WriteLxpackProjectResult>;
|
|
204
256
|
|
|
@@ -225,6 +277,9 @@ type BuildStagingPackageResult = {
|
|
|
225
277
|
}>;
|
|
226
278
|
outputPath?: string;
|
|
227
279
|
outputDir?: string;
|
|
280
|
+
/** Absolute project-root output path when `output` was explicitly requested. */
|
|
281
|
+
requestedOutputPath?: string;
|
|
282
|
+
requestedOutputDir?: string;
|
|
228
283
|
} | {
|
|
229
284
|
ok: false;
|
|
230
285
|
stagingDir: string;
|
|
@@ -260,6 +315,8 @@ type PackageLessonkitCourseOptions = WriteLxpackProjectOptions & {
|
|
|
260
315
|
outputBaseDir?: string;
|
|
261
316
|
/** Treat React parity warnings as packaging errors. */
|
|
262
317
|
strictParity?: boolean;
|
|
318
|
+
/** Treat LXPack build warnings as packaging errors. */
|
|
319
|
+
strictBuild?: boolean;
|
|
263
320
|
};
|
|
264
321
|
type PackageLessonkitCourseResult = {
|
|
265
322
|
ok: true;
|
|
@@ -282,12 +339,43 @@ type PackageLessonkitCourseResult = {
|
|
|
282
339
|
severity?: string;
|
|
283
340
|
}>;
|
|
284
341
|
};
|
|
342
|
+
/**
|
|
343
|
+
* Validate an on-disk LXPack course directory before packaging.
|
|
344
|
+
*
|
|
345
|
+
* @example
|
|
346
|
+
* ```ts
|
|
347
|
+
* import { validateLessonkitProject } from "@lessonkit/lxpack";
|
|
348
|
+
*
|
|
349
|
+
* const result = await validateLessonkitProject({
|
|
350
|
+
* courseDir: ".lxpack/course",
|
|
351
|
+
* target: "scorm12",
|
|
352
|
+
* });
|
|
353
|
+
* ```
|
|
354
|
+
*/
|
|
285
355
|
declare function validateLessonkitProject(options: ValidateLessonkitProjectOptions): Promise<ValidateCourseResult>;
|
|
286
356
|
declare function buildLessonkitProject(options: BuildLessonkitProjectOptions): Promise<BuildCourseResult>;
|
|
287
357
|
|
|
288
358
|
/**
|
|
289
359
|
* Package a built SPA into SCORM, xAPI, cmi5, or standalone LMS artifacts.
|
|
290
360
|
* Prefer `lessonkit package --target …` in course projects; call directly for custom pipelines.
|
|
361
|
+
*
|
|
362
|
+
* @example
|
|
363
|
+
* ```ts
|
|
364
|
+
* import { packageLessonkitCourse } from "@lessonkit/lxpack";
|
|
365
|
+
*
|
|
366
|
+
* const result = await packageLessonkitCourse({
|
|
367
|
+
* descriptor: manifest.course,
|
|
368
|
+
* outDir: ".lxpack/course",
|
|
369
|
+
* spaDistDir: "dist",
|
|
370
|
+
* projectRoot: process.cwd(),
|
|
371
|
+
* target: "scorm12",
|
|
372
|
+
* strictBuild: true,
|
|
373
|
+
* });
|
|
374
|
+
* if (!result.ok) console.error(result.issues);
|
|
375
|
+
* ```
|
|
376
|
+
*
|
|
377
|
+
* @remarks Returns `{ ok: false, issues }` (does not throw) for manifest parity failures,
|
|
378
|
+
* missing `dist/`, LXPack validation errors, or `strictBuild` / `strictParity` warnings.
|
|
291
379
|
*/
|
|
292
380
|
declare function packageLessonkitCourse(options: PackageLessonkitCourseOptions): Promise<PackageLessonkitCourseResult>;
|
|
293
381
|
|
|
@@ -311,6 +399,11 @@ declare function validatePackageInputs(options: Pick<PackageLessonkitCourseOptio
|
|
|
311
399
|
}): ValidatePackageInputsResult;
|
|
312
400
|
declare function remapArtifactPaths(stagingRoot: string, outDir: string, artifactPath: string | undefined): string | undefined;
|
|
313
401
|
|
|
402
|
+
/**
|
|
403
|
+
* Reject symlinks and paths escaping dist roots before packaging LMS artifacts.
|
|
404
|
+
*/
|
|
405
|
+
declare function assertSpaDistContentsSafe(spaDirs: Record<string, string>, projectRoot?: string): Promise<void>;
|
|
406
|
+
|
|
314
407
|
type LessonkitManifestPaths = {
|
|
315
408
|
spaDistDir: string;
|
|
316
409
|
lxpackOutDir: string;
|
|
@@ -340,4 +433,121 @@ type ParseManifestResult = {
|
|
|
340
433
|
declare function parseLessonkitManifest(raw: unknown, label?: string, projectRoot?: string): ParseManifestResult;
|
|
341
434
|
declare function loadLessonkitManifestFromFile(readJson: () => Promise<unknown>, label?: string, projectRoot?: string): Promise<ParseManifestResult>;
|
|
342
435
|
|
|
343
|
-
|
|
436
|
+
type LkcourseEnvelopeV1 = {
|
|
437
|
+
format: "lkcourse";
|
|
438
|
+
schemaVersion: 1;
|
|
439
|
+
lessonkitVersion: string;
|
|
440
|
+
exportedAt: string;
|
|
441
|
+
sourceManifest: LessonkitManifest;
|
|
442
|
+
entries: string[];
|
|
443
|
+
};
|
|
444
|
+
type BlockTreeNodeV1 = {
|
|
445
|
+
type: string;
|
|
446
|
+
rawTag?: string;
|
|
447
|
+
courseId?: string;
|
|
448
|
+
lessonId?: string;
|
|
449
|
+
checkId?: string;
|
|
450
|
+
blockId?: string;
|
|
451
|
+
nodeId?: string;
|
|
452
|
+
children?: BlockTreeNodeV1[];
|
|
453
|
+
};
|
|
454
|
+
type BlockTreeV1 = {
|
|
455
|
+
schemaVersion: 1;
|
|
456
|
+
sources: string[];
|
|
457
|
+
blocks: BlockTreeNodeV1[];
|
|
458
|
+
};
|
|
459
|
+
type LkcourseValidationIssue = {
|
|
460
|
+
path: string;
|
|
461
|
+
message: string;
|
|
462
|
+
};
|
|
463
|
+
type ExportLkcourseOptions = {
|
|
464
|
+
projectRoot: string;
|
|
465
|
+
manifest: LessonkitManifest;
|
|
466
|
+
outPath?: string;
|
|
467
|
+
includeBlockTree?: boolean;
|
|
468
|
+
lessonkitVersion?: string;
|
|
469
|
+
};
|
|
470
|
+
type ExportLkcourseResult = {
|
|
471
|
+
ok: true;
|
|
472
|
+
archivePath: string;
|
|
473
|
+
fileCount: number;
|
|
474
|
+
includeBlockTree: boolean;
|
|
475
|
+
} | {
|
|
476
|
+
ok: false;
|
|
477
|
+
issues: LkcourseValidationIssue[];
|
|
478
|
+
};
|
|
479
|
+
type ValidateLkcourseResult = {
|
|
480
|
+
ok: true;
|
|
481
|
+
envelope: LkcourseEnvelopeV1;
|
|
482
|
+
interchange: LessonkitInterchangeV1;
|
|
483
|
+
} | {
|
|
484
|
+
ok: false;
|
|
485
|
+
issues: LkcourseValidationIssue[];
|
|
486
|
+
};
|
|
487
|
+
type ImportLkcourseOptions = {
|
|
488
|
+
archivePath: string;
|
|
489
|
+
targetDir: string;
|
|
490
|
+
};
|
|
491
|
+
type ImportLkcourseResult = {
|
|
492
|
+
ok: true;
|
|
493
|
+
targetDir: string;
|
|
494
|
+
manifest: LessonkitManifest;
|
|
495
|
+
interchange: LessonkitInterchangeV1;
|
|
496
|
+
fileCount: number;
|
|
497
|
+
} | {
|
|
498
|
+
ok: false;
|
|
499
|
+
issues: LkcourseValidationIssue[];
|
|
500
|
+
};
|
|
501
|
+
type ExtractBlockTreeOptions = {
|
|
502
|
+
projectRoot: string;
|
|
503
|
+
blockTypes?: string[];
|
|
504
|
+
appSources?: string[];
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
type ParseEnvelopeResult = {
|
|
508
|
+
ok: true;
|
|
509
|
+
envelope: LkcourseEnvelopeV1;
|
|
510
|
+
} | {
|
|
511
|
+
ok: false;
|
|
512
|
+
issues: LkcourseValidationIssue[];
|
|
513
|
+
};
|
|
514
|
+
declare function parseLkcourseEnvelope(raw: unknown, label?: string): ParseEnvelopeResult;
|
|
515
|
+
|
|
516
|
+
declare function extractBlockTree(options: ExtractBlockTreeOptions): BlockTreeV1;
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Build a portable `.lkcourse` zip (manifest envelope + interchange + dist).
|
|
520
|
+
* Prefer `lessonkit export` in course projects.
|
|
521
|
+
*
|
|
522
|
+
* @example
|
|
523
|
+
* ```ts
|
|
524
|
+
* import { exportLkcourse } from "@lessonkit/lxpack";
|
|
525
|
+
*
|
|
526
|
+
* const result = await exportLkcourse({
|
|
527
|
+
* projectRoot: "/path/to/course",
|
|
528
|
+
* manifest: parsedLessonkitJson,
|
|
529
|
+
* archivePath: "handoff.lkcourse",
|
|
530
|
+
* });
|
|
531
|
+
* ```
|
|
532
|
+
*/
|
|
533
|
+
declare function exportLkcourse(options: ExportLkcourseOptions): Promise<ExportLkcourseResult>;
|
|
534
|
+
|
|
535
|
+
declare function validateLkcourseArchiveEntries(entries: Map<string, Uint8Array>, _archiveLabel: string): ValidateLkcourseResult;
|
|
536
|
+
declare function validateLkcourse(archivePath: string): ValidateLkcourseResult;
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Extract a `.lkcourse` archive into a project directory (manifest + dist tree).
|
|
540
|
+
*
|
|
541
|
+
* @example
|
|
542
|
+
* ```ts
|
|
543
|
+
* import { importLkcourse } from "@lessonkit/lxpack";
|
|
544
|
+
*
|
|
545
|
+
* const result = await importLkcourse({
|
|
546
|
+
* archivePath: "handoff.lkcourse",
|
|
547
|
+
* targetDir: "/path/to/dest",
|
|
548
|
+
* });
|
|
549
|
+
* ```
|
|
550
|
+
*/
|
|
551
|
+
declare function importLkcourse(options: ImportLkcourseOptions): Promise<ImportLkcourseResult>;
|
|
552
|
+
|
|
553
|
+
export { type AssessmentDescriptor, type BlockTreeNodeV1, type BlockTreeV1, type BuildLessonkitProjectOptions, type BuildStagingPackageOptions, type BuildStagingPackageResult, type DescriptorValidationIssue, type DescriptorValidationResult, type ExportLkcourseOptions, type ExportLkcourseResult, type ExtractBlockTreeOptions, type FillInBlanksAssessmentDescriptor, type ImportLkcourseOptions, type ImportLkcourseResult, type LessonDescriptor, type LessonkitCourseDescriptor, type LessonkitExportTarget, type LessonkitManifest, type LessonkitManifestPaths, type LkcourseEnvelopeV1, type LkcourseValidationIssue, type LxpackInjectedAssessment, type LxpackRuntimeTheme, type ManifestParseIssue, type MappedLessonkitIds, type McqAssessmentDescriptor, type PackageLessonkitCourseOptions, type PackageLessonkitCourseResult, type PackageValidationIssue, type ParseManifestResult, type ProjectPathsInput, type ReactParityIssue, type SpaLayout, type SpaLessonEntry, type TrueFalseAssessmentDescriptor, type ValidateLessonkitProjectOptions, type ValidateLkcourseResult, type ValidatePackageInputsResult, type ValidationIssue, type WriteLxpackProjectOptions, type WriteLxpackProjectResult, assertSpaDistContentsSafe, assessmentDescriptorToLxpack, buildLessonkitProject, buildStagingPackage, descriptorToInterchange, ensureOutDirParent, escapeShellText, exportLkcourse, extractAssessments, extractBlockTree, importLkcourse, loadLessonkitManifestFromFile, mapLessonkitIds, packageLessonkitCourse, parseLessonkitManifest, parseLkcourseEnvelope, promoteStagingToOutDir, remapArtifactPaths, resolveSafePackageOutputOverride, resolveSpaLessons, themeToLxpackRuntime, validateDescriptor, validateDescriptorForTarget, validateLessonkitProject, validateLkcourse, validateLkcourseArchiveEntries, validateManifestName, validatePackageInputs, validateProjectPaths, validateReactManifestParity, writeLxpackProject };
|