Exosphere.ATProto.DataModel (Exosphere v0.3.0)

Copy Markdown View Source

Validation of values against the atproto data model.

atproto records are restricted to a subset of DAG-CBOR: no non-integral floats, string map keys, and the special wrapper objects ($link, $bytes, blobs) must have exactly the right shape. This module checks those rules on the JSON representation used by XRPC and the interop fixtures — the form where wrappers are still plain maps (%{"$link" => cid_string}) — so a value can be validated before encoding or after decoding.

Rules

  • Top level must be an object (map); map keys must be strings.
  • Allowed leaves: nil, booleans, integers, strings, and integer-valued floats (JSON has no integer/float distinction; 123.0 is fine, 123.456 is not representable in the data model).
  • {"$link": cid} — exactly one key; the value must be a string containing a valid CID.
  • {"$bytes": b64} — exactly one key; the value must be an unpadded base64 string (standard alphabet, no = padding), the form atproto specifies for byte strings.
  • A blob is {"$type": "blob", "ref": {"$link": …}, "mimeType": string, "size": non-negative integer} with exactly those keys.
  • $type, where present, must be a non-empty string (blobs require it).
  • Lists and maps validate recursively.

Examples

iex> Exosphere.ATProto.DataModel.valid?(%{"a" => [1, 2, nil]})
true

iex> Exosphere.ATProto.DataModel.valid?(%{"a" => 123.456})
false

Summary

Functions

Returns true when value conforms to the atproto data model.

Validate a value against the atproto data model.

Validate an atproto record: like validate/1 but the top level must be an object.

Types

value()

@type value() ::
  nil
  | boolean()
  | integer()
  | float()
  | String.t()
  | [value()]
  | %{optional(String.t()) => value()}

Functions

valid?(value)

@spec valid?(term()) :: boolean()

Returns true when value conforms to the atproto data model.

validate(value)

@spec validate(term()) :: :ok | {:error, {path :: String.t(), reason :: atom()}}

Validate a value against the atproto data model.

Returns :ok or {:error, reason} with a path-prefixed reason such as {:error, {"rcrd.a", :non_integral_float}}.

validate_record(v)

@spec validate_record(term()) ::
  :ok | {:error, {path :: String.t(), reason :: atom()}}

Validate an atproto record: like validate/1 but the top level must be an object.