@lxpack/api
v0.7.0
Published
Programmatic validate/build API for LXPack
Maintainers
Readme
@lxpack/api
Programmatic validate and build API for LXPack courses — the same logic the CLI uses, with structured results for Node integrations (LessonKit, CI, custom exporters).
Part of LXPack. Docs: LessonKit & React hub · Export to LMS.
| Related | Package |
|---------|---------|
| CLI (wraps this package) | @lxpack/cli |
| Schemas & filesystem checks | @lxpack/validators |
| ZIP / directory export | @lxpack/scorm |
Install
npm install @lxpack/apiRequires Node.js 18 or 20 (18+).
Usage
Validate
import { validateCourse } from "@lxpack/api";
const result = await validateCourse({
courseDir: "/path/to/my-course",
target: "scorm2004", // optional export-specific checks
});
if (!result.ok) {
for (const issue of result.issues) {
console.error(`${issue.severity} ${issue.path}: ${issue.message}`);
}
} else {
console.log(result.manifest.title);
}Build
import { buildCourse } from "@lxpack/api";
// ZIP (default)
const zip = await buildCourse({
courseDir: "/path/to/my-course",
target: "scorm12",
output: ".lxpack/course-scorm12.zip", // optional
outputBaseDir: ".lxpack",
});
if (!zip.ok) throw new Error("build failed");
console.log(zip.outputPath, zip.fileCount);
// Unpacked directory
const dir = await buildCourse({
courseDir: "/path/to/my-course",
target: "standalone",
dir: true,
output: ".lxpack/standalone",
});Targets: scorm12, scorm2004, standalone, xapi, cmi5.
Injected assessments
Pass assessment objects instead of reading assessments/*.yaml from disk:
await buildCourse({
courseDir: "/path/to/my-course",
target: "scorm12",
assessments: [
{
id: "quiz",
passingScore: 0.7,
questions: [
{
id: "q1",
prompt: "Ready?",
choices: [
{ id: "yes", text: "Yes", correct: true },
{ id: "no", text: "No" },
],
},
],
},
],
});The course manifest must still declare assessments: [{ id: quiz, file: ... }]; the API uses injected data at validate/build time.
LessonKit interchange (lessonkit.json)
v1 interchange requires format: "lessonkit" and version: "1". See lessonkit interchange reference.
packageLessonkit() (v0.5.0)
Package without hand-written course.yaml:
import { packageLessonkit } from "@lxpack/api";
const result = await packageLessonkit({
interchange: {
format: "lessonkit",
version: "1",
course: { title: "My SPA Course" },
lessons: [{ id: "main", type: "spa", path: "dist/main" }],
},
spaDirs: { main: "/abs/path/to/vite-dist" },
configDir: "/path/to/project", // optional — loads lxpack.config.json for defaultTarget / output.dir
target: "scorm12", // optional when configDir (or outputAnchorDir) has lxpack.config.json
assessments: [/* optional MCQ payloads */],
});Exports
| Export | Description |
|--------|-------------|
| validateCourse(options) | Validate course directory; returns { ok, manifest?, issues } |
| buildCourse(options) | Validate and package; returns paths and file counts |
| packageLessonkit(options) | Materialize interchange + SPA dirs, then build |
| ExportTarget | Re-exported from @lxpack/scorm |
| CourseManifest, ValidationIssue | Re-exported from @lxpack/validators |
Development
From the monorepo root:
pnpm --filter @lxpack/api build
pnpm --filter @lxpack/api test
pnpm --filter @lxpack/api typecheckLinks
License
Apache-2.0
