@7mind.io/baboon

中文文档
0.0.199发布于 2026/11/04BSD-2-ClauseTypeScriptES Module零依赖构建来源已验证近 30 天下载 3381

Baboon compiler and runtime bindings for JavaScript consumers.

原始使用文档
文档目录9 节
  1. Installation
  2. Usage
  3. Environment
  4. Running in a Web Worker
  5. API surface
  6. Loading a schema archive
  7. Converting envelopes
  8. Performance Optimization
  9. License

@7mind.io/baboon

JavaScript bindings for the Baboon compiler and runtime codecs.

Baboon lets you define data models in a compact DSL, generate source code for multiple languages, and encode/decode payloads with version-aware codecs.

Installation

npm install @7mind.io/baboon

Usage

import { BaboonCompiler } from "@7mind.io/baboon";

const model = `
model example.npm
version "1.0.0"

root data User {
  name: str
  age: i32
}
`;

const inputs = [{ path: "model.baboon", content: model }];

const result = await BaboonCompiler.compile({
  inputs,
  targets: [
    {
      language: "cs",
      generic: {
        generateTests: false,
        generateFixtures: false
      },
      cs: {
        generateJsonCodecs: true,
        generateUebaCodecs: true,
        deduplicate: true
      }
    }
  ],
  debug: false
});

if (!result.success) {
  throw new Error(result.errors?.join("\n") ?? "Compilation failed");
}

const files = { "model.baboon": model };

// Type identifiers follow `<pkg>/<owner>#<name>`, with `:` for top-level types.
const typeId = "example.npm/:#User";

const encoded = await BaboonCompiler.encode(
  files,
  "example.npm",
  "1.0.0",
  typeId,
  JSON.stringify({ name: "Ada", age: 42 }),
  false
);

if (!encoded.success || !encoded.data) {
  throw new Error(encoded.error ?? "Encoding failed");
}

const decoded = await BaboonCompiler.decode(
  files,
  "example.npm",
  "1.0.0",
  typeId,
  encoded.data
);

if (!decoded.success || !decoded.json) {
  throw new Error(decoded.error ?? "Decoding failed");
}

console.log(JSON.parse(decoded.json));

Environment

The package is plain ES modules with no runtime dependencies: the compiler is a single main.js, and it needs no host-provided globals, so the same files run in Node, in browsers and in Web Workers.

Running in a Web Worker

Loading and type-checking a model is synchronous and CPU-bound: a large multi-version archive can keep a thread busy for seconds. To keep a page responsive, run the compiler in a Web Worker. worker.js is a ready-made module-worker entry, and connectBaboonWorker gives the main thread the same methods as BaboonCompiler, each returning a Promise; the main thread never downloads or parses the compiler bundle:

// baboon.worker.js — the worker's entry, one line:
import "@7mind.io/baboon/worker.js";
import { connectBaboonWorker } from "@7mind.io/baboon/worker-client.js";

// `new Worker(new URL("./x.js", import.meta.url), { type: "module" })` is the form bundlers
// document for emitting a module worker with its dependencies.
const worker = new Worker(new URL("./baboon.worker.js", import.meta.url), { type: "module" });
const baboon = connectBaboonWorker(worker);

const model = await baboon.loadMany({ bytes });                 // runs in the worker
const result = await baboon.decodeEnvelopeLoaded(model, envelope);
await baboon.release(model);                                    // frees it in the worker

