@rvoh/dream 2.15.1 → 2.16.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/dist/cjs/src/decorators/class/STI.js +31 -2
- package/dist/cjs/src/dream-app/helpers/importers/importModels.js +61 -44
- package/dist/esm/src/decorators/class/STI.js +31 -2
- package/dist/esm/src/dream-app/helpers/importers/importModels.js +61 -44
- package/dist/types/src/decorators/class/STI.d.ts +1 -0
- package/docs/classes/db.DreamMigrationHelpers.html +11 -11
- package/docs/classes/db.KyselyQueryDriver.html +35 -35
- package/docs/classes/db.PostgresQueryDriver.html +36 -36
- package/docs/classes/db.QueryDriverBase.html +34 -34
- package/docs/classes/errors.CheckConstraintViolation.html +3 -3
- package/docs/classes/errors.ColumnOverflow.html +3 -3
- package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
- package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +3 -3
- package/docs/classes/errors.DataTypeColumnTypeMismatch.html +3 -3
- package/docs/classes/errors.DecryptionError.html +2 -2
- package/docs/classes/errors.DecryptionParseError.html +2 -2
- package/docs/classes/errors.DecryptionRotationError.html +3 -3
- package/docs/classes/errors.GlobalNameNotSet.html +3 -3
- package/docs/classes/errors.InvalidCalendarDate.html +2 -2
- package/docs/classes/errors.InvalidClockTime.html +2 -2
- package/docs/classes/errors.InvalidClockTimeTz.html +2 -2
- package/docs/classes/errors.InvalidDateTime.html +2 -2
- package/docs/classes/errors.MissingSerializersDefinition.html +3 -3
- package/docs/classes/errors.NonLoadedAssociation.html +3 -3
- package/docs/classes/errors.NotNullViolation.html +3 -3
- package/docs/classes/errors.RecordNotFound.html +3 -3
- package/docs/classes/errors.ValidationError.html +3 -3
- package/docs/classes/index.CalendarDate.html +33 -33
- package/docs/classes/index.ClockTime.html +32 -32
- package/docs/classes/index.ClockTimeTz.html +35 -35
- package/docs/classes/index.DateTime.html +86 -86
- package/docs/classes/index.Decorators.html +19 -19
- package/docs/classes/index.Dream.html +118 -118
- package/docs/classes/index.DreamApp.html +10 -10
- package/docs/classes/index.DreamTransaction.html +2 -2
- package/docs/classes/index.Env.html +2 -2
- package/docs/classes/index.Query.html +58 -58
- package/docs/classes/system.CliFileWriter.html +4 -4
- package/docs/classes/system.DreamBin.html +2 -2
- package/docs/classes/system.DreamCLI.html +7 -7
- package/docs/classes/system.DreamImporter.html +2 -2
- package/docs/classes/system.DreamLogos.html +2 -2
- package/docs/classes/system.DreamSerializerBuilder.html +11 -11
- package/docs/classes/system.ObjectSerializerBuilder.html +8 -8
- package/docs/classes/system.PathHelpers.html +3 -3
- package/docs/classes/utils.Encrypt.html +3 -3
- package/docs/classes/utils.Range.html +2 -2
- package/docs/functions/db.closeAllDbConnections.html +1 -1
- package/docs/functions/db.dreamDbConnections.html +1 -1
- package/docs/functions/db.untypedDb.html +1 -1
- package/docs/functions/db.validateColumn.html +1 -1
- package/docs/functions/db.validateTable.html +1 -1
- package/docs/functions/errors.pgErrorType.html +1 -1
- package/docs/functions/index.DreamSerializer.html +1 -1
- package/docs/functions/index.ObjectSerializer.html +1 -1
- package/docs/functions/index.ReplicaSafe.html +1 -1
- package/docs/functions/index.STI.html +1 -1
- package/docs/functions/index.SoftDelete.html +1 -1
- package/docs/functions/utils.camelize.html +1 -1
- package/docs/functions/utils.capitalize.html +1 -1
- package/docs/functions/utils.cloneDeepSafe.html +1 -1
- package/docs/functions/utils.compact.html +1 -1
- package/docs/functions/utils.groupBy.html +1 -1
- package/docs/functions/utils.hyphenize.html +1 -1
- package/docs/functions/utils.intersection.html +1 -1
- package/docs/functions/utils.isEmpty.html +1 -1
- package/docs/functions/utils.normalizeUnicode.html +1 -1
- package/docs/functions/utils.pascalize.html +1 -1
- package/docs/functions/utils.percent.html +1 -1
- package/docs/functions/utils.range.html +1 -1
- package/docs/functions/utils.round.html +1 -1
- package/docs/functions/utils.sanitizeString.html +1 -1
- package/docs/functions/utils.snakeify.html +1 -1
- package/docs/functions/utils.sort.html +1 -1
- package/docs/functions/utils.sortBy.html +1 -1
- package/docs/functions/utils.sortObjectByKey.html +1 -1
- package/docs/functions/utils.sortObjectByValue.html +1 -1
- package/docs/functions/utils.uncapitalize.html +1 -1
- package/docs/functions/utils.uniq.html +1 -1
- package/docs/interfaces/openapi.OpenapiDescription.html +2 -2
- package/docs/interfaces/openapi.OpenapiSchemaProperties.html +1 -1
- package/docs/interfaces/openapi.OpenapiSchemaPropertiesShorthand.html +1 -1
- package/docs/interfaces/openapi.OpenapiTypeFieldObject.html +1 -1
- package/docs/interfaces/types.BelongsToStatement.html +2 -2
- package/docs/interfaces/types.DecoratorContext.html +2 -2
- package/docs/interfaces/types.DreamAppInitOptions.html +2 -2
- package/docs/interfaces/types.DreamAppOpts.html +2 -2
- package/docs/interfaces/types.DreamDbConfig.html +5 -5
- package/docs/interfaces/types.DurationObject.html +2 -2
- package/docs/interfaces/types.EncryptOptions.html +2 -2
- package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
- package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
- package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
- package/docs/types/openapi.CommonOpenapiSchemaObjectFields.html +1 -1
- package/docs/types/openapi.OpenapiAllTypes.html +1 -1
- package/docs/types/openapi.OpenapiFormats.html +1 -1
- package/docs/types/openapi.OpenapiNumberFormats.html +1 -1
- package/docs/types/openapi.OpenapiPrimitiveBaseTypes.html +1 -1
- package/docs/types/openapi.OpenapiPrimitiveTypes.html +1 -1
- package/docs/types/openapi.OpenapiSchemaArray.html +1 -1
- package/docs/types/openapi.OpenapiSchemaArrayShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaBase.html +1 -1
- package/docs/types/openapi.OpenapiSchemaBody.html +1 -1
- package/docs/types/openapi.OpenapiSchemaBodyShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaCommonFields.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaExpressionRef.html +2 -2
- package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +2 -2
- package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
- package/docs/types/openapi.OpenapiSchemaNull.html +2 -2
- package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAnyOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAnyOfShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectOneOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectOneOfShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaPrimitiveGeneric.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionAllOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
- package/docs/types/openapi.OpenapiSchemaString.html +1 -1
- package/docs/types/openapi.OpenapiShorthandAllTypes.html +1 -1
- package/docs/types/openapi.OpenapiShorthandPrimitiveBaseTypes.html +1 -1
- package/docs/types/openapi.OpenapiShorthandPrimitiveTypes.html +1 -1
- package/docs/types/openapi.OpenapiTypeField.html +1 -1
- package/docs/types/system.DreamAppAllowedPackageManagersEnum.html +1 -1
- package/docs/types/types.CalendarDateDurationUnit.html +1 -1
- package/docs/types/types.CalendarDateObject.html +1 -1
- package/docs/types/types.Camelized.html +1 -1
- package/docs/types/types.ClockTimeObject.html +1 -1
- package/docs/types/types.DbConnectionType.html +1 -1
- package/docs/types/types.DbTypes.html +1 -1
- package/docs/types/types.DreamAssociationMetadata.html +1 -1
- package/docs/types/types.DreamAttributes.html +1 -1
- package/docs/types/types.DreamClassAssociationAndStatement.html +1 -1
- package/docs/types/types.DreamClassColumn.html +1 -1
- package/docs/types/types.DreamColumn.html +1 -1
- package/docs/types/types.DreamColumnNames.html +1 -1
- package/docs/types/types.DreamLogLevel.html +1 -1
- package/docs/types/types.DreamLogger.html +2 -2
- package/docs/types/types.DreamModelSerializerType.html +1 -1
- package/docs/types/types.DreamOrViewModelClassSerializerKey.html +1 -1
- package/docs/types/types.DreamOrViewModelSerializerKey.html +1 -1
- package/docs/types/types.DreamParamSafeAttributes.html +1 -1
- package/docs/types/types.DreamParamSafeColumnNames.html +1 -1
- package/docs/types/types.DreamSerializable.html +1 -1
- package/docs/types/types.DreamSerializableArray.html +1 -1
- package/docs/types/types.DreamSerializerKey.html +1 -1
- package/docs/types/types.DreamSerializers.html +1 -1
- package/docs/types/types.DreamVirtualColumns.html +1 -1
- package/docs/types/types.DurationUnit.html +1 -1
- package/docs/types/types.EncryptAlgorithm.html +1 -1
- package/docs/types/types.HasManyStatement.html +1 -1
- package/docs/types/types.HasOneStatement.html +1 -1
- package/docs/types/types.Hyphenized.html +1 -1
- package/docs/types/types.Pascalized.html +1 -1
- package/docs/types/types.PrimaryKeyType.html +1 -1
- package/docs/types/types.RoundingPrecision.html +1 -1
- package/docs/types/types.SerializerCasing.html +1 -1
- package/docs/types/types.SimpleObjectSerializerType.html +1 -1
- package/docs/types/types.Snakeified.html +1 -1
- package/docs/types/types.StrictInterface.html +1 -1
- package/docs/types/types.UpdateableAssociationProperties.html +1 -1
- package/docs/types/types.UpdateableProperties.html +1 -1
- package/docs/types/types.ValidationType.html +1 -1
- package/docs/types/types.ViewModel.html +2 -2
- package/docs/types/types.ViewModelClass.html +1 -1
- package/docs/types/types.WeekdayName.html +1 -1
- package/docs/types/types.WhereStatementForDream.html +1 -1
- package/docs/types/types.WhereStatementForDreamClass.html +1 -1
- package/docs/variables/index.DreamConst.html +1 -1
- package/docs/variables/index.ops.html +1 -1
- package/docs/variables/openapi.openapiPrimitiveTypes.html +1 -1
- package/docs/variables/openapi.openapiShorthandPrimitiveTypes.html +1 -1
- package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
- package/docs/variables/system.primaryKeyTypes.html +1 -1
- package/package.json +2 -2
|
@@ -6,8 +6,6 @@ export const STI_SCOPE_NAME = 'dream:STI';
|
|
|
6
6
|
export default function STI(dreamClass) {
|
|
7
7
|
return function (stiChildClass) {
|
|
8
8
|
const baseClass = dreamClass['sti'].baseClass || dreamClass;
|
|
9
|
-
if (Object.getOwnPropertyDescriptor(stiChildClass, 'associationMetadataByType'))
|
|
10
|
-
throw new StiChildCannotDefineNewAssociations(baseClass, stiChildClass);
|
|
11
9
|
if (Object.getOwnPropertyDescriptor(stiChildClass, 'replicaSafe'))
|
|
12
10
|
throw new StiChildIncompatibleWithReplicaSafeDecorator(stiChildClass);
|
|
13
11
|
if (Object.getOwnPropertyDescriptor(stiChildClass, 'softDelete'))
|
|
@@ -28,3 +26,34 @@ export default function STI(dreamClass) {
|
|
|
28
26
|
scopeImplementation(stiChildClass, STI_SCOPE_NAME, { default: true });
|
|
29
27
|
};
|
|
30
28
|
}
|
|
29
|
+
export function validateStiChildAssociations(dreamClasses) {
|
|
30
|
+
dreamClasses.forEach(dreamClass => {
|
|
31
|
+
if (!dreamClass?.isDream)
|
|
32
|
+
return;
|
|
33
|
+
if (!dreamClass['sti'].active)
|
|
34
|
+
return;
|
|
35
|
+
const baseClass = dreamClass['sti'].baseClass;
|
|
36
|
+
if (!baseClass)
|
|
37
|
+
return;
|
|
38
|
+
if (hasAssociationsUnavailableOnBase(baseClass, dreamClass))
|
|
39
|
+
throw new StiChildCannotDefineNewAssociations(baseClass, dreamClass);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function hasAssociationsUnavailableOnBase(baseClass, stiChildClass) {
|
|
43
|
+
const baseAssociationKeys = associationKeysByTypeAndName(baseClass['associationMetadataByType']);
|
|
44
|
+
const childAssociationKeys = associationKeysByTypeAndName(stiChildClass['associationMetadataByType']);
|
|
45
|
+
for (const associationKey of childAssociationKeys) {
|
|
46
|
+
if (!baseAssociationKeys.has(associationKey))
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
function associationKeysByTypeAndName(associationMetadataByType) {
|
|
52
|
+
const res = new Set();
|
|
53
|
+
Object.entries(associationMetadataByType).forEach(([associationType, associations]) => {
|
|
54
|
+
associations.forEach((association) => {
|
|
55
|
+
res.add(`${associationType}:${association.as}`);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
return res;
|
|
59
|
+
}
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import Dream from '../../../Dream.js';
|
|
2
|
+
import { validateStiChildAssociations } from '../../../decorators/class/STI.js';
|
|
2
3
|
import DreamMissingRequiredOverride from '../../../errors/DreamMissingRequiredOverride.js';
|
|
3
4
|
import DreamImporter from '../DreamImporter.js';
|
|
4
5
|
import globalModelKeyFromPath from '../globalModelKeyFromPath.js';
|
|
5
6
|
let _models;
|
|
7
|
+
let _importModelsPromise;
|
|
6
8
|
export default async function importModels(modelsPath, modelImportCb) {
|
|
7
9
|
if (_models)
|
|
8
10
|
return _models;
|
|
11
|
+
if (_importModelsPromise)
|
|
12
|
+
return await _importModelsPromise;
|
|
13
|
+
_importModelsPromise = importModelsUncached(modelsPath, modelImportCb).finally(() => {
|
|
14
|
+
_importModelsPromise = undefined;
|
|
15
|
+
});
|
|
16
|
+
return await _importModelsPromise;
|
|
17
|
+
}
|
|
18
|
+
async function importModelsUncached(modelsPath, modelImportCb) {
|
|
9
19
|
const modelClasses = await DreamImporter.importDreams(modelsPath, modelImportCb);
|
|
10
20
|
/**
|
|
11
21
|
* Certain features (e.g. passing a Dream instance to `create` so that it automatically destructures polymorphic type and primary key)
|
|
@@ -14,58 +24,65 @@ export default async function importModels(modelsPath, modelImportCb) {
|
|
|
14
24
|
* to only apply static values once, on boot, `globallyInitializingDecorators` is set to true on Dream, and all Dream models are instantiated.
|
|
15
25
|
*/
|
|
16
26
|
Dream['globallyInitializingDecorators'] = true;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
modelClass
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
const models = {};
|
|
28
|
+
try {
|
|
29
|
+
for (const [modelPath, modelClass] of modelClasses) {
|
|
30
|
+
// `?` in case modelClass is undefined (e.g. a file without a default export exists in the models directory hierarchy)
|
|
31
|
+
if (modelClass?.isDream) {
|
|
32
|
+
try {
|
|
33
|
+
// Don't create a global lookup for ApplicationModel
|
|
34
|
+
// ApplicationModel does not have a table
|
|
35
|
+
if (modelClass.table) {
|
|
36
|
+
modelClass['defineAttributeAccessors']();
|
|
37
|
+
const modelKey = globalModelKeyFromPath(modelPath, modelsPath);
|
|
38
|
+
modelClass['setGlobalName'](modelKey);
|
|
39
|
+
models[modelKey] = modelClass;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
// ApplicationModel will automatically raise an exception here,
|
|
44
|
+
// since it does not have a table.
|
|
45
|
+
if (!(error instanceof DreamMissingRequiredOverride))
|
|
46
|
+
throw error;
|
|
29
47
|
}
|
|
30
|
-
}
|
|
31
|
-
catch (error) {
|
|
32
|
-
// ApplicationModel will automatically raise an exception here,
|
|
33
|
-
// since it does not have a table.
|
|
34
|
-
if (!(error instanceof DreamMissingRequiredOverride))
|
|
35
|
-
throw error;
|
|
36
48
|
}
|
|
37
49
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
50
|
+
for (const [, modelClass] of modelClasses) {
|
|
51
|
+
// `?` in case modelClass is undefined (e.g. a file without a default export exists in the models directory hierarchy)
|
|
52
|
+
if (modelClass?.isDream) {
|
|
53
|
+
try {
|
|
54
|
+
/**
|
|
55
|
+
* Certain features (e.g. passing a Dream instance to `create` so that it automatically destructures polymorphic type and primary key)
|
|
56
|
+
* need static access to things set up by decorators (e.g. associations). Stage 3 Decorators change the context that is available
|
|
57
|
+
* at decoration time such that the class of a property being decorated is only avilable during instance instantiation. In order
|
|
58
|
+
* to only apply static values once, on boot, `globallyInitializingDecorators` is set to true on Dream, and all Dream models are instantiated.
|
|
59
|
+
*/
|
|
60
|
+
new modelClass({}, { _internalUseOnly: true });
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
// ApplicationModel will automatically raise an exception here,
|
|
64
|
+
// since it does not have a table.
|
|
65
|
+
if (!(error instanceof DreamMissingRequiredOverride))
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
56
68
|
}
|
|
57
69
|
}
|
|
70
|
+
validateStiChildAssociations(modelClasses.map(([, modelClass]) => modelClass));
|
|
71
|
+
_models = models;
|
|
72
|
+
return _models;
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
/**
|
|
76
|
+
* Certain features (e.g. passing a Dream instance to `create` so that it automatically destructures polymorphic type and primary key)
|
|
77
|
+
* need static access to things set up by decorators (e.g. associations). Stage 3 Decorators change the context that is available
|
|
78
|
+
* at decoration time such that the class of a property being decorated is only avilable during instance instantiation. In order
|
|
79
|
+
* to only apply static values once, on boot, `globallyInitializingDecorators` is set to true on Dream, and all Dream models are instantiated.
|
|
80
|
+
*/
|
|
81
|
+
Dream['globallyInitializingDecorators'] = false;
|
|
58
82
|
}
|
|
59
|
-
/**
|
|
60
|
-
* Certain features (e.g. passing a Dream instance to `create` so that it automatically destructures polymorphic type and primary key)
|
|
61
|
-
* need static access to things set up by decorators (e.g. associations). Stage 3 Decorators change the context that is available
|
|
62
|
-
* at decoration time such that the class of a property being decorated is only avilable during instance instantiation. In order
|
|
63
|
-
* to only apply static values once, on boot, `globallyInitializingDecorators` is set to true on Dream, and all Dream models are instantiated.
|
|
64
|
-
*/
|
|
65
|
-
Dream['globallyInitializingDecorators'] = false;
|
|
66
|
-
return _models;
|
|
67
83
|
}
|
|
68
84
|
export function setCachedModels(models) {
|
|
85
|
+
_importModelsPromise = undefined;
|
|
69
86
|
_models = models;
|
|
70
87
|
}
|
|
71
88
|
export function getModelsOrFail() {
|
|
@@ -6,8 +6,6 @@ export const STI_SCOPE_NAME = 'dream:STI';
|
|
|
6
6
|
export default function STI(dreamClass) {
|
|
7
7
|
return function (stiChildClass) {
|
|
8
8
|
const baseClass = dreamClass['sti'].baseClass || dreamClass;
|
|
9
|
-
if (Object.getOwnPropertyDescriptor(stiChildClass, 'associationMetadataByType'))
|
|
10
|
-
throw new StiChildCannotDefineNewAssociations(baseClass, stiChildClass);
|
|
11
9
|
if (Object.getOwnPropertyDescriptor(stiChildClass, 'replicaSafe'))
|
|
12
10
|
throw new StiChildIncompatibleWithReplicaSafeDecorator(stiChildClass);
|
|
13
11
|
if (Object.getOwnPropertyDescriptor(stiChildClass, 'softDelete'))
|
|
@@ -28,3 +26,34 @@ export default function STI(dreamClass) {
|
|
|
28
26
|
scopeImplementation(stiChildClass, STI_SCOPE_NAME, { default: true });
|
|
29
27
|
};
|
|
30
28
|
}
|
|
29
|
+
export function validateStiChildAssociations(dreamClasses) {
|
|
30
|
+
dreamClasses.forEach(dreamClass => {
|
|
31
|
+
if (!dreamClass?.isDream)
|
|
32
|
+
return;
|
|
33
|
+
if (!dreamClass['sti'].active)
|
|
34
|
+
return;
|
|
35
|
+
const baseClass = dreamClass['sti'].baseClass;
|
|
36
|
+
if (!baseClass)
|
|
37
|
+
return;
|
|
38
|
+
if (hasAssociationsUnavailableOnBase(baseClass, dreamClass))
|
|
39
|
+
throw new StiChildCannotDefineNewAssociations(baseClass, dreamClass);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function hasAssociationsUnavailableOnBase(baseClass, stiChildClass) {
|
|
43
|
+
const baseAssociationKeys = associationKeysByTypeAndName(baseClass['associationMetadataByType']);
|
|
44
|
+
const childAssociationKeys = associationKeysByTypeAndName(stiChildClass['associationMetadataByType']);
|
|
45
|
+
for (const associationKey of childAssociationKeys) {
|
|
46
|
+
if (!baseAssociationKeys.has(associationKey))
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
function associationKeysByTypeAndName(associationMetadataByType) {
|
|
52
|
+
const res = new Set();
|
|
53
|
+
Object.entries(associationMetadataByType).forEach(([associationType, associations]) => {
|
|
54
|
+
associations.forEach((association) => {
|
|
55
|
+
res.add(`${associationType}:${association.as}`);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
return res;
|
|
59
|
+
}
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import Dream from '../../../Dream.js';
|
|
2
|
+
import { validateStiChildAssociations } from '../../../decorators/class/STI.js';
|
|
2
3
|
import DreamMissingRequiredOverride from '../../../errors/DreamMissingRequiredOverride.js';
|
|
3
4
|
import DreamImporter from '../DreamImporter.js';
|
|
4
5
|
import globalModelKeyFromPath from '../globalModelKeyFromPath.js';
|
|
5
6
|
let _models;
|
|
7
|
+
let _importModelsPromise;
|
|
6
8
|
export default async function importModels(modelsPath, modelImportCb) {
|
|
7
9
|
if (_models)
|
|
8
10
|
return _models;
|
|
11
|
+
if (_importModelsPromise)
|
|
12
|
+
return await _importModelsPromise;
|
|
13
|
+
_importModelsPromise = importModelsUncached(modelsPath, modelImportCb).finally(() => {
|
|
14
|
+
_importModelsPromise = undefined;
|
|
15
|
+
});
|
|
16
|
+
return await _importModelsPromise;
|
|
17
|
+
}
|
|
18
|
+
async function importModelsUncached(modelsPath, modelImportCb) {
|
|
9
19
|
const modelClasses = await DreamImporter.importDreams(modelsPath, modelImportCb);
|
|
10
20
|
/**
|
|
11
21
|
* Certain features (e.g. passing a Dream instance to `create` so that it automatically destructures polymorphic type and primary key)
|
|
@@ -14,58 +24,65 @@ export default async function importModels(modelsPath, modelImportCb) {
|
|
|
14
24
|
* to only apply static values once, on boot, `globallyInitializingDecorators` is set to true on Dream, and all Dream models are instantiated.
|
|
15
25
|
*/
|
|
16
26
|
Dream['globallyInitializingDecorators'] = true;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
modelClass
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
const models = {};
|
|
28
|
+
try {
|
|
29
|
+
for (const [modelPath, modelClass] of modelClasses) {
|
|
30
|
+
// `?` in case modelClass is undefined (e.g. a file without a default export exists in the models directory hierarchy)
|
|
31
|
+
if (modelClass?.isDream) {
|
|
32
|
+
try {
|
|
33
|
+
// Don't create a global lookup for ApplicationModel
|
|
34
|
+
// ApplicationModel does not have a table
|
|
35
|
+
if (modelClass.table) {
|
|
36
|
+
modelClass['defineAttributeAccessors']();
|
|
37
|
+
const modelKey = globalModelKeyFromPath(modelPath, modelsPath);
|
|
38
|
+
modelClass['setGlobalName'](modelKey);
|
|
39
|
+
models[modelKey] = modelClass;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
// ApplicationModel will automatically raise an exception here,
|
|
44
|
+
// since it does not have a table.
|
|
45
|
+
if (!(error instanceof DreamMissingRequiredOverride))
|
|
46
|
+
throw error;
|
|
29
47
|
}
|
|
30
|
-
}
|
|
31
|
-
catch (error) {
|
|
32
|
-
// ApplicationModel will automatically raise an exception here,
|
|
33
|
-
// since it does not have a table.
|
|
34
|
-
if (!(error instanceof DreamMissingRequiredOverride))
|
|
35
|
-
throw error;
|
|
36
48
|
}
|
|
37
49
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
50
|
+
for (const [, modelClass] of modelClasses) {
|
|
51
|
+
// `?` in case modelClass is undefined (e.g. a file without a default export exists in the models directory hierarchy)
|
|
52
|
+
if (modelClass?.isDream) {
|
|
53
|
+
try {
|
|
54
|
+
/**
|
|
55
|
+
* Certain features (e.g. passing a Dream instance to `create` so that it automatically destructures polymorphic type and primary key)
|
|
56
|
+
* need static access to things set up by decorators (e.g. associations). Stage 3 Decorators change the context that is available
|
|
57
|
+
* at decoration time such that the class of a property being decorated is only avilable during instance instantiation. In order
|
|
58
|
+
* to only apply static values once, on boot, `globallyInitializingDecorators` is set to true on Dream, and all Dream models are instantiated.
|
|
59
|
+
*/
|
|
60
|
+
new modelClass({}, { _internalUseOnly: true });
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
// ApplicationModel will automatically raise an exception here,
|
|
64
|
+
// since it does not have a table.
|
|
65
|
+
if (!(error instanceof DreamMissingRequiredOverride))
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
56
68
|
}
|
|
57
69
|
}
|
|
70
|
+
validateStiChildAssociations(modelClasses.map(([, modelClass]) => modelClass));
|
|
71
|
+
_models = models;
|
|
72
|
+
return _models;
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
/**
|
|
76
|
+
* Certain features (e.g. passing a Dream instance to `create` so that it automatically destructures polymorphic type and primary key)
|
|
77
|
+
* need static access to things set up by decorators (e.g. associations). Stage 3 Decorators change the context that is available
|
|
78
|
+
* at decoration time such that the class of a property being decorated is only avilable during instance instantiation. In order
|
|
79
|
+
* to only apply static values once, on boot, `globallyInitializingDecorators` is set to true on Dream, and all Dream models are instantiated.
|
|
80
|
+
*/
|
|
81
|
+
Dream['globallyInitializingDecorators'] = false;
|
|
58
82
|
}
|
|
59
|
-
/**
|
|
60
|
-
* Certain features (e.g. passing a Dream instance to `create` so that it automatically destructures polymorphic type and primary key)
|
|
61
|
-
* need static access to things set up by decorators (e.g. associations). Stage 3 Decorators change the context that is available
|
|
62
|
-
* at decoration time such that the class of a property being decorated is only avilable during instance instantiation. In order
|
|
63
|
-
* to only apply static values once, on boot, `globallyInitializingDecorators` is set to true on Dream, and all Dream models are instantiated.
|
|
64
|
-
*/
|
|
65
|
-
Dream['globallyInitializingDecorators'] = false;
|
|
66
|
-
return _models;
|
|
67
83
|
}
|
|
68
84
|
export function setCachedModels(models) {
|
|
85
|
+
_importModelsPromise = undefined;
|
|
69
86
|
_models = models;
|
|
70
87
|
}
|
|
71
88
|
export function getModelsOrFail() {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import Dream from '../../Dream.js';
|
|
2
2
|
export declare const STI_SCOPE_NAME = "dream:STI";
|
|
3
3
|
export default function STI(dreamClass: typeof Dream): (stiChildClass: typeof Dream) => void;
|
|
4
|
+
export declare function validateStiChildAssociations(dreamClasses: (typeof Dream)[]): void;
|