@spinajs/orm 2.0.180 → 2.0.181

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 (91) hide show
  1. package/lib/cjs/builders.d.ts +643 -643
  2. package/lib/cjs/builders.js +1602 -1602
  3. package/lib/cjs/builders.js.map +1 -1
  4. package/lib/cjs/converters.d.ts +34 -34
  5. package/lib/cjs/converters.js +104 -104
  6. package/lib/cjs/decorators.d.ts +152 -152
  7. package/lib/cjs/decorators.js +449 -449
  8. package/lib/cjs/dehydrators.d.ts +10 -10
  9. package/lib/cjs/dehydrators.js +47 -47
  10. package/lib/cjs/driver.d.ts +82 -82
  11. package/lib/cjs/driver.js +102 -102
  12. package/lib/cjs/driver.js.map +1 -1
  13. package/lib/cjs/enums.d.ts +116 -116
  14. package/lib/cjs/enums.js +126 -126
  15. package/lib/cjs/enums.js.map +1 -1
  16. package/lib/cjs/exceptions.d.ts +6 -6
  17. package/lib/cjs/exceptions.js +10 -10
  18. package/lib/cjs/hydrators.d.ts +19 -19
  19. package/lib/cjs/hydrators.js +132 -132
  20. package/lib/cjs/hydrators.js.map +1 -1
  21. package/lib/cjs/index.d.ts +17 -17
  22. package/lib/cjs/index.js +33 -33
  23. package/lib/cjs/interfaces.d.ts +919 -919
  24. package/lib/cjs/interfaces.js +279 -279
  25. package/lib/cjs/interfaces.js.map +1 -1
  26. package/lib/cjs/middlewares.d.ts +62 -62
  27. package/lib/cjs/middlewares.js +258 -258
  28. package/lib/cjs/model.d.ts +284 -284
  29. package/lib/cjs/model.js +810 -810
  30. package/lib/cjs/orm.d.ts +61 -61
  31. package/lib/cjs/orm.js +333 -333
  32. package/lib/cjs/orm.js.map +1 -1
  33. package/lib/cjs/relation-objects.d.ts +108 -108
  34. package/lib/cjs/relation-objects.js +221 -221
  35. package/lib/cjs/relations.d.ts +61 -61
  36. package/lib/cjs/relations.js +194 -194
  37. package/lib/cjs/relations.js.map +1 -1
  38. package/lib/cjs/statements.d.ts +143 -143
  39. package/lib/cjs/statements.js +309 -309
  40. package/lib/cjs/statements.js.map +1 -1
  41. package/lib/cjs/types.d.ts +32 -32
  42. package/lib/cjs/types.js +2 -2
  43. package/lib/cjs/wrappers.d.ts +5 -5
  44. package/lib/cjs/wrappers.js +12 -12
  45. package/lib/mjs/builders.d.ts +643 -643
  46. package/lib/mjs/builders.js +1594 -1594
  47. package/lib/mjs/builders.js.map +1 -1
  48. package/lib/mjs/converters.d.ts +34 -34
  49. package/lib/mjs/converters.js +96 -96
  50. package/lib/mjs/decorators.d.ts +152 -152
  51. package/lib/mjs/decorators.js +422 -422
  52. package/lib/mjs/dehydrators.d.ts +10 -10
  53. package/lib/mjs/dehydrators.js +41 -41
  54. package/lib/mjs/driver.d.ts +82 -82
  55. package/lib/mjs/driver.js +98 -98
  56. package/lib/mjs/driver.js.map +1 -1
  57. package/lib/mjs/enums.d.ts +116 -116
  58. package/lib/mjs/enums.js +123 -123
  59. package/lib/mjs/enums.js.map +1 -1
  60. package/lib/mjs/exceptions.d.ts +6 -6
  61. package/lib/mjs/exceptions.js +6 -6
  62. package/lib/mjs/hydrators.d.ts +19 -19
  63. package/lib/mjs/hydrators.js +128 -128
  64. package/lib/mjs/hydrators.js.map +1 -1
  65. package/lib/mjs/index.d.ts +17 -17
  66. package/lib/mjs/index.js +17 -17
  67. package/lib/mjs/interfaces.d.ts +919 -919
  68. package/lib/mjs/interfaces.js +267 -267
  69. package/lib/mjs/interfaces.js.map +1 -1
  70. package/lib/mjs/middlewares.d.ts +62 -62
  71. package/lib/mjs/middlewares.js +249 -249
  72. package/lib/mjs/model.d.ts +284 -284
  73. package/lib/mjs/model.js +800 -800
  74. package/lib/mjs/orm.d.ts +61 -61
  75. package/lib/mjs/orm.js +326 -326
  76. package/lib/mjs/orm.js.map +1 -1
  77. package/lib/mjs/relation-objects.d.ts +108 -108
  78. package/lib/mjs/relation-objects.js +211 -211
  79. package/lib/mjs/relations.d.ts +61 -61
  80. package/lib/mjs/relations.js +191 -191
  81. package/lib/mjs/relations.js.map +1 -1
  82. package/lib/mjs/statements.d.ts +143 -143
  83. package/lib/mjs/statements.js +301 -301
  84. package/lib/mjs/statements.js.map +1 -1
  85. package/lib/mjs/types.d.ts +32 -32
  86. package/lib/mjs/types.js +1 -1
  87. package/lib/mjs/wrappers.d.ts +5 -5
  88. package/lib/mjs/wrappers.js +9 -9
  89. package/lib/tsconfig.cjs.tsbuildinfo +1 -1
  90. package/lib/tsconfig.mjs.tsbuildinfo +1 -1
  91. package/package.json +5 -5
@@ -1,423 +1,423 @@
1
- /* eslint-disable prettier/prettier */
2
- import { JsonValueConverter, UuidConverter } from './converters.js';
3
- import { DI } from '@spinajs/di';
4
- import { RelationType, DatetimeValueConverter, SetValueConverter } from './interfaces.js';
5
- import 'reflect-metadata';
6
- import { extractModelDescriptor } from './model.js';
7
- import { InvalidOperation, InvalidArgument } from '@spinajs/exceptions';
8
- export const MODEL_DESCTRIPTION_SYMBOL = Symbol.for('MODEL_DESCRIPTOR');
9
- export const MIGRATION_DESCRIPTION_SYMBOL = Symbol.for('MIGRATION_DESCRIPTOR');
10
- /**
11
- * Helper func to create model metadata
12
- */
13
- export function extractDecoratorDescriptor(callback, base = false) {
14
- return (target, propertyKey, indexOrDescriptor) => {
15
- let metadata = null;
16
- if (!base) {
17
- metadata = target.constructor[MODEL_DESCTRIPTION_SYMBOL];
18
- }
19
- else {
20
- metadata = target[MODEL_DESCTRIPTION_SYMBOL];
21
- }
22
- if (!metadata) {
23
- metadata = {
24
- Driver: null,
25
- Converters: new Map(),
26
- Columns: [],
27
- Connection: null,
28
- PrimaryKey: '',
29
- SoftDelete: {
30
- DeletedAt: '',
31
- },
32
- Archived: {
33
- ArchivedAt: '',
34
- },
35
- TableName: '',
36
- Timestamps: {
37
- CreatedAt: '',
38
- UpdatedAt: '',
39
- },
40
- Relations: new Map(),
41
- Name: target.constructor.name,
42
- JunctionModelProperties: [],
43
- DiscriminationMap: {
44
- Field: '',
45
- Models: null,
46
- },
47
- Schema: {},
48
- };
49
- if (!base) {
50
- target.constructor[MODEL_DESCTRIPTION_SYMBOL] = metadata;
51
- }
52
- else {
53
- target[MODEL_DESCTRIPTION_SYMBOL] = metadata;
54
- }
55
- }
56
- if (callback) {
57
- callback(metadata, target, propertyKey, indexOrDescriptor);
58
- }
59
- };
60
- }
61
- /**
62
- * Sets migration option
63
- *
64
- * @param connection - connection name, must exists in configuration file
65
- */
66
- export function Migration(connection) {
67
- return (target) => {
68
- let metadata = target[MIGRATION_DESCRIPTION_SYMBOL];
69
- if (!metadata) {
70
- metadata = {
71
- Connection: '',
72
- };
73
- target[MIGRATION_DESCRIPTION_SYMBOL] = metadata;
74
- }
75
- metadata.Connection = connection;
76
- DI.register(target).as('__migrations__');
77
- };
78
- }
79
- /**
80
- * Connection model decorator, assigns connection to model
81
- *
82
- * @param name - connection name, must be avaible in db config
83
- */
84
- export function Connection(name) {
85
- return extractDecoratorDescriptor((model) => {
86
- model.Connection = name;
87
- }, true);
88
- }
89
- /**
90
- * TableName model decorator, assigns table from database to model
91
- *
92
- * @param name - table name in database that is referred by this model
93
- */
94
- export function Model(tableName) {
95
- return extractDecoratorDescriptor((model, target) => {
96
- DI.register(target).as('__models__');
97
- model.TableName = tableName;
98
- model.Name = target.name;
99
- }, true);
100
- }
101
- /**
102
- * Set create timestamps feature to model. Proper columns must be avaible in database table.
103
- * It allow to track creation times & changes to model
104
- */
105
- export function CreatedAt() {
106
- return extractDecoratorDescriptor((model, target, propertyKey) => {
107
- const type = Reflect.getMetadata('design:type', target, propertyKey);
108
- if (type.name !== 'DateTime') {
109
- throw Error(`Proprety ${propertyKey} marked as CreatedAt must be DateTime type, but is ${type.name}. Type: ${target.name}`);
110
- }
111
- model.Timestamps.CreatedAt = propertyKey;
112
- // add converter for this field
113
- model.Converters.set(propertyKey, {
114
- Class: DatetimeValueConverter,
115
- });
116
- });
117
- }
118
- /**
119
- * Set update timestamps feature to model. Proper columns must be avaible in database table.
120
- * It allow to track creation times & changes to model
121
- */
122
- export function UpdatedAt() {
123
- return extractDecoratorDescriptor((model, target, propertyKey) => {
124
- const type = Reflect.getMetadata('design:type', target, propertyKey);
125
- if (type.name !== 'DateTime') {
126
- throw Error(`Proprety ${propertyKey} marked as UpdatedAt must be DateTime type, but is ${type.name}. Type: ${target.name}`);
127
- }
128
- model.Timestamps.UpdatedAt = propertyKey;
129
- // add converter for this field
130
- model.Converters.set(propertyKey, {
131
- Class: DatetimeValueConverter,
132
- });
133
- });
134
- }
135
- /**
136
- * Sets soft delete feature to model. Soft delete dont delete model, but sets deletion date and hides from
137
- * select result by default.
138
- */
139
- export function SoftDelete() {
140
- return extractDecoratorDescriptor((model, target, propertyKey) => {
141
- const type = Reflect.getMetadata('design:type', target, propertyKey);
142
- if (type.name !== 'DateTime') {
143
- throw Error(`Proprety ${propertyKey} marked as DeletedAt must be DateTime type, but is ${type.name}. Type: ${target.name}`);
144
- }
145
- model.SoftDelete.DeletedAt = propertyKey;
146
- // add converter for this field
147
- model.Converters.set(propertyKey, {
148
- Class: DatetimeValueConverter,
149
- });
150
- });
151
- }
152
- /**
153
- * Enable archive mode for model. If enabled all changes creates new instance in DB and old have set archived field
154
- * and gets attached to new model. It enabled to track changes to model in DB and also preserve data in relations.
155
- *
156
- */
157
- export function Archived() {
158
- return extractDecoratorDescriptor((model, target, propertyKey) => {
159
- const type = Reflect.getMetadata('design:type', target, propertyKey);
160
- if (type.name !== 'DateTime') {
161
- throw Error(`Proprety ${propertyKey} marked as ArchivedAt must be DateTime type, but is ${type.name}. Type: ${target.name}`);
162
- }
163
- model.Archived.ArchivedAt = propertyKey;
164
- // add converter for this field
165
- model.Converters.set(propertyKey, {
166
- Class: DatetimeValueConverter,
167
- });
168
- });
169
- }
170
- /**
171
- * Makrs field as primary key
172
- */
173
- export function Primary() {
174
- return extractDecoratorDescriptor((model, _target, propertyKey) => {
175
- model.PrimaryKey = propertyKey;
176
- });
177
- }
178
- /**
179
- * Marks columns as UUID. Column will be generated ad creation
180
- */
181
- export function Ignore() {
182
- return extractDecoratorDescriptor((model, _target, propertyKey) => {
183
- const columnDesc = model.Columns.find((c) => c.Name === propertyKey);
184
- if (!columnDesc) {
185
- // we dont want to fill all props, they will be loaded from db and mergeg with this
186
- model.Columns.push({ Name: propertyKey, Ignore: true });
187
- }
188
- else {
189
- columnDesc.Ignore = true;
190
- }
191
- }, true);
192
- }
193
- /**
194
- * Marks columns as UUID. Column will be generated ad creation
195
- */
196
- export function Uuid() {
197
- return extractDecoratorDescriptor((model, _target, propertyKey) => {
198
- const columnDesc = model.Columns.find((c) => c.Name === propertyKey);
199
- if (!columnDesc) {
200
- // we dont want to fill all props, they will be loaded from db and mergeg with this
201
- model.Columns.push({ Name: propertyKey, Uuid: true });
202
- }
203
- else {
204
- columnDesc.Uuid = true;
205
- }
206
- model.Converters.set(propertyKey, {
207
- Class: UuidConverter,
208
- });
209
- }, true);
210
- }
211
- export function JunctionTable() {
212
- return extractDecoratorDescriptor((model, target, propertyKey) => {
213
- model.JunctionModelProperties.push({
214
- Name: propertyKey,
215
- Model: Reflect.getMetadata('design:type', target, propertyKey),
216
- });
217
- });
218
- }
219
- /**
220
- *
221
- * Marks model to have discrimination map.
222
- *
223
- * @param fieldName - db field name to look for
224
- * @param discriminationMap - field - model mapping
225
- */
226
- export function DiscriminationMap(fieldName, discriminationMap) {
227
- return extractDecoratorDescriptor((model, _target, _propertyKey) => {
228
- model.DiscriminationMap.Field = fieldName;
229
- model.DiscriminationMap.Models = new Map();
230
- discriminationMap.forEach((d) => {
231
- model.DiscriminationMap.Models.set(d.Key, d.Value);
232
- });
233
- }, true);
234
- }
235
- /**
236
- * Marks relation as recursive. When relation is populated it loads all to the top
237
- *
238
- */
239
- export function Recursive() {
240
- return extractDecoratorDescriptor((model, _target, propertyKey) => {
241
- if (!model.Relations.has(propertyKey)) {
242
- throw new InvalidOperation(`cannot set recursive on not existing relation ( relation ${propertyKey} on model ${model.Name} )`);
243
- }
244
- const relation = model.Relations.get(propertyKey);
245
- relation.Recursive = true;
246
- });
247
- }
248
- export const forwardRef = (fn) => ({
249
- forwardRef: fn,
250
- });
251
- /**
252
- * Creates one to one relation with target model.
253
- *
254
- * @param foreignKey - foreign key name in db, defaults to lowercase property name with _id suffix eg. owner_id
255
- * @param primaryKey - primary key in related model, defaults to primary key taken from db
256
- */
257
- export function BelongsTo(targetModel, foreignKey, primaryKey) {
258
- return extractDecoratorDescriptor((model, target, propertyKey) => {
259
- model.Relations.set(propertyKey, {
260
- Name: propertyKey,
261
- Type: RelationType.One,
262
- SourceModel: target.constructor,
263
- TargetModelType: targetModel,
264
- TargetModel: null,
265
- ForeignKey: foreignKey ?? `${propertyKey.toLowerCase()}_id`,
266
- PrimaryKey: primaryKey ?? model.PrimaryKey,
267
- Recursive: false,
268
- });
269
- });
270
- }
271
- /**
272
- * Creates one to one relation with target model.
273
- *
274
- * @param foreignKey - foreign key name in db, defaults to lowercase property name with _id suffix eg. owner_id
275
- * @param primaryKey - primary key in related model, defaults to primary key taken from db
276
- */
277
- export function ForwardBelongsTo(forwardRef, foreignKey, primaryKey) {
278
- return extractDecoratorDescriptor((model, target, propertyKey) => {
279
- model.Relations.set(propertyKey, {
280
- Name: propertyKey,
281
- Type: RelationType.One,
282
- SourceModel: target.constructor,
283
- TargetModelType: forwardRef.forwardRef,
284
- TargetModel: null,
285
- ForeignKey: foreignKey ?? `${propertyKey.toLowerCase()}_id`,
286
- PrimaryKey: primaryKey ?? model.PrimaryKey,
287
- Recursive: false,
288
- });
289
- });
290
- }
291
- /**
292
- * Creates one to many relation with target model.
293
- *
294
- * @param targetModel - due to limitations of metadata reflection api in typescript target model mus be set explicitly
295
- * @param foreignKey - foreign key name in db, defaults to lowercase property name with _id suffix eg. owner_id
296
- * @param primaryKey - primary key in source table defaults to lowercase property name with _id suffix eg. owner_id
297
- *
298
- */
299
- export function HasMany(targetModel, options) {
300
- return extractDecoratorDescriptor((model, target, propertyKey) => {
301
- model.Relations.set(propertyKey, {
302
- Name: propertyKey,
303
- Type: RelationType.Many,
304
- SourceModel: target.constructor,
305
- TargetModelType: targetModel,
306
- TargetModel: null,
307
- ForeignKey: options ? options.foreignKey ?? `${model.Name.toLowerCase()}_id` : `${model.Name.toLowerCase()}_id`,
308
- PrimaryKey: options ? options.primaryKey ?? model.PrimaryKey : model.PrimaryKey,
309
- Recursive: false,
310
- Factory: options ? options.factory : null,
311
- RelationClass: options ? options.type : null,
312
- });
313
- });
314
- }
315
- export function Historical(targetModel) {
316
- return extractDecoratorDescriptor((model, target, propertyKey) => {
317
- model.Relations.set(propertyKey, {
318
- Name: propertyKey,
319
- Type: RelationType.Many,
320
- SourceModel: target.constructor,
321
- TargetModelType: targetModel,
322
- TargetModel: null,
323
- ForeignKey: model.PrimaryKey,
324
- PrimaryKey: model.PrimaryKey,
325
- Recursive: false,
326
- });
327
- });
328
- }
329
- /**
330
- * Creates many to many relation with separate join table
331
- *
332
- * @param junctionModel - model for junction table
333
- * @param targetModel - model for related data
334
- * @param targetModelPKey - target model primary key name
335
- * @param sourceModelPKey - source model primary key name
336
- * @param junctionModelTargetPk - junction table target primary key name ( foreign key for target model )
337
- * @param junctionModelSourcePk - junction table source primary key name ( foreign key for source model )
338
- */
339
- export function HasManyToMany(junctionModel, targetModel, targetModelPKey, sourceModelPKey, junctionModelTargetPk, junctionModelSourcePk) {
340
- return extractDecoratorDescriptor((model, target, propertyKey) => {
341
- const targetModelDescriptor = extractModelDescriptor(targetModel);
342
- model.Relations.set(propertyKey, {
343
- Name: propertyKey,
344
- Recursive: false,
345
- Type: RelationType.ManyToMany,
346
- SourceModel: target.constructor,
347
- TargetModelType: targetModel,
348
- TargetModel: null,
349
- ForeignKey: targetModelPKey ?? targetModelDescriptor.PrimaryKey,
350
- PrimaryKey: sourceModelPKey ?? model.PrimaryKey,
351
- JunctionModel: junctionModel,
352
- JunctionModelTargetModelFKey_Name: junctionModelTargetPk ?? `${targetModelDescriptor.Name.toLowerCase()}_id`,
353
- JunctionModelSourceModelFKey_Name: junctionModelSourcePk ?? `${model.Name.toLowerCase()}_id`,
354
- });
355
- });
356
- }
357
- /**
358
- * Mark field as datetime type. It will ensure that conversion to & from DB is valid, eg. sqlite DB
359
- * saves datetime as TEXT and ISO8601 strings
360
- */
361
- export function DateTime() {
362
- return extractDecoratorDescriptor((model, target, propertyKey) => {
363
- const type = Reflect.getMetadata('design:type', target, propertyKey);
364
- if (type.name !== 'DateTime') {
365
- throw Error(`Proprety ${propertyKey} must be DateTime type`);
366
- }
367
- if (model.Converters.has(propertyKey)) {
368
- throw new InvalidArgument(`property ${propertyKey} already have data converter attached`);
369
- }
370
- model.Converters.set(propertyKey, {
371
- Class: DatetimeValueConverter,
372
- });
373
- });
374
- }
375
- /**
376
- * Converts data in db to json object. Column type in DB should be STRING.
377
- * DO not use this decorator for use of native DB JSON implementation.
378
- * ORM will detect automatically if field is native JSON DB type.
379
- */
380
- export function Json() {
381
- return extractDecoratorDescriptor((model, _, propertyKey) => {
382
- // add converter for this field
383
- model.Converters.set(propertyKey, {
384
- Class: JsonValueConverter,
385
- });
386
- });
387
- }
388
- /**
389
- *
390
- * Universal converter that guess whitch type to return. Usefull in tables that holds as text different values
391
- * eg. metadata table
392
- *
393
- * @param typeColumn - type column that defines final type of value
394
- */
395
- export function UniversalConverter(typeColumn) {
396
- return extractDecoratorDescriptor((model, _, propertyKey) => {
397
- // add converter for this field
398
- model.Converters.set(propertyKey, {
399
- Class: JsonValueConverter,
400
- Options: {
401
- TypeColumn: typeColumn,
402
- },
403
- });
404
- });
405
- }
406
- /**
407
- * Mark field as SET type. It will ensure that conversion to & from DB is valid, eg. to emulate field type SET in sqlite
408
- */
409
- export function Set() {
410
- return extractDecoratorDescriptor((model, target, propertyKey) => {
411
- const type = Reflect.getMetadata('design:type', target, propertyKey);
412
- if (type.name !== 'Array') {
413
- throw Error(`Proprety ${propertyKey} must be an array type`);
414
- }
415
- if (model.Converters.has(propertyKey)) {
416
- throw new InvalidArgument(`property ${propertyKey} already have data converter attached`);
417
- }
418
- model.Converters.set(propertyKey, {
419
- Class: SetValueConverter,
420
- });
421
- });
422
- }
1
+ /* eslint-disable prettier/prettier */
2
+ import { JsonValueConverter, UuidConverter } from './converters.js';
3
+ import { DI } from '@spinajs/di';
4
+ import { RelationType, DatetimeValueConverter, SetValueConverter } from './interfaces.js';
5
+ import 'reflect-metadata';
6
+ import { extractModelDescriptor } from './model.js';
7
+ import { InvalidOperation, InvalidArgument } from '@spinajs/exceptions';
8
+ export const MODEL_DESCTRIPTION_SYMBOL = Symbol.for('MODEL_DESCRIPTOR');
9
+ export const MIGRATION_DESCRIPTION_SYMBOL = Symbol.for('MIGRATION_DESCRIPTOR');
10
+ /**
11
+ * Helper func to create model metadata
12
+ */
13
+ export function extractDecoratorDescriptor(callback, base = false) {
14
+ return (target, propertyKey, indexOrDescriptor) => {
15
+ let metadata = null;
16
+ if (!base) {
17
+ metadata = target.constructor[MODEL_DESCTRIPTION_SYMBOL];
18
+ }
19
+ else {
20
+ metadata = target[MODEL_DESCTRIPTION_SYMBOL];
21
+ }
22
+ if (!metadata) {
23
+ metadata = {
24
+ Driver: null,
25
+ Converters: new Map(),
26
+ Columns: [],
27
+ Connection: null,
28
+ PrimaryKey: '',
29
+ SoftDelete: {
30
+ DeletedAt: '',
31
+ },
32
+ Archived: {
33
+ ArchivedAt: '',
34
+ },
35
+ TableName: '',
36
+ Timestamps: {
37
+ CreatedAt: '',
38
+ UpdatedAt: '',
39
+ },
40
+ Relations: new Map(),
41
+ Name: target.constructor.name,
42
+ JunctionModelProperties: [],
43
+ DiscriminationMap: {
44
+ Field: '',
45
+ Models: null,
46
+ },
47
+ Schema: {},
48
+ };
49
+ if (!base) {
50
+ target.constructor[MODEL_DESCTRIPTION_SYMBOL] = metadata;
51
+ }
52
+ else {
53
+ target[MODEL_DESCTRIPTION_SYMBOL] = metadata;
54
+ }
55
+ }
56
+ if (callback) {
57
+ callback(metadata, target, propertyKey, indexOrDescriptor);
58
+ }
59
+ };
60
+ }
61
+ /**
62
+ * Sets migration option
63
+ *
64
+ * @param connection - connection name, must exists in configuration file
65
+ */
66
+ export function Migration(connection) {
67
+ return (target) => {
68
+ let metadata = target[MIGRATION_DESCRIPTION_SYMBOL];
69
+ if (!metadata) {
70
+ metadata = {
71
+ Connection: '',
72
+ };
73
+ target[MIGRATION_DESCRIPTION_SYMBOL] = metadata;
74
+ }
75
+ metadata.Connection = connection;
76
+ DI.register(target).as('__migrations__');
77
+ };
78
+ }
79
+ /**
80
+ * Connection model decorator, assigns connection to model
81
+ *
82
+ * @param name - connection name, must be avaible in db config
83
+ */
84
+ export function Connection(name) {
85
+ return extractDecoratorDescriptor((model) => {
86
+ model.Connection = name;
87
+ }, true);
88
+ }
89
+ /**
90
+ * TableName model decorator, assigns table from database to model
91
+ *
92
+ * @param name - table name in database that is referred by this model
93
+ */
94
+ export function Model(tableName) {
95
+ return extractDecoratorDescriptor((model, target) => {
96
+ DI.register(target).as('__models__');
97
+ model.TableName = tableName;
98
+ model.Name = target.name;
99
+ }, true);
100
+ }
101
+ /**
102
+ * Set create timestamps feature to model. Proper columns must be avaible in database table.
103
+ * It allow to track creation times & changes to model
104
+ */
105
+ export function CreatedAt() {
106
+ return extractDecoratorDescriptor((model, target, propertyKey) => {
107
+ const type = Reflect.getMetadata('design:type', target, propertyKey);
108
+ if (type.name !== 'DateTime') {
109
+ throw Error(`Proprety ${propertyKey} marked as CreatedAt must be DateTime type, but is ${type.name}. Type: ${target.name}`);
110
+ }
111
+ model.Timestamps.CreatedAt = propertyKey;
112
+ // add converter for this field
113
+ model.Converters.set(propertyKey, {
114
+ Class: DatetimeValueConverter,
115
+ });
116
+ });
117
+ }
118
+ /**
119
+ * Set update timestamps feature to model. Proper columns must be avaible in database table.
120
+ * It allow to track creation times & changes to model
121
+ */
122
+ export function UpdatedAt() {
123
+ return extractDecoratorDescriptor((model, target, propertyKey) => {
124
+ const type = Reflect.getMetadata('design:type', target, propertyKey);
125
+ if (type.name !== 'DateTime') {
126
+ throw Error(`Proprety ${propertyKey} marked as UpdatedAt must be DateTime type, but is ${type.name}. Type: ${target.name}`);
127
+ }
128
+ model.Timestamps.UpdatedAt = propertyKey;
129
+ // add converter for this field
130
+ model.Converters.set(propertyKey, {
131
+ Class: DatetimeValueConverter,
132
+ });
133
+ });
134
+ }
135
+ /**
136
+ * Sets soft delete feature to model. Soft delete dont delete model, but sets deletion date and hides from
137
+ * select result by default.
138
+ */
139
+ export function SoftDelete() {
140
+ return extractDecoratorDescriptor((model, target, propertyKey) => {
141
+ const type = Reflect.getMetadata('design:type', target, propertyKey);
142
+ if (type.name !== 'DateTime') {
143
+ throw Error(`Proprety ${propertyKey} marked as DeletedAt must be DateTime type, but is ${type.name}. Type: ${target.name}`);
144
+ }
145
+ model.SoftDelete.DeletedAt = propertyKey;
146
+ // add converter for this field
147
+ model.Converters.set(propertyKey, {
148
+ Class: DatetimeValueConverter,
149
+ });
150
+ });
151
+ }
152
+ /**
153
+ * Enable archive mode for model. If enabled all changes creates new instance in DB and old have set archived field
154
+ * and gets attached to new model. It enabled to track changes to model in DB and also preserve data in relations.
155
+ *
156
+ */
157
+ export function Archived() {
158
+ return extractDecoratorDescriptor((model, target, propertyKey) => {
159
+ const type = Reflect.getMetadata('design:type', target, propertyKey);
160
+ if (type.name !== 'DateTime') {
161
+ throw Error(`Proprety ${propertyKey} marked as ArchivedAt must be DateTime type, but is ${type.name}. Type: ${target.name}`);
162
+ }
163
+ model.Archived.ArchivedAt = propertyKey;
164
+ // add converter for this field
165
+ model.Converters.set(propertyKey, {
166
+ Class: DatetimeValueConverter,
167
+ });
168
+ });
169
+ }
170
+ /**
171
+ * Makrs field as primary key
172
+ */
173
+ export function Primary() {
174
+ return extractDecoratorDescriptor((model, _target, propertyKey) => {
175
+ model.PrimaryKey = propertyKey;
176
+ });
177
+ }
178
+ /**
179
+ * Marks columns as UUID. Column will be generated ad creation
180
+ */
181
+ export function Ignore() {
182
+ return extractDecoratorDescriptor((model, _target, propertyKey) => {
183
+ const columnDesc = model.Columns.find((c) => c.Name === propertyKey);
184
+ if (!columnDesc) {
185
+ // we dont want to fill all props, they will be loaded from db and mergeg with this
186
+ model.Columns.push({ Name: propertyKey, Ignore: true });
187
+ }
188
+ else {
189
+ columnDesc.Ignore = true;
190
+ }
191
+ }, true);
192
+ }
193
+ /**
194
+ * Marks columns as UUID. Column will be generated ad creation
195
+ */
196
+ export function Uuid() {
197
+ return extractDecoratorDescriptor((model, _target, propertyKey) => {
198
+ const columnDesc = model.Columns.find((c) => c.Name === propertyKey);
199
+ if (!columnDesc) {
200
+ // we dont want to fill all props, they will be loaded from db and mergeg with this
201
+ model.Columns.push({ Name: propertyKey, Uuid: true });
202
+ }
203
+ else {
204
+ columnDesc.Uuid = true;
205
+ }
206
+ model.Converters.set(propertyKey, {
207
+ Class: UuidConverter,
208
+ });
209
+ }, true);
210
+ }
211
+ export function JunctionTable() {
212
+ return extractDecoratorDescriptor((model, target, propertyKey) => {
213
+ model.JunctionModelProperties.push({
214
+ Name: propertyKey,
215
+ Model: Reflect.getMetadata('design:type', target, propertyKey),
216
+ });
217
+ });
218
+ }
219
+ /**
220
+ *
221
+ * Marks model to have discrimination map.
222
+ *
223
+ * @param fieldName - db field name to look for
224
+ * @param discriminationMap - field - model mapping
225
+ */
226
+ export function DiscriminationMap(fieldName, discriminationMap) {
227
+ return extractDecoratorDescriptor((model, _target, _propertyKey) => {
228
+ model.DiscriminationMap.Field = fieldName;
229
+ model.DiscriminationMap.Models = new Map();
230
+ discriminationMap.forEach((d) => {
231
+ model.DiscriminationMap.Models.set(d.Key, d.Value);
232
+ });
233
+ }, true);
234
+ }
235
+ /**
236
+ * Marks relation as recursive. When relation is populated it loads all to the top
237
+ *
238
+ */
239
+ export function Recursive() {
240
+ return extractDecoratorDescriptor((model, _target, propertyKey) => {
241
+ if (!model.Relations.has(propertyKey)) {
242
+ throw new InvalidOperation(`cannot set recursive on not existing relation ( relation ${propertyKey} on model ${model.Name} )`);
243
+ }
244
+ const relation = model.Relations.get(propertyKey);
245
+ relation.Recursive = true;
246
+ });
247
+ }
248
+ export const forwardRef = (fn) => ({
249
+ forwardRef: fn,
250
+ });
251
+ /**
252
+ * Creates one to one relation with target model.
253
+ *
254
+ * @param foreignKey - foreign key name in db, defaults to lowercase property name with _id suffix eg. owner_id
255
+ * @param primaryKey - primary key in related model, defaults to primary key taken from db
256
+ */
257
+ export function BelongsTo(targetModel, foreignKey, primaryKey) {
258
+ return extractDecoratorDescriptor((model, target, propertyKey) => {
259
+ model.Relations.set(propertyKey, {
260
+ Name: propertyKey,
261
+ Type: RelationType.One,
262
+ SourceModel: target.constructor,
263
+ TargetModelType: targetModel,
264
+ TargetModel: null,
265
+ ForeignKey: foreignKey ?? `${propertyKey.toLowerCase()}_id`,
266
+ PrimaryKey: primaryKey ?? model.PrimaryKey,
267
+ Recursive: false,
268
+ });
269
+ });
270
+ }
271
+ /**
272
+ * Creates one to one relation with target model.
273
+ *
274
+ * @param foreignKey - foreign key name in db, defaults to lowercase property name with _id suffix eg. owner_id
275
+ * @param primaryKey - primary key in related model, defaults to primary key taken from db
276
+ */
277
+ export function ForwardBelongsTo(forwardRef, foreignKey, primaryKey) {
278
+ return extractDecoratorDescriptor((model, target, propertyKey) => {
279
+ model.Relations.set(propertyKey, {
280
+ Name: propertyKey,
281
+ Type: RelationType.One,
282
+ SourceModel: target.constructor,
283
+ TargetModelType: forwardRef.forwardRef,
284
+ TargetModel: null,
285
+ ForeignKey: foreignKey ?? `${propertyKey.toLowerCase()}_id`,
286
+ PrimaryKey: primaryKey ?? model.PrimaryKey,
287
+ Recursive: false,
288
+ });
289
+ });
290
+ }
291
+ /**
292
+ * Creates one to many relation with target model.
293
+ *
294
+ * @param targetModel - due to limitations of metadata reflection api in typescript target model mus be set explicitly
295
+ * @param foreignKey - foreign key name in db, defaults to lowercase property name with _id suffix eg. owner_id
296
+ * @param primaryKey - primary key in source table defaults to lowercase property name with _id suffix eg. owner_id
297
+ *
298
+ */
299
+ export function HasMany(targetModel, options) {
300
+ return extractDecoratorDescriptor((model, target, propertyKey) => {
301
+ model.Relations.set(propertyKey, {
302
+ Name: propertyKey,
303
+ Type: RelationType.Many,
304
+ SourceModel: target.constructor,
305
+ TargetModelType: targetModel,
306
+ TargetModel: null,
307
+ ForeignKey: options ? options.foreignKey ?? `${model.Name.toLowerCase()}_id` : `${model.Name.toLowerCase()}_id`,
308
+ PrimaryKey: options ? options.primaryKey ?? model.PrimaryKey : model.PrimaryKey,
309
+ Recursive: false,
310
+ Factory: options ? options.factory : null,
311
+ RelationClass: options ? options.type : null,
312
+ });
313
+ });
314
+ }
315
+ export function Historical(targetModel) {
316
+ return extractDecoratorDescriptor((model, target, propertyKey) => {
317
+ model.Relations.set(propertyKey, {
318
+ Name: propertyKey,
319
+ Type: RelationType.Many,
320
+ SourceModel: target.constructor,
321
+ TargetModelType: targetModel,
322
+ TargetModel: null,
323
+ ForeignKey: model.PrimaryKey,
324
+ PrimaryKey: model.PrimaryKey,
325
+ Recursive: false,
326
+ });
327
+ });
328
+ }
329
+ /**
330
+ * Creates many to many relation with separate join table
331
+ *
332
+ * @param junctionModel - model for junction table
333
+ * @param targetModel - model for related data
334
+ * @param targetModelPKey - target model primary key name
335
+ * @param sourceModelPKey - source model primary key name
336
+ * @param junctionModelTargetPk - junction table target primary key name ( foreign key for target model )
337
+ * @param junctionModelSourcePk - junction table source primary key name ( foreign key for source model )
338
+ */
339
+ export function HasManyToMany(junctionModel, targetModel, targetModelPKey, sourceModelPKey, junctionModelTargetPk, junctionModelSourcePk) {
340
+ return extractDecoratorDescriptor((model, target, propertyKey) => {
341
+ const targetModelDescriptor = extractModelDescriptor(targetModel);
342
+ model.Relations.set(propertyKey, {
343
+ Name: propertyKey,
344
+ Recursive: false,
345
+ Type: RelationType.ManyToMany,
346
+ SourceModel: target.constructor,
347
+ TargetModelType: targetModel,
348
+ TargetModel: null,
349
+ ForeignKey: targetModelPKey ?? targetModelDescriptor.PrimaryKey,
350
+ PrimaryKey: sourceModelPKey ?? model.PrimaryKey,
351
+ JunctionModel: junctionModel,
352
+ JunctionModelTargetModelFKey_Name: junctionModelTargetPk ?? `${targetModelDescriptor.Name.toLowerCase()}_id`,
353
+ JunctionModelSourceModelFKey_Name: junctionModelSourcePk ?? `${model.Name.toLowerCase()}_id`,
354
+ });
355
+ });
356
+ }
357
+ /**
358
+ * Mark field as datetime type. It will ensure that conversion to & from DB is valid, eg. sqlite DB
359
+ * saves datetime as TEXT and ISO8601 strings
360
+ */
361
+ export function DateTime() {
362
+ return extractDecoratorDescriptor((model, target, propertyKey) => {
363
+ const type = Reflect.getMetadata('design:type', target, propertyKey);
364
+ if (type.name !== 'DateTime') {
365
+ throw Error(`Proprety ${propertyKey} must be DateTime type`);
366
+ }
367
+ if (model.Converters.has(propertyKey)) {
368
+ throw new InvalidArgument(`property ${propertyKey} already have data converter attached`);
369
+ }
370
+ model.Converters.set(propertyKey, {
371
+ Class: DatetimeValueConverter,
372
+ });
373
+ });
374
+ }
375
+ /**
376
+ * Converts data in db to json object. Column type in DB should be STRING.
377
+ * DO not use this decorator for use of native DB JSON implementation.
378
+ * ORM will detect automatically if field is native JSON DB type.
379
+ */
380
+ export function Json() {
381
+ return extractDecoratorDescriptor((model, _, propertyKey) => {
382
+ // add converter for this field
383
+ model.Converters.set(propertyKey, {
384
+ Class: JsonValueConverter,
385
+ });
386
+ });
387
+ }
388
+ /**
389
+ *
390
+ * Universal converter that guess whitch type to return. Usefull in tables that holds as text different values
391
+ * eg. metadata table
392
+ *
393
+ * @param typeColumn - type column that defines final type of value
394
+ */
395
+ export function UniversalConverter(typeColumn) {
396
+ return extractDecoratorDescriptor((model, _, propertyKey) => {
397
+ // add converter for this field
398
+ model.Converters.set(propertyKey, {
399
+ Class: JsonValueConverter,
400
+ Options: {
401
+ TypeColumn: typeColumn,
402
+ },
403
+ });
404
+ });
405
+ }
406
+ /**
407
+ * Mark field as SET type. It will ensure that conversion to & from DB is valid, eg. to emulate field type SET in sqlite
408
+ */
409
+ export function Set() {
410
+ return extractDecoratorDescriptor((model, target, propertyKey) => {
411
+ const type = Reflect.getMetadata('design:type', target, propertyKey);
412
+ if (type.name !== 'Array') {
413
+ throw Error(`Proprety ${propertyKey} must be an array type`);
414
+ }
415
+ if (model.Converters.has(propertyKey)) {
416
+ throw new InvalidArgument(`property ${propertyKey} already have data converter attached`);
417
+ }
418
+ model.Converters.set(propertyKey, {
419
+ Class: SetValueConverter,
420
+ });
421
+ });
422
+ }
423
423
  //# sourceMappingURL=decorators.js.map