@sutraa/kalpa-compiler
@sutraa/kalpa-compiler validates canonical manifests and provides a Node-only subpath for loading files, normalizing supported multi-file composition, and building portable JSON artifacts. The root entry point is framework-neutral; @sutraa/kalpa-compiler/node uses synchronous Node.js filesystem APIs.
npm install @sutraa/kalpa-compiler
Root API: validate an in-memory manifest
compileManifest(input, options?) accepts unknown input. It checks the schema, duplicate IDs, unresolved semantic references, and whether every behavior command is declared by its target capability.
import { compileManifest } from "@sutraa/kalpa-compiler";
const result = compileManifest(input, {
source: { file: "experience.kalpa.json", line: 1, column: 1 },
});
if (!result.ok || !result.manifest) {
for (const diagnostic of result.diagnostics) {
console.error(diagnostic.code, diagnostic.path, diagnostic.message);
}
} else {
console.log(result.summary);
}
| Result field | Meaning |
|---|---|
ok |
true only when no compiler diagnostic exists. |
manifest |
validated canonical manifest when ok is true. |
summary |
entity, relationship, capability, behavior, and representation counts. |
diagnostics |
structured errors with code, path, message, and optional source. |
Node API: files, composition, and artifacts
Import Node-only helpers from the explicit subpath.
import {
buildProjectArtifact,
compileManifestFile,
compileProjectFile,
loadProjectArtifact,
} from "@sutraa/kalpa-compiler/node";
Use compileManifestFile for a single canonical JSON manifest. Use compileProjectFile for either a canonical manifest or a supported composition entry. The latter normalizes valid fragments into a canonical manifest before returning it.
const project = compileProjectFile("./manifests/equipment.kalpa.json");
if (!project.ok) throw new Error(JSON.stringify(project.diagnostics));
const built = buildProjectArtifact(
"./manifests/equipment.kalpa.json",
"./dist/equipment.artifact.json",
);
if (!built.ok) throw new Error(JSON.stringify(built.diagnostics));
const loaded = loadProjectArtifact("./dist/equipment.artifact.json");
if (loaded.ok) console.log(loaded.artifact?.summary);
Supported composition model
Composition is authoring input, not renderer or runtime input. A composition entry owns the experience declaration and relationships; fragments each own exactly one or more of the required semantic collections. Every required collection must have one owner: entities, capabilities, behaviors, and representations.
{
"compositionVersion": "0.1",
"experience": { "id": "pump-demo", "name": "Pump demo", "purpose": "Inspect a pump", "defaultRepresentation": "dom" },
"relationships": [],
"fragments": ["./entities.kalpa.json", "./interaction.kalpa.json"]
}
{
"fragmentVersion": "0.1",
"owns": ["entities"],
"entities": []
}
| Rule | Consequence |
|---|---|
| A fragment reference appears twice | deterministic COMPOSITION_CONFLICT diagnostic. |
| Two fragments own the same collection | deterministic COMPOSITION_CONFLICT diagnostic. |
| A required collection has no owner | COMPOSITION_INVALID diagnostic. |
| Raw composition is sent to a runtime or renderer | unsupported contract use; compile first. |
The normal boundary is: raw composition → compileProjectFile → canonical manifest → runtime / renderer / artifact.
Artifact contents
buildProjectArtifact writes a JSON artifact with version, source provenance, semantic summary, canonical manifest, and graph snapshot. loadProjectArtifact reparses and revalidates that canonical manifest before returning it. Artifacts are designed for portable structured processing, not as an executable bundle.
License
MIT. Requires Node.js 18 or later.