Bloccs.Schema (bloccs v0.1.0)

Copy Markdown View Source

Versioned schema registry (Name@N).

Schemas declare the shape of payloads flowing between node ports. v0.1 ships a deliberately minimal API surface — this is the swap-out point for Protobuf or Avro at v0.5+.

A schema is identified by "Name@Version" (e.g. "Event@1"). Fields are a keyword list of {name, type} pairs. Types: :string, :integer, :float, :boolean, :atom, :map, {:list, type}, or another schema reference string.

Example

Bloccs.Schema.register("Event@1",
  id: :string,
  type: :string,
  payload: :map
)

Bloccs.Schema.validate("Event@1", %{
  id: "evt_1",
  type: "order.created",
  payload: %{"order_id" => 1001}
})
#=> :ok

The registry is backed by :persistent_term so lookups are fast and lock-free. Schemas are registered eagerly by the consuming application (or by the manifest parser as it walks port declarations).

Summary

Functions

Clear the entire registry. Test-only — never call from application code.

Look up a schema, raising if missing.

Format a {name, version} pair as "Name@N".

List every registered schema id.

Look up a schema by "Name@N".

Parse a "Name@N" identifier. Raises on malformed input.

Register a schema. Idempotent — re-registering with the same fields is a no-op; changing the fields raises.

Validate that a payload matches a registered schema. Returns :ok or {:error, [reason]} listing every problem found.

Types

field()

@type field() :: {atom(), field_type()}

field_type()

@type field_type() ::
  :string
  | :integer
  | :float
  | :boolean
  | :atom
  | :map
  | {:list, field_type()}
  | String.t()

t()

@type t() :: %Bloccs.Schema{
  fields: [field()],
  name: String.t(),
  version: pos_integer()
}

Functions

clear!()

@spec clear!() :: :ok

Clear the entire registry. Test-only — never call from application code.

fetch!(id)

@spec fetch!(String.t()) :: t()

Look up a schema, raising if missing.

format_id(name, version)

@spec format_id(String.t(), pos_integer()) :: String.t()

Format a {name, version} pair as "Name@N".

list()

@spec list() :: [String.t()]

List every registered schema id.

lookup(id)

@spec lookup(String.t()) :: {:ok, t()} | :error

Look up a schema by "Name@N".

parse_id!(id)

@spec parse_id!(String.t()) :: {String.t(), pos_integer()}

Parse a "Name@N" identifier. Raises on malformed input.

register(id, fields)

@spec register(String.t() | {String.t(), pos_integer()}, [field()]) :: :ok

Register a schema. Idempotent — re-registering with the same fields is a no-op; changing the fields raises.

Accepts the "Name@N" shorthand or an explicit {name, version} tuple.

validate(id, payload)

@spec validate(String.t(), map()) :: :ok | {:error, [String.t()]}

Validate that a payload matches a registered schema. Returns :ok or {:error, [reason]} listing every problem found.