ts-prorm-orm 1.2.3 → 2.1.0

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 (204) hide show
  1. package/CHANGELOG.md +331 -1
  2. package/README.md +32 -24
  3. package/dist/compliance/data-classifier.d.ts +6 -0
  4. package/dist/compliance/data-classifier.js +6 -0
  5. package/dist/compliance/data-lineage.d.ts +4 -0
  6. package/dist/compliance/data-lineage.js +4 -0
  7. package/dist/compliance/data-masker.d.ts +4 -0
  8. package/dist/compliance/data-masker.js +4 -0
  9. package/dist/compliance/index.d.ts +4 -0
  10. package/dist/compliance/index.js +15 -1
  11. package/dist/compliance/pseudonymization.d.ts +4 -0
  12. package/dist/compliance/pseudonymization.js +4 -0
  13. package/dist/compliance/query-firewall.d.ts +9 -9
  14. package/dist/compliance/query-firewall.js +9 -9
  15. package/dist/compliance/rate-limiter.d.ts +4 -0
  16. package/dist/compliance/rate-limiter.js +4 -0
  17. package/dist/compliance/row-level-security.d.ts +2 -0
  18. package/dist/compliance/row-level-security.js +2 -0
  19. package/dist/compliance/security-decorator.d.ts +8 -0
  20. package/dist/compliance/security-decorator.js +8 -0
  21. package/dist/compliance/session-isolation.d.ts +4 -0
  22. package/dist/compliance/session-isolation.js +4 -0
  23. package/dist/compliance/worm-storage.d.ts +4 -0
  24. package/dist/compliance/worm-storage.js +4 -0
  25. package/dist/connection-manager.js +13 -1
  26. package/dist/core/expressions.d.ts +58 -0
  27. package/dist/core/expressions.js +83 -0
  28. package/dist/core/hooks-manager.d.ts +179 -0
  29. package/dist/core/hooks-manager.js +291 -0
  30. package/dist/core/types.d.ts +235 -0
  31. package/dist/core/types.js +9 -0
  32. package/dist/decorators/audit.d.ts +3 -1
  33. package/dist/decorators/audit.js +3 -1
  34. package/dist/decorators/check.d.ts +15 -15
  35. package/dist/decorators/check.js +15 -15
  36. package/dist/decorators/collate.d.ts +16 -0
  37. package/dist/decorators/collate.js +16 -0
  38. package/dist/decorators/comment.d.ts +3 -1
  39. package/dist/decorators/comment.js +3 -1
  40. package/dist/decorators/database-settings.d.ts +6 -0
  41. package/dist/decorators/database-settings.js +6 -0
  42. package/dist/decorators/default.d.ts +2 -0
  43. package/dist/decorators/default.js +2 -0
  44. package/dist/decorators/encryption.d.ts +7 -1
  45. package/dist/decorators/encryption.js +7 -1
  46. package/dist/decorators/engine.d.ts +4 -0
  47. package/dist/decorators/engine.js +4 -0
  48. package/dist/decorators/fk-constraints.d.ts +32 -32
  49. package/dist/decorators/fk-constraints.js +32 -32
  50. package/dist/decorators/foreign-table.d.ts +1 -1
  51. package/dist/decorators/generated.d.ts +8 -0
  52. package/dist/decorators/generated.js +8 -0
  53. package/dist/decorators/hstore.d.ts +6 -0
  54. package/dist/decorators/hstore.js +6 -0
  55. package/dist/decorators/index.d.ts +2 -0
  56. package/dist/decorators/index.js +11 -1
  57. package/dist/decorators/json-column.d.ts +2 -0
  58. package/dist/decorators/json-column.js +2 -0
  59. package/dist/decorators/jsonb.d.ts +6 -0
  60. package/dist/decorators/jsonb.js +6 -0
  61. package/dist/decorators/permissions.d.ts +12 -0
  62. package/dist/decorators/permissions.js +12 -0
  63. package/dist/decorators/procedure.d.ts +4 -2
  64. package/dist/decorators/procedure.js +4 -2
  65. package/dist/decorators/query-options.d.ts +24 -0
  66. package/dist/decorators/query-options.js +24 -0
  67. package/dist/decorators/range.d.ts +8 -0
  68. package/dist/decorators/range.js +8 -0
  69. package/dist/decorators/set-column.d.ts +2 -0
  70. package/dist/decorators/set-column.js +2 -0
  71. package/dist/decorators/spatial.d.ts +2 -0
  72. package/dist/decorators/spatial.js +2 -0
  73. package/dist/decorators/storage.d.ts +24 -0
  74. package/dist/decorators/storage.js +24 -0
  75. package/dist/decorators/timezone.d.ts +7 -7
  76. package/dist/decorators/timezone.js +7 -7
  77. package/dist/decorators/trigger.d.ts +3 -1
  78. package/dist/decorators/trigger.js +3 -1
  79. package/dist/decorators/uuid.d.ts +6 -0
  80. package/dist/decorators/uuid.js +6 -0
  81. package/dist/decorators/view.d.ts +7 -1
  82. package/dist/decorators/view.js +7 -1
  83. package/dist/diagrams/chen-diagram.d.ts +15 -12
  84. package/dist/diagrams/chen-diagram.js +76 -85
  85. package/dist/diagrams/class-diagram.d.ts +9 -8
  86. package/dist/diagrams/class-diagram.js +60 -82
  87. package/dist/diagrams/core/index.d.ts +13 -0
  88. package/dist/diagrams/core/index.js +33 -0
  89. package/dist/diagrams/core/layout.d.ts +104 -0
  90. package/dist/diagrams/core/layout.js +223 -0
  91. package/dist/diagrams/{svg-dom.d.ts → core/svg.d.ts} +8 -20
  92. package/dist/diagrams/{svg-dom.js → core/svg.js} +21 -29
  93. package/dist/diagrams/core/theme.d.ts +84 -0
  94. package/dist/diagrams/core/theme.js +62 -0
  95. package/dist/diagrams/dependency-diagram.d.ts +15 -14
  96. package/dist/diagrams/dependency-diagram.js +71 -105
  97. package/dist/diagrams/er-diagram.d.ts +13 -26
  98. package/dist/diagrams/er-diagram.js +180 -259
  99. package/dist/diagrams/flow-diagram.d.ts +16 -11
  100. package/dist/diagrams/flow-diagram.js +96 -91
  101. package/dist/diagrams/gantt-diagram.d.ts +10 -5
  102. package/dist/diagrams/gantt-diagram.js +77 -103
  103. package/dist/diagrams/index-diagram.d.ts +10 -10
  104. package/dist/diagrams/index-diagram.js +106 -116
  105. package/dist/diagrams/index.d.ts +6 -9
  106. package/dist/diagrams/index.js +9 -24
  107. package/dist/diagrams/migration-diagram.d.ts +8 -4
  108. package/dist/diagrams/migration-diagram.js +189 -161
  109. package/dist/diagrams/model-diagram.d.ts +34 -34
  110. package/dist/diagrams/model-diagram.js +106 -485
  111. package/dist/diagrams/package-diagram.d.ts +9 -6
  112. package/dist/diagrams/package-diagram.js +64 -101
  113. package/dist/diagrams/relational-diagram.d.ts +12 -10
  114. package/dist/diagrams/relational-diagram.js +87 -114
  115. package/dist/diagrams/schemadoc-diagram.d.ts +8 -8
  116. package/dist/diagrams/schemadoc-diagram.js +71 -93
  117. package/dist/diagrams/sequence-diagram.d.ts +10 -10
  118. package/dist/diagrams/sequence-diagram.js +64 -89
  119. package/dist/diagrams/state-diagram.d.ts +10 -9
  120. package/dist/diagrams/state-diagram.js +69 -92
  121. package/dist/diagrams/tree-diagram.d.ts +11 -5
  122. package/dist/diagrams/tree-diagram.js +41 -65
  123. package/dist/dialects/clickhouse/index.js +15 -0
  124. package/dist/dialects/cockroachdb/index.d.ts +1 -1
  125. package/dist/dialects/cockroachdb/index.js +32 -63
  126. package/dist/dialects/db2/index.js +23 -8
  127. package/dist/dialects/dialect.d.ts +141 -5
  128. package/dist/dialects/duckdb/index.js +9 -2
  129. package/dist/dialects/hana/index.js +22 -5
  130. package/dist/dialects/lock-clause-helper.d.ts +167 -0
  131. package/dist/dialects/lock-clause-helper.js +316 -0
  132. package/dist/dialects/mariadb/index.d.ts +7 -4
  133. package/dist/dialects/mariadb/index.js +36 -60
  134. package/dist/dialects/mssql/index.js +34 -3
  135. package/dist/dialects/mysql/index.d.ts +1 -1
  136. package/dist/dialects/mysql/index.js +17 -45
  137. package/dist/dialects/oracle/index.d.ts +14 -3
  138. package/dist/dialects/oracle/index.js +66 -36
  139. package/dist/dialects/order-expression-helper.d.ts +72 -0
  140. package/dist/dialects/order-expression-helper.js +154 -0
  141. package/dist/dialects/partial-index.d.ts +52 -0
  142. package/dist/dialects/partial-index.js +251 -0
  143. package/dist/dialects/postgres/index.d.ts +1 -1
  144. package/dist/dialects/postgres/index.js +43 -68
  145. package/dist/dialects/redshift/index.js +9 -2
  146. package/dist/dialects/snowflake/index.js +17 -0
  147. package/dist/dialects/spanner/index.js +7 -2
  148. package/dist/dialects/sqlite/driver.d.ts +55 -0
  149. package/dist/dialects/sqlite/driver.js +102 -0
  150. package/dist/dialects/sqlite/index.d.ts +1 -1
  151. package/dist/dialects/sqlite/index.js +49 -27
  152. package/dist/external-fields/decorator.d.ts +2 -0
  153. package/dist/external-fields/decorator.js +2 -0
  154. package/dist/graph/base-graph-dialect.d.ts +24 -3
  155. package/dist/graph/base-graph-dialect.js +43 -2
  156. package/dist/graph/dgraph/index.js +6 -0
  157. package/dist/graph/gremlin/index.d.ts +6 -0
  158. package/dist/graph/gremlin/index.js +12 -1
  159. package/dist/graph/index.d.ts +1 -1
  160. package/dist/graph/neo4j/index.d.ts +2 -0
  161. package/dist/graph/neo4j/index.js +6 -1
  162. package/dist/graph/types.d.ts +12 -1
  163. package/dist/index.d.ts +12 -3
  164. package/dist/index.js +53 -7
  165. package/dist/logging/index.d.ts +10 -0
  166. package/dist/logging/index.js +23 -0
  167. package/dist/logging/query-logging.d.ts +82 -0
  168. package/dist/logging/query-logging.js +102 -0
  169. package/dist/models/associations.d.ts +38 -0
  170. package/dist/models/associations.js +16 -0
  171. package/dist/models/decorators.d.ts +55 -19
  172. package/dist/models/decorators.js +95 -19
  173. package/dist/models/eager-load.d.ts +99 -0
  174. package/dist/models/eager-load.js +348 -5
  175. package/dist/models/indexes.d.ts +3 -2
  176. package/dist/models/indexes.js +7 -1
  177. package/dist/models/model.js +69 -43
  178. package/dist/prorm.d.ts +175 -409
  179. package/dist/prorm.js +1132 -553
  180. package/dist/query-builders/order-limit-builder.js +12 -10
  181. package/dist/query-builders/sql-compiler.d.ts +10 -3
  182. package/dist/query-builders/sql-compiler.js +14 -43
  183. package/dist/query-interface.d.ts +2 -1
  184. package/dist/schema-objects.d.ts +42 -0
  185. package/dist/schema-objects.js +28 -0
  186. package/dist/sql-constants.d.ts +44 -0
  187. package/dist/sql-constants.js +138 -1
  188. package/dist/types/index.d.ts +387 -17
  189. package/dist/types/index.js +10 -15
  190. package/dist/types/query-types.d.ts +26 -0
  191. package/dist/types/query-types.js +30 -0
  192. package/package.json +39 -8
  193. package/dist/decorators/belongs-to-many.js +0 -115
  194. package/dist/decorators/belongs-to.js +0 -115
  195. package/dist/decorators/has-many.js +0 -127
  196. package/dist/decorators/has-one.js +0 -116
  197. package/dist/diagrams/palette.d.ts +0 -138
  198. package/dist/diagrams/palette.js +0 -194
  199. package/dist/hooks/hooks-manager.d.ts +0 -189
  200. package/dist/hooks/hooks-manager.js +0 -350
  201. package/dist/hooks/index.d.ts +0 -8
  202. package/dist/hooks/index.js +0 -37
  203. /package/dist/{logging.d.ts → logging/logger.d.ts} +0 -0
  204. /package/dist/{logging.js → logging/logger.js} +0 -0
