Behaviour defining the output-format interface for schema generators.
Implement this behaviour to add a new validation library target (e.g. Zod, Valibot).
AshTypescript.Codegen.SchemaCore handles all resource introspection, topological
sorting, and structural generation; implementations only provide the output syntax.
Implementing a new formatter
defmodule MyLib.SchemaFormatter do
@behaviour AshTypescript.Codegen.SchemaFormatter
def null_schema, do: "ml.null()"
def any_schema, do: "ml.any()"
# ...
end
Summary
Callbacks
Map of aggregate kind atoms to their schema strings (e.g. %{count: "z.number().int()"}).
Fallback schema for unknown/any type
Map of atom-symbol primitives (e.g. :map) to schema strings.
The import path for the validation library from application config.
Fallback for custom Ash types that carry a typescript_type_name
Enum schema from a comma-joined string of quoted values.
Build a float schema, applying min/max/gt/lt constraints if present.
Build an integer schema, applying min/max constraints if present.
Build a string schema, applying constraints if present.
require_non_empty is true when the field is non-nullable — callers should
enforce a minimum length of 1 when no explicit :min_length constraint exists.
Whether schema generation is enabled in the current project config.
The TypeScript import statement for the validation library (e.g. import { z } from "zod").
Human-readable library name for comments and error messages (e.g. "Zod" or "Valibot").
The library namespace prefix used when building schema declarations ("z" or "v").
Ltree type represented as an array of strings.
Ltree type represented as a string-or-array-of-strings union.
Schema for nil / null type
The schema variable name suffix (e.g. "Schema" or "ValibotSchema").
Human-readable label for the resource schemas section comment header.
Map of simple Ash type modules to schema strings — no constraint handling needed.
Map of third-party Ash type modules (e.g. AshMoney.Types.Money) to schema strings.
Wrap an inner schema string in an array type.
Wrap a schema string as nullable — i.e. the field's value may be null.
In zod this is .nullable(); in valibot, v.nullable(...).
Wrap a comma-joined set of key: schema fields in an inline object schema.
Wrap a schema string as omittable — i.e. the field may be absent from the
input object. In zod this is .optional(); in valibot, v.optional(...).
Both libraries' optional accepts undefined only — not null. To accept
null, compose with wrap_nullable/1.
Record/map schema — string keys, any values.
Wrap a comma-joined set of schema strings in a union type.
Callbacks
Map of aggregate kind atoms to their schema strings (e.g. %{count: "z.number().int()"}).
@callback any_schema() :: String.t()
Fallback schema for unknown/any type
Map of atom-symbol primitives (e.g. :map) to schema strings.
@callback configured_import_path() :: String.t()
The import path for the validation library from application config.
@callback custom_type_fallback() :: String.t()
Fallback for custom Ash types that carry a typescript_type_name
Enum schema from a comma-joined string of quoted values.
Build a float schema, applying min/max/gt/lt constraints if present.
Build an integer schema, applying min/max constraints if present.
Build a string schema, applying constraints if present.
require_non_empty is true when the field is non-nullable — callers should
enforce a minimum length of 1 when no explicit :min_length constraint exists.
@callback generate_schemas_enabled?() :: boolean()
Whether schema generation is enabled in the current project config.
The TypeScript import statement for the validation library (e.g. import { z } from "zod").
@callback library_name() :: String.t()
Human-readable library name for comments and error messages (e.g. "Zod" or "Valibot").
@callback library_prefix() :: String.t()
The library namespace prefix used when building schema declarations ("z" or "v").
@callback ltree_array() :: String.t()
Ltree type represented as an array of strings.
@callback ltree_union() :: String.t()
Ltree type represented as a string-or-array-of-strings union.
@callback null_schema() :: String.t()
Schema for nil / null type
@callback schema_suffix() :: String.t()
The schema variable name suffix (e.g. "Schema" or "ValibotSchema").
@callback section_header() :: String.t()
Human-readable label for the resource schemas section comment header.
Map of simple Ash type modules to schema strings — no constraint handling needed.
Map of third-party Ash type modules (e.g. AshMoney.Types.Money) to schema strings.
Wrap an inner schema string in an array type.
Wrap a schema string as nullable — i.e. the field's value may be null.
In zod this is .nullable(); in valibot, v.nullable(...).
For fields that may be both omitted and null (the common case for nullable
Ash attributes — JSON.stringify drops undefined keys, so clearing a
nullable attribute requires sending "field": null), compose with
wrap_optional/1. Convention: apply wrap_nullable first (innermost), then
wrap_optional. The result is equivalent to zod's .nullish() shorthand.
Wrap a comma-joined set of key: schema fields in an inline object schema.
Wrap a schema string as omittable — i.e. the field may be absent from the
input object. In zod this is .optional(); in valibot, v.optional(...).
Both libraries' optional accepts undefined only — not null. To accept
null, compose with wrap_nullable/1.
@callback wrap_record() :: String.t()
Record/map schema — string keys, any values.
Wrap a comma-joined set of schema strings in a union type.