Documentation
¶
Overview ¶
Package engine is the pure mock-data core: it lifts an OpenAPI 3.1 document's component schemas into an entity model, infers the relation graph between them, and materializes relationally-consistent seed data into an in-memory store. It performs no I/O beyond parsing the spec bytes handed to it — no filesystem, no network — so it can be embedded by the server, the CLI, or a test with identical behaviour.
Index ¶
- Constants
- func FingerprintModel(model EntityModel) string
- func SpecPaths(spec []byte) []string
- func SpecTitle(spec []byte) string
- func SpecVersion(spec []byte) string
- func SpecWebhooks(spec []byte) []string
- func ValidateRelations(model EntityModel, entity string, row Row, ...) error
- type Cardinality
- type Confidence
- type Discriminator
- type DuplicateIDError
- type Entity
- type EntityModel
- type Field
- type InMemoryStore
- func (s *InMemoryStore) Collections() []string
- func (s *InMemoryStore) Create(_ context.Context, entity string, data Row) (Row, error)
- func (s *InMemoryStore) Delete(_ context.Context, entity, id string) (bool, error)
- func (s *InMemoryStore) Get(_ context.Context, entity, id string) (Row, error)
- func (s *InMemoryStore) Hydrate(_ context.Context, data MaterializedData) error
- func (s *InMemoryStore) List(_ context.Context, entity string) ([]Row, error)
- func (s *InMemoryStore) Model() EntityModel
- func (s *InMemoryStore) Reset(_ context.Context) error
- func (s *InMemoryStore) Update(_ context.Context, entity, id string, patch Row) (Row, error)
- type JSONSchema
- type MaterializeOptions
- type MaterializedData
- type RefIntegrityError
- type Relation
- type RelationShapeError
- type Row
- type SchemaProp
- type Snapshot
- type SnapshotIntegrityError
- type SnapshotMeta
- type SnapshotVersionError
- type SpecParseError
- type StateStore
- type UnknownEntityError
- type Via
Constants ¶
const SnapshotFormatVersion = 1
SnapshotFormatVersion is the on-disk envelope version.
Variables ¶
This section is empty.
Functions ¶
func FingerprintModel ¶
func FingerprintModel(model EntityModel) string
FingerprintModel returns a stable hex digest over the structural shape of the model (entity set, field shapes, relation graph) — NOT the raw OpenAPI doc. Two specs that yield the same entities/fields/relations fingerprint alike, so a snapshot is portable across cosmetic edits but rejected when the shape drifts.
func SpecPaths ¶
SpecPaths parses a spec and returns its declared top-level path templates in document order (best-effort; nil if the spec does not parse). The server uses these to alias declared path stems onto entity collections.
func SpecTitle ¶
SpecTitle parses a spec and returns its info.title (best-effort; "" if the spec does not parse or carries no title). Used as the graph heading.
func SpecVersion ¶
SpecVersion parses a spec and returns its info.version (best-effort; "" if the spec does not parse or carries no version). Used to stamp snapshots.
func SpecWebhooks ¶
SpecWebhooks parses a spec and returns the names of its declared top-level webhooks, sorted (best-effort; nil if the spec does not parse). Webhooks are incoming-event definitions, not servable routes — the server uses this only to warn at boot that they are declared but not served.
func ValidateRelations ¶
func ValidateRelations(model EntityModel, entity string, row Row, exists func(target, id string) (bool, error)) error
ValidateRelations is the single source of truth for relational integrity. It returns RelationShapeError for a malformed inferred FK value (non-array to-many / non-string to-one) before the existence check, and RefIntegrityError for a dangling id — so the live write path, the snapshot loader, and any external store (e.g. Postgres) enforce the same contract. Only inferred relations are enforced; null/absent values pass. exists reports whether id is present in target; an exists error aborts validation, and returning (true, nil) for an unknown target skips only that existence check (the shape check still runs).
Types ¶
type Cardinality ¶
type Cardinality string
Cardinality is the multiplicity of a relation edge.
const ( One Cardinality = "one" Many Cardinality = "many" )
Relation cardinalities.
type Confidence ¶
type Confidence string
Confidence records how sure relation inference is about an edge.
inferred — auto-wired with high confidence.
abstain — ambiguous (e.g. polymorphic anyOf); NOT wired, surfaced for an
x-relation promotion so it degrades safely.
const ( Inferred Confidence = "inferred" Abstain Confidence = "abstain" )
Relation-inference confidence levels.
type Discriminator ¶
type Discriminator struct {
PropertyName string `json:"propertyName,omitempty"`
}
Discriminator carries an OpenAPI polymorphism hint: which property names the active variant. It is captured so a generated polymorphic object can stamp the property identifying the variant it was built from.
type DuplicateIDError ¶
DuplicateIDError is returned when a create supplies an explicit id that already exists, so the server can answer 409 instead of silently overwriting.
func (*DuplicateIDError) Error ¶
func (e *DuplicateIDError) Error() string
type Entity ¶
type Entity struct {
Name string `json:"name"`
Fields []Field `json:"fields"`
Schema *JSONSchema `json:"schema,omitempty"`
}
Entity is a component schema lifted into the model.
func BuildEntities ¶
func BuildEntities(schemas []SchemaProp) []Entity
BuildEntities lifts ordered component schemas into the entity model. Only object-like schemas that carry properties (directly or via allOf) become entities; pure enums and scalar aliases are skipped — they are not relational nodes.
type EntityModel ¶
type EntityModel struct {
Entities []Entity `json:"entities"`
Relations []Relation `json:"relations"`
}
EntityModel is the full inferred model: entities plus the relation graph.
func BuildModel ¶
func BuildModel(spec []byte) (EntityModel, error)
BuildModel parses an OpenAPI 3.1 spec and builds its full entity model: the entities lifted from components.schemas plus the inferred relation graph.
type Field ¶
type Field struct {
Name string `json:"name"`
Type string `json:"type"` // string|number|integer|boolean|object|array|null
Format string `json:"format,omitempty"`
IsArray bool `json:"isArray"`
Required bool `json:"required"`
Schema *JSONSchema `json:"schema,omitempty"` // raw (still $ref-bearing) schema
}
Field is one property of an entity, with its coarse type resolved.
type InMemoryStore ¶
type InMemoryStore struct {
// contains filtered or unexported fields
}
InMemoryStore holds a working copy of the materialized data plus an immutable seed for Reset. Every read returns a clone; writes are checked against the model's inferred relations.
func NewInMemoryStore ¶
func NewInMemoryStore(model EntityModel, data MaterializedData) *InMemoryStore
NewInMemoryStore builds a store from a model and its materialized seed.
func (*InMemoryStore) Collections ¶
func (s *InMemoryStore) Collections() []string
Collections returns the entity names that have a collection, in model order.
func (*InMemoryStore) Create ¶
Create inserts a row, generating a missing id and checking FK integrity.
func (*InMemoryStore) Hydrate ¶
func (s *InMemoryStore) Hydrate(_ context.Context, data MaterializedData) error
Hydrate replaces every collection with pre-validated snapshot data.
func (*InMemoryStore) List ¶
List returns all rows for an entity (clones), or an error for an unknown entity.
func (*InMemoryStore) Model ¶
func (s *InMemoryStore) Model() EntityModel
Model returns the model this store was built from.
type JSONSchema ¶
type JSONSchema struct {
Ref string `json:"$ref,omitempty"` // e.g. "#/components/schemas/User"; empty if none
Type []string `json:"type,omitempty"` // normalized to a slice: nil, ["string"], or ["string","null"]
Format string `json:"format,omitempty"` // "uuid", "email", "date-time", …
Enum []any `json:"enum,omitempty"` // non-nil ⇒ a closed value set
Properties []SchemaProp `json:"properties,omitempty"` // ordered object properties
Required []string `json:"required,omitempty"`
Items *JSONSchema `json:"items,omitempty"` // element schema when Type includes "array"
OneOf []*JSONSchema `json:"oneOf,omitempty"`
AnyOf []*JSONSchema `json:"anyOf,omitempty"`
AllOf []*JSONSchema `json:"allOf,omitempty"`
Minimum *float64 `json:"minimum,omitempty"`
Maximum *float64 `json:"maximum,omitempty"`
MinLength *int `json:"minLength,omitempty"`
MaxLength *int `json:"maxLength,omitempty"`
MinItems *int `json:"minItems,omitempty"`
MaxItems *int `json:"maxItems,omitempty"`
Nullable bool `json:"nullable,omitempty"`
Default any `json:"default,omitempty"`
XRelation string `json:"x-relation,omitempty"` // x-relation extension: explicit target entity name
Discriminator *Discriminator `json:"discriminator,omitempty"`
}
JSONSchema is a minimal structural view of an OpenAPI 3.1 / JSON Schema node. A $ref is preserved verbatim as a relation-inference signal — it is never dereferenced here.
type MaterializeOptions ¶
type MaterializeOptions struct {
Count int // rows per entity; <=0 means the default (5)
}
MaterializeOptions tunes seed-data generation.
type MaterializedData ¶
MaterializedData maps an entity name to its rows.
func DeserializeSnapshot ¶
func DeserializeSnapshot(input any, model EntityModel) (MaterializedData, error)
DeserializeSnapshot validates an untrusted, JSON-decoded snapshot against the model and returns fully-cloned, ready-to-hydrate data. It returns SnapshotVersionError (wrong format/spec) or SnapshotIntegrityError (corrupt contents) and never loads partially.
func Materialize ¶
func Materialize(model EntityModel, opts MaterializeOptions) MaterializedData
Materialize produces relationally-consistent seed data in two phases.
Phase 1 creates every row of every entity with a stable id and leaf scalar values — relational fields are skipped. Phase 2 wires foreign keys by referencing ids that now exist, so cycles are inherently safe. Each entity and each relation draws from its own stable seed, so the dataset is deterministic.
Relational fields hold target ids, not embedded objects: one → an id, many → an array of ids. Abstain edges are left empty (null / []) — never guessed.
type RefIntegrityError ¶
RefIntegrityError is returned when a write would break referential integrity — a foreign-key field points at a non-existent target row. Servers map it to 422.
func (*RefIntegrityError) Error ¶
func (e *RefIntegrityError) Error() string
type Relation ¶
type Relation struct {
From string `json:"from"`
Field string `json:"field"`
To string `json:"to"`
Cardinality Cardinality `json:"cardinality"`
Confidence Confidence `json:"confidence"`
Via Via `json:"via"`
Candidates []string `json:"candidates,omitempty"` // abstain edges: targets that could not be disambiguated
}
Relation is a directed edge from one entity field to a target entity.
func InferRelations ¶
InferRelations infers the relation graph over a set of entities (heuristic v2). Edges resolve in descending priority: x-relation, direct $ref, single-entity anyOf/oneOf, Id/Sid/Gid suffix, then bare-name. Multi-entity anyOf/oneOf is polymorphic → an abstain edge (NOT wired) carrying its candidate targets. Output is sorted for deterministic graph dumps.
type RelationShapeError ¶
RelationShapeError is returned when a relational field has the wrong shape — an inferred to-one FK that is not an id string, or a to-many FK that is not an array of id strings. Distinct from RefIntegrityError (well-shaped but pointing at a missing row): this catches the value before it could be FK-checked at all. Servers map it to 422.
func (*RelationShapeError) Error ¶
func (e *RelationShapeError) Error() string
type Row ¶
Row is a stored entity row. It always carries a string "id"; other fields are dynamic. JSON (un)marshalling produces exactly this shape.
type SchemaProp ¶
type SchemaProp struct {
Name string `json:"name"`
Schema *JSONSchema `json:"schema"`
}
SchemaProp is one named property of an object schema. Properties are kept in document order (not a map) so field generation is deterministic across runs.
type Snapshot ¶
type Snapshot struct {
Meta SnapshotMeta `json:"meta"`
Data MaterializedData `json:"data"`
}
Snapshot is a portable capture of a store's working rows plus its guard header. The model, relations and reset baseline are rebuilt from the spec on load.
func SerializeSnapshot ¶
SerializeSnapshot captures the store's current rows into a fingerprinted snapshot. specVersion is optional (pass "" to omit).
type SnapshotIntegrityError ¶
type SnapshotIntegrityError struct {
Entity string
Field string // empty ⇒ omitted from the message
Reason string
}
SnapshotIntegrityError is returned when a loaded snapshot is structurally corrupt — a bad envelope, a non-string/duplicate id, an unknown/non-array collection, a malformed or dangling foreign key. Field is empty when not applicable. Servers map it to 422.
func (*SnapshotIntegrityError) Error ¶
func (e *SnapshotIntegrityError) Error() string
type SnapshotMeta ¶
type SnapshotMeta struct {
FormatVersion int `json:"formatVersion"`
Fingerprint string `json:"fingerprint"`
SpecVersion string `json:"specVersion,omitempty"`
GeneratedAt string `json:"generatedAt"`
Counts map[string]int `json:"counts"`
}
SnapshotMeta is the guard header carried by every snapshot.
type SnapshotVersionError ¶
SnapshotVersionError is returned when a snapshot is well-formed but not for THIS server — an unsupported format version or a model fingerprint that does not match the current spec. Servers map it to 409.
func (*SnapshotVersionError) Error ¶
func (e *SnapshotVersionError) Error() string
type SpecParseError ¶
type SpecParseError struct{ Reason string }
SpecParseError is returned when input is not a usable OpenAPI 3.x document.
func (*SpecParseError) Error ¶
func (e *SpecParseError) Error() string
type StateStore ¶
type StateStore interface {
// Model returns the model this store was built from.
Model() EntityModel
// Collections returns entity names that have a collection.
Collections() []string
// List returns all rows for an entity (clones). Errors on an unknown entity.
List(ctx context.Context, entity string) ([]Row, error)
// Get returns a single row by id (clone), or (nil,nil) when absent.
Get(ctx context.Context, entity, id string) (Row, error)
// Create inserts a row; a missing id is generated. FK fields are checked.
Create(ctx context.Context, entity string, data Row) (Row, error)
// Update shallow-merges a patch; returns (nil,nil) when no such row.
Update(ctx context.Context, entity, id string, patch Row) (Row, error)
// Delete removes a row, reporting whether it existed.
Delete(ctx context.Context, entity, id string) (bool, error)
// Reset restores every collection to the original materialized seed.
Reset(ctx context.Context) error
// Hydrate atomically replaces every collection with pre-validated snapshot
// data. Callers MUST pass data already validated by DeserializeSnapshot. Does
// NOT change the reset baseline.
Hydrate(ctx context.Context, data MaterializedData) error
}
StateStore is the persistence seam. The server and CLI depend on this interface, never on a concrete store. v0 ships the in-memory implementation. The I/O methods take a context so a future DB-backed store can cancel work; the in-memory store ignores it.
func BuildStore ¶
func BuildStore(spec []byte, opts MaterializeOptions) (StateStore, error)
BuildStore is the one-call pipeline: spec → model → materialized seed → live in-memory store. The returned store is relationally consistent and rejects FK-breaking writes.
type UnknownEntityError ¶
type UnknownEntityError struct{ Entity string }
UnknownEntityError is returned when an operation names an entity the model does not define. Servers map it to 404.
func (*UnknownEntityError) Error ¶
func (e *UnknownEntityError) Error() string