@@ -106,11 +106,47 @@ interface AttributeMetadata {
106
106
  validate?: Record<string, any>;
107
107
  }
108
108
  /**
109
- * Define model options (use on model class)
109
+ * Mark a class as an abstract base model.
110
110
  *
111
- * @example
112
- * @Table({ tableName: 'users', timestamps: true })
111
+ * An abstract model gets no table of its own. Its columns, and any
112
+ * `@PrimaryKey` / `@Default` / validation applied to them, are inherited by the
113
+ * concrete models that extend it, so shared fields are declared once:
114
+ *
115
+ * ```typescript
116
+ * // This is the base model, which defines the common fields between all comments.
117
+ * @AbstractModel()
118
+ * class BaseComment {
119
+ * @Column(DataTypes.INTEGER())
120
+ * @PrimaryKey()
121
+ * @AutoIncrement()
122
+ * declare id: number;
123
+ *
124
+ * @Column(DataTypes.TEXT())
125
+ * declare body: string;
126
+ * }
127
+ *
128
+ * @Table({ tableName: 'post_comments' })
129
+ * class PostComment extends BaseComment {
130
+ * @Column(DataTypes.INTEGER())
131
+ * declare postId: number;
132
+ * }
133
+ * ```
134
+ *
135
+ * `PostComment` is created with id, body and postId. Passing the abstract class
136
+ * itself to `addModel()` is an error - there is no table to address.
137
+ */
138
+ export declare function AbstractModel(options?: TableOptions): ClassDecorator;
139
+ /** True when the class (by name) was declared `@AbstractModel`. */
140
+ export declare function isAbstractModel(nameOrClass: string | Function): boolean;
141
+ /**
142
+ * Attribute metadata for a model, including everything inherited from abstract
143
+ * base classes up the prototype chain.
144
+ *
145
+ * Metadata is keyed by constructor name, so a subclass would otherwise see only
146
+ * the columns declared directly on it. Base columns come first, and a subclass
147
+ * redeclaring a column overrides it.
113
148
  */
