@decaf-ts/core 0.8.29 → 0.8.31
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/README.md +1 -1
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/lib/esm/identity/decorators.js +1 -1
- package/lib/esm/identity/decorators.js.map +1 -1
- package/lib/esm/index.d.ts +1 -1
- package/lib/esm/index.js +1 -1
- package/lib/esm/model/SequenceModel.js +2 -1
- package/lib/esm/model/SequenceModel.js.map +1 -1
- package/lib/esm/model/construction.d.ts +13 -0
- package/lib/esm/model/construction.js +286 -1
- package/lib/esm/model/construction.js.map +1 -1
- package/lib/esm/model/decorators.d.ts +1 -20
- package/lib/esm/model/decorators.js +9 -41
- package/lib/esm/model/decorators.js.map +1 -1
- package/lib/esm/model/index.d.ts +1 -0
- package/lib/esm/model/index.js +1 -0
- package/lib/esm/model/index.js.map +1 -1
- package/lib/esm/model/indexing.d.ts +20 -0
- package/lib/esm/model/indexing.js +37 -0
- package/lib/esm/model/indexing.js.map +1 -0
- package/lib/esm/persistence/Adapter.js +4 -2
- package/lib/esm/persistence/Adapter.js.map +1 -1
- package/lib/esm/repository/decorators.js +2 -1
- package/lib/esm/repository/decorators.js.map +1 -1
- package/lib/esm/tasks/TaskEngine.js +13 -6
- package/lib/esm/tasks/TaskEngine.js.map +1 -1
- package/lib/esm/tasks/TaskTracker.d.ts +2 -0
- package/lib/esm/tasks/TaskTracker.js +26 -3
- package/lib/esm/tasks/TaskTracker.js.map +1 -1
- package/lib/esm/tasks/models/TaskIOSerializer.d.ts +8 -2
- package/lib/esm/tasks/models/TaskIOSerializer.js +70 -30
- package/lib/esm/tasks/models/TaskIOSerializer.js.map +1 -1
- package/lib/identity/decorators.cjs +2 -2
- package/lib/identity/decorators.js.map +1 -1
- package/lib/index.cjs +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/model/SequenceModel.cjs +2 -1
- package/lib/model/SequenceModel.js.map +1 -1
- package/lib/model/construction.cjs +293 -0
- package/lib/model/construction.d.ts +13 -0
- package/lib/model/construction.js.map +1 -1
- package/lib/model/decorators.cjs +7 -40
- package/lib/model/decorators.d.ts +1 -20
- package/lib/model/decorators.js.map +1 -1
- package/lib/model/index.cjs +1 -0
- package/lib/model/index.d.ts +1 -0
- package/lib/model/index.js.map +1 -1
- package/lib/model/indexing.cjs +40 -0
- package/lib/model/indexing.d.ts +20 -0
- package/lib/model/indexing.js.map +1 -0
- package/lib/persistence/Adapter.cjs +4 -2
- package/lib/persistence/Adapter.js.map +1 -1
- package/lib/repository/decorators.cjs +4 -3
- package/lib/repository/decorators.js.map +1 -1
- package/lib/tasks/TaskEngine.cjs +13 -6
- package/lib/tasks/TaskEngine.js.map +1 -1
- package/lib/tasks/TaskTracker.cjs +26 -3
- package/lib/tasks/TaskTracker.d.ts +2 -0
- package/lib/tasks/TaskTracker.js.map +1 -1
- package/lib/tasks/models/TaskIOSerializer.cjs +70 -30
- package/lib/tasks/models/TaskIOSerializer.d.ts +8 -2
- package/lib/tasks/models/TaskIOSerializer.js.map +1 -1
- package/package.json +1 -1
|
@@ -10,32 +10,11 @@ export class TaskIOSerializer extends JSONSerializer {
|
|
|
10
10
|
* @description returns a shallow copy of the object, containing an enumerable {@link ModelKeys#ANCHOR} property
|
|
11
11
|
* so the object can be recognized upon deserialization
|
|
12
12
|
*
|
|
13
|
-
* @param {
|
|
13
|
+
* @param {any} value
|
|
14
14
|
* @protected
|
|
15
15
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (model === null || typeof model !== "object") {
|
|
19
|
-
return model;
|
|
20
|
-
}
|
|
21
|
-
const toSerialize = Object.assign({}, model);
|
|
22
|
-
if (model instanceof Condition) {
|
|
23
|
-
toSerialize[ModelKeys.ANCHOR] = "??condition";
|
|
24
|
-
return toSerialize;
|
|
25
|
-
}
|
|
26
|
-
if (Model.isModel(model)) {
|
|
27
|
-
let metadata;
|
|
28
|
-
try {
|
|
29
|
-
metadata = Metadata.modelName(model.constructor);
|
|
30
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
31
|
-
}
|
|
32
|
-
catch (error) {
|
|
33
|
-
metadata = undefined;
|
|
34
|
-
}
|
|
35
|
-
if (metadata)
|
|
36
|
-
toSerialize[ModelKeys.ANCHOR] = metadata;
|
|
37
|
-
}
|
|
38
|
-
return toSerialize;
|
|
16
|
+
preSerialize(value, ...args) {
|
|
17
|
+
return this.serializeValue(value, ...args);
|
|
39
18
|
}
|
|
40
19
|
/**
|
|
41
20
|
* @summary Rebuilds a model from a serialization
|
|
@@ -46,12 +25,73 @@ export class TaskIOSerializer extends JSONSerializer {
|
|
|
46
25
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
47
26
|
deserialize(str, ...args) {
|
|
48
27
|
const deserialization = JSON.parse(str);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (
|
|
53
|
-
return
|
|
54
|
-
|
|
28
|
+
return this.rebuildValue(deserialization);
|
|
29
|
+
}
|
|
30
|
+
serializeValue(value, ...args) {
|
|
31
|
+
if (value === undefined || value === null)
|
|
32
|
+
return value;
|
|
33
|
+
if (typeof value !== "object")
|
|
34
|
+
return value;
|
|
35
|
+
if (value instanceof Date)
|
|
36
|
+
return value.toISOString();
|
|
37
|
+
if (Array.isArray(value)) {
|
|
38
|
+
return value.map((item) => this.serializeValue(item, ...args));
|
|
39
|
+
}
|
|
40
|
+
if (value instanceof Condition) {
|
|
41
|
+
const condition = this.serializePlain(value, ...args);
|
|
42
|
+
condition[ModelKeys.ANCHOR] = "??condition";
|
|
43
|
+
return condition;
|
|
44
|
+
}
|
|
45
|
+
if (Model.isModel(value)) {
|
|
46
|
+
return this.serializeModel(value, ...args);
|
|
47
|
+
}
|
|
48
|
+
return this.serializePlain(value, ...args);
|
|
49
|
+
}
|
|
50
|
+
serializeModel(value, ...args) {
|
|
51
|
+
const serialized = this.serializePlain(value, ...args);
|
|
52
|
+
const metadata = this.getMetadata(value.constructor) ??
|
|
53
|
+
value.constructor?.name;
|
|
54
|
+
if (metadata)
|
|
55
|
+
serialized[ModelKeys.ANCHOR] = metadata;
|
|
56
|
+
return serialized;
|
|
57
|
+
}
|
|
58
|
+
serializePlain(value, ...args) {
|
|
59
|
+
const result = {};
|
|
60
|
+
for (const [key, child] of Object.entries(value)) {
|
|
61
|
+
result[key] = this.serializeValue(child, ...args);
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
getMetadata(constructor) {
|
|
66
|
+
try {
|
|
67
|
+
return Metadata.modelName(constructor);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
rebuildValue(value) {
|
|
74
|
+
if (value === null || typeof value !== "object")
|
|
75
|
+
return value;
|
|
76
|
+
if (Array.isArray(value)) {
|
|
77
|
+
return value.map((item) => this.rebuildValue(item));
|
|
78
|
+
}
|
|
79
|
+
const anchor = value[ModelKeys.ANCHOR];
|
|
80
|
+
const rebuilt = this.rebuildObject(value);
|
|
81
|
+
if (!anchor)
|
|
82
|
+
return rebuilt;
|
|
83
|
+
if (anchor === "??condition")
|
|
84
|
+
return Condition.from(rebuilt);
|
|
85
|
+
return Model.build(rebuilt, anchor);
|
|
86
|
+
}
|
|
87
|
+
rebuildObject(value) {
|
|
88
|
+
const result = {};
|
|
89
|
+
for (const [key, child] of Object.entries(value)) {
|
|
90
|
+
if (key === ModelKeys.ANCHOR)
|
|
91
|
+
continue;
|
|
92
|
+
result[key] = this.rebuildValue(child);
|
|
93
|
+
}
|
|
94
|
+
return result;
|
|
55
95
|
}
|
|
56
96
|
/**
|
|
57
97
|
* @summary Serializes a model
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskIOSerializer.js","sourceRoot":"","sources":["../../../../src/tasks/models/TaskIOSerializer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,KAAK,EACL,SAAS,GACV,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAe,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,mCAA8B;AAElD,MAAM,OAAO,gBAAkC,SAAQ,cAAiB;IACtE;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAED;;;;;;;OAOG;IACH,6DAA6D;
|
|
1
|
+
{"version":3,"file":"TaskIOSerializer.js","sourceRoot":"","sources":["../../../../src/tasks/models/TaskIOSerializer.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,9 +6,9 @@ exports.pk = pk;
|
|
|
6
6
|
const decorator_validation_1 = require("@decaf-ts/decorator-validation");
|
|
7
7
|
const SequenceOptions_1 = require("./../interfaces/SequenceOptions.cjs");
|
|
8
8
|
const db_decorators_1 = require("@decaf-ts/db-decorators");
|
|
9
|
-
const decorators_1 = require("./../model/decorators.cjs");
|
|
10
9
|
const constants_1 = require("./../repository/constants.cjs");
|
|
11
10
|
const decoration_1 = require("@decaf-ts/decoration");
|
|
11
|
+
const indexing_1 = require("./../model/indexing.cjs");
|
|
12
12
|
const defaultPkPriority = 60; // Default priority for primary key to run latter than other properties
|
|
13
13
|
/**
|
|
14
14
|
* @description Callback function for primary key creation
|
|
@@ -111,7 +111,7 @@ function pkDec(options, groupsort) {
|
|
|
111
111
|
}
|
|
112
112
|
const decs = [
|
|
113
113
|
(0, decoration_1.prop)(),
|
|
114
|
-
(0,
|
|
114
|
+
(0, indexing_1.index)([constants_1.OrderDirection.ASC, constants_1.OrderDirection.DSC]),
|
|
115
115
|
(0, decorator_validation_1.required)(),
|
|
116
116
|
(0, db_decorators_1.readonly)(),
|
|
117
117
|
(0, decoration_1.propMetadata)(decoration_1.Metadata.key(db_decorators_1.DBKeys.ID, attr), options),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/identity/decorators.ts"],"names":[],"mappings":";;AA+DA,gCAmCC;AAED,sBA4DC;AAsBD,gBAaC;AAnMD,yEAAiE;AACjE,yEAGuC;AACvC,2DAOiC;
|
|
1
|
+
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/identity/decorators.ts"],"names":[],"mappings":"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"}
|
package/lib/index.cjs
CHANGED
|
@@ -48,7 +48,7 @@ __exportStar(require("./persistence/index.cjs"), exports);
|
|
|
48
48
|
* @const VERSION
|
|
49
49
|
* @memberOf module:core
|
|
50
50
|
*/
|
|
51
|
-
exports.VERSION = "0.8.
|
|
51
|
+
exports.VERSION = "0.8.30";
|
|
52
52
|
/**
|
|
53
53
|
* @description Stores the current package version
|
|
54
54
|
* @summary A constant representing the version of the core package
|
package/lib/index.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export * from "./persistence";
|
|
|
21
21
|
* @const VERSION
|
|
22
22
|
* @memberOf module:core
|
|
23
23
|
*/
|
|
24
|
-
export declare const VERSION = "0.8.
|
|
24
|
+
export declare const VERSION = "0.8.30";
|
|
25
25
|
/**
|
|
26
26
|
* @description Stores the current package version
|
|
27
27
|
* @summary A constant representing the version of the core package
|
|
@@ -14,6 +14,7 @@ const decorator_validation_1 = require("@decaf-ts/decorator-validation");
|
|
|
14
14
|
const BaseModel_1 = require("./BaseModel.cjs");
|
|
15
15
|
const decorators_1 = require("./decorators.cjs");
|
|
16
16
|
const decorators_2 = require("./../identity/decorators.cjs");
|
|
17
|
+
const indexing_1 = require("./indexing.cjs");
|
|
17
18
|
/**
|
|
18
19
|
* @description RAM sequence model for auto-incrementing values
|
|
19
20
|
* @summary A model class that represents a sequence in the RAM adapter. It stores the current value
|
|
@@ -44,7 +45,7 @@ __decorate([
|
|
|
44
45
|
], SequenceModel.prototype, "id", void 0);
|
|
45
46
|
__decorate([
|
|
46
47
|
(0, decorator_validation_1.required)(),
|
|
47
|
-
(0,
|
|
48
|
+
(0, indexing_1.index)(),
|
|
48
49
|
__metadata("design:type", Object)
|
|
49
50
|
], SequenceModel.prototype, "current", void 0);
|
|
50
51
|
exports.SequenceModel = SequenceModel = __decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SequenceModel.js","sourceRoot":"","sources":["../../src/model/SequenceModel.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,yEAAiE;AAEjE,+CAAwC;AACxC,
|
|
1
|
+
{"version":3,"file":"SequenceModel.js","sourceRoot":"","sources":["../../src/model/SequenceModel.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,yEAAiE;AAEjE,+CAAwC;AACxC,iDAAqC;AACrC,6DAA4C;AAC5C,6CAAmC;AACnC;;;;;;;;;;;;;;;;;GAiBG;AAGI,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,qBAAS;IAe1C,YAAY,GAA6B;QACvC,KAAK,CAAC,GAAG,CAAC,CAAC;IACb,CAAC;CACF,CAAA;AAlBY,sCAAa;AAKxB;IADC,IAAA,eAAE,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;;yCAC3B;AAQZ;IAFC,IAAA,+BAAQ,GAAE;IACV,IAAA,gBAAK,GAAE;;8CACkB;wBAbf,aAAa;IAFzB,IAAA,kBAAK,EAAC,YAAY,CAAC;IACnB,IAAA,4BAAK,GAAE;;GACK,aAAa,CAkBzB"}
|
|
@@ -7,6 +7,14 @@ exports.oneToOneOnDelete = oneToOneOnDelete;
|
|
|
7
7
|
exports.oneToManyOnCreate = oneToManyOnCreate;
|
|
8
8
|
exports.oneToManyOnUpdate = oneToManyOnUpdate;
|
|
9
9
|
exports.oneToManyOnDelete = oneToManyOnDelete;
|
|
10
|
+
exports.manyToOneOnCreate = manyToOneOnCreate;
|
|
11
|
+
exports.validBidirectionalRelation = validBidirectionalRelation;
|
|
12
|
+
exports.manyToOneOnUpdate = manyToOneOnUpdate;
|
|
13
|
+
exports.manyToOneOnDelete = manyToOneOnDelete;
|
|
14
|
+
exports.manyToManyOnCreate = manyToManyOnCreate;
|
|
15
|
+
exports.getAndConstructJunctionTable = getAndConstructJunctionTable;
|
|
16
|
+
exports.manyToManyOnUpdate = manyToManyOnUpdate;
|
|
17
|
+
exports.manyToManyOnDelete = manyToManyOnDelete;
|
|
10
18
|
exports.getPopulateKey = getPopulateKey;
|
|
11
19
|
exports.getTagForDeleteKey = getTagForDeleteKey;
|
|
12
20
|
exports.cacheModelForPopulate = cacheModelForPopulate;
|
|
@@ -19,6 +27,7 @@ const db_decorators_1 = require("@decaf-ts/db-decorators");
|
|
|
19
27
|
const constants_1 = require("./../persistence/constants.cjs");
|
|
20
28
|
const constants_2 = require("./../repository/constants.cjs");
|
|
21
29
|
const decoration_1 = require("@decaf-ts/decoration");
|
|
30
|
+
const decorators_1 = require("./../identity/decorators.cjs");
|
|
22
31
|
/**
|
|
23
32
|
* @description Creates or updates a model instance
|
|
24
33
|
* @summary Determines whether to create a new model or update an existing one based on the presence of a primary key
|
|
@@ -208,6 +217,8 @@ async function oneToOneOnCreate(context, data, key, model) {
|
|
|
208
217
|
const propertyValue = model[key];
|
|
209
218
|
if (!propertyValue)
|
|
210
219
|
return;
|
|
220
|
+
if (!validBidirectionalRelation(model, data))
|
|
221
|
+
return;
|
|
211
222
|
if (typeof propertyValue !== "object") {
|
|
212
223
|
const innerRepo = repositoryFromTypeMetadata(model, key, this.adapter.alias);
|
|
213
224
|
const read = await innerRepo.read(propertyValue, context);
|
|
@@ -408,6 +419,8 @@ async function oneToManyOnCreate(context, data, key, model) {
|
|
|
408
419
|
const propertyValues = model[key];
|
|
409
420
|
if (!propertyValues || !propertyValues.length)
|
|
410
421
|
return;
|
|
422
|
+
if (!validBidirectionalRelation(model, data))
|
|
423
|
+
return;
|
|
411
424
|
const arrayType = typeof propertyValues[0];
|
|
412
425
|
if (!propertyValues.every((item) => typeof item === arrayType))
|
|
413
426
|
throw new db_decorators_1.InternalError(`Invalid operation. All elements of property ${key} must match the same type.`);
|
|
@@ -576,6 +589,286 @@ async function oneToManyOnDelete(context, data, key, model) {
|
|
|
576
589
|
}
|
|
577
590
|
model[key] = ids;
|
|
578
591
|
}
|
|
592
|
+
async function manyToOneOnCreate(context, data, key, model) {
|
|
593
|
+
const propertyValue = model[key];
|
|
594
|
+
if (!propertyValue)
|
|
595
|
+
return;
|
|
596
|
+
if (!validBidirectionalRelation(model, data))
|
|
597
|
+
return;
|
|
598
|
+
const log = context.logger.for(manyToOneOnCreate);
|
|
599
|
+
// If it's a primitive value (ID), read the existing record
|
|
600
|
+
if (typeof propertyValue !== "object") {
|
|
601
|
+
const innerRepo = repositoryFromTypeMetadata(model, key, this.adapter.alias);
|
|
602
|
+
const read = await innerRepo.read(propertyValue);
|
|
603
|
+
await cacheModelForPopulate(context, model, key, propertyValue, read);
|
|
604
|
+
model[key] = propertyValue;
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
const constructor = data.class instanceof decorator_validation_1.Model ? data.class.constructor : data.class;
|
|
608
|
+
if (!constructor)
|
|
609
|
+
throw new db_decorators_1.InternalError(`Could not find model ${data.class}`);
|
|
610
|
+
log.info(`Creating or updating many-to-one model: ${JSON.stringify(propertyValue)}`);
|
|
611
|
+
const record = await createOrUpdate(propertyValue, context, this.adapter.alias);
|
|
612
|
+
const pk = decorator_validation_1.Model.pk(record);
|
|
613
|
+
log.info(`caching: ${JSON.stringify(record)} under ${record[pk]}`);
|
|
614
|
+
await cacheModelForPopulate(context, model, key, record[pk], record);
|
|
615
|
+
model[key] = record[pk];
|
|
616
|
+
}
|
|
617
|
+
function validBidirectionalRelation(model, data) {
|
|
618
|
+
let metaReverseRelation;
|
|
619
|
+
const relationConstructor = typeof data.class === "function" && data.class.name
|
|
620
|
+
? data.class
|
|
621
|
+
: data.class();
|
|
622
|
+
// get the inverse relation metadata
|
|
623
|
+
const metaReverseRelationMeta = decoration_1.Metadata.get(relationConstructor, constants_1.PersistenceKeys.RELATIONS);
|
|
624
|
+
if (metaReverseRelationMeta)
|
|
625
|
+
metaReverseRelation = Object.values(metaReverseRelationMeta)?.find((rel) => {
|
|
626
|
+
const relationConstructor = typeof rel.class === "function" && rel.class.name
|
|
627
|
+
? rel.class
|
|
628
|
+
: rel.class();
|
|
629
|
+
return model instanceof relationConstructor;
|
|
630
|
+
});
|
|
631
|
+
// If populate is set to true on both sides, we should throw an error.
|
|
632
|
+
if (metaReverseRelation?.populate === true && data?.populate === true) {
|
|
633
|
+
throw new db_decorators_1.InternalError("Bidirectional populate is not allowed. Please set populate to false on one side of the relation.");
|
|
634
|
+
}
|
|
635
|
+
return true;
|
|
636
|
+
}
|
|
637
|
+
async function manyToOneOnUpdate(context, data, key, model) {
|
|
638
|
+
const { cascade } = data;
|
|
639
|
+
if (cascade.update !== constants_2.Cascade.CASCADE)
|
|
640
|
+
return;
|
|
641
|
+
return manyToOneOnCreate.apply(this, [
|
|
642
|
+
context,
|
|
643
|
+
data,
|
|
644
|
+
key,
|
|
645
|
+
model,
|
|
646
|
+
]);
|
|
647
|
+
}
|
|
648
|
+
async function manyToOneOnDelete(context, data, key, model) {
|
|
649
|
+
if (data.cascade.delete !== constants_2.Cascade.CASCADE)
|
|
650
|
+
return;
|
|
651
|
+
const value = model[key];
|
|
652
|
+
if (!value)
|
|
653
|
+
return;
|
|
654
|
+
const isInstantiated = typeof value === "object";
|
|
655
|
+
const repo = isInstantiated
|
|
656
|
+
? Repository_1.Repository.forModel(value, this.adapter.alias)
|
|
657
|
+
: repositoryFromTypeMetadata(model, key, this.adapter.alias);
|
|
658
|
+
const repoId = isInstantiated ? value[repo["pk"]] : value;
|
|
659
|
+
const deleted = await repo.delete(repoId);
|
|
660
|
+
await cacheModelForPopulate(context, model, key, repoId, deleted);
|
|
661
|
+
model[key] = repoId;
|
|
662
|
+
}
|
|
663
|
+
async function manyToManyOnCreate(context, data, key, modelA) {
|
|
664
|
+
console.warn("DECORATOR manyToMany UNDER DEVELOPMENT");
|
|
665
|
+
const propertyValues = modelA[key];
|
|
666
|
+
if (!propertyValues || !propertyValues.length)
|
|
667
|
+
return;
|
|
668
|
+
if (!validBidirectionalRelation(modelA, data))
|
|
669
|
+
return;
|
|
670
|
+
const arrayType = typeof propertyValues[0];
|
|
671
|
+
if (!propertyValues.every((item) => typeof item === arrayType))
|
|
672
|
+
throw new db_decorators_1.InternalError(`Invalid operation. All elements of property ${key} must match the same type.`);
|
|
673
|
+
const log = context.logger.for(manyToManyOnCreate);
|
|
674
|
+
const uniqueValues = new Set([...propertyValues]);
|
|
675
|
+
// If it's a primitive value (ID), read the existing record
|
|
676
|
+
if (arrayType !== "object") {
|
|
677
|
+
const repo = repositoryFromTypeMetadata(modelA, key, this.adapter.alias);
|
|
678
|
+
const read = await repo.readAll([...uniqueValues.values()], context);
|
|
679
|
+
for (let i = 0; i < read.length; i++) {
|
|
680
|
+
const model = read[i];
|
|
681
|
+
log.info(`FOUND MANY TO MANY VALUE: ${JSON.stringify(model)}`);
|
|
682
|
+
await cacheModelForPopulate(context, model, key, [...uniqueValues.values()][i], read);
|
|
683
|
+
}
|
|
684
|
+
// Create junction table entries
|
|
685
|
+
await getOrCreateJunctionModel.apply(this, [
|
|
686
|
+
modelA,
|
|
687
|
+
[...propertyValues],
|
|
688
|
+
log,
|
|
689
|
+
context,
|
|
690
|
+
data,
|
|
691
|
+
]);
|
|
692
|
+
modelA[key] = [...uniqueValues];
|
|
693
|
+
log.info(`SET MANY TO MANY IDS: ${modelA[key]}`);
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
const pkName = decorator_validation_1.Model.pk(propertyValues[0].constructor);
|
|
697
|
+
const result = new Set();
|
|
698
|
+
for (const propertyValue of propertyValues) {
|
|
699
|
+
log.info(`Creating or updating many-to-many model: ${JSON.stringify(propertyValue)}`);
|
|
700
|
+
const record = await createOrUpdate(propertyValue, context, this.adapter.alias);
|
|
701
|
+
log.info(`caching: ${JSON.stringify(record)} under ${record[pkName]}`);
|
|
702
|
+
await cacheModelForPopulate(context, modelA, key, record[pkName], record);
|
|
703
|
+
log.info(`Creating or updating many-to-many model: ${JSON.stringify(propertyValue)}`);
|
|
704
|
+
propertyValue.id = record.id;
|
|
705
|
+
result.add(record[pkName]);
|
|
706
|
+
}
|
|
707
|
+
// Get or generate the ID for modelA before persisting junction records
|
|
708
|
+
const modelPkName = decorator_validation_1.Model.pk(modelA.constructor);
|
|
709
|
+
if (typeof modelA[modelPkName] === "undefined") {
|
|
710
|
+
const nextId = await getNextId(this, modelA, context);
|
|
711
|
+
modelA[modelPkName] = nextId;
|
|
712
|
+
}
|
|
713
|
+
// Create junction table entries
|
|
714
|
+
const JunctionModel = await getOrCreateJunctionModel.apply(this, [modelA, propertyValues, log, context, data]);
|
|
715
|
+
// This will require creating junction repository and storing the relationships
|
|
716
|
+
log.info(`Junction model created: ${JunctionModel.name}`);
|
|
717
|
+
modelA[key] = [...result];
|
|
718
|
+
}
|
|
719
|
+
async function getNextId(repo, modelA, context) {
|
|
720
|
+
// Get the next id for the model before it is persisted so we can put it in the junction table
|
|
721
|
+
const modelPkName = decorator_validation_1.Model.pk(modelA.constructor);
|
|
722
|
+
const modelAId = modelA[modelPkName];
|
|
723
|
+
if (modelAId !== undefined) {
|
|
724
|
+
return modelAId;
|
|
725
|
+
}
|
|
726
|
+
const pkProps = decorator_validation_1.Model.sequenceFor(modelA.constructor);
|
|
727
|
+
if (!pkProps?.name) {
|
|
728
|
+
pkProps.name = decorator_validation_1.Model.sequenceName(modelA, "pk");
|
|
729
|
+
}
|
|
730
|
+
let sequence;
|
|
731
|
+
try {
|
|
732
|
+
// Access adapter through the public property 'db' or use type assertion
|
|
733
|
+
sequence = await repo.adapter.Sequence(pkProps);
|
|
734
|
+
return await sequence.next(context);
|
|
735
|
+
}
|
|
736
|
+
catch (e) {
|
|
737
|
+
throw new db_decorators_1.InternalError(`Failed to instantiate Sequence ${pkProps.name}: ${e}`);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
async function getOrCreateJunctionModel(modelA, modelsB, log, context, metadata) {
|
|
741
|
+
const { JunctionModel, fkA, fkB } = getAndConstructJunctionTable(modelA, modelsB[0], metadata);
|
|
742
|
+
const recordIds = [];
|
|
743
|
+
for (const modelB of modelsB) {
|
|
744
|
+
log.info(`Creating or updating many-to-many junction model: ${JSON.stringify(modelB)}`);
|
|
745
|
+
// If it is a model, find and store fk content, else it is fk value directly
|
|
746
|
+
const junctionRegister = {
|
|
747
|
+
[fkA]: modelA instanceof decorator_validation_1.Model
|
|
748
|
+
? modelA[decorator_validation_1.Model.pk(modelA.constructor)]
|
|
749
|
+
: modelA,
|
|
750
|
+
[fkB]: modelB instanceof decorator_validation_1.Model
|
|
751
|
+
? modelB[decorator_validation_1.Model.pk(modelB.constructor)]
|
|
752
|
+
: modelB,
|
|
753
|
+
};
|
|
754
|
+
const record = await createOrUpdate(new JunctionModel(junctionRegister), context, this.adapter.alias);
|
|
755
|
+
if (record?.id)
|
|
756
|
+
recordIds.push(record.id);
|
|
757
|
+
}
|
|
758
|
+
if (recordIds.length === modelsB?.length) {
|
|
759
|
+
console.log(`All junction records created successfully for table ${JunctionModel?.name}`);
|
|
760
|
+
const repository = Repository_1.Repository.forModel(JunctionModel);
|
|
761
|
+
const results = await repository?.readAll(recordIds);
|
|
762
|
+
console.log("results:", results);
|
|
763
|
+
}
|
|
764
|
+
else
|
|
765
|
+
console.error(`Some junction records failed to be created for table ${JunctionModel?.name}`);
|
|
766
|
+
return JunctionModel;
|
|
767
|
+
}
|
|
768
|
+
function getAndConstructJunctionTable(modelA, modelB, metadata) {
|
|
769
|
+
// Get the name of the table and fks
|
|
770
|
+
const modelAName = decorator_validation_1.Model.tableName(modelA);
|
|
771
|
+
let modelBName;
|
|
772
|
+
if (modelB instanceof decorator_validation_1.Model)
|
|
773
|
+
modelBName = decorator_validation_1.Model.tableName(modelB);
|
|
774
|
+
else if (decorator_validation_1.Model.isModel(modelB) &&
|
|
775
|
+
typeof modelB === "function") {
|
|
776
|
+
modelBName = modelB.name ? modelB.name : modelB()?.name;
|
|
777
|
+
}
|
|
778
|
+
else if (metadata?.class) {
|
|
779
|
+
const clazz = typeof metadata.class === "function" && !metadata.class.name
|
|
780
|
+
? metadata.class()
|
|
781
|
+
: metadata.class;
|
|
782
|
+
modelBName = decorator_validation_1.Model.tableName(clazz);
|
|
783
|
+
}
|
|
784
|
+
if (!modelAName || !modelBName)
|
|
785
|
+
throw new db_decorators_1.InternalError("Missing tablenames to create junction table");
|
|
786
|
+
const junctionTableName = metadata?.joinTable?.name
|
|
787
|
+
? metadata?.joinTable?.name
|
|
788
|
+
: `${modelAName}_${modelBName}`;
|
|
789
|
+
const fkA = `${modelAName?.toLowerCase()}_fk`;
|
|
790
|
+
const fkB = `${modelBName?.toLowerCase()}_fk`;
|
|
791
|
+
// Anonymous class to be able to change name
|
|
792
|
+
const DynamicJunctionModel = class extends decorator_validation_1.Model {
|
|
793
|
+
constructor(arg) {
|
|
794
|
+
super(arg);
|
|
795
|
+
}
|
|
796
|
+
};
|
|
797
|
+
Object.defineProperty(DynamicJunctionModel, "name", {
|
|
798
|
+
value: junctionTableName,
|
|
799
|
+
writable: false,
|
|
800
|
+
});
|
|
801
|
+
// Apply the decorators
|
|
802
|
+
(0, decorators_1.pk)({ type: Number })(DynamicJunctionModel.prototype, "id");
|
|
803
|
+
(0, decorator_validation_1.required)()(DynamicJunctionModel.prototype, fkA);
|
|
804
|
+
(0, decorator_validation_1.required)()(DynamicJunctionModel.prototype, fkB);
|
|
805
|
+
// Apply @model() decorator to the class
|
|
806
|
+
const DecoratedModel = (0, decorator_validation_1.model)()(DynamicJunctionModel);
|
|
807
|
+
decoration_1.Metadata.set(DynamicJunctionModel, constants_1.PersistenceKeys.TABLE, junctionTableName);
|
|
808
|
+
return {
|
|
809
|
+
fkA,
|
|
810
|
+
fkB,
|
|
811
|
+
JunctionModel: DecoratedModel,
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
async function manyToManyOnUpdate(context, data, key, model) {
|
|
815
|
+
console.warn("method not yet implemented");
|
|
816
|
+
const { cascade } = data;
|
|
817
|
+
if (cascade.update !== constants_2.Cascade.CASCADE)
|
|
818
|
+
return;
|
|
819
|
+
return manyToManyOnCreate.apply(this, [
|
|
820
|
+
context,
|
|
821
|
+
data,
|
|
822
|
+
key,
|
|
823
|
+
model,
|
|
824
|
+
]);
|
|
825
|
+
}
|
|
826
|
+
async function manyToManyOnDelete(context, data, key, model) {
|
|
827
|
+
console.warn("Method under development");
|
|
828
|
+
if (data.cascade.delete !== constants_2.Cascade.CASCADE)
|
|
829
|
+
return;
|
|
830
|
+
const values = model[key];
|
|
831
|
+
if (!values || !values.length)
|
|
832
|
+
return;
|
|
833
|
+
const arrayType = typeof values[0];
|
|
834
|
+
const areAllSameType = values.every((item) => typeof item === arrayType);
|
|
835
|
+
if (!areAllSameType)
|
|
836
|
+
throw new db_decorators_1.InternalError(`Invalid operation. All elements of property ${key} must match the same type.`);
|
|
837
|
+
// Delete the values and the junction table entries
|
|
838
|
+
const clazz = typeof data.class === "function" && !data.class.name
|
|
839
|
+
? data.class()
|
|
840
|
+
: data.class;
|
|
841
|
+
const isInstantiated = arrayType === "object";
|
|
842
|
+
const repo = isInstantiated
|
|
843
|
+
? Repository_1.Repository.forModel(clazz, this.adapter.alias)
|
|
844
|
+
: repositoryFromTypeMetadata(model, key, this.adapter.alias);
|
|
845
|
+
const uniqueValues = new Set([
|
|
846
|
+
...(isInstantiated
|
|
847
|
+
? values.map((v) => v[repo["pk"]])
|
|
848
|
+
: values),
|
|
849
|
+
]);
|
|
850
|
+
const ids = [...uniqueValues.values()];
|
|
851
|
+
let deleted;
|
|
852
|
+
try {
|
|
853
|
+
deleted = await repo.deleteAll(ids, context);
|
|
854
|
+
}
|
|
855
|
+
catch (e) {
|
|
856
|
+
context.logger.error(`Failed to delete all records`, e);
|
|
857
|
+
throw e;
|
|
858
|
+
}
|
|
859
|
+
let del;
|
|
860
|
+
for (let i = 0; i < deleted.length; i++) {
|
|
861
|
+
del = deleted[i];
|
|
862
|
+
try {
|
|
863
|
+
await cacheModelForPopulate(context, model, key, ids[i], del);
|
|
864
|
+
}
|
|
865
|
+
catch (e) {
|
|
866
|
+
context.logger.error(`Failed to cache record ${ids[i]} with key ${key} and model ${JSON.stringify(model, undefined, 2)} `, e);
|
|
867
|
+
throw e;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
model[key] = ids;
|
|
871
|
+
}
|
|
579
872
|
/**
|
|
580
873
|
* @description Generates a key for caching populated model relationships
|
|
581
874
|
* @summary Creates a unique key for storing and retrieving populated model relationships in the cache
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Model } from "@decaf-ts/decorator-validation";
|
|
2
2
|
import { Repo } from "../repository/Repository";
|
|
3
3
|
import { RelationsMetadata } from "./types";
|
|
4
|
+
import { Constructor } from "@decaf-ts/decoration";
|
|
4
5
|
import { AdapterFlags, ContextOf } from "../persistence/types";
|
|
5
6
|
import { Context } from "../persistence/Context";
|
|
6
7
|
/**
|
|
@@ -323,6 +324,18 @@ export declare function oneToManyOnUpdate<M extends Model, R extends Repo<M>>(th
|
|
|
323
324
|
* oneToManyOnDelete-->>Caller: void
|
|
324
325
|
*/
|
|
325
326
|
export declare function oneToManyOnDelete<M extends Model, R extends Repo<M>>(this: R, context: ContextOf<R>, data: RelationsMetadata, key: keyof M, model: M): Promise<void>;
|
|
327
|
+
export declare function manyToOneOnCreate<M extends Model, R extends Repo<M>>(this: R, context: ContextOf<R>, data: RelationsMetadata, key: keyof M, model: M): Promise<void>;
|
|
328
|
+
export declare function validBidirectionalRelation<M extends Model>(model: M, data: RelationsMetadata): boolean;
|
|
329
|
+
export declare function manyToOneOnUpdate<M extends Model, R extends Repo<M>>(this: R, context: ContextOf<R>, data: RelationsMetadata, key: keyof M, model: M): Promise<void>;
|
|
330
|
+
export declare function manyToOneOnDelete<M extends Model, R extends Repo<M>>(this: R, context: ContextOf<R>, data: RelationsMetadata, key: keyof M, model: M): Promise<void>;
|
|
331
|
+
export declare function manyToManyOnCreate<M extends Model, R extends Repo<M>>(this: R, context: ContextOf<R>, data: RelationsMetadata, key: keyof M, modelA: M): Promise<void>;
|
|
332
|
+
export declare function getAndConstructJunctionTable(modelA: Model, modelB: Model | any, metadata?: RelationsMetadata): {
|
|
333
|
+
fkA: string;
|
|
334
|
+
fkB: string;
|
|
335
|
+
JunctionModel: Constructor<Model<false>>;
|
|
336
|
+
};
|
|
337
|
+
export declare function manyToManyOnUpdate<M extends Model, R extends Repo<M>>(this: R, context: ContextOf<R>, data: RelationsMetadata, key: keyof M, model: M): Promise<void>;
|
|
338
|
+
export declare function manyToManyOnDelete<M extends Model, R extends Repo<M>>(this: R, context: ContextOf<R>, data: RelationsMetadata, key: keyof M, model: M): Promise<void>;
|
|
326
339
|
/**
|
|
327
340
|
* @description Generates a key for caching populated model relationships
|
|
328
341
|
* @summary Creates a unique key for storing and retrieving populated model relationships in the cache
|