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 associations suitable for nested creation (has_many and has_one). Excludes belongs_to (handled via FK), many_to_many, and through associations.
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
}
@spec associations_for_create(module()) :: [ %{field: atom(), cardinality: atom(), related: module(), type: atom()} ]
Returns associations suitable for nested creation (has_many and has_one). Excludes belongs_to (handled via FK), many_to_many, and through associations.
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]