149
+ export declare function getInheritedAttributeMetadata(modelClass: Function): Map<string, AttributeMetadata>;
114
150
  export declare function Table(options?: TableOptions): ClassDecorator;
115
151
  /**
116
152
  * Table options interface
@@ -179,55 +215,55 @@ export declare function AllowNull(allowNull?: boolean): PropertyDecorator;
179
215
  * Mark attribute as primary key
180
216
  *
181
217
  * @example
182
- * @Attribute(DataTypes.INTEGER)
183
- * @PrimaryKey
218
+ * `@Attribute`(DataTypes.INTEGER)
219
+ * `@PrimaryKey`
184
220
  */
185
221
  export declare function PrimaryKey(): PropertyDecorator;
186
222
  /**
187
223
  * Enable auto-increment on attribute
188
224
  *
189
225
  * @example
190
- * @Attribute(DataTypes.INTEGER)
191
- * @AutoIncrement
226
+ * `@Attribute`(DataTypes.INTEGER)
227
+ * `@AutoIncrement`
192
228
  */
193
229
  export declare function AutoIncrement(): PropertyDecorator;
194
230
  /**
195
231
  * Add NOT NULL constraint
196
232
  *
197
233
  * @example
198
- * @Attribute(DataTypes.STRING)
199
- * @NotNull
234
+ * `@Attribute`(DataTypes.STRING)
235
+ * `@NotNull`
200
236
  */
