AshOaskit.SchemaBuilder.PropertyBuilders (AshOasKit v0.2.1)

View Source

Property builders for attributes, calculations, and aggregates.

This module handles the conversion of Ash resource properties (attributes, calculations, and aggregates) into OpenAPI JSON Schema property definitions.

Overview

When building schemas for Ash resources, each property type requires different handling:

  • Attributes - Core fields that map directly to JSON Schema types
  • Calculations - Computed fields that are always nullable (may not be loaded)
  • Aggregates - Computed summaries with type-specific schemas

Type Mapping

The module provides bidirectional type mapping between Ash types and JSON Schema:

Ash TypeJSON Schema
:string{"type": "string"}
:integer{"type": "integer"}
:float{"type": "number", "format": "float"}
:boolean{"type": "boolean"}
:uuid{"type": "string", "format": "uuid"}
:datetime{"type": "string", "format": "date-time"}
{:array, type}{"type": "array", "items": ...}

Aggregate Kinds

Different aggregate kinds produce different schemas:

KindSchema
:count{"type": "integer"}
:exists{"type": "boolean"}
:sum, :avg{"type": "number"}
:list{"type": "array", ...}
:first, :min, :maxType-dependent

Usage

This module is used internally by AshOaskit.SchemaBuilder to build property definitions:

properties = PropertyBuilders.build_attribute_properties(builder, attributes)
calc_props = PropertyBuilders.build_calculation_properties(builder, calculations)
agg_props = PropertyBuilders.build_aggregate_properties(builder, aggregates)

Summary

Functions

Maps aggregate kind to JSON Schema type.

Converts an aggregate to a JSON Schema.

Builds properties map from aggregates.

Builds properties map from attributes.

Builds properties map from calculations.

Converts a calculation to a JSON Schema.

Adds description to schema if present in the source map.

Normalizes Ash.Type.* modules to their atom equivalents.

Converts an Ash type to a basic JSON Schema.

Functions

aggregate_kind_to_schema(kind, agg)

@spec aggregate_kind_to_schema(atom(), map()) :: map()

Maps aggregate kind to JSON Schema type.

Static kinds (count, exists, sum, avg) have fixed schemas. Dynamic kinds (list, first, min, max, custom) depend on the aggregate's configured type.

Parameters

  • kind - The aggregate kind atom
  • agg - The aggregate struct (for type info)

Returns

A JSON Schema map for the aggregate kind.

aggregate_to_schema(builder, agg)

@spec aggregate_to_schema(map(), map()) :: map()

Converts an aggregate to a JSON Schema.

Maps the aggregate kind to its appropriate schema type, makes it nullable, and adds any description.

Parameters

  • builder - The SchemaBuilder accumulator
  • agg - The aggregate struct

Returns

A JSON Schema map for the aggregate.

build_aggregate_properties(builder, aggregates)

@spec build_aggregate_properties(map(), [map()]) :: map()

Builds properties map from aggregates.

Aggregates are computed values that summarize related data. Like calculations, they are always nullable because they may not be loaded. The schema depends on the aggregate kind.

Parameters

  • builder - The SchemaBuilder accumulator (for version info)
  • aggregates - List of Ash aggregate structs

Returns

A map of aggregate names (strings) to JSON Schema definitions.

build_attribute_properties(builder, attributes)

@spec build_attribute_properties(map(), [map()]) :: map()

Builds properties map from attributes.

Uses TypeMapper to convert Ash types to JSON Schema, selecting the appropriate version-specific mapper based on the builder's OpenAPI version.

Parameters

  • builder - The SchemaBuilder accumulator (for version info)
  • attributes - List of Ash attribute structs

Returns

A map of attribute names (strings) to JSON Schema definitions.

Examples

iex> attrs = [%{name: :title, type: :string, allow_nil?: false, constraints: []}]
...> PropertyBuilders.build_attribute_properties(%{version: "3.1"}, attrs)
%{title: %{"type" => "string"}}

build_attribute_properties_with_embedded(builder, attributes, embedded_handler)

@spec build_attribute_properties_with_embedded(map(), [map()], function()) ::
  {map(), map()}

Builds properties and generates embedded schemas.

Similar to build_attribute_properties/2 but also detects embedded resource types and adds their schemas to the builder. This is necessary for attributes that reference embedded Ash resources.

Parameters

  • builder - The SchemaBuilder accumulator
  • attributes - List of Ash attribute structs
  • embedded_handler - Function to call for embedded types

Returns

A tuple of {properties_map, updated_builder}.

build_calculation_properties(builder, calculations)

@spec build_calculation_properties(map(), [map()]) :: map()

Builds properties map from calculations.

Calculations are always nullable because they may not be loaded in the response. Each calculation is converted to its base schema and then wrapped to allow null values.

Parameters

  • builder - The SchemaBuilder accumulator (for version info)
  • calculations - List of Ash calculation structs

Returns

A map of calculation names (strings) to JSON Schema definitions.

calculation_to_schema(builder, calc)

@spec calculation_to_schema(map(), map()) :: map()

Converts a calculation to a JSON Schema.

Builds the base schema from the calculation's type, makes it nullable (calculations may not be loaded), and adds any description.

Parameters

  • builder - The SchemaBuilder accumulator
  • calc - The calculation struct

Returns

A JSON Schema map for the calculation.

make_nullable(schema, version)

See AshOaskit.Schemas.Nullable.make_nullable/2.

maybe_add_description(schema, source)

@spec maybe_add_description(map(), map()) :: map()

Adds description to schema if present in the source map.

Parameters

  • schema - The schema map to enhance
  • source - The source struct/map that may contain a description

Returns

The schema with description added if present.

normalize_type(type)

@spec normalize_type(atom()) :: atom()

Normalizes Ash.Type.* modules to their atom equivalents.

Maps module-based types like Ash.Type.String to their corresponding atom :string for consistent lookup.

Parameters

  • type - The type to normalize

Returns

The normalized atom type.

Examples

iex> PropertyBuilders.normalize_type(Ash.Type.String)
:string

iex> PropertyBuilders.normalize_type(:boolean)
:boolean

type_to_schema(type)

@spec type_to_schema(atom() | tuple()) :: map()

Converts an Ash type to a basic JSON Schema.

Used for calculations and aggregates. Handles both atom types (:string) and module types (Ash.Type.String) by normalizing to atoms first.

Parameters

  • type - The Ash type (atom, module, or tuple like {:array, type})

Returns

A JSON Schema map for the type.

Examples

iex> PropertyBuilders.type_to_schema(:string)
%{type: :string}

iex> PropertyBuilders.type_to_schema({:array, :integer})
%{type: :array, items: %{type: :integer}}