Returns the primary key field(s) for a schema.
Examples
iex> Ectomancer.SchemaIntrospection.primary_key(MyApp.Accounts.User)
[:id]
iex> Ectomancer.SchemaIntrospection.primary_key(MyApp.CompositeKeyModel)
[:org_id, :user_id]
Compile-time Ecto schema introspection for generating MCP tools.
This module provides utilities to read Ecto schema metadata at compile time and use it to generate MCP-compatible tool definitions.
schema_info = Ectomancer.SchemaIntrospection.analyze(MyApp.Accounts.User)
# Returns: %{
# fields: [:id, :email, :name, :inserted_at, :updated_at],
# types: %{id: :id, email: :string, name: :string, ...},
# associations: [%{field: :posts, cardinality: :many, related: MyApp.Blog.Post}],
# primary_key: [:id]
# }:string - String values:integer - Integer values:float / :decimal - Number values:boolean - Boolean values:date - Date values:time / :time_usec - Time values:naive_datetime / :naive_datetime_usec - Naive datetime values:utc_datetime / :utc_datetime_usec - UTC datetime valuesEcto.UUID - UUID values{:array, inner} - Array values:map - Map/object valuesAnalyzes an Ecto schema module and returns its metadata.
Returns true if the module is an Ecto schema.
Gets field information including type and nullable status.
Gets all associations for a schema module.
Returns the primary key field(s) for a schema.
Detects if a schema has a soft-delete field (e.g., deleted_at, archived_at).
Converts an Ecto type to a human-readable string representation.
Returns all fields except associations and primary key fields.
@spec analyze(module()) :: %{ fields: [atom()], types: %{required(atom()) => any()}, associations: [%{field: atom(), cardinality: atom(), related: module()}], primary_key: [atom()], embedded: boolean() }
Analyzes an Ecto schema module and returns its metadata.
schema_module - The Ecto schema module to analyzeA map containing:
:fields - List of field names (atoms):types - Map of field names to their Ecto types:associations - List of association information:primary_key - List of primary key field names:embedded - Boolean indicating if this is an embedded schemaiex> Ectomancer.SchemaIntrospection.analyze(MyApp.Accounts.User)
%{
fields: [:id, :email, :name, :role, :inserted_at, :updated_at],
types: %{
id: :id,
email: :string,
name: :string,
role: :string,
inserted_at: :utc_datetime,
updated_at: :utc_datetime
},
associations: [
%{field: :posts, cardinality: :many, related: MyApp.Blog.Post}
],
primary_key: [:id],
embedded: false
}
Returns true if the module is an Ecto schema.
iex> Ectomancer.SchemaIntrospection.ecto_schema?(MyApp.Accounts.User)
true
iex> Ectomancer.SchemaIntrospection.ecto_schema?(String)
false
Gets field information including type and nullable status.
iex> Ectomancer.SchemaIntrospection.field_info(MyApp.Accounts.User, :email)
%{type: :string, nullable: false}
Gets all associations for a schema module.
Returns a list of maps with association metadata.
Returns the primary key field(s) for a schema.
iex> Ectomancer.SchemaIntrospection.primary_key(MyApp.Accounts.User)
[:id]
iex> Ectomancer.SchemaIntrospection.primary_key(MyApp.CompositeKeyModel)
[:org_id, :user_id]
Detects if a schema has a soft-delete field (e.g., deleted_at, archived_at).
Returns the field name (atom) if found, nil otherwise. Only datetime-type
fields are considered valid soft-delete markers.
iex> Ectomancer.SchemaIntrospection.soft_delete_field(MyApp.Accounts.User)
:deleted_at
iex> Ectomancer.SchemaIntrospection.soft_delete_field(MyApp.Blog.Post)
nil
Converts an Ecto type to a human-readable string representation.
iex> Ectomancer.SchemaIntrospection.type_to_string(:string)
"string"
iex> Ectomancer.SchemaIntrospection.type_to_string({:array, :string})
"array of string"
iex> Ectomancer.SchemaIntrospection.type_to_string(Ecto.UUID)
"uuid"
Returns all fields except associations and primary key fields.
Useful for generating create/update forms.
iex> Ectomancer.SchemaIntrospection.writable_fields(MyApp.Accounts.User)
[:email, :name, :role]