201
237
  export declare function NotNull(): PropertyDecorator;
202
238
  /**
203
239
  * Set default value
204
240
  *
205
241
  * @example
206
- * @Default('value')
207
- * @Default(DataTypes.NOW)
208
- * @Default(() => Math.random())
242
+ * `@Default`('value')
243
+ * `@Default`(DataTypes.NOW)
244
+ * `@Default`(() => Math.random())
209
245
  */
210
246
  export declare function Default(value: any): PropertyDecorator;
211
247
  /**
212
248
  * Add UNIQUE constraint
213
249
  *
214
250
  * @example
215
- * @Unique
216
- * @Unique('unique_name')
251
+ * `@Unique`
252
+ * `@Unique`('unique_name')
217
253
  */
218
254
  export declare function Unique(nameOrOptions?: string | boolean): PropertyDecorator;
219
255
  /**
220
256
  * Add comment to column
221
257
  *
222
258
  * @example
223
- * @Comment('User email address')
259
+ * `@Comment`('User email address')
224
260
  */
225
261
  export declare function Comment(text: string): PropertyDecorator;
226
262
  /**
227
263
  * Define a hasOne association
228
264
  *
229
265
  * @example
230
- * @HasOne(() => Profile)
266
+ * `@HasOne`(() => Profile)
231
267
  * declare profile: HasOne<Profile>;
232
268
  */
233
269
  export declare function HasOne(targetFn: () => any, options?: HasOneOptions): PropertyDecorator;
@@ -235,7 +271,7 @@ export declare function HasOne(targetFn: () => any, options?: HasOneOptions): Pr
235
271
  * Define a hasMany association
236
272
  *
237
273
  * @example
