1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use TokenStream;
/// Attribute macro for declaring a SeaORM database entity with auto-registration.
///
/// The macro wraps the annotated struct in a SeaORM entity module and submits an
/// `EntityRegistration` to the `inventory` collector so `modo_db::sync_and_migrate`
/// can discover it at startup.
///
/// # Required argument
///
/// - `table = "<name>"` — SQL table name.
///
/// # Optional argument
///
/// - `group = "<name>"` — assigns the entity to a named group (default: `"default"`).
/// Entities in a group can be synced separately via `modo_db::sync_and_migrate_group`.
///
/// # Struct-level options (applied as a second `#[entity(...)]` attribute)
///
/// - `timestamps` — injects `created_at` and `updated_at` columns of type
/// `DateTime<Utc>`; both are set automatically via `Record::apply_auto_fields`
/// on every insert and update.
/// - `soft_delete` — injects a `deleted_at: Option<DateTime<Utc>>` column. The
/// `delete` method becomes a soft-delete (sets `deleted_at`). Extra methods
/// generated on the struct: `with_deleted`, `only_deleted`, `restore`,
/// `force_delete`, `force_delete_by_id`, `delete_many` (bulk soft-delete),
/// `force_delete_many` (bulk hard-delete). `find_all` and `query` are overridden
/// to exclude soft-deleted rows automatically.
/// - `framework` — marks the entity as framework-internal (non-user schema).
/// - `index(columns = ["col1", "col2"])` — creates a composite index. Add `unique`
/// inside to make it a unique index.
///
/// # Field-level options (applied as `#[entity(...)]` on individual fields)
///
/// - `primary_key` — marks the field as the primary key.
/// - `auto_increment = true|false` — overrides SeaORM's default auto-increment behaviour.
/// - `auto = "ulid"|"nanoid"` — generates a ULID or NanoID before insert; only valid
/// on `primary_key` fields.
/// - `unique` — adds a unique constraint.
/// - `indexed` — creates a single-column index.
/// - `nullable` — accepted but has no effect (SeaORM infers nullability from `Option<T>`).
/// - `column_type = "<type>"` — overrides the inferred SeaORM column type string.
/// - `default_value = <literal>` — sets a default value (passed to SeaORM).
/// - `default_expr = "<expr>"` — sets a default SQL expression string.
/// - `belongs_to = "<Entity>"` — declares a `BelongsTo` relation to the named entity.
/// Pair with `on_delete` / `on_update` as needed.
/// - `to_column = "<Column>"` — overrides the target column for a `belongs_to` FK
/// (default: `"Id"`).
/// - `on_delete = "<action>"` — FK action on delete. One of: `Cascade`, `SetNull`,
/// `Restrict`, `NoAction`, `SetDefault`.
/// - `on_update = "<action>"` — FK action on update. Same values as `on_delete`.
/// - `has_many` — declares a `HasMany` relation (field is excluded from the model).
/// - `has_one` — declares a `HasOne` relation (field is excluded from the model).
/// - `via = "<JoinEntity>"` — used with `has_many` / `has_one` for many-to-many
/// relations through a join entity.
/// - `target = "<Entity>"` — overrides the inferred target entity name for `has_many`
/// / `has_one` relations when the field name does not match the entity name.
/// - `renamed_from = "<old_name>"` — records a rename hint as a column comment.
///
/// # Example
///
/// ```rust,ignore
/// #[modo_db::entity(table = "users")]
/// #[entity(timestamps, soft_delete)]
/// pub struct User {
/// #[entity(primary_key, auto = "ulid")]
/// pub id: String,
/// #[entity(unique)]
/// pub email: String,
/// pub name: String,
/// }
/// ```
/// Attribute macro for registering an escape-hatch SQL migration function.
///
/// The annotated async function is kept as-is and a `MigrationRegistration` is submitted
/// to the `inventory` collector so `modo_db::sync_and_migrate` runs it in version order.
///
/// # Required arguments
///
/// - `version = <u64>` — monotonically increasing migration version number.
/// - `description = "<text>"` — human-readable description shown in logs.
///
/// # Optional argument
///
/// - `group = "<name>"` — assigns the migration to a named group (default: `"default"`).
/// Migrations in a group run only when `modo_db::sync_and_migrate_group` is called
/// with the matching group name.
///
/// # Function signature
///
/// The annotated function must be `async` and accept a single `&sea_orm::DatabaseConnection`
/// parameter. Return type must be `Result<(), modo::Error>`.
///
/// # Example
///
/// ```rust,ignore
/// #[modo_db::migration(version = 1, description = "seed default roles")]
/// async fn seed_roles(db: &sea_orm::DatabaseConnection) -> Result<(), modo::Error> {
/// // run raw SQL or SeaORM operations
/// Ok(())
/// }
/// ```