morphic

module
v0.0.0-...-d4700bc Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 27, 2026 License: MIT

README

dexpace

morphic

Idiomatic SDKs and docs from any API spec. One spec-agnostic IR, many targets.

gate License Go Coverage

Morphic is a spec-to-SDK compiler. It reads an API specification in any supported source format, lowers it into one spec-agnostic intermediate representation (IR), and generates idiomatic SDKs and documentation from that IR. The IR is the contract: a compiler's only output is an IR document, and an emitter's only input is an IR document — the two never see each other, so a new source format and a new target language are independent pieces of work.

The design goal is lossless by default. Compilers preserve source semantics — composition (allOf/oneOf/anyOf), unions, discriminators, visibility, encodings, streaming — rather than flattening them early. Lowering to what a target language can express happens late, in emitter refiners, so no target's limitations leak backward into the shared representation.

Status: early development. The ir package and the OpenAPI 3.x compiler (Milestone 1) are implemented and exercised end-to-end by the morphic compile CLI; emitters are not built yet. There is no released version — the IR schema and the CLI surface are unstable and may change between commits. The full IR capability surface is fixed from day one, so later compilers land without reshaping it.

Contents

Pipeline · Status · Install · Usage · Package layout · Design docs · Building · License

Pipeline

spec ──▶ compiler ──▶ IR ──▶ passes ──▶ IR ──▶ emitter ──▶ SDK / docs
        (spec → IR)         (IR → IR)          (IR → artifacts)
  • Compilers (compilers/*) turn one source format into an IR document plus diagnostics. OpenAPI 3.x ships first; Swagger 2.0, TypeSpec, Smithy, GraphQL, AsyncAPI, Protobuf, and Erlang/OTP are planned against the same IR.
  • Passes (pass/) are small, order-explicit IR → IR transforms (validate, dedup, filter, version-slice, overlay). validate — referential integrity — runs by default.
  • Emitters (emitters/*, future) turn an IR document into artifacts for one target. SDK runtime policy (retry, timeout, telemetry, error taxonomy) is a separate emitter input, not part of the IR.

Every stage is a pure function f(input, options) → (output, diagnostics) with no package-level state. Stages never write to stderr or log; they return typed ir.Diagnostic values and the engine (or CLI) decides what is fatal.

Status

Milestone Scope State
1 IR package + OpenAPI 3.x compiler, validate pass, golden corpus, JSON round-trip Implemented
2 Swagger 2.0 lift into the OpenAPI compiler (format-version-normalization seam) Planned
3 First emitter — one language end-to-end (plan / refine / emit boundary) Planned
4 Second family compiler (TypeSpec or Smithy) — proves the spec-agnostic claim Planned
5 Event-shaped compiler (AsyncAPI), then GraphQL, Protobuf, Erlang/OTP Planned

Install

Requires Go 1.26 or newer.

go install github.com/dexpace/morphic/cmd/morphic@latest

Or build the CLI from a checkout:

go build -o morphic ./cmd/morphic

Usage

CLI

morphic compile lowers one OpenAPI 3.x spec into Morphic IR JSON on stdout, and writes diagnostics to stderr.

morphic compile openapi.yaml                 # IR JSON to stdout
morphic compile openapi.yaml -o api.ir.json  # ...or to a file
usage:
  morphic compile <spec-file> [-o out.json] [--fail-on error|warning] [--skip-validate]
Flag Meaning
-o <file> Write IR JSON to <file> instead of stdout.
--fail-on error|warning Exit non-zero when a diagnostic at or above this severity is emitted (default error).
--skip-validate Skip the referential-integrity validate pass.

Diagnostics print one per line as <severity> <code> <path>#<pointer>: <message>. Exit codes: 0 clean, 1 a diagnostic reached the --fail-on threshold (or the spec could not be lowered), 2 a usage or I/O error.

Library

The same pipeline is available as a package. engine.New builds the default registry (OpenAPI compiler + validate pass); Run sniffs the format, compiles, and runs passes.

eng, err := engine.New()
if err != nil {
    return err
}

res, err := eng.Run(context.Background(), "openapi.yaml", engine.RunOptions{})
if err != nil {
    return err
}

for _, d := range res.Diagnostics {
    // res.Diagnostics are typed ir.Diagnostic values, not log lines.
}
doc := res.Document // *ir.Document — round-trips through JSON deterministically

Package layout

The import graph is layered and enforced by an architecture test (internal/archtest): each package may import only the packages one layer below it.

Package Layer Imports
ir/ 0 — IR nodes, IDs, traversal, JSON round-trip stdlib only
compilers/* 1 — one compiler per format (compilers/openapi) ir + own format libs
pass/ 1 — IR → IR passes ir only
emitters/* 2 — IR → artifacts (future) ir + emitter contract
engine/ 3 — orchestration everything below
cmd/morphic/ 4 — CLI engine

Compilers and emitters never import each other; the IR is the only thing that crosses between them.

Design docs

The design documents are normative — read them before proposing changes to the IR or pipeline.

Document Description
Architecture Pipeline stages, package layout, layering rules, milestones.
IR design The intermediate representation: node catalog, semantics, per-format lowering. ir-design.md field shapes are the contract.
Spec capability matrix What each source format can express — the union the IR is designed against.
Emitter design The emitter contract and the plan / refine / emit boundary.
Prior art Lessons taken from oagen, Kiota, and TypeSpec/TCGC, and the mistakes each Morphic decision avoids.
Reference learnings Detailed notes from the reference codebases studied during design.

Building

Standard Go tooling. These are the same checks the CI gate runs, and all must pass before a change lands:

gofmt -l .          # must print nothing
go vet ./...
golangci-lint run
go build ./...
go test ./...
./scripts/check-coverage.sh   # enforces 100% statement coverage, overall and per package

Run a single test with go test ./ir -run TestName. Golden IR snapshots are regenerated with the corpus test's -update flag after an intentional change.

License

Licensed under the MIT License. Copyright © 2026 dexpace.

Directories

Path Synopsis
cmd
morphic command
Command morphic is the Morphic CLI: it lowers an API spec into Morphic IR.
Command morphic is the Morphic CLI: it lowers an API spec into Morphic IR.
morphic-harness command
Command morphic-harness sweeps API specs through the Morphic bug-catching oracles (no panic/error, IR invariants, JSON round-trip, determinism) and reports the outcome per spec.
Command morphic-harness sweeps API specs through the Morphic bug-catching oracles (no panic/error, IR invariants, JSON round-trip, determinism) and reports the outcome per spec.
Package compilers defines the contract between spec compilers and the engine: a Compiler lowers source documents of its formats into an ir.Document plus diagnostics, purely and reentrantly.
Package compilers defines the contract between spec compilers and the engine: a Compiler lowers source documents of its formats into an ir.Document plus diagnostics, purely and reentrantly.
openapi
Package openapi lowers OpenAPI 3.0/3.1/3.2 documents into the Morphic IR.
Package openapi lowers OpenAPI 3.0/3.1/3.2 documents into the Morphic IR.
Package engine orchestrates the Morphic pipeline: it sniffs the source format, dispatches to the registered compiler, and runs IR passes.
Package engine orchestrates the Morphic pipeline: it sniffs the source format, dispatches to the registered compiler, and runs IR passes.
internal
harness
Package harness compiles OpenAPI specs and applies the bug-catching oracles (no panic/error, irverify invariants, JSON round-trip, determinism), returning a structured Result per spec.
Package harness compiles OpenAPI specs and applies the bug-catching oracles (no panic/error, irverify invariants, JSON round-trip, determinism), returning a structured Result per spec.
ir
Package ir defines Morphic's spec-agnostic intermediate representation: the single contract between spec compilers and generator emitters.
Package ir defines Morphic's spec-agnostic intermediate representation: the single contract between spec compilers and generator emitters.
irtest
Package irtest provides golden-snapshot helpers for IR documents.
Package irtest provides golden-snapshot helpers for IR documents.
irverify
Package irverify checks a compiled ir.Document against the structural invariants every compiler must uphold (stable IDs, no dangling references, neutral naming).
Package irverify checks a compiled ir.Document against the structural invariants every compiler must uphold (stable IDs, no dangling references, neutral naming).
Package pass hosts Morphic's IR-to-IR passes: pure analyses and transforms that consume an ir.Document and emit diagnostics (or, in later passes, a rewritten document).
Package pass hosts Morphic's IR-to-IR passes: pure analyses and transforms that consume an ir.Document and emit diagnostics (or, in later passes, a rewritten document).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL