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.
- package/CHANGELOG.md +331 -1
- package/README.md +32 -24
- package/dist/compliance/data-classifier.d.ts +6 -0
- package/dist/compliance/data-classifier.js +6 -0
- package/dist/compliance/data-lineage.d.ts +4 -0
- package/dist/compliance/data-lineage.js +4 -0
- package/dist/compliance/data-masker.d.ts +4 -0
- package/dist/compliance/data-masker.js +4 -0
- package/dist/compliance/index.d.ts +4 -0
- package/dist/compliance/index.js +15 -1
- package/dist/compliance/pseudonymization.d.ts +4 -0
- package/dist/compliance/pseudonymization.js +4 -0
- package/dist/compliance/query-firewall.d.ts +9 -9
- package/dist/compliance/query-firewall.js +9 -9
- package/dist/compliance/rate-limiter.d.ts +4 -0
- package/dist/compliance/rate-limiter.js +4 -0
- package/dist/compliance/row-level-security.d.ts +2 -0
- package/dist/compliance/row-level-security.js +2 -0
- package/dist/compliance/security-decorator.d.ts +8 -0
- package/dist/compliance/security-decorator.js +8 -0
- package/dist/compliance/session-isolation.d.ts +4 -0
- package/dist/compliance/session-isolation.js +4 -0
- package/dist/compliance/worm-storage.d.ts +4 -0
- package/dist/compliance/worm-storage.js +4 -0
- package/dist/connection-manager.js +13 -1
- package/dist/core/expressions.d.ts +58 -0
- package/dist/core/expressions.js +83 -0
- package/dist/core/hooks-manager.d.ts +179 -0
- package/dist/core/hooks-manager.js +291 -0
- package/dist/core/types.d.ts +235 -0
- package/dist/core/types.js +9 -0
- package/dist/decorators/audit.d.ts +3 -1
- package/dist/decorators/audit.js +3 -1
- package/dist/decorators/check.d.ts +15 -15
- package/dist/decorators/check.js +15 -15
- package/dist/decorators/collate.d.ts +16 -0
- package/dist/decorators/collate.js +16 -0
- package/dist/decorators/comment.d.ts +3 -1
- package/dist/decorators/comment.js +3 -1
- package/dist/decorators/database-settings.d.ts +6 -0
- package/dist/decorators/database-settings.js +6 -0
- package/dist/decorators/default.d.ts +2 -0
- package/dist/decorators/default.js +2 -0
- package/dist/decorators/encryption.d.ts +7 -1
- package/dist/decorators/encryption.js +7 -1
- package/dist/decorators/engine.d.ts +4 -0
- package/dist/decorators/engine.js +4 -0
- package/dist/decorators/fk-constraints.d.ts +32 -32
- package/dist/decorators/fk-constraints.js +32 -32
- package/dist/decorators/foreign-table.d.ts +1 -1
- package/dist/decorators/generated.d.ts +8 -0
- package/dist/decorators/generated.js +8 -0
- package/dist/decorators/hstore.d.ts +6 -0
- package/dist/decorators/hstore.js +6 -0
- package/dist/decorators/index.d.ts +2 -0
- package/dist/decorators/index.js +11 -1
- package/dist/decorators/json-column.d.ts +2 -0
- package/dist/decorators/json-column.js +2 -0
- package/dist/decorators/jsonb.d.ts +6 -0
- package/dist/decorators/jsonb.js +6 -0
- package/dist/decorators/permissions.d.ts +12 -0
- package/dist/decorators/permissions.js +12 -0
- package/dist/decorators/procedure.d.ts +4 -2
- package/dist/decorators/procedure.js +4 -2
- package/dist/decorators/query-options.d.ts +24 -0
- package/dist/decorators/query-options.js +24 -0
- package/dist/decorators/range.d.ts +8 -0
- package/dist/decorators/range.js +8 -0
- package/dist/decorators/set-column.d.ts +2 -0
- package/dist/decorators/set-column.js +2 -0
- package/dist/decorators/spatial.d.ts +2 -0
- package/dist/decorators/spatial.js +2 -0
- package/dist/decorators/storage.d.ts +24 -0
- package/dist/decorators/storage.js +24 -0
- package/dist/decorators/timezone.d.ts +7 -7
- package/dist/decorators/timezone.js +7 -7
- package/dist/decorators/trigger.d.ts +3 -1
- package/dist/decorators/trigger.js +3 -1
- package/dist/decorators/uuid.d.ts +6 -0
- package/dist/decorators/uuid.js +6 -0
- package/dist/decorators/view.d.ts +7 -1
- package/dist/decorators/view.js +7 -1
- package/dist/diagrams/chen-diagram.d.ts +15 -12
- package/dist/diagrams/chen-diagram.js +76 -85
- package/dist/diagrams/class-diagram.d.ts +9 -8
- package/dist/diagrams/class-diagram.js +60 -82
- package/dist/diagrams/core/index.d.ts +13 -0
- package/dist/diagrams/core/index.js +33 -0
- package/dist/diagrams/core/layout.d.ts +104 -0
- package/dist/diagrams/core/layout.js +223 -0
- package/dist/diagrams/{svg-dom.d.ts → core/svg.d.ts} +8 -20
- package/dist/diagrams/{svg-dom.js → core/svg.js} +21 -29
- package/dist/diagrams/core/theme.d.ts +84 -0
- package/dist/diagrams/core/theme.js +62 -0
- package/dist/diagrams/dependency-diagram.d.ts +15 -14
- package/dist/diagrams/dependency-diagram.js +71 -105
- package/dist/diagrams/er-diagram.d.ts +13 -26
- package/dist/diagrams/er-diagram.js +180 -259
- package/dist/diagrams/flow-diagram.d.ts +16 -11
- package/dist/diagrams/flow-diagram.js +96 -91
- package/dist/diagrams/gantt-diagram.d.ts +10 -5
- package/dist/diagrams/gantt-diagram.js +77 -103
- package/dist/diagrams/index-diagram.d.ts +10 -10
- package/dist/diagrams/index-diagram.js +106 -116
- package/dist/diagrams/index.d.ts +6 -9
- package/dist/diagrams/index.js +9 -24
- package/dist/diagrams/migration-diagram.d.ts +8 -4
- package/dist/diagrams/migration-diagram.js +189 -161
- package/dist/diagrams/model-diagram.d.ts +34 -34
- package/dist/diagrams/model-diagram.js +106 -485
- package/dist/diagrams/package-diagram.d.ts +9 -6
- package/dist/diagrams/package-diagram.js +64 -101
- package/dist/diagrams/relational-diagram.d.ts +12 -10
- package/dist/diagrams/relational-diagram.js +87 -114
- package/dist/diagrams/schemadoc-diagram.d.ts +8 -8
- package/dist/diagrams/schemadoc-diagram.js +71 -93
- package/dist/diagrams/sequence-diagram.d.ts +10 -10
- package/dist/diagrams/sequence-diagram.js +64 -89
- package/dist/diagrams/state-diagram.d.ts +10 -9
- package/dist/diagrams/state-diagram.js +69 -92
- package/dist/diagrams/tree-diagram.d.ts +11 -5
- package/dist/diagrams/tree-diagram.js +41 -65
- package/dist/dialects/clickhouse/index.js +15 -0
- package/dist/dialects/cockroachdb/index.d.ts +1 -1
- package/dist/dialects/cockroachdb/index.js +32 -63
- package/dist/dialects/db2/index.js +23 -8
- package/dist/dialects/dialect.d.ts +141 -5
- package/dist/dialects/duckdb/index.js +9 -2
- package/dist/dialects/hana/index.js +22 -5
- package/dist/dialects/lock-clause-helper.d.ts +167 -0
- package/dist/dialects/lock-clause-helper.js +316 -0
- package/dist/dialects/mariadb/index.d.ts +7 -4
- package/dist/dialects/mariadb/index.js +36 -60
- package/dist/dialects/mssql/index.js +34 -3
- package/dist/dialects/mysql/index.d.ts +1 -1
- package/dist/dialects/mysql/index.js +17 -45
- package/dist/dialects/oracle/index.d.ts +14 -3
- package/dist/dialects/oracle/index.js +66 -36
- package/dist/dialects/order-expression-helper.d.ts +72 -0
- package/dist/dialects/order-expression-helper.js +154 -0
- package/dist/dialects/partial-index.d.ts +52 -0
- package/dist/dialects/partial-index.js +251 -0
- package/dist/dialects/postgres/index.d.ts +1 -1
- package/dist/dialects/postgres/index.js +43 -68
- package/dist/dialects/redshift/index.js +9 -2
- package/dist/dialects/snowflake/index.js +17 -0
- package/dist/dialects/spanner/index.js +7 -2
- package/dist/dialects/sqlite/driver.d.ts +55 -0
- package/dist/dialects/sqlite/driver.js +102 -0
- package/dist/dialects/sqlite/index.d.ts +1 -1
- package/dist/dialects/sqlite/index.js +49 -27
- package/dist/external-fields/decorator.d.ts +2 -0
- package/dist/external-fields/decorator.js +2 -0
- package/dist/graph/base-graph-dialect.d.ts +24 -3
- package/dist/graph/base-graph-dialect.js +43 -2
- package/dist/graph/dgraph/index.js +6 -0
- package/dist/graph/gremlin/index.d.ts +6 -0
- package/dist/graph/gremlin/index.js +12 -1
- package/dist/graph/index.d.ts +1 -1
- package/dist/graph/neo4j/index.d.ts +2 -0
- package/dist/graph/neo4j/index.js +6 -1
- package/dist/graph/types.d.ts +12 -1
- package/dist/index.d.ts +12 -3
- package/dist/index.js +53 -7
- package/dist/logging/index.d.ts +10 -0
- package/dist/logging/index.js +23 -0
- package/dist/logging/query-logging.d.ts +82 -0
- package/dist/logging/query-logging.js +102 -0
- package/dist/models/associations.d.ts +38 -0
- package/dist/models/associations.js +16 -0
- package/dist/models/decorators.d.ts +55 -19
- package/dist/models/decorators.js +95 -19
- package/dist/models/eager-load.d.ts +99 -0
- package/dist/models/eager-load.js +348 -5
- package/dist/models/indexes.d.ts +3 -2
- package/dist/models/indexes.js +7 -1
- package/dist/models/model.js +69 -43
- package/dist/prorm.d.ts +175 -409
- package/dist/prorm.js +1132 -553
- package/dist/query-builders/order-limit-builder.js +12 -10
- package/dist/query-builders/sql-compiler.d.ts +10 -3
- package/dist/query-builders/sql-compiler.js +14 -43
- package/dist/query-interface.d.ts +2 -1
- package/dist/schema-objects.d.ts +42 -0
- package/dist/schema-objects.js +28 -0
- package/dist/sql-constants.d.ts +44 -0
- package/dist/sql-constants.js +138 -1
- package/dist/types/index.d.ts +387 -17
- package/dist/types/index.js +10 -15
- package/dist/types/query-types.d.ts +26 -0
- package/dist/types/query-types.js +30 -0
- package/package.json +39 -8
- package/dist/decorators/belongs-to-many.js +0 -115
- package/dist/decorators/belongs-to.js +0 -115
- package/dist/decorators/has-many.js +0 -127
- package/dist/decorators/has-one.js +0 -116
- package/dist/diagrams/palette.d.ts +0 -138
- package/dist/diagrams/palette.js +0 -194
- package/dist/hooks/hooks-manager.d.ts +0 -189
- package/dist/hooks/hooks-manager.js +0 -350
- package/dist/hooks/index.d.ts +0 -8
- package/dist/hooks/index.js +0 -37
- /package/dist/{logging.d.ts → logging/logger.d.ts} +0 -0
- /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
|
-
*
|
|
109
|
+
* Mark a class as an abstract base model.
|
|
110
110
|
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
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
|
-
*
|
|
183
|
-
*
|
|
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
|
-
*
|
|
191
|
-
*
|
|
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
|
-
*
|
|
199
|
-
*
|
|
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
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
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
|
-
*
|
|
216
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
111
|
-
*
|
|
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
|
-
*
|
|
179
|
-
*
|
|
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
|
-
*
|
|
195
|
-
*
|
|
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
|
-
*
|
|
209
|
-
*
|
|
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
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
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
|
-
*
|
|
244
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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>;
|