Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

parsec-gen

parsec-gen reads a schema-registry snapshot and emits typed Go and TypeScript bindings for every registered channel pattern.

It is a separate binary from parsec; build it with go build ./cmd/parsec-gen or vendor the published release artifact.

Usage

# Go bindings from a running registry into ./gen/parsecgen.
parsec-gen --registry http://localhost:8000/parsec/schemas \
           --lang go --out ./gen/parsecgen \
           --package parsecgen

# Both languages from a committed snapshot file.
parsec-gen --registry-file ./schemas.json \
           --lang go,ts --out ./gen

Flags

FlagDefaultPurpose
--registry <url>required if no --registry-fileSchema-registry HTTP endpoint
--registry-file <path>required if no --registryJSON snapshot on disk
--out <dir>./genOutput directory (created if missing)
--lang <list>goComma-separated targets: go, ts
--package <name>parsecgenGo package name (ignored for non-Go)
--header <text>emptyOptional header prepended to every emitted file

--registry and --registry-file are mutually exclusive.

Output

LanguageFileFormat
go<out>/parsec_gen.gogofmt-formatted package
ts<out>/index.tsNo external imports

For each ChannelPattern the generator emits:

  • A <Name>Pattern constant carrying the raw registry pattern.
  • A <Name>Channel(...) helper (only if the pattern has placeholders) that reconstructs a concrete channel name from typed arguments. Trailing ** placeholders become rest ...string in Go and rest: string[] in TypeScript.
  • One <Name><Aspect> type per declared aspect. The type follows the declared payload_schema: object becomes a struct/interface, array becomes an alias, scalars become a typed alias.

Naming

Pattern segments contribute to the type name in PascalCase; placeholder segments are dropped from the name and surface only in helper signatures. Aspect names are PascalCased and appended.

PatternAspectGenerated type
sessions:{id}dataSessionsData
brands:meridian.reportssummaryBrandsMeridianReportsSummary
events.**rawEventsRaw

Common initialisms (id, url, api, http, …) are uppercased in their entirety so the output passes staticcheck ST1003.

Wiring with the client

The Go output drops straight into client.OnAspectTyped[T any]:

sub, _ := pc.Subscribe(channel)
client.OnAspectTyped[parsecgen.SessionsData](sub, "data",
    func(d parsecgen.SessionsData, env envelope.Envelope) {
        fmt.Println(d.Text)
    })

The TypeScript output drops straight into parsec-client’s typedSubscribe<T> ergonomic:

import { sessionsChannel, type SessionsData } from "./gen/index";

const sub = client.typedSubscribe<SessionsData>(sessionsChannel(userId));
sub.on("publication", ({ data }) => {
  // data: SessionsData
});
await sub.subscribe();

See JavaScript Client (parsec-client) for the full integration.

Regeneration

The generator is deterministic — patterns and aspects are emitted in lexicographic order. Re-running with the same registry yields a byte-identical file. Commit the output and re-run in CI to detect unintended schema drift.