Without a bundler, point the worker at the package file itself (new Worker("/node_modules/@7mind.io/baboon/worker.js", { type: "module" }), or wherever it is served).

  • Models stay in the worker; the main thread holds opaque handles, usable only through the connection that loaded them, until release(model).
  • Arguments and results are copied with the structured-clone algorithm (no transfer): the caller keeps its buffers.
  • A worker-side failure rejects with the same message the in-thread call would; if the worker script fails to load or crashes, pending and later calls reject.
  • To serve on another port (a MessagePort, Node's worker_threads), call serveBaboon(port) from @7mind.io/baboon/worker-server.js in the worker and connectBaboonWorker(otherPort) on the other side.

API surface

  • BaboonCompiler.compile(options) → Promise<{ success, files?, errors? }>
  • BaboonCompiler.load(files) → Promise<BaboonLoadedModel>
  • BaboonCompiler.loadMany({ bytes } | { base64 }) → Promise<BaboonLoadedModel>
  • BaboonCompiler.listTypes(model) → BaboonTypeInfo[]
  • BaboonCompiler.generateRandom(model, pkg, version, idString) → { success, json?, error? }
  • BaboonCompiler.encode(files, pkg, version, idString, json, indexed) → Promise<{ success, data?, error? }>
  • BaboonCompiler.encodeLoaded(model, pkg, version, idString, json, indexed) → Promise<{ success, data?, error? }>
  • BaboonCompiler.decode(files, pkg, version, idString, data) → Promise<{ success, json?, error? }>
  • BaboonCompiler.decodeLoaded(model, pkg, version, idString, data) → Promise<{ success, json?, error? }>
  • BaboonCompiler.encodedEnvelopeLoaded(model, jsonEnvelope, { envelopeVersion, indexed }) → Promise<{ success, data?, error? }>
  • BaboonCompiler.decodeEnvelopeLoaded(model, uebaEnvelope) → Promise<{ success, json?, error? }>
  • BaboonCompiler.cleanupScheme(files, domain, version) / cleanupSchemeLoaded(model, domain, version) → Promise<{ success, content?, error? }>

load and loadMany reject with an Error whose message starts with Loading failed:; model issues are listed with the paths of the files (or archive entries) they come from.

Loading a schema archive

loadMany loads every schema of a schema archive (a ZIP file, conventionally *.bsm) held in memory, together, through the same pipeline as load, and returns the same handle:

// e.g. written by: baboon --model-dir ./models :scheme --domains="*@*" --zip-output=schemas.bsm
const model = await BaboonCompiler.loadMany({ bytes: new Uint8Array(await response.arrayBuffer()) });
const same = await BaboonCompiler.loadMany({ base64: "UEsDBAoAAAg..." }); // plain base64, not a data: URL

Pass exactly one of bytes (a Uint8Array, Node's Buffer included) or base64 (the standard alphabet; no data: prefix, no whitespace). Archive contract:

  • entries must be stored (method 0, what baboon :scheme --zip-output writes) or deflated (method 8, what zip tools write by default); other methods, encryption and ZIP64 are rejected;
  • entry paths must be relative /-separated paths without empty, . or .. segments, backslashes or drive prefixes, and unique;
  • directory entries are ignored; *.baboon entries are the schemas (UTF-8, at least one); *.bmo entries are only available to include, whose paths resolve next to the including entry first, then against the archive root; any other entry is rejected;
  • CRC-32 checksums are verified.

Archives are read in memory with no extra dependency, in Node and in browsers alike.

Converting envelopes

The facades of the generated runtimes wrap values in a top-level envelope that names the domain, version and type (docs/spec/codec-envelope.md). encodedEnvelopeLoaded turns a JSON envelope into a binary UEBA one; decodeEnvelopeLoaded does the reverse:

const json = JSON.stringify({ $mv: 1, $d: "example.npm", $v: "1.0.0", $t: typeId, $c: { name: "Ada", age: 42 } });
const bin = await BaboonCompiler.encodedEnvelopeLoaded(model, json, { envelopeVersion: 1, indexed: false });
const back = await BaboonCompiler.decodeEnvelopeLoaded(model, bin.data); // back.json === json
  • Both options are required: envelopeVersion is the binary layout (1, the facades' default, carries one compatibility bound; 2 carries both and is only readable by current runtimes), indexed the UEBA index mode (facades default to compact, false). Binary input is self-describing (v1 or v2, compact or indexed), so decoding takes no options.
  • This is format conversion, not migration: the domain, version and full type identifier (pkg/:#Name, pkg/ns#Name, pkg/[pkg/:#Adt]#Branch) are taken from the input and kept. The payload is read with that exact version. A writer newer than every loaded version is converted only when its envelope proves the payload byte-identical to a loaded version ($uv, or binary v2 minCompat); binary v1 envelopes cannot prove that and are refused.
  • Compatibility bounds are recomputed from the loaded model for the output format: JSON $rv (json-additive) and binary readableMin (prefix-compact / prefix-any-mode) promise different things and are never copied across. Bounds computed from a model that holds only part of a domain's lineage are conservative.
  • Errors are reported in error: malformed or truncated envelopes, unsupported metaVersion or flags, bounds out of order, unknown domains, versions or types, JSON fields the type does not declare, trailing bytes, and values the runtime codec cannot convert (any fields, foreign types without an rt mapping). JSON $mv may be the number 1 or the legacy string "1", or absent.

Performance Optimization

For repeated operations, load the model once and reuse it. This skips parsing and validation steps on each call:

// 1. Load model once
const model = await BaboonCompiler.load(files);

// 2. Encode/Decode multiple times efficiently
const encoded = await BaboonCompiler.encodeLoaded(
  model,
  "example.npm",
  "1.0.0",
  typeId,
  jsonPayload,
  false
);

const decoded = await BaboonCompiler.decodeLoaded(
  model,
  "example.npm",
  "1.0.0",
  typeId,
  encoded.data
);

License

BSD-2-Clause

版本与发布记录

@7mind.io/baboon 共发布 31 个版本,首次发布于 2025/12/02;过去 12 个月发布了 31 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.0.199latest2026/11/044 天前
0.0.1982026/10/2117 天前
0.0.1962026/09/251 个月前
0.0.1952026/07/283 个月前
0.0.1942026/07/243 个月前
0.0.1932026/07/074 个月前

关于 @7mind.io/baboon 的常见问题

@7mind.io/baboon 是什么?

Baboon compiler and runtime bindings for JavaScript consumers.

如何安装 @7mind.io/baboon?

在项目目录运行 npm install @7mind.io/baboon,或使用 pnpm add / yarn add / bun add。

@7mind.io/baboon 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@7mind.io/baboon 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@7mind.io/baboon 可以商用吗?

@7mind.io/baboon 使用 BSD-2-Clause 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@7mind.io/baboon 的下载量有多少?

根据 npm 官方下载统计,@7mind.io/baboon 在 2026/10/05 – 2026/11/03 这 30 天内被下载 3,381 次,日均约 113 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@7mind.io/baboon 还在维护吗?

最新版本 0.0.199 发布于 2026/11/04(4 天前);至今共发布 31 个版本,其中过去 12 个月发布了 31 个;首次发布于 2025/12/02。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。