238
- * @HasMany(() => Post)
274
+ * `@HasMany`(() => Post)
239
275
  * declare posts: HasMany<Post>;
240
276
  */
241
277
  export declare function HasMany(targetFn: () => any, options?: HasManyOptions): PropertyDecorator;
@@ -243,7 +279,7 @@ export declare function HasMany(targetFn: () => any, options?: HasManyOptions):
243
279
  * Define a belongsTo association
244
280
  *
245
281
  * @example
246
- * @BelongsTo(() => User)
282
+ * `@BelongsTo`(() => User)
247
283
  * declare user: BelongsTo<User>;
248
284
  */
249
285
  export declare function BelongsTo(targetFn: () => any, options?: BelongsToOptions): PropertyDecorator;
@@ -251,7 +287,7 @@ export declare function BelongsTo(targetFn: () => any, options?: BelongsToOption
251
287
  * Define a belongsToMany association
252
288
  *
253
289
  * @example
254
- * @BelongsToMany(() => Role, { through: UserRole })
290
+ * `@BelongsToMany`(() => Role, { through: UserRole })
255
291
  * declare roles: BelongsToMany<Role>;
256
292
  */
257
293
  export declare function BelongsToMany(targetFn: () => any, options: BelongsToManyOptions): PropertyDecorator;
@@ -13,6 +13,9 @@
13
13
  * - @Comment - Add column comment
14
14
  */
15
15
  Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.AbstractModel = AbstractModel;
17
+ exports.isAbstractModel = isAbstractModel;
18
+ exports.getInheritedAttributeMetadata = getInheritedAttributeMetadata;
16
19
  exports.Table = Table;
17
20
  exports.Attribute = Attribute;
18
21
  exports.Column = Column;
@@ -68,8 +71,79 @@ const associationMetadata = new Map();
68
71
  * Define model options (use on model class)
69
72
  *
70
73
  * @example
71
- * @Table({ tableName: 'users', timestamps: true })
74
+ * `@Table`({ tableName: 'users', timestamps: true })
75
+ */
76
+ /** Classes marked with `@AbstractModel`, by constructor name. */
77
+ const abstractModels = new Set();
78
+ /**
79
+ * Mark a class as an abstract base model.
80
+ *
81
+ * An abstract model gets no table of its own. Its columns, and any
82
+ * `@PrimaryKey` / `@Default` / validation applied to them, are inherited by the
83
+ * concrete models that extend it, so shared fields are declared once:
84
+ *
85
+ * ```typescript
86
+ * // This is the base model, which defines the common fields between all comments.
87
+ * @AbstractModel()
88
+ * class BaseComment {
89
+ * @Column(DataTypes.INTEGER())
90
+ * @PrimaryKey()
91
+ * @AutoIncrement()
92
+ * declare id: number;
93
+ *
94
+ * @Column(DataTypes.TEXT())
95
+ * declare body: string;
96
+ * }
97
+ *
98
+ * @Table({ tableName: 'post_comments' })
99
+ * class PostComment extends BaseComment {
100
+ * @Column(DataTypes.INTEGER())
101
+ * declare postId: number;
102
+ * }
103
+ * ```
104
+ *
105
+ * `PostComment` is created with id, body and postId. Passing the abstract class
106
+ * itself to `addModel()` is an error - there is no table to address.
72
107
  */
108
+ function AbstractModel(options = {}) {
109
+ return function (target) {
110
+ abstractModels.add(target.name);
111
+ // Record the options so subclasses can inherit timestamps/paranoid and the
112
+ // rest, but never a tableName - each concrete model names its own table.
113
+ const { tableName: _ignored, ...inheritable } = options;
114
+ modelMetadata.set(target.name, { ...inheritable });
115
+ return target;
116
+ };
117
+ }
118
+ /** True when the class (by name) was declared `@AbstractModel`. */
119
+ function isAbstractModel(nameOrClass) {
120
+ return abstractModels.has(typeof nameOrClass === 'string' ? nameOrClass : nameOrClass.name);
121
+ }
122
+ /**
123
+ * Attribute metadata for a model, including everything inherited from abstract
124
+ * base classes up the prototype chain.
125
+ *
126
+ * Metadata is keyed by constructor name, so a subclass would otherwise see only
127
+ * the columns declared directly on it. Base columns come first, and a subclass
128
+ * redeclaring a column overrides it.
129
+ */
130
+ function getInheritedAttributeMetadata(modelClass) {
131
+ const chain = [];
132
+ let current = modelClass;
133
+ while (current && current !== Function.prototype && current.name) {
134
+ chain.unshift(current);
135
+ current = Object.getPrototypeOf(current);
136
+ }
137
+ const merged = new Map();
138
+ for (const cls of chain) {
139
+ const own = attributeMetadata.get(cls.name);
140
+ if (!own)
141
+ continue;
142
+ for (const [field, meta] of own)
143
+ merged.set(field, meta);
144
+ }
145
+ return merged;
146
+ }
73
147
  function Table(options = {}) {
74
148
  return function (target) {
75
149
  const modelName = target.name;
@@ -107,8 +181,8 @@ function Table(options = {}) {
107
181
  * Define a model attribute/column
108
182
  *
109
183
  * @example
110
- * @Attribute(DataTypes.STRING)
111
- * @Attribute(DataTypes.INTEGER)
184
+ * `@Attribute`(DataTypes.STRING)
185
+ * `@Attribute`(DataTypes.INTEGER)
112
186
  */
113
187
  /**
114
188
  * Get (creating if needed) the attribute entry for a decorated property.
@@ -119,10 +193,12 @@ function Table(options = {}) {
119
193
  * yet, and `@Column` then replaced whatever they had set - so the documented
120
194
  * ordering
121
195
  *
196
+ * ```ts
122
197
  * @Column(DataTypes.INTEGER())
123
198
  * @PrimaryKey()
124
199
  * @AutoIncrement()
125
200
  * declare id: number;
201
+ * ```
126
202
  *
127
203
  * produced a plain nullable INTEGER with no primary key and no auto-increment.
128
204
  * Every decorator now goes through this helper and merges, making the stack
@@ -175,8 +251,8 @@ function AllowNull(allowNull = true) {
175
251
  * Mark attribute as primary key
176
252
  *
177
253
  * @example
178
- * @Attribute(DataTypes.INTEGER)
179
- * @PrimaryKey
254
+ * `@Attribute`(DataTypes.INTEGER)
255
+ * `@PrimaryKey`
180
256
  */
181
257
  function PrimaryKey() {
182
258
  return function (target, propertyKey) {
@@ -191,8 +267,8 @@ function PrimaryKey() {
191
267
  * Enable auto-increment on attribute
192
268
  *
193
269
  * @example
194
- * @Attribute(DataTypes.INTEGER)
195
- * @AutoIncrement
270
+ * `@Attribute`(DataTypes.INTEGER)
271
+ * `@AutoIncrement`
196
272
  */
197
273
  function AutoIncrement() {
198
274
  return function (target, propertyKey) {
@@ -205,8 +281,8 @@ function AutoIncrement() {
205
281
  * Add NOT NULL constraint
206
282
  *
207
283
  * @example
208
- * @Attribute(DataTypes.STRING)
209
- * @NotNull
284
+ * `@Attribute`(DataTypes.STRING)
285
+ * `@NotNull`
210
286
  */
211
287
  function NotNull() {
212
288
  return function (target, propertyKey) {
@@ -224,9 +300,9 @@ function NotNull() {
224
300
  * Set default value
225
301
  *
226
302
  * @example
227
- * @Default('value')
228
- * @Default(DataTypes.NOW)
229
- * @Default(() => Math.random())
303
+ * `@Default`('value')
304
+ * `@Default`(DataTypes.NOW)
305
+ * `@Default`(() => Math.random())
230
306
  */
231
307
  function Default(value) {
232
308
  return function (target, propertyKey) {
@@ -240,8 +316,8 @@ function Default(value) {
240
316
  * Add UNIQUE constraint
241
317
  *
242
318
  * @example
243
- * @Unique
244
- * @Unique('unique_name')
319
+ * `@Unique`
320
+ * `@Unique`('unique_name')
245
321
  */
246
322
  function Unique(nameOrOptions) {
247
323
  return function (target, propertyKey) {
@@ -255,7 +331,7 @@ function Unique(nameOrOptions) {
255
331
  * Add comment to column
256
332
  *
257
333
  * @example
258
- * @Comment('User email address')
334
+ * `@Comment`('User email address')
259
335
  */
260
336
  function Comment(text) {
261
337
  return function (target, propertyKey) {
@@ -270,7 +346,7 @@ function Comment(text) {
270
346
  * Define a hasOne association
271
347
  *
272
348
  * @example
273
- * @HasOne(() => Profile)
349
+ * `@HasOne`(() => Profile)
274
350
  * declare profile: HasOne<Profile>;
275
351
  */
276
352
  function HasOne(targetFn, options = {}) {
@@ -299,7 +375,7 @@ function HasOne(targetFn, options = {}) {
299
375
  * Define a hasMany association
300
376
  *
301
377
  * @example
302
- * @HasMany(() => Post)
378
+ * `@HasMany`(() => Post)
303
379
  * declare posts: HasMany<Post>;
304
380
  */
305
381
  function HasMany(targetFn, options = {}) {
@@ -328,7 +404,7 @@ function HasMany(targetFn, options = {}) {
328
404
  * Define a belongsTo association
329
405
  *
330
406
  * @example
331
- * @BelongsTo(() => User)
407
+ * `@BelongsTo`(() => User)
332
408
  * declare user: BelongsTo<User>;
333
409
  */
334
410
  function BelongsTo(targetFn, options = {}) {
@@ -357,7 +433,7 @@ function BelongsTo(targetFn, options = {}) {
357
433
  * Define a belongsToMany association
358
434
  *
359
435
  * @example
360
- * @BelongsToMany(() => Role, { through: UserRole })
436
+ * `@BelongsToMany`(() => Role, { through: UserRole })
361
437
  * declare roles: BelongsToMany<Role>;
362
438
  */
363
439
  function BelongsToMany(targetFn, options) {
@@ -11,6 +11,16 @@
11
11
  * bugs you hit depended on which API you had used to define the model.
12
12
  *
13
13
  * Both paths now call `loadIncludes()` below.
14
+ *
15
+ * Two things about this loader are worth knowing before reading it:
16
+ *
17
+ * 1. An include is resolved with ONE query per association level, never a JOIN:
18
+ * all parents are satisfied by a single `WHERE fk IN (...)`. That is
19
+ * deliberate - it keeps the statement count constant in the number of rows -
20
+ * but it is also why a per-include `limit` cannot simply be forwarded to that
21
+ * query; see the per-parent window notes on `loadIncludes()`.
22
+ * 2. `{ all: true }` entries are expanded to one concrete include per
23
+ * association before any of that happens; see `expandAllIncludes()`.
14
24
  */
15
25
  /** Minimal view of the association records kept in `Prorm.associations`. */
16
26
  export interface EagerLoadAssociation {
@@ -52,6 +62,49 @@ export declare function resolvePrimaryKeyAttr(m: any): string;
52
62
  * foreign-key logic to it.
53
63
  */
54
64
  export declare function resolveIncludeAssociation(ctx: EagerLoadContext, parentModel: any, parentModelName: string, includeOpt: any): EagerLoadAssociation;
65
+ /**
66
+ * Expand `{ all: true }` / `{ all: 'alias' }` include entries into one concrete
67
+ * include per association.
68
+ *
69
+ * `loadIncludes()` used to open each iteration with `if (!includeOpt.model)
70
+ * continue`, so an entry carrying no `model` - which is exactly what
71
+ * `{ all: true }` is - was skipped without a word: `include: [{ all: true }]`
72
+ * emitted the parent SELECT and attached nothing. The class-based path expanded
73
+ * it (models/model.ts) and the `prorm.define()` path did not, so which of the
74
+ * two APIs you had used decided whether the option existed.
75
+ *
76
+ * Bounding the recursion. `nested: true` walks the association graph, and that
77
+ * graph routinely contains cycles (`User.hasMany(Post)` + `Post.belongsTo(User)`)
78
+ * and self-references (`Category.hasMany(Category)`). Depth alone does not bound
79
+ * those usefully here: unlike the class-based expander - which builds one SQL
80
+ * statement - every expanded include is another round trip, so a cycle across a
81
+ * model with three associations would reach 3^10 queries before the depth cap
82
+ * bit. So expansion is bounded twice: by `MAX_ALL_EXPANSION_DEPTH`, and by the
83
+ * chain of models already expanded on the current branch - a model is never
84
+ * auto-expanded twice on one path, which terminates cycles and self-references
85
+ * at their first repeat.
86
+ *
87
+ * The chain stops *re-expansion*, not the association itself: `User` with
88
+ * `{ all: true, nested: true }` still loads `posts` and each post's `user` (that
89
+ * is one of Post's associations, and `all` means all), but stops there rather
90
+ * than walking back into User's associations again. So a two-model cycle costs
91
+ * three queries, not ten levels of ping-pong.
92
+ *
93
+ * Two deliberate differences from the class-based expander:
94
+ * - the depth cap only ever stops *automatic* expansion; a hand-written include
95
+ * is passed through at any depth rather than silently dropped.
96
+ * - an unknown `{ all: 'alias' }` is an error rather than a console warning.
97
+ *
98
+ * `required` carried onto an expanded include filters parents like any other
99
+ * required include. That needs expansion to happen before the parent-filtering
100
+ * pass rather than inside `loadIncludes()` at the end of the query - the
101
+ * filtering pass calls `resolveRequiredIncludeFilter`, which returns null for an
102
+ * entry with no `model`, so while `{ all: true }` was still un-expanded at that
103
+ * point `{ all: true, required: true }` loaded the associations and narrowed
104
+ * nothing. Callers therefore expand once, up front; expansion is idempotent, so
105
+ * `loadIncludes()` re-running it on an already-expanded list is a no-op.
106
+ */
107
+ export declare function expandAllIncludes(ctx: EagerLoadContext, parentModel: any, parentModelName: string, includeList: any[], depth?: number, chain?: readonly string[]): any[];
55
108
  /**
56
109
  * An include filters its parents when it is `required`, and `required` defaults
57
110
  * to true whenever the include carries its own `where` - the same rule Sequelize
@@ -75,6 +128,18 @@ export declare function resolveRequiredIncludeFilter(ctx: EagerLoadContext, pare
75
128
  parentAttr: string;
76
129
  values: any[];
77
130
  } | null>;
131
+ /**
132
+ * Attach a count of related rows to each parent, without loading them.
133
+ *
134
+ * `findAll({ withCount: ['posts'] })` sets `row.postsCount` on every parent.
135
+ * The counts are resolved with one grouped query per association, so this stays
136
+ * a constant number of statements no matter how many parents there are - the
137
+ * naive alternative is a count query per row.
138
+ *
139
+ * Use this when you need "how many" but not the rows themselves; a full
140
+ * `include` fetches every child just to measure the array.
141
+ */
142
+ export declare function loadCounts(ctx: EagerLoadContext, parentRows: any[], parentModel: any, parentModelName: string, aliases: string[]): Promise<void>;
78
143
  /**
79
144
  * Eager-load `includeList` onto `parentRows`, recursing into nested includes.
80
145
  *
@@ -82,5 +147,39 @@ export declare function resolveRequiredIncludeFilter(ctx: EagerLoadContext, pare
82
147
  * caught and reported as an empty result, which made a typo'd alias, a missing
83
148
  * foreign key column, an unresolvable through model and a genuinely childless
84
149
  * parent all look identical - and hid most of the bugs this module now fixes.
150
+ *
151
+ * ## Per-include `limit` / `offset`
152
+ *
153
+ * `include: [{ model: Post, order: [['id', 'DESC']], limit: 5 }]` reads as "the
154
+ * 5 most recent posts *per user*", and that is what it now means. Getting there
155
+ * needs care, because one query serves every parent:
156
+ *
157
+ * SELECT ... FROM "posts" WHERE "userId" IN (1, 2, 3) ORDER BY "id" DESC
158
+ *
159
+ * Forwarding `LIMIT 5` into that statement would cap the *whole result set* at 5
160
+ * rows - user 1 would get five posts and users 2 and 3 none - which is worse
161
+ * than the old behaviour of dropping the option, because the answer looks
162
+ * plausible while being wrong for every parent but the first. So the limit is
163
+ * never forwarded into a multi-parent `IN (...)` query. Instead:
164
+ *
165
+ * - `order` is still applied *in SQL*, so the database decides which rows come
166
+ * first - the window is a window over the ordering the caller asked for, not
167
+ * over insertion order.
168
+ * - the window is then applied per parent, in memory, when the fetched rows are
169
+ * grouped onto their parents.
170
+ * - the one case where the shared query and a per-parent window coincide is a
171
+ * single parent row (`findByPk(...)` with an include, the common case): there
172
+ * `LIMIT`/`OFFSET` *are* pushed down to SQL, for `hasMany` only - see below.
173
+ *
174
+ * What this does NOT do: reduce what crosses the wire for multi-parent queries.
175
+ * All matching children are fetched and most of them are then discarded.
176
+ * `limit` here bounds the arrays you get back, it is not a transfer
177
+ * optimization. Doing better needs per-parent SQL windows (`ROW_NUMBER() OVER
178
+ * (PARTITION BY ...)` or `LATERAL`), which is a dialect-level feature this
179
+ * loader - which only ever calls `Model.findAll()` - cannot express today.
180
+ *
181
+ * `limit`/`offset` are only meaningful on a to-many include. On `belongsTo` and
182
+ * `hasOne` the result is a single row rather than a list, so they are reported
183
+ * and ignored rather than quietly accepted.
85
184
  */
86
185
  export declare function loadIncludes(ctx: EagerLoadContext, parentRows: any[], parentModel: any, parentModelName: string, includeList: any[]): Promise<void>;