Motivation
defineGraphExtension covers two distinct use cases that look identical to the runtime:
- Agent-induced schema — the kind set is unknown until an LLM proposes it. Compile-time types are genuinely impossible. String-keyed APIs are the right answer.
- Plugin / install-time extension — the extension document is known at publish time, just not when the core library was authored. A package ships an extension JSON; downstream consumers install it and want full typed ergonomics (
store.nodes.Paper.create(...), typed query builder rows, etc.).
Today both cases collapse to the runtime ergonomics, so case (2) pays the cost of case (1) without benefit.
Proposal
A codegen path that turns a static GraphExtension document into TypeScript declarations equivalent to what defineNode / defineEdge would produce.
CLI:
pnpm typegraph generate-types ./paper-extension.json --out ./paper-extension.d.ts
Programmatic:
import { generateTypesFromExtension } from "@nicia-ai/typegraph/codegen";
const dts = generateTypesFromExtension(document, { graphTypeName: "PaperGraph" });
Output declares branded NodeDefinition / EdgeDefinition types and a merged graph type so consumers can:
import type { PaperGraph } from "./paper-extension-types";
const store = (await createStoreWithSchema(graph, backend))[0] as Store<PaperGraph>;
await store.nodes.Paper.create({ doi: "...", title: "...", year: 2024 });
// ^ fully typed against the extension's property shape
The runtime path is unchanged — codegen is purely a TS surface that mirrors what the runtime already merges. Plugin authors ship the JSON; consumers run codegen at install time.
Acceptance criteria
- CLI generates
.d.ts from a valid GraphExtension JSON document, covering nodes, edges (including endpoint kinds), property modifiers (optional, searchable, embedding), unique constraints.
- Generated types pass
pnpm typecheck when imported.
- Generated types compose with existing compile-time graphs (merged graph type).
- Documentation distinguishes the two use cases (agent-induced vs. plugin/install-time) and points each to the appropriate API.
- Example: a small plugin package in
examples/ that ships an extension document + generated types, consumed by another example.
Scope
References
Motivation
defineGraphExtensioncovers two distinct use cases that look identical to the runtime:store.nodes.Paper.create(...), typed query builder rows, etc.).Today both cases collapse to the runtime ergonomics, so case (2) pays the cost of case (1) without benefit.
Proposal
A codegen path that turns a static
GraphExtensiondocument into TypeScript declarations equivalent to whatdefineNode/defineEdgewould produce.CLI:
Programmatic:
Output declares branded
NodeDefinition/EdgeDefinitiontypes and a merged graph type so consumers can:The runtime path is unchanged — codegen is purely a TS surface that mirrors what the runtime already merges. Plugin authors ship the JSON; consumers run codegen at install time.
Acceptance criteria
.d.tsfrom a validGraphExtensionJSON document, covering nodes, edges (including endpoint kinds), property modifiers (optional, searchable, embedding), unique constraints.pnpm typecheckwhen imported.examples/that ships an extension document + generated types, consumed by another example.Scope
defineGraphExtensionandstore.evolve()#101.References
defineGraphExtensionandstore.evolve()#101 graph extensionspackages/typegraph/src/graph-extension/defineNode,defineEdge,defineGraph