@blue-labs/language
v4.1.1
Published
Small, fast TypeScript runtime for the Blue Language: parse YAML/JSON into BlueNode graphs, preprocess (directives & mappings), resolve/merge types and references, and compute stable Blue IDs (Base58-SHA256) with first-class Zod interop.
Downloads
4,180
Readme
@blue-labs/language
Small, fast TypeScript runtime for the Blue Language: parse YAML/JSON into BlueNode graphs, preprocess (directives & mappings), resolve/merge types and references, and compute stable Blue IDs (Base58-SHA256) with first-class Zod interop.
Features
- BlueNode graph: single, list, map, typed values, metadata (name/description),
contracts, and references byblueId. - Preprocessing:
blue:directive (aliases, BlueId, or URL fetch with allow-list), inline-type mappings, implicit type inference for primitives. - Resolution/Merge: deterministic resolver with a pluggable MergingProcessor pipeline (value propagation, type checking, list/dict validators, metadata propagation, basic-type guard).
- BlueId: semantic content identity via
Blue.calculateBlueId*; low-level Section 8 hashing viaBlueIdCalculator; spec-native list controls ($previous,$pos,$empty); CIDv1 conversion. - Providers: resolve by BlueId from memory, repositories or built-in bootstrap content; sequential composition.
- Zod mapping: convert nodes to typed objects with schema extensions & Blue annotations; serialize objects back to Blue-shaped JSON.
- Limits & paths: restrict extension/merge by path or depth; compose limits.
- Patching & transforms: RFC-6902-style patch ops for BlueNode; recursive transform utilities.
- URL fetching: pluggable strategy + caching + domain allow-list (opt-in).
Installation
npm i @blue-labs/language zod
# or
yarn add @blue-labs/language zodQuick start
import { Blue, BasicNodeProvider, PathLimits } from '@blue-labs/language';
import { z } from 'zod';
// 1) Construct runtime (uses bootstrap types + your provider chain)
const blue = new Blue({
nodeProvider: new BasicNodeProvider(),
});
// 2) Parse YAML (or JSON) into a BlueNode
const yaml = `
name: Greeting
value: Hello, Blue!
`;
const node = blue.yamlToNode(yaml);
// 3) Resolve (merge types/references), optionally with limits
const resolved = blue.resolve(node, PathLimits.withMaxDepth(10));
// 4) Compute semantic BlueId
const blueId = blue.calculateBlueIdSync(resolved);
// 5) Map to a Zod schema (with annotations supported)
const Greeting = z.object({
name: z.string().optional(),
value: z.string(),
});
const asObject = blue.nodeToSchemaOutput(resolved, Greeting);
// 6) Convert back to JSON (choose strategy)
const official = blue.nodeToJson(resolved, 'official');Repository registration & versioned output
Register a generated repository package to resolve types and aliases. Historical type BlueIds are normalized by the ingestion helpers (yamlToNode/jsonValueToNode) after preprocessing; when you create nodes manually, ensure they already use current type BlueIds before type checks or schema output.
import { Blue } from '@blue-labs/language';
import { repository } from '@blue-repository/types';
const blue = new Blue({ repositories: [repository] });
const node = blue.jsonValueToNode({
type: { blueId: '...historical-blue-id...' },
value: 'hello',
});
// For manually constructed nodes, ensure current type BlueIds are used.Serialize to a specific repository version with BlueContext:
const json = blue.nodeToJson(node, {
format: 'official',
blueContext: {
repositories: {
myos: '...repo-blue-id...',
},
},
});API Overview (essentials)
Core graph
BlueNode– node model (name, description, type, itemType, keyType, valueType, value, items, properties, referenceblueId, blue directive).ResolvedBlueNode– wrapper for resolved nodes; includesgetMinimalNode()andgetMinimalBlueId().
Entry point
class Blue- Parsing:
yamlToNode(_)/jsonValueToNode(_)(+ async variants), which preprocess and normalize. - Preprocess: blue directive (
BlueDirectivePreprocessor) + default pipeline (Preprocessor). - Resolve:
resolve(node, limits)→ResolvedBlueNode. - IDs:
calculateBlueId(_)/calculateBlueIdSync(_)for semantic BlueId. - Mapping:
nodeToJson(node, 'official'|'simple'|'original'|{ format, blueContext }),nodeToSchemaOutput(node, zod). - Type checks:
isTypeOf(node, zod),isTypeOfNode(node, typeNode),isTypeOfBlueId(node, blueId). - Type aliases:
getTypeAliasByBlueId(blueId)(returns inline aliases likeTextfor core types andPackage/Typefor repository types, including historicalblueIdvalues resolved to current aliases;undefinedfor empty/unknown ids). - Helpers:
extend(node, limits),transform(node, fn),minimize(node),reverse(node)(deprecated alias),restoreInlineTypes(node). - Config: URL fetch allow-list (
enablePreprocessingDirectivesFetchForDomains([...])), global limits, repositories.
- Parsing:
Resolution & merge
Merger+MergingProcessorpipeline: value → types → lists/dicts → metadata → basic checks.- List overlays support
$previousappend anchors, positional$posrefinements, and$emptycontent elements. Legacy inherited-list marker forms are not emitted by minimization. createDefaultMergingProcessor()exports the default pipeline.
Providers
NodeProvider,SequentialNodeProvider,BootstrapProvider,InMemoryNodeProvider,BasicNodeProvider,RepositoryBasedNodeProvider.NodeProviderWrapper.wrap(...)composes bootstrap, repositories, and your provider.
Preprocessing
BlueDirectivePreprocessor: resolvesblue:directive (alias, BlueId, or URL).Preprocessor: runs transformations declared underblue:(replace inline type strings → BlueIds; infer basic types; validate inline types removed).BlueIdsMappingGenerator: accumulate BlueId mappings (repositories, custom, core).
Mapping & Zod
NodeToObjectConverter+ converters for primitives/arrays/tuples/sets/maps/objects; supports schema extension resolution viaTypeSchemaResolver.- Schema annotations:
withTypeBlueId,withBlueId,withBlueName,withBlueDescription,blueIdField,blueNodeField.
Blue IDs & CIDs
Blue.calculateBlueId*computes semantic BlueId by resolving and minimizing.BlueIdCalculatoris the low-level Section 8 hasher for already prepared shapes.BlueIdsvalidator;BlueIdToCidandCidToBlueIdconverters.
Identity and storage terms
- official / wrapped: spec representation using
valueanditems. - minimal overlay: compact authoring/storage form that resolves back to the same semantic identity.
- resolved tree: mutable runtime
ResolvedBlueNodeproduced byresolve(). - semantic BlueId: public identity stable across equivalent authoring, resolved, and minimal forms.
- reference BlueId: the document
blueIdfield, exposed asgetReferenceBlueId()/setReferenceBlueId()with legacygetBlueId()/setBlueId()aliases.
Provider ingest is strict: mixed blueId + payload and single-document
blueId: this / blueId: this#k inputs are rejected, while top-level document
sets with indexed this#k references are stored under a cyclic MASTER BlueId
and exposed as MASTER#i document identities. Supplied repository IDs must
match computed IDs. yamlToNode and jsonValueToNode remain permissive parse
APIs, while BlueNode input to calculateBlueId* is assumed to be already
preprocessed/normalized. Spec-native list controls are supported in Phase 1K,
and direct cyclic document-set identities are supported in Phase 2.
Limits
PathLimits,CompositeLimits, andNO_LIMITS. Build from node shape or explicit patterns.
Utilities
Nodes,NodeTransformer,NodePathAccessor(/pathgetter), patching viaapplyBlueNodePatch(es)implementing RFC-6902.- URL fetching:
UrlContentFetcherwith pluggable{ fetchUrl }and domain allow-list.
Docs
docs/resolve.md– resolver & merging pipeline.docs/preprocessor.md– blue directive, inference & mappings.docs/blue-id.md– BlueId algorithm and APIs.docs/benchmarks.md– benchmark scenarios, baselines, and comparison workflow.docs/glossary.md– identity, minimization, storage, and snapshot terminology.docs/adr/– architecture decisions for semantic BlueId, minimal storage, snapshots, list controls, and direct cycles.docs/mapping.md– Zod mapping and serialization.docs/architecture.md– end-to-end architecture.
Changelog
The Changelog is regularly updated to reflect what's changed in each new release.
Contributing
We welcome contributions! Please read our Contributing Guide to learn about how you can contribute.
License
This project is licensed under the MIT License. See the LICENSE file for more details.
