@c9up/atlas 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/db.darwin-arm64.node +0 -0
  2. package/db.darwin-x64.node +0 -0
  3. package/db.linux-arm64-gnu.node +0 -0
  4. package/db.linux-x64-gnu.node +0 -0
  5. package/db.win32-x64-msvc.node +0 -0
  6. package/dist/AtlasProvider.d.ts +106 -0
  7. package/dist/AtlasProvider.d.ts.map +1 -0
  8. package/dist/AtlasProvider.js +190 -0
  9. package/dist/AtlasProvider.js.map +1 -0
  10. package/dist/BaseEntity.d.ts +255 -0
  11. package/dist/BaseEntity.d.ts.map +1 -0
  12. package/dist/BaseEntity.js +420 -0
  13. package/dist/BaseEntity.js.map +1 -0
  14. package/dist/BaseRepository.d.ts +175 -0
  15. package/dist/BaseRepository.d.ts.map +1 -0
  16. package/dist/BaseRepository.js +1451 -0
  17. package/dist/BaseRepository.js.map +1 -0
  18. package/dist/ModelQuery.d.ts +338 -0
  19. package/dist/ModelQuery.d.ts.map +1 -0
  20. package/dist/ModelQuery.js +1598 -0
  21. package/dist/ModelQuery.js.map +1 -0
  22. package/dist/Transaction.d.ts +15 -0
  23. package/dist/Transaction.d.ts.map +1 -0
  24. package/dist/Transaction.js +67 -0
  25. package/dist/Transaction.js.map +1 -0
  26. package/dist/adapters/NapiDbAdapter.d.ts +34 -0
  27. package/dist/adapters/NapiDbAdapter.d.ts.map +1 -0
  28. package/dist/adapters/NapiDbAdapter.js +96 -0
  29. package/dist/adapters/NapiDbAdapter.js.map +1 -0
  30. package/dist/config.d.ts +4 -0
  31. package/dist/config.d.ts.map +1 -0
  32. package/dist/config.js +4 -0
  33. package/dist/config.js.map +1 -0
  34. package/dist/configure.d.ts +10 -0
  35. package/dist/configure.d.ts.map +1 -0
  36. package/dist/configure.js +25 -0
  37. package/dist/configure.js.map +1 -0
  38. package/dist/decorators/entity.d.ts +235 -0
  39. package/dist/decorators/entity.d.ts.map +1 -0
  40. package/dist/decorators/entity.js +264 -0
  41. package/dist/decorators/entity.js.map +1 -0
  42. package/dist/decorators/hooks.d.ts +70 -0
  43. package/dist/decorators/hooks.d.ts.map +1 -0
  44. package/dist/decorators/hooks.js +107 -0
  45. package/dist/decorators/hooks.js.map +1 -0
  46. package/dist/decorators/scope.d.ts +35 -0
  47. package/dist/decorators/scope.d.ts.map +1 -0
  48. package/dist/decorators/scope.js +29 -0
  49. package/dist/decorators/scope.js.map +1 -0
  50. package/dist/errors.d.ts +54 -0
  51. package/dist/errors.d.ts.map +1 -0
  52. package/dist/errors.js +82 -0
  53. package/dist/errors.js.map +1 -0
  54. package/dist/index.d.ts +39 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +28 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/naming/NamingStrategy.d.ts +52 -0
  59. package/dist/naming/NamingStrategy.d.ts.map +1 -0
  60. package/dist/naming/NamingStrategy.js +65 -0
  61. package/dist/naming/NamingStrategy.js.map +1 -0
  62. package/dist/query/QueryBuilder.d.ts +95 -0
  63. package/dist/query/QueryBuilder.d.ts.map +1 -0
  64. package/dist/query/QueryBuilder.js +310 -0
  65. package/dist/query/QueryBuilder.js.map +1 -0
  66. package/dist/query/native.d.ts +18 -0
  67. package/dist/query/native.d.ts.map +1 -0
  68. package/dist/query/native.js +49 -0
  69. package/dist/query/native.js.map +1 -0
  70. package/dist/schema/Migration.d.ts +55 -0
  71. package/dist/schema/Migration.d.ts.map +1 -0
  72. package/dist/schema/Migration.js +68 -0
  73. package/dist/schema/Migration.js.map +1 -0
  74. package/dist/schema/MigrationRunner.d.ts +115 -0
  75. package/dist/schema/MigrationRunner.d.ts.map +1 -0
  76. package/dist/schema/MigrationRunner.js +406 -0
  77. package/dist/schema/MigrationRunner.js.map +1 -0
  78. package/dist/schema/Schema.d.ts +22 -0
  79. package/dist/schema/Schema.d.ts.map +1 -0
  80. package/dist/schema/Schema.js +51 -0
  81. package/dist/schema/Schema.js.map +1 -0
  82. package/dist/schema/SchemaBuilder.d.ts +14 -0
  83. package/dist/schema/SchemaBuilder.d.ts.map +1 -0
  84. package/dist/schema/SchemaBuilder.js +13 -0
  85. package/dist/schema/SchemaBuilder.js.map +1 -0
  86. package/dist/schema/Seeder.d.ts +54 -0
  87. package/dist/schema/Seeder.d.ts.map +1 -0
  88. package/dist/schema/Seeder.js +89 -0
  89. package/dist/schema/Seeder.js.map +1 -0
  90. package/dist/schema/TableBuilder.d.ts +95 -0
  91. package/dist/schema/TableBuilder.d.ts.map +1 -0
  92. package/dist/schema/TableBuilder.js +234 -0
  93. package/dist/schema/TableBuilder.js.map +1 -0
  94. package/dist/schema/types.d.ts +30 -0
  95. package/dist/schema/types.d.ts.map +1 -0
  96. package/dist/schema/types.js +19 -0
  97. package/dist/schema/types.js.map +1 -0
  98. package/dist/services/db.d.ts +22 -0
  99. package/dist/services/db.d.ts.map +1 -0
  100. package/dist/services/db.js +37 -0
  101. package/dist/services/db.js.map +1 -0
  102. package/dist/testing/DatabaseCleanup.d.ts +19 -0
  103. package/dist/testing/DatabaseCleanup.d.ts.map +1 -0
  104. package/dist/testing/DatabaseCleanup.js +39 -0
  105. package/dist/testing/DatabaseCleanup.js.map +1 -0
  106. package/dist/testing/Factory.d.ts +59 -0
  107. package/dist/testing/Factory.d.ts.map +1 -0
  108. package/dist/testing/Factory.js +105 -0
  109. package/dist/testing/Factory.js.map +1 -0
  110. package/dist/testing/TestDatabase.d.ts +25 -0
  111. package/dist/testing/TestDatabase.d.ts.map +1 -0
  112. package/dist/testing/TestDatabase.js +52 -0
  113. package/dist/testing/TestDatabase.js.map +1 -0
  114. package/dist/testing/index.d.ts +4 -0
  115. package/dist/testing/index.d.ts.map +1 -0
  116. package/dist/testing/index.js +4 -0
  117. package/dist/testing/index.js.map +1 -0
  118. package/dist/utils/casing.d.ts +5 -0
  119. package/dist/utils/casing.d.ts.map +1 -0
  120. package/dist/utils/casing.js +9 -0
  121. package/dist/utils/casing.js.map +1 -0
  122. package/dist/utils/dialectFromUrl.d.ts +10 -0
  123. package/dist/utils/dialectFromUrl.d.ts.map +1 -0
  124. package/dist/utils/dialectFromUrl.js +8 -0
  125. package/dist/utils/dialectFromUrl.js.map +1 -0
  126. package/dist/utils/identifier.d.ts +19 -0
  127. package/dist/utils/identifier.d.ts.map +1 -0
  128. package/dist/utils/identifier.js +27 -0
  129. package/dist/utils/identifier.js.map +1 -0
  130. package/dist/utils/safePath.d.ts +22 -0
  131. package/dist/utils/safePath.d.ts.map +1 -0
  132. package/dist/utils/safePath.js +46 -0
  133. package/dist/utils/safePath.js.map +1 -0
  134. package/dist/utils/transactionBrand.d.ts +5 -0
  135. package/dist/utils/transactionBrand.d.ts.map +1 -0
  136. package/dist/utils/transactionBrand.js +5 -0
  137. package/dist/utils/transactionBrand.js.map +1 -0
  138. package/index.darwin-arm64.node +0 -0
  139. package/index.darwin-x64.node +0 -0
  140. package/index.linux-arm64-gnu.node +0 -0
  141. package/index.linux-x64-gnu.node +0 -0
  142. package/index.win32-x64-msvc.node +0 -0
  143. package/package.json +1 -1
  144. package/src/AtlasProvider.ts +2 -2
  145. package/src/BaseRepository.ts +73 -11
  146. package/src/adapters/NapiDbAdapter.ts +1 -1
  147. package/src/schema/MigrationRunner.ts +16 -12
  148. package/src/schema/TableBuilder.ts +26 -0
  149. package/src/schema/types.ts +2 -0
  150. package/src/testing/DatabaseCleanup.ts +6 -7
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Entity decorators — @Entity, @Column, @PrimaryKey, @BelongsTo, @HasMany, @computed
3
+ *
4
+ * @implements FR29, FR30, stories 32.3, 32.4
5
+ */
6
+ import "reflect-metadata";
7
+ /** Auto-generation strategy for `@PrimaryKey({ generated: ... })`. */
8
+ export type PrimaryKeyGenerator = "uuid";
9
+ export interface PrimaryKeyOptions {
10
+ /**
11
+ * Auto-generate the primary-key value on INSERT when the entity has none
12
+ * (undefined). `'uuid'` produces an RFC-4122 v4 string via `crypto.randomUUID()`.
13
+ * Default: no auto-generation — the column relies on a DB default
14
+ * (`AUTOINCREMENT`, `SERIAL`, …) or the caller supplies a value.
15
+ */
16
+ generated?: PrimaryKeyGenerator;
17
+ }
18
+ export interface EntityMetadata {
19
+ tableName: string;
20
+ }
21
+ /**
22
+ * Column adapter — the `{ prepare?, consume? }` callback pair shared between
23
+ * `@Column({ prepare, consume })` (entity columns) and `pivotColumnAdapters`
24
+ * (m2m pivot extras). Single source of truth for the adapter shape; both
25
+ * `ColumnOptions` and `ColumnMetadata` extend this interface.
26
+ */
27
+ export interface ColumnAdapter {
28
+ /**
29
+ * Transform the model value before it is persisted (model → DB). Mirror of
30
+ * Adonis Lucid's `@column.prepare`.
31
+ *
32
+ * For entity columns, runs in `#entityToRow`, `#entityToRowPairs`,
33
+ * `#plainToRowPairs`, `#update`, and `#buildSetPairs`. For m2m pivot extras
34
+ * (`pivotColumnAdapters`), runs in the `attach()`/`sync()` row builder.
35
+ *
36
+ * **You MUST handle `null` and `undefined` yourself** — atlas calls the
37
+ * callback unconditionally for every value, including null/undefined, so a
38
+ * naive `(v: Decimal) => v.toString()` will throw on a null column. Return
39
+ * `null` for null/undefined inputs to preserve nullable semantics.
40
+ *
41
+ * For pivot extras specifically: when `attach()` is called with
42
+ * heterogeneous entries (the same extra key present on some entries and
43
+ * absent on others), the absent entries back-fill the missing key as
44
+ * `null` BEFORE `prepare` is called — your adapter must be null-safe even
45
+ * when no caller wrote null explicitly on that row.
46
+ *
47
+ * MUST stay synchronous; the bind layer cannot await before handing values
48
+ * to the Rust DML compiler. Returning a Promise throws.
49
+ */
50
+ prepare?: (value: unknown) => unknown;
51
+ /**
52
+ * Transform the raw DB value into the model attribute (DB → model). Mirror
53
+ * of Adonis Lucid's `@column.consume`. For entity columns, runs in
54
+ * `#hydrate`. For m2m pivot extras, runs in the `$extras.pivot_<col>`
55
+ * projection (currently dormant — see `pivotColumnAdapters` JSDoc).
56
+ *
57
+ * **You MUST handle `null` and `undefined` yourself** — atlas calls the
58
+ * callback unconditionally for every present row key, so a naive
59
+ * `(v: string) => v.trim()` will throw on a null column. Return `null` for
60
+ * null/undefined inputs to preserve nullable semantics.
61
+ *
62
+ * MUST stay synchronous (same constraint as `prepare`).
63
+ */
64
+ consume?: (value: unknown) => unknown;
65
+ }
66
+ export interface ColumnMetadata extends ColumnAdapter {
67
+ propertyKey: string;
68
+ type?: string;
69
+ nullable?: boolean;
70
+ default?: unknown;
71
+ serializeAs?: string | null;
72
+ serialize?: (value: unknown) => unknown;
73
+ }
74
+ export interface ColumnOptions extends ColumnAdapter {
75
+ type?: string;
76
+ nullable?: boolean;
77
+ default?: unknown;
78
+ /** Rename this column at `toJSON` time. Use `null` to hide it entirely. */
79
+ serializeAs?: string | null;
80
+ /** Transform the value at `toJSON` time (e.g. mask a phone number, coerce a Date). */
81
+ serialize?: (value: unknown) => unknown;
82
+ }
83
+ type Constructor = new (...args: unknown[]) => unknown;
84
+ export interface ManyToManyOptions {
85
+ /** Pivot table name joining the two sides (e.g., 'users_roles'). */
86
+ pivotTable: string;
87
+ /** Foreign key in the pivot table pointing to THIS entity (default: `${thisTable}_id`). */
88
+ foreignKey?: string;
89
+ /** Foreign key in the pivot table pointing to the RELATED entity (default: `${relatedTable}_id`). */
90
+ otherKey?: string;
91
+ /** Pivot extra columns to project into `$extras.pivot_<col>` on loaded relations (Story 31.8). */
92
+ pivotColumns?: string[];
93
+ /** Auto-write `created_at`/`updated_at` on `attach`/`sync` (Story 31.8). */
94
+ pivotTimestamps?: boolean | {
95
+ createdAt?: string | false;
96
+ updatedAt?: string | false;
97
+ };
98
+ /**
99
+ * Per-extra-column adapter map for typed pivot values. Mirrors
100
+ * `@Column({ prepare, consume })` for entity columns: `prepare` runs on
101
+ * every `attach()` / `sync()` write, before the value reaches the SQL bind
102
+ * layer; `consume` runs on every load that projects the extra into
103
+ * `$extras.pivot_<col>` (when the projection mechanism lands — currently
104
+ * the load-side hook is dormant).
105
+ *
106
+ * Keys are pivot-row column names as written in the SQL (e.g. `amount`);
107
+ * adapters are reused verbatim from `@c9up/atom/atlas` and friends so a
108
+ * caller can pass `{ amount: decimalAtlasAdapter }` without wrapping.
109
+ *
110
+ * Adapters that are NOT listed here keep current pass-through behaviour
111
+ * — backward compatible.
112
+ */
113
+ pivotColumnAdapters?: Record<string, ColumnAdapter>;
114
+ }
115
+ /** Per-relation key/onQuery overrides (Story 31.3 + 31.4). */
116
+ export interface RelationOptions {
117
+ /** Override the parent-side join column (default: parent PK). */
118
+ localKey?: string;
119
+ /** Override the child-side FK (default: `${parentSnake}_id` for hasOne/hasMany, `${relatedSnake}_id` on belongsTo parent row). */
120
+ foreignKey?: string;
121
+ /** `belongsTo` only — owner (target) side join column (default: related PK). */
122
+ ownerKey?: string;
123
+ /** Default constraint applied on every preload + lazy load (Story 31.4). */
124
+ onQuery?: (q: unknown) => void;
125
+ /** `toJSON()` key override — `null` hides the relation from serialization (Story 31.3). */
126
+ serializeAs?: string | null;
127
+ }
128
+ /** Configuration for `@HasOneThrough` / `@HasManyThrough` — two-hop relations (Story 31.2). */
129
+ export interface ThroughOptions extends RelationOptions {
130
+ /** FK on the *intermediate* table that points at the parent (default: `${parentSnake}_id`). */
131
+ firstKey?: string;
132
+ /** FK on the *related* table that points at the intermediate (default: `${intermediateSnake}_id`). */
133
+ secondKey?: string;
134
+ /** Parent-side local join column (default: parent PK). */
135
+ localKey?: string;
136
+ /** Intermediate-side local join column matched by `secondKey` (default: intermediate PK). */
137
+ secondLocalKey?: string;
138
+ }
139
+ export interface RelationMetadata extends RelationOptions {
140
+ propertyKey: string;
141
+ type: "belongsTo" | "hasOne" | "hasMany" | "hasOneThrough" | "hasManyThrough" | "manyToMany";
142
+ target: () => Constructor;
143
+ /** Intermediate ("through") model for two-hop relations — Story 31.2. */
144
+ through?: () => Constructor;
145
+ /** Extra through-specific keys. */
146
+ firstKey?: string;
147
+ secondKey?: string;
148
+ secondLocalKey?: string;
149
+ /** ManyToMany pivot configuration — required for type === 'manyToMany'. */
150
+ pivot?: ManyToManyOptions;
151
+ }
152
+ /** @Entity('table_name') — marks a class as a database entity. */
153
+ export declare function Entity(tableName: string): ClassDecorator;
154
+ /** @Column() — marks a property as a database column. */
155
+ export declare function Column(options?: ColumnOptions): PropertyDecorator;
156
+ /**
157
+ * @computed() — marks a getter as a computed column that shows up in `toJSON()`.
158
+ * The getter is NEVER read or written during persistence (it's derived from other
159
+ * real columns). Lucid-compatible alias.
160
+ *
161
+ * @implements Story 32.3
162
+ */
163
+ export declare function computed(): MethodDecorator;
164
+ export interface DateTimeColumnOptions extends ColumnOptions {
165
+ /** Set the column to `new Date()` on INSERT (like `created_at`). */
166
+ autoCreate?: boolean;
167
+ /** Set the column to `new Date()` on every UPDATE (like `updated_at`). */
168
+ autoUpdate?: boolean;
169
+ }
170
+ /** Symbol metadata key for per-column date-column config. Read by BaseRepository. */
171
+ export declare const DATE_COLUMNS_KEY: unique symbol;
172
+ export interface DateColumnConfig {
173
+ /** `true` means the column holds date-only values (no time). */
174
+ dateOnly: boolean;
175
+ autoCreate?: boolean;
176
+ autoUpdate?: boolean;
177
+ }
178
+ /**
179
+ * `@column.date()` — marks a property as a date-only column (YYYY-MM-DD).
180
+ * The raw DB value is hydrated to a JS Date; nulls pass through.
181
+ */
182
+ declare function columnDate(options?: ColumnOptions): PropertyDecorator;
183
+ /**
184
+ * `@column.dateTime({ autoCreate, autoUpdate })` — marks a property as a
185
+ * timestamp column. Hydrated to JS Date on read.
186
+ *
187
+ * `autoCreate`: BaseRepository sets it to `new Date()` on INSERT.
188
+ * `autoUpdate`: BaseRepository sets it to `new Date()` on every UPDATE.
189
+ */
190
+ declare function columnDateTime(options?: DateTimeColumnOptions): PropertyDecorator;
191
+ /**
192
+ * `Column` exposed with its sub-decorators (`Column.date()`, `Column.dateTime()`).
193
+ * Alias exports so TS users can `import { column } from '@c9up/atlas'` for a
194
+ * Lucid-style lowercase naming when they prefer.
195
+ */
196
+ export declare const column: typeof Column & {
197
+ date: typeof columnDate;
198
+ dateTime: typeof columnDateTime;
199
+ };
200
+ /** Read the date-column configuration map for an entity class (walks prototype chain). */
201
+ export declare function getDateColumnConfig(entityClass: object): Record<string, DateColumnConfig>;
202
+ /** @PrimaryKey() — marks a property as the primary key. */
203
+ export declare function PrimaryKey(options?: PrimaryKeyOptions): PropertyDecorator;
204
+ /**
205
+ * Read the PK auto-generation strategy declared via `@PrimaryKey({ generated })`.
206
+ * Returns `undefined` when the entity's PK has no generator — caller-supplied
207
+ * or DB-defaulted.
208
+ */
209
+ export declare function getPrimaryKeyGenerator(entityClass: object): PrimaryKeyGenerator | undefined;
210
+ /** @BelongsTo(() => Related, { foreignKey, ownerKey, onQuery, serializeAs }) */
211
+ export declare function BelongsTo(target: () => Constructor, options?: RelationOptions): PropertyDecorator;
212
+ /** @HasOne(() => Related, { localKey, foreignKey, onQuery, serializeAs }) */
213
+ export declare function HasOne(target: () => Constructor, options?: RelationOptions): PropertyDecorator;
214
+ /** @HasMany(() => Related, { localKey, foreignKey, onQuery, serializeAs }) */
215
+ export declare function HasMany(target: () => Constructor, options?: RelationOptions): PropertyDecorator;
216
+ /** @HasOneThrough(() => Related, () => Through, { firstKey, secondKey, localKey, secondLocalKey, onQuery }) */
217
+ export declare function HasOneThrough(target: () => Constructor, through: () => Constructor, options?: ThroughOptions): PropertyDecorator;
218
+ /** @HasManyThrough(() => Related, () => Through, { firstKey, secondKey, localKey, secondLocalKey, onQuery }) */
219
+ export declare function HasManyThrough(target: () => Constructor, through: () => Constructor, options?: ThroughOptions): PropertyDecorator;
220
+ /** @ManyToMany(() => Related, { pivotTable: 'users_roles' }) */
221
+ export declare function ManyToMany(target: () => Constructor, options: ManyToManyOptions & RelationOptions): PropertyDecorator;
222
+ /** Get entity metadata for a class. */
223
+ export declare function getEntityMetadata(target: Constructor): EntityMetadata | undefined;
224
+ /** Get column metadata for a class (returns a copy). */
225
+ export declare function getColumnMetadata(target: Constructor): ColumnMetadata[];
226
+ /** Get primary key property name. */
227
+ export declare function getPrimaryKey(target: Constructor): string | undefined;
228
+ /** Get relation metadata for a class (returns a copy). */
229
+ export declare function getRelationMetadata(target: Constructor): RelationMetadata[];
230
+ /** @SoftDeletes() — marks entity as soft-deletable via deleted_at column. */
231
+ export declare function SoftDeletes(): ClassDecorator;
232
+ /** Check if an entity class uses soft deletes. */
233
+ export declare function hasSoftDeletes(target: Constructor): boolean;
234
+ export {};
235
+ //# sourceMappingURL=entity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../src/decorators/entity.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,kBAAkB,CAAC;AAa1B,sEAAsE;AACtE,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC;AAEzC,MAAM,WAAW,iBAAiB;IACjC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,mBAAmB,CAAC;CAChC;AAED,MAAM,WAAW,cAAc;IAC9B,SAAS,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC7B;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;IACtC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;CACtC;AAED,MAAM,WAAW,cAAe,SAAQ,aAAa;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;CACxC;AAED,MAAM,WAAW,aAAc,SAAQ,aAAa;IACnD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,sFAAsF;IACtF,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;CACxC;AAED,KAAK,WAAW,GAAG,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;AAEvD,MAAM,WAAW,iBAAiB;IACjC,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAC;IACnB,2FAA2F;IAC3F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qGAAqG;IACrG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kGAAkG;IAClG,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,4EAA4E;IAC5E,eAAe,CAAC,EACb,OAAO,GACP;QAAE,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;KAAE,CAAC;IAC9D;;;;;;;;;;;;;;OAcG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CACpD;AAED,8DAA8D;AAC9D,MAAM,WAAW,eAAe;IAC/B,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kIAAkI;IAClI,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/B,2FAA2F;IAC3F,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,+FAA+F;AAC/F,MAAM,WAAW,cAAe,SAAQ,eAAe;IACtD,+FAA+F;IAC/F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sGAAsG;IACtG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6FAA6F;IAC7F,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACxD,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EACD,WAAW,GACX,QAAQ,GACR,SAAS,GACT,eAAe,GACf,gBAAgB,GAChB,YAAY,CAAC;IAChB,MAAM,EAAE,MAAM,WAAW,CAAC;IAC1B,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,WAAW,CAAC;IAC5B,mCAAmC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,iBAAiB,CAAC;CAC1B;AAED,kEAAkE;AAClE,wBAAgB,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAIxD;AAED,yDAAyD;AACzD,wBAAgB,MAAM,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,iBAAiB,CAuCjE;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,IAAI,eAAe,CAU1C;AAID,MAAM,WAAW,qBAAsB,SAAQ,aAAa;IAC3D,oEAAoE;IACpE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,qFAAqF;AACrF,eAAO,MAAM,gBAAgB,eAAkC,CAAC;AAEhE,MAAM,WAAW,gBAAgB;IAChC,gEAAgE;IAChE,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAcD;;;GAGG;AACH,iBAAS,UAAU,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,iBAAiB,CAK9D;AAED;;;;;;GAMG;AACH,iBAAS,cAAc,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,iBAAiB,CAS1E;AAUD;;;;GAIG;AACH,eAAO,MAAM,MAAM,EAAa,OAAO,MAAM,GAAG;IAC/C,IAAI,EAAE,OAAO,UAAU,CAAC;IACxB,QAAQ,EAAE,OAAO,cAAc,CAAC;CAChC,CAAC;AAEF,0FAA0F;AAC1F,wBAAgB,mBAAmB,CAClC,WAAW,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAWlC;AAED,2DAA2D;AAC3D,wBAAgB,UAAU,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,CAiBzE;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACrC,WAAW,EAAE,MAAM,GACjB,mBAAmB,GAAG,SAAS,CAUjC;AAED,gFAAgF;AAChF,wBAAgB,SAAS,CACxB,MAAM,EAAE,MAAM,WAAW,EACzB,OAAO,GAAE,eAAoB,GAC3B,iBAAiB,CASnB;AAED,6EAA6E;AAC7E,wBAAgB,MAAM,CACrB,MAAM,EAAE,MAAM,WAAW,EACzB,OAAO,GAAE,eAAoB,GAC3B,iBAAiB,CASnB;AAED,8EAA8E;AAC9E,wBAAgB,OAAO,CACtB,MAAM,EAAE,MAAM,WAAW,EACzB,OAAO,GAAE,eAAoB,GAC3B,iBAAiB,CASnB;AAED,+GAA+G;AAC/G,wBAAgB,aAAa,CAC5B,MAAM,EAAE,MAAM,WAAW,EACzB,OAAO,EAAE,MAAM,WAAW,EAC1B,OAAO,GAAE,cAAmB,GAC1B,iBAAiB,CAUnB;AAED,gHAAgH;AAChH,wBAAgB,cAAc,CAC7B,MAAM,EAAE,MAAM,WAAW,EACzB,OAAO,EAAE,MAAM,WAAW,EAC1B,OAAO,GAAE,cAAmB,GAC1B,iBAAiB,CAUnB;AAED,gEAAgE;AAChE,wBAAgB,UAAU,CACzB,MAAM,EAAE,MAAM,WAAW,EACzB,OAAO,EAAE,iBAAiB,GAAG,eAAe,GAC1C,iBAAiB,CAWnB;AASD,uCAAuC;AACvC,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,WAAW,GACjB,cAAc,GAAG,SAAS,CAE5B;AAED,wDAAwD;AACxD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,cAAc,EAAE,CAEvE;AAED,qCAAqC;AACrC,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAErE;AAED,0DAA0D;AAC1D,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,gBAAgB,EAAE,CAE3E;AAMD,6EAA6E;AAC7E,wBAAgB,WAAW,IAAI,cAAc,CAe5C;AAED,kDAAkD;AAClD,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAE3D"}
@@ -0,0 +1,264 @@
1
+ /**
2
+ * Entity decorators — @Entity, @Column, @PrimaryKey, @BelongsTo, @HasMany, @computed
3
+ *
4
+ * @implements FR29, FR30, stories 32.3, 32.4
5
+ */
6
+ import "reflect-metadata";
7
+ import { COLUMN_SERIALIZE_KEY, COMPUTED_KEY, } from "../BaseEntity.js";
8
+ const ENTITY_KEY = Symbol("atlas:entity");
9
+ const COLUMNS_KEY = Symbol("atlas:columns");
10
+ const PRIMARY_KEY = Symbol("atlas:primary");
11
+ const PRIMARY_KEY_GEN = Symbol("atlas:primary-gen");
12
+ const RELATIONS_KEY = Symbol("atlas:relations");
13
+ /** @Entity('table_name') — marks a class as a database entity. */
14
+ export function Entity(tableName) {
15
+ return (target) => {
16
+ Reflect.defineMetadata(ENTITY_KEY, { tableName }, target);
17
+ };
18
+ }
19
+ /** @Column() — marks a property as a database column. */
20
+ export function Column(options) {
21
+ return (target, propertyKey) => {
22
+ const columns = Reflect.getOwnMetadata(COLUMNS_KEY, target.constructor) ?? [];
23
+ const key = String(propertyKey);
24
+ // Deduplicate — @PrimaryKey also calls Column()
25
+ if (!columns.some((c) => c.propertyKey === key)) {
26
+ columns.push({
27
+ propertyKey: key,
28
+ type: options?.type,
29
+ nullable: options?.nullable,
30
+ default: options?.default,
31
+ serializeAs: options?.serializeAs,
32
+ serialize: options?.serialize,
33
+ prepare: options?.prepare,
34
+ consume: options?.consume,
35
+ });
36
+ Reflect.defineMetadata(COLUMNS_KEY, columns, target.constructor);
37
+ }
38
+ // Register serialize overrides on a separate map read by BaseEntity.toJSON.
39
+ // Stored per-class so subclasses can override a parent's serializeAs.
40
+ if (options?.serializeAs !== undefined ||
41
+ options?.serialize !== undefined) {
42
+ const serializeMap = Reflect.getOwnMetadata(COLUMN_SERIALIZE_KEY, target.constructor) ?? {};
43
+ serializeMap[key] = {
44
+ serializeAs: options.serializeAs,
45
+ serialize: options.serialize,
46
+ };
47
+ Reflect.defineMetadata(COLUMN_SERIALIZE_KEY, serializeMap, target.constructor);
48
+ }
49
+ };
50
+ }
51
+ /**
52
+ * @computed() — marks a getter as a computed column that shows up in `toJSON()`.
53
+ * The getter is NEVER read or written during persistence (it's derived from other
54
+ * real columns). Lucid-compatible alias.
55
+ *
56
+ * @implements Story 32.3
57
+ */
58
+ export function computed() {
59
+ return (target, propertyKey) => {
60
+ const list = Reflect.getOwnMetadata(COMPUTED_KEY, target.constructor) ?? [];
61
+ const key = String(propertyKey);
62
+ if (!list.includes(key)) {
63
+ list.push(key);
64
+ Reflect.defineMetadata(COMPUTED_KEY, list, target.constructor);
65
+ }
66
+ };
67
+ }
68
+ /** Symbol metadata key for per-column date-column config. Read by BaseRepository. */
69
+ export const DATE_COLUMNS_KEY = Symbol.for("atlas:dateColumns");
70
+ function registerDateColumn(target, propertyKey, config) {
71
+ const ctor = target.constructor;
72
+ const map = Reflect.getOwnMetadata(DATE_COLUMNS_KEY, ctor) ?? {};
73
+ map[String(propertyKey)] = config;
74
+ Reflect.defineMetadata(DATE_COLUMNS_KEY, map, ctor);
75
+ }
76
+ /**
77
+ * `@column.date()` — marks a property as a date-only column (YYYY-MM-DD).
78
+ * The raw DB value is hydrated to a JS Date; nulls pass through.
79
+ */
80
+ function columnDate(options) {
81
+ return (target, propertyKey) => {
82
+ Column(options)(target, propertyKey);
83
+ registerDateColumn(target, propertyKey, { dateOnly: true });
84
+ };
85
+ }
86
+ /**
87
+ * `@column.dateTime({ autoCreate, autoUpdate })` — marks a property as a
88
+ * timestamp column. Hydrated to JS Date on read.
89
+ *
90
+ * `autoCreate`: BaseRepository sets it to `new Date()` on INSERT.
91
+ * `autoUpdate`: BaseRepository sets it to `new Date()` on every UPDATE.
92
+ */
93
+ function columnDateTime(options) {
94
+ return (target, propertyKey) => {
95
+ Column(options)(target, propertyKey);
96
+ registerDateColumn(target, propertyKey, {
97
+ dateOnly: false,
98
+ autoCreate: options?.autoCreate,
99
+ autoUpdate: options?.autoUpdate,
100
+ });
101
+ };
102
+ }
103
+ /** Namespace access so users write `@column.date()` / `@column.dateTime()`. */
104
+ const columnWithSubs = Column;
105
+ columnWithSubs.date = columnDate;
106
+ columnWithSubs.dateTime = columnDateTime;
107
+ /**
108
+ * `Column` exposed with its sub-decorators (`Column.date()`, `Column.dateTime()`).
109
+ * Alias exports so TS users can `import { column } from '@c9up/atlas'` for a
110
+ * Lucid-style lowercase naming when they prefer.
111
+ */
112
+ export const column = Column;
113
+ /** Read the date-column configuration map for an entity class (walks prototype chain). */
114
+ export function getDateColumnConfig(entityClass) {
115
+ const merged = {};
116
+ let current = entityClass;
117
+ while (current && current !== Function.prototype) {
118
+ const map = Reflect.getOwnMetadata(DATE_COLUMNS_KEY, current);
119
+ if (map)
120
+ Object.assign(merged, map);
121
+ current = Object.getPrototypeOf(current);
122
+ }
123
+ return merged;
124
+ }
125
+ /** @PrimaryKey() — marks a property as the primary key. */
126
+ export function PrimaryKey(options) {
127
+ return (target, propertyKey) => {
128
+ Reflect.defineMetadata(PRIMARY_KEY, String(propertyKey), target.constructor);
129
+ if (options?.generated) {
130
+ Reflect.defineMetadata(PRIMARY_KEY_GEN, options.generated, target.constructor);
131
+ }
132
+ // Also register as a column
133
+ Column()(target, propertyKey);
134
+ };
135
+ }
136
+ /**
137
+ * Read the PK auto-generation strategy declared via `@PrimaryKey({ generated })`.
138
+ * Returns `undefined` when the entity's PK has no generator — caller-supplied
139
+ * or DB-defaulted.
140
+ */
141
+ export function getPrimaryKeyGenerator(entityClass) {
142
+ let current = entityClass;
143
+ while (current && current !== Function.prototype) {
144
+ const gen = Reflect.getOwnMetadata(PRIMARY_KEY_GEN, current);
145
+ if (gen)
146
+ return gen;
147
+ current = Object.getPrototypeOf(current);
148
+ }
149
+ return undefined;
150
+ }
151
+ /** @BelongsTo(() => Related, { foreignKey, ownerKey, onQuery, serializeAs }) */
152
+ export function BelongsTo(target, options = {}) {
153
+ return (proto, propertyKey) => {
154
+ addRelation(proto.constructor, {
155
+ propertyKey: String(propertyKey),
156
+ type: "belongsTo",
157
+ target,
158
+ ...options,
159
+ });
160
+ };
161
+ }
162
+ /** @HasOne(() => Related, { localKey, foreignKey, onQuery, serializeAs }) */
163
+ export function HasOne(target, options = {}) {
164
+ return (proto, propertyKey) => {
165
+ addRelation(proto.constructor, {
166
+ propertyKey: String(propertyKey),
167
+ type: "hasOne",
168
+ target,
169
+ ...options,
170
+ });
171
+ };
172
+ }
173
+ /** @HasMany(() => Related, { localKey, foreignKey, onQuery, serializeAs }) */
174
+ export function HasMany(target, options = {}) {
175
+ return (proto, propertyKey) => {
176
+ addRelation(proto.constructor, {
177
+ propertyKey: String(propertyKey),
178
+ type: "hasMany",
179
+ target,
180
+ ...options,
181
+ });
182
+ };
183
+ }
184
+ /** @HasOneThrough(() => Related, () => Through, { firstKey, secondKey, localKey, secondLocalKey, onQuery }) */
185
+ export function HasOneThrough(target, through, options = {}) {
186
+ return (proto, propertyKey) => {
187
+ addRelation(proto.constructor, {
188
+ propertyKey: String(propertyKey),
189
+ type: "hasOneThrough",
190
+ target,
191
+ through,
192
+ ...options,
193
+ });
194
+ };
195
+ }
196
+ /** @HasManyThrough(() => Related, () => Through, { firstKey, secondKey, localKey, secondLocalKey, onQuery }) */
197
+ export function HasManyThrough(target, through, options = {}) {
198
+ return (proto, propertyKey) => {
199
+ addRelation(proto.constructor, {
200
+ propertyKey: String(propertyKey),
201
+ type: "hasManyThrough",
202
+ target,
203
+ through,
204
+ ...options,
205
+ });
206
+ };
207
+ }
208
+ /** @ManyToMany(() => Related, { pivotTable: 'users_roles' }) */
209
+ export function ManyToMany(target, options) {
210
+ return (proto, propertyKey) => {
211
+ addRelation(proto.constructor, {
212
+ propertyKey: String(propertyKey),
213
+ type: "manyToMany",
214
+ target,
215
+ pivot: options,
216
+ onQuery: options.onQuery,
217
+ serializeAs: options.serializeAs,
218
+ });
219
+ };
220
+ }
221
+ function addRelation(target, relation) {
222
+ const relations = Reflect.getOwnMetadata(RELATIONS_KEY, target) ?? [];
223
+ relations.push(relation);
224
+ Reflect.defineMetadata(RELATIONS_KEY, relations, target);
225
+ }
226
+ /** Get entity metadata for a class. */
227
+ export function getEntityMetadata(target) {
228
+ return Reflect.getMetadata(ENTITY_KEY, target);
229
+ }
230
+ /** Get column metadata for a class (returns a copy). */
231
+ export function getColumnMetadata(target) {
232
+ return [...(Reflect.getMetadata(COLUMNS_KEY, target) ?? [])];
233
+ }
234
+ /** Get primary key property name. */
235
+ export function getPrimaryKey(target) {
236
+ return Reflect.getMetadata(PRIMARY_KEY, target);
237
+ }
238
+ /** Get relation metadata for a class (returns a copy). */
239
+ export function getRelationMetadata(target) {
240
+ return [...(Reflect.getMetadata(RELATIONS_KEY, target) ?? [])];
241
+ }
242
+ // ─── Soft Deletes ────────────────────────────────────────────
243
+ const SOFT_DELETE_KEY = Symbol("atlas:softDeletes");
244
+ /** @SoftDeletes() — marks entity as soft-deletable via deleted_at column. */
245
+ export function SoftDeletes() {
246
+ return (target) => {
247
+ Reflect.defineMetadata(SOFT_DELETE_KEY, true, target);
248
+ // Auto-add deleted_at as a column
249
+ const columns = Reflect.getOwnMetadata(COLUMNS_KEY, target) ?? [];
250
+ if (!columns.some((c) => c.propertyKey === "deletedAt")) {
251
+ columns.push({
252
+ propertyKey: "deletedAt",
253
+ type: "timestamp",
254
+ nullable: true,
255
+ });
256
+ Reflect.defineMetadata(COLUMNS_KEY, columns, target);
257
+ }
258
+ };
259
+ }
260
+ /** Check if an entity class uses soft deletes. */
261
+ export function hasSoftDeletes(target) {
262
+ return Reflect.getMetadata(SOFT_DELETE_KEY, target) === true;
263
+ }
264
+ //# sourceMappingURL=entity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity.js","sourceRoot":"","sources":["../../src/decorators/entity.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EACN,oBAAoB,EACpB,YAAY,GAEZ,MAAM,kBAAkB,CAAC;AAE1B,MAAM,UAAU,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;AAC1C,MAAM,WAAW,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;AAC5C,MAAM,WAAW,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;AAC5C,MAAM,eAAe,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC;AACpD,MAAM,aAAa,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAmKhD,kEAAkE;AAClE,MAAM,UAAU,MAAM,CAAC,SAAiB;IACvC,OAAO,CAAC,MAAM,EAAE,EAAE;QACjB,OAAO,CAAC,cAAc,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;IAC3D,CAAC,CAAC;AACH,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,MAAM,CAAC,OAAuB;IAC7C,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE;QAC9B,MAAM,OAAO,GACZ,OAAO,CAAC,cAAc,CAAC,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QAC/D,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;QAChC,gDAAgD;QAChD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,GAAG,CAAC,EAAE,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC;gBACZ,WAAW,EAAE,GAAG;gBAChB,IAAI,EAAE,OAAO,EAAE,IAAI;gBACnB,QAAQ,EAAE,OAAO,EAAE,QAAQ;gBAC3B,OAAO,EAAE,OAAO,EAAE,OAAO;gBACzB,WAAW,EAAE,OAAO,EAAE,WAAW;gBACjC,SAAS,EAAE,OAAO,EAAE,SAAS;gBAC7B,OAAO,EAAE,OAAO,EAAE,OAAO;gBACzB,OAAO,EAAE,OAAO,EAAE,OAAO;aACzB,CAAC,CAAC;YACH,OAAO,CAAC,cAAc,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QAClE,CAAC;QAED,4EAA4E;QAC5E,sEAAsE;QACtE,IACC,OAAO,EAAE,WAAW,KAAK,SAAS;YAClC,OAAO,EAAE,SAAS,KAAK,SAAS,EAC/B,CAAC;YACF,MAAM,YAAY,GACjB,OAAO,CAAC,cAAc,CAAC,oBAAoB,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;YACxE,YAAY,CAAC,GAAG,CAAC,GAAG;gBACnB,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,SAAS,EAAE,OAAO,CAAC,SAAS;aAC5B,CAAC;YACF,OAAO,CAAC,cAAc,CACrB,oBAAoB,EACpB,YAAY,EACZ,MAAM,CAAC,WAAW,CAClB,CAAC;QACH,CAAC;IACF,CAAC,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ;IACvB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE;QAC9B,MAAM,IAAI,GACT,OAAO,CAAC,cAAc,CAAC,YAAY,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QAChE,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACf,OAAO,CAAC,cAAc,CAAC,YAAY,EAAE,IAAI,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QAChE,CAAC;IACF,CAAC,CAAC;AACH,CAAC;AAWD,qFAAqF;AACrF,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;AAShE,SAAS,kBAAkB,CAC1B,MAAc,EACd,WAA4B,EAC5B,MAAwB;IAExB,MAAM,IAAI,GAAI,MAAkC,CAAC,WAAW,CAAC;IAC7D,MAAM,GAAG,GACR,OAAO,CAAC,cAAc,CAAC,gBAAgB,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;IACtD,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,MAAM,CAAC;IAClC,OAAO,CAAC,cAAc,CAAC,gBAAgB,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;AACrD,CAAC;AAED;;;GAGG;AACH,SAAS,UAAU,CAAC,OAAuB;IAC1C,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE;QAC9B,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACrC,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,cAAc,CAAC,OAA+B;IACtD,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE;QAC9B,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACrC,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE;YACvC,QAAQ,EAAE,KAAK;YACf,UAAU,EAAE,OAAO,EAAE,UAAU;YAC/B,UAAU,EAAE,OAAO,EAAE,UAAU;SAC/B,CAAC,CAAC;IACJ,CAAC,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,MAAM,cAAc,GAAG,MAGtB,CAAC;AACF,cAAc,CAAC,IAAI,GAAG,UAAU,CAAC;AACjC,cAAc,CAAC,QAAQ,GAAG,cAAc,CAAC;AAEzC;;;;GAIG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,MAGrB,CAAC;AAEF,0FAA0F;AAC1F,MAAM,UAAU,mBAAmB,CAClC,WAAmB;IAEnB,MAAM,MAAM,GAAqC,EAAE,CAAC;IACpD,IAAI,OAAO,GAAkB,WAAW,CAAC;IACzC,OAAO,OAAO,IAAI,OAAO,KAAK,QAAQ,CAAC,SAAS,EAAE,CAAC;QAClD,MAAM,GAAG,GAAG,OAAO,CAAC,cAAc,CAAC,gBAAgB,EAAE,OAAO,CAEhD,CAAC;QACb,IAAI,GAAG;YAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACpC,OAAO,GAAG,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,UAAU,CAAC,OAA2B;IACrD,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE;QAC9B,OAAO,CAAC,cAAc,CACrB,WAAW,EACX,MAAM,CAAC,WAAW,CAAC,EACnB,MAAM,CAAC,WAAW,CAClB,CAAC;QACF,IAAI,OAAO,EAAE,SAAS,EAAE,CAAC;YACxB,OAAO,CAAC,cAAc,CACrB,eAAe,EACf,OAAO,CAAC,SAAS,EACjB,MAAM,CAAC,WAAW,CAClB,CAAC;QACH,CAAC;QACD,4BAA4B;QAC5B,MAAM,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC/B,CAAC,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACrC,WAAmB;IAEnB,IAAI,OAAO,GAAkB,WAAW,CAAC;IACzC,OAAO,OAAO,IAAI,OAAO,KAAK,QAAQ,CAAC,SAAS,EAAE,CAAC;QAClD,MAAM,GAAG,GAAG,OAAO,CAAC,cAAc,CAAC,eAAe,EAAE,OAAO,CAE/C,CAAC;QACb,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC;QACpB,OAAO,GAAG,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,SAAS,CACxB,MAAyB,EACzB,UAA2B,EAAE;IAE7B,OAAO,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;QAC7B,WAAW,CAAC,KAAK,CAAC,WAAW,EAAE;YAC9B,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC;YAChC,IAAI,EAAE,WAAW;YACjB,MAAM;YACN,GAAG,OAAO;SACV,CAAC,CAAC;IACJ,CAAC,CAAC;AACH,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,MAAM,CACrB,MAAyB,EACzB,UAA2B,EAAE;IAE7B,OAAO,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;QAC7B,WAAW,CAAC,KAAK,CAAC,WAAW,EAAE;YAC9B,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC;YAChC,IAAI,EAAE,QAAQ;YACd,MAAM;YACN,GAAG,OAAO;SACV,CAAC,CAAC;IACJ,CAAC,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,OAAO,CACtB,MAAyB,EACzB,UAA2B,EAAE;IAE7B,OAAO,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;QAC7B,WAAW,CAAC,KAAK,CAAC,WAAW,EAAE;YAC9B,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC;YAChC,IAAI,EAAE,SAAS;YACf,MAAM;YACN,GAAG,OAAO;SACV,CAAC,CAAC;IACJ,CAAC,CAAC;AACH,CAAC;AAED,+GAA+G;AAC/G,MAAM,UAAU,aAAa,CAC5B,MAAyB,EACzB,OAA0B,EAC1B,UAA0B,EAAE;IAE5B,OAAO,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;QAC7B,WAAW,CAAC,KAAK,CAAC,WAAW,EAAE;YAC9B,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC;YAChC,IAAI,EAAE,eAAe;YACrB,MAAM;YACN,OAAO;YACP,GAAG,OAAO;SACV,CAAC,CAAC;IACJ,CAAC,CAAC;AACH,CAAC;AAED,gHAAgH;AAChH,MAAM,UAAU,cAAc,CAC7B,MAAyB,EACzB,OAA0B,EAC1B,UAA0B,EAAE;IAE5B,OAAO,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;QAC7B,WAAW,CAAC,KAAK,CAAC,WAAW,EAAE;YAC9B,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC;YAChC,IAAI,EAAE,gBAAgB;YACtB,MAAM;YACN,OAAO;YACP,GAAG,OAAO;SACV,CAAC,CAAC;IACJ,CAAC,CAAC;AACH,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,UAAU,CACzB,MAAyB,EACzB,OAA4C;IAE5C,OAAO,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;QAC7B,WAAW,CAAC,KAAK,CAAC,WAAW,EAAE;YAC9B,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC;YAChC,IAAI,EAAE,YAAY;YAClB,MAAM;YACN,KAAK,EAAE,OAAO;YACd,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,WAAW,EAAE,OAAO,CAAC,WAAW;SAChC,CAAC,CAAC;IACJ,CAAC,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,MAAc,EAAE,QAA0B;IAC9D,MAAM,SAAS,GACd,OAAO,CAAC,cAAc,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;IACrD,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzB,OAAO,CAAC,cAAc,CAAC,aAAa,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;AAC1D,CAAC;AAED,uCAAuC;AACvC,MAAM,UAAU,iBAAiB,CAChC,MAAmB;IAEnB,OAAO,OAAO,CAAC,WAAW,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AAChD,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,iBAAiB,CAAC,MAAmB;IACpD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,qCAAqC;AACrC,MAAM,UAAU,aAAa,CAAC,MAAmB;IAChD,OAAO,OAAO,CAAC,WAAW,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;AACjD,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,mBAAmB,CAAC,MAAmB;IACtD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,gEAAgE;AAEhE,MAAM,eAAe,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAEpD,6EAA6E;AAC7E,MAAM,UAAU,WAAW;IAC1B,OAAO,CAAC,MAAM,EAAE,EAAE;QACjB,OAAO,CAAC,cAAc,CAAC,eAAe,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QACtD,kCAAkC;QAClC,MAAM,OAAO,GACZ,OAAO,CAAC,cAAc,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;QACnD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC,EAAE,CAAC;YACzD,OAAO,CAAC,IAAI,CAAC;gBACZ,WAAW,EAAE,WAAW;gBACxB,IAAI,EAAE,WAAW;gBACjB,QAAQ,EAAE,IAAI;aACd,CAAC,CAAC;YACH,OAAO,CAAC,cAAc,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QACtD,CAAC;IACF,CAAC,CAAC;AACH,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,cAAc,CAAC,MAAmB;IACjD,OAAO,OAAO,CAAC,WAAW,CAAC,eAAe,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Lifecycle hook decorators — Lucid-compatible hook surface.
3
+ *
4
+ * Decorate a static method on an entity with one of the hooks below; Atlas
5
+ * fires it at the matching point in the BaseRepository CRUD pipeline. Hooks
6
+ * are inherited from the prototype chain — a hook on a parent entity also
7
+ * fires for subclasses.
8
+ *
9
+ * class User extends BaseEntity {
10
+ * @beforeSave()
11
+ * static async hashPassword(user: User) {
12
+ * if (user.isDirty('password')) {
13
+ * user.password = await hash(user.password)
14
+ * }
15
+ * }
16
+ * }
17
+ *
18
+ * @implements Story 32.1
19
+ */
20
+ import "reflect-metadata";
21
+ import type { BaseEntity } from "../BaseEntity.js";
22
+ import type { ModelQuery } from "../ModelQuery.js";
23
+ /** All hook kinds Atlas supports — mirrors Lucid's surface. */
24
+ export type HookKind = "beforeSave" | "afterSave" | "beforeCreate" | "afterCreate" | "beforeUpdate" | "afterUpdate" | "beforeDelete" | "afterDelete" | "beforeFind" | "afterFind" | "beforeFetch" | "afterFetch" | "beforePaginate" | "afterPaginate";
25
+ /** Argument shape for each hook kind. */
26
+ export interface HookArgs {
27
+ beforeSave: BaseEntity;
28
+ afterSave: BaseEntity;
29
+ beforeCreate: BaseEntity;
30
+ afterCreate: BaseEntity;
31
+ beforeUpdate: BaseEntity;
32
+ afterUpdate: BaseEntity;
33
+ beforeDelete: BaseEntity;
34
+ afterDelete: BaseEntity;
35
+ beforeFind: ModelQuery<BaseEntity>;
36
+ afterFind: BaseEntity | null;
37
+ beforeFetch: ModelQuery<BaseEntity>;
38
+ afterFetch: BaseEntity[];
39
+ beforePaginate: ModelQuery<BaseEntity>;
40
+ afterPaginate: BaseEntity[];
41
+ }
42
+ /** A hook handler is a static function that receives the kind-specific arg. */
43
+ export type HookHandler<K extends HookKind = HookKind> = (arg: HookArgs[K]) => void | Promise<void>;
44
+ export declare const beforeSave: () => MethodDecorator;
45
+ export declare const afterSave: () => MethodDecorator;
46
+ export declare const beforeCreate: () => MethodDecorator;
47
+ export declare const afterCreate: () => MethodDecorator;
48
+ export declare const beforeUpdate: () => MethodDecorator;
49
+ export declare const afterUpdate: () => MethodDecorator;
50
+ export declare const beforeDelete: () => MethodDecorator;
51
+ export declare const afterDelete: () => MethodDecorator;
52
+ export declare const beforeFind: () => MethodDecorator;
53
+ export declare const afterFind: () => MethodDecorator;
54
+ export declare const beforeFetch: () => MethodDecorator;
55
+ export declare const afterFetch: () => MethodDecorator;
56
+ export declare const beforePaginate: () => MethodDecorator;
57
+ export declare const afterPaginate: () => MethodDecorator;
58
+ /**
59
+ * Walk the prototype chain and collect every handler registered for `kind`.
60
+ * Parent-class hooks fire BEFORE child-class hooks (so a base entity can set
61
+ * up scoping that the child then refines).
62
+ */
63
+ export declare function collectHooks<K extends HookKind>(entityClass: new (...args: unknown[]) => BaseEntity, kind: K): HookHandler<K>[];
64
+ /**
65
+ * Fire every handler for `kind` sequentially. Awaits each one so a hook can
66
+ * mutate the entity before the next hook (or the persistence step) sees it.
67
+ * If any hook throws, the whole operation aborts and the error propagates.
68
+ */
69
+ export declare function fireHooks<K extends HookKind>(entityClass: new (...args: unknown[]) => BaseEntity, kind: K, arg: HookArgs[K]): Promise<void>;
70
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/decorators/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,+DAA+D;AAC/D,MAAM,MAAM,QAAQ,GACjB,YAAY,GACZ,WAAW,GACX,cAAc,GACd,aAAa,GACb,cAAc,GACd,aAAa,GACb,cAAc,GACd,aAAa,GACb,YAAY,GACZ,WAAW,GACX,aAAa,GACb,YAAY,GACZ,gBAAgB,GAChB,eAAe,CAAC;AAEnB,yCAAyC;AACzC,MAAM,WAAW,QAAQ;IACxB,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,UAAU,CAAC;IACtB,YAAY,EAAE,UAAU,CAAC;IACzB,WAAW,EAAE,UAAU,CAAC;IACxB,YAAY,EAAE,UAAU,CAAC;IACzB,WAAW,EAAE,UAAU,CAAC;IACxB,YAAY,EAAE,UAAU,CAAC;IACzB,WAAW,EAAE,UAAU,CAAC;IACxB,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;IACnC,SAAS,EAAE,UAAU,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;IACpC,UAAU,EAAE,UAAU,EAAE,CAAC;IACzB,cAAc,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;IACvC,aAAa,EAAE,UAAU,EAAE,CAAC;CAC5B;AAED,+EAA+E;AAC/E,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,IAAI,CACxD,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,KACZ,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AA8C1B,eAAO,MAAM,UAAU,QAAO,eAAyC,CAAC;AACxE,eAAO,MAAM,SAAS,QAAO,eAAwC,CAAC;AACtE,eAAO,MAAM,YAAY,QAAO,eAA2C,CAAC;AAC5E,eAAO,MAAM,WAAW,QAAO,eAA0C,CAAC;AAC1E,eAAO,MAAM,YAAY,QAAO,eAA2C,CAAC;AAC5E,eAAO,MAAM,WAAW,QAAO,eAA0C,CAAC;AAC1E,eAAO,MAAM,YAAY,QAAO,eAA2C,CAAC;AAC5E,eAAO,MAAM,WAAW,QAAO,eAA0C,CAAC;AAC1E,eAAO,MAAM,UAAU,QAAO,eAAyC,CAAC;AACxE,eAAO,MAAM,SAAS,QAAO,eAAwC,CAAC;AACtE,eAAO,MAAM,WAAW,QAAO,eAA0C,CAAC;AAC1E,eAAO,MAAM,UAAU,QAAO,eAAyC,CAAC;AACxE,eAAO,MAAM,cAAc,QAAO,eAA6C,CAAC;AAChF,eAAO,MAAM,aAAa,QAAO,eAA4C,CAAC;AAE9E;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,QAAQ,EAC9C,WAAW,EAAE,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,UAAU,EACnD,IAAI,EAAE,CAAC,GACL,WAAW,CAAC,CAAC,CAAC,EAAE,CAqBlB;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,CAAC,SAAS,QAAQ,EACjD,WAAW,EAAE,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,UAAU,EACnD,IAAI,EAAE,CAAC,EACP,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,GACd,OAAO,CAAC,IAAI,CAAC,CAKf"}