Skip to main content

L1: Compile-first

L1 is the second adoption level. You call compileApp() in your build pipeline and produce a CompiledEntrypointBundle that is deterministic, hashed, and CI-verifiable.

Why this exists

Without a compilation step, there is no artifact to inspect, diff in code review, or gate CI on. A raw spec document is a declaration; a compiled artifact is a verifiable guarantee. Every dependency, every entrypoint, and every capability requirement is resolved and committed.

A compiled artifact also tells you exactly what providers your spec needs at deploy time, before deployment begins. Provider mismatches are caught at compile time, not when a user hits an affected code path.

Installation

bun add @gooi/app
# or
npm install @gooi/app

Usage

import { readFileSync } from "node:fs";
import { defineApp } from "@gooi/app/define";
import { compileApp } from "@gooi/app/compile";

const raw = readFileSync("./app.yml", "utf-8");

// defineApp validates the spec and throws with a descriptive error if invalid
const spec = defineApp({ yaml: raw });

// compileApp produces a deterministic, hashed CompiledEntrypointBundle
const bundle = compileApp({ spec });

console.log("App ID:", bundle.appId);
console.log("Artifact hash:", bundle.hash);
console.log("Entrypoints:", Object.keys(bundle.entrypoints));
console.log(
"Capability requirements:",
bundle.capabilityRequirements.map((r) => r.portId)
);

The CompiledEntrypointBundle

The CompiledEntrypointBundle is the canonical output of compilation. It contains:

  • appId: the application identifier from app.id
  • hash: a SHA-256 hash of the deterministically serialized artifact
  • entrypoints: a map of entrypoint IDs to compiled entrypoint descriptors
  • capabilityRequirements: the full list of capability ports this app needs at runtime
  • surfaceDispatchPlans: compiled input binding maps for each declared surface

The hash is computed over lexically sorted keys and lexically ordered set-valued fields. Two compilations of the same spec at the same schema version always produce the same hash. Hash mismatches at runtime activation are hard failures.

warning

The compiled artifact is the only thing the runtime executes. The raw spec YAML is never read after compilation. Do not pass the raw spec to createAppRuntime().

Committing compiled artifacts

Committing compiled artifacts to source control gives you diffable history of what changed between deployments. You can gate CI on artifact validity using parseCompiledBundle().

import { parseCompiledBundle } from "@gooi/app/compile";
import { readFileSync } from "node:fs";

const raw = JSON.parse(readFileSync("./dist/bundle.json", "utf-8"));
const result = parseCompiledBundle(raw);
if (!result.success) {
console.error("Bundle is invalid:", result.error.issues);
process.exit(1);
}

What's next