@rvoh/dream 2.15.1 → 2.17.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/db/migration-helpers/DreamMigrationHelpers.js +6 -3
- package/dist/cjs/src/decorators/class/STI.js +3 -2
- package/dist/cjs/src/decorators/class/SoftDelete.js +1 -1
- package/dist/cjs/src/decorators/field/association/BelongsTo.js +6 -1
- package/dist/cjs/src/decorators/field/association/HasMany.js +6 -1
- package/dist/cjs/src/decorators/field/association/HasOne.js +6 -1
- package/dist/cjs/src/decorators/field/association/shared.js +16 -0
- package/dist/cjs/src/dream/constants.js +1 -1
- package/dist/cjs/src/dream-app/helpers/importers/importModels.js +59 -44
- package/dist/cjs/src/dream-app/index.js +1 -1
- package/dist/cjs/src/helpers/cli/generateMigrationContent.js +5 -1
- package/dist/esm/src/db/migration-helpers/DreamMigrationHelpers.js +6 -3
- package/dist/esm/src/decorators/class/STI.js +3 -2
- package/dist/esm/src/decorators/class/SoftDelete.js +1 -1
- package/dist/esm/src/decorators/field/association/BelongsTo.js +6 -1
- package/dist/esm/src/decorators/field/association/HasMany.js +6 -1
- package/dist/esm/src/decorators/field/association/HasOne.js +6 -1
- package/dist/esm/src/decorators/field/association/shared.js +16 -0
- package/dist/esm/src/dream/constants.js +1 -1
- package/dist/esm/src/dream-app/helpers/importers/importModels.js +59 -44
- package/dist/esm/src/dream-app/index.js +1 -1
- package/dist/esm/src/helpers/cli/generateMigrationContent.js +5 -1
- package/dist/types/src/db/migration-helpers/DreamMigrationHelpers.d.ts +6 -3
- package/dist/types/src/decorators/class/STI.d.ts +1 -1
- package/dist/types/src/decorators/class/SoftDelete.d.ts +1 -1
- package/dist/types/src/decorators/field/association/shared.d.ts +4 -0
- package/dist/types/src/dream/constants.d.ts +1 -1
- package/dist/types/src/types/db.d.ts +1 -1
- package/dist/types/src/types/types/db.ts +1 -1
- package/docs/classes/db.DreamMigrationHelpers.html +17 -14
- 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 +2 -2
- 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
|
@@ -7,9 +7,12 @@ export default class DreamMigrationHelpers {
|
|
|
7
7
|
* This method renames the table, its primary key index (`{tablename}_pkey`),
|
|
8
8
|
* and its primary key sequence (`{tablename}_id_seq`) to keep them in sync.
|
|
9
9
|
*
|
|
10
|
-
* The sequence rename
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* The sequence rename applies to both legacy `serial`/`bigserial` columns and
|
|
11
|
+
* modern `GENERATED ... AS IDENTITY` columns: identity columns are also backed
|
|
12
|
+
* by a `{tablename}_id_seq` sequence, so they need the same rename. It is
|
|
13
|
+
* skipped only for tables with UUID primary keys (which have no associated
|
|
14
|
+
* sequence). The primary key index is always renamed since PostgreSQL does not
|
|
15
|
+
* automatically rename it when the table is renamed.
|
|
13
16
|
*
|
|
14
17
|
* @param db - The Kysely database object passed into the migration up/down function
|
|
15
18
|
* @param from - The current name of the table to rename
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import StiChildCannotDefineNewAssociations from '../../errors/sti/StiChildCannotDefineNewAssociations.js';
|
|
2
2
|
import StiChildIncompatibleWithReplicaSafeDecorator from '../../errors/sti/StiChildIncompatibleWithReplicaSafeDecorator.js';
|
|
3
3
|
import StiChildIncompatibleWithSoftDeleteDecorator from '../../errors/sti/StiChildIncompatibleWithSoftDeleteDecorator.js';
|
|
4
|
+
import { associationDeclarationNamesFromMetadata } from '../field/association/shared.js';
|
|
4
5
|
import { scopeImplementation } from '../static-method/Scope.js';
|
|
5
6
|
export const STI_SCOPE_NAME = 'dream:STI';
|
|
6
7
|
export default function STI(dreamClass) {
|
|
7
|
-
return function (stiChildClass) {
|
|
8
|
+
return function (stiChildClass, context) {
|
|
8
9
|
const baseClass = dreamClass['sti'].baseClass || dreamClass;
|
|
9
|
-
if (
|
|
10
|
+
if (associationDeclarationNamesFromMetadata(context?.metadata).length)
|
|
10
11
|
throw new StiChildCannotDefineNewAssociations(baseClass, stiChildClass);
|
|
11
12
|
if (Object.getOwnPropertyDescriptor(stiChildClass, 'replicaSafe'))
|
|
12
13
|
throw new StiChildIncompatibleWithReplicaSafeDecorator(stiChildClass);
|
|
@@ -14,7 +14,7 @@ export const SOFT_DELETE_SCOPE_NAME = 'dream:SoftDelete';
|
|
|
14
14
|
* export async function up(db: Kysely<any>): Promise<void> {
|
|
15
15
|
* await db.schema
|
|
16
16
|
* .createTable('posts')
|
|
17
|
-
* .addColumn('id', '
|
|
17
|
+
* .addColumn('id', 'bigint', col => col.primaryKey().generatedByDefaultAsIdentity())
|
|
18
18
|
* .addColumn('deleted_at', 'timestamp', col => col.defaultTo(null))
|
|
19
19
|
* .addColumn('created_at', 'timestamp', col => col.notNull())
|
|
20
20
|
* .addColumn('updated_at', 'timestamp', col => col.notNull())
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import lookupModelByGlobalNameOrNames from '../../../dream-app/helpers/lookupModelByGlobalNameOrNames.js';
|
|
2
2
|
import ArrayTargetOnlyOnPolymorphicBelongsTo from '../../../errors/associations/ArrayTargetOnlyOnPolymorphicBelongsTo.js';
|
|
3
3
|
import { validatesImplementation } from '../validation/Validates.js';
|
|
4
|
-
import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociationsFactory, finalForeignKey, foreignKeyTypeField, } from './shared.js';
|
|
4
|
+
import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociationsFactory, finalForeignKey, foreignKeyTypeField, markAssociationDeclaration, } from './shared.js';
|
|
5
5
|
/**
|
|
6
6
|
* Establishes a "BelongsTo" association between the base dream
|
|
7
7
|
* and the child dream, where the base dream has a foreign key
|
|
@@ -56,6 +56,7 @@ import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociations
|
|
|
56
56
|
export default function BelongsTo(globalAssociationNameOrNames, opts = {}) {
|
|
57
57
|
const { on: foreignKey, optional = false, polymorphic = false, primaryKeyOverride = null, withoutDefaultScopes, } = opts;
|
|
58
58
|
return function (_, context) {
|
|
59
|
+
markAssociationDeclaration(context);
|
|
59
60
|
const key = context.name;
|
|
60
61
|
context.addInitializer(function () {
|
|
61
62
|
const target = this;
|
|
@@ -93,6 +94,10 @@ export default function BelongsTo(globalAssociationNameOrNames, opts = {}) {
|
|
|
93
94
|
return foreignKeyTypeField(foreignKey, dreamClass, partialAssociation);
|
|
94
95
|
},
|
|
95
96
|
};
|
|
97
|
+
if (dreamClass['isSTIChild']) {
|
|
98
|
+
applyGetterAndSetter(target, association, { isBelongsTo: true, foreignKeyBase: foreignKey });
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
96
101
|
if (!Object.getOwnPropertyDescriptor(dreamClass, 'associationMetadataByType'))
|
|
97
102
|
dreamClass['associationMetadataByType'] = blankAssociationsFactory(dreamClass);
|
|
98
103
|
dreamClass['associationMetadataByType']['belongsTo'].push(association);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import lookupModelByGlobalNameOrNames from '../../../dream-app/helpers/lookupModelByGlobalNameOrNames.js';
|
|
2
|
-
import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociationsFactory, finalForeignKey, foreignKeyTypeField, validateHasStatementArgs, } from './shared.js';
|
|
2
|
+
import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociationsFactory, finalForeignKey, foreignKeyTypeField, markAssociationDeclaration, validateHasStatementArgs, } from './shared.js';
|
|
3
3
|
/**
|
|
4
4
|
* Establishes a "HasMany" association between the base dream
|
|
5
5
|
* and the child dream, where the child dream has a foreign key
|
|
@@ -36,6 +36,7 @@ import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociations
|
|
|
36
36
|
export default function HasMany(globalAssociationNameOrNames, opts = {}) {
|
|
37
37
|
const { dependent, distinct, on: foreignKey, and, andNot, andAny, order, polymorphic = false, primaryKeyOverride = null, selfAnd, selfAndNot, source, through, withoutDefaultScopes, } = opts;
|
|
38
38
|
return function (_, context) {
|
|
39
|
+
markAssociationDeclaration(context);
|
|
39
40
|
const key = context.name;
|
|
40
41
|
context.addInitializer(function () {
|
|
41
42
|
const target = this;
|
|
@@ -86,6 +87,10 @@ export default function HasMany(globalAssociationNameOrNames, opts = {}) {
|
|
|
86
87
|
return foreignKeyTypeField(foreignKey, dreamClass, partialAssociation);
|
|
87
88
|
},
|
|
88
89
|
};
|
|
90
|
+
if (dreamClass['isSTIChild']) {
|
|
91
|
+
applyGetterAndSetter(target, association);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
89
94
|
if (!Object.getOwnPropertyDescriptor(dreamClass, 'associationMetadataByType'))
|
|
90
95
|
dreamClass['associationMetadataByType'] = blankAssociationsFactory(dreamClass);
|
|
91
96
|
dreamClass['associationMetadataByType']['hasMany'].push(association);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import lookupModelByGlobalNameOrNames from '../../../dream-app/helpers/lookupModelByGlobalNameOrNames.js';
|
|
2
|
-
import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociationsFactory, finalForeignKey, foreignKeyTypeField, validateHasStatementArgs, } from './shared.js';
|
|
2
|
+
import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociationsFactory, finalForeignKey, foreignKeyTypeField, markAssociationDeclaration, validateHasStatementArgs, } from './shared.js';
|
|
3
3
|
/**
|
|
4
4
|
* Establishes a "HasOne" association between the base dream
|
|
5
5
|
* and the child dream, where the child dream has a foreign key
|
|
@@ -34,6 +34,7 @@ import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociations
|
|
|
34
34
|
export default function HasOne(globalAssociationNameOrNames, opts = {}) {
|
|
35
35
|
const { dependent, on: foreignKey, and, andNot, andAny, polymorphic = false, primaryKeyOverride = null, selfAnd, selfAndNot, source, through, withoutDefaultScopes, } = opts;
|
|
36
36
|
return function (_, context) {
|
|
37
|
+
markAssociationDeclaration(context);
|
|
37
38
|
const key = context.name;
|
|
38
39
|
context.addInitializer(function () {
|
|
39
40
|
const target = this;
|
|
@@ -82,6 +83,10 @@ export default function HasOne(globalAssociationNameOrNames, opts = {}) {
|
|
|
82
83
|
return foreignKeyTypeField(foreignKey, dreamClass, partialAssociation);
|
|
83
84
|
},
|
|
84
85
|
};
|
|
86
|
+
if (dreamClass['isSTIChild']) {
|
|
87
|
+
applyGetterAndSetter(target, association);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
85
90
|
if (!Object.getOwnPropertyDescriptor(dreamClass, 'associationMetadataByType'))
|
|
86
91
|
dreamClass['associationMetadataByType'] = blankAssociationsFactory(dreamClass);
|
|
87
92
|
dreamClass['associationMetadataByType']['hasOne'].push(association);
|
|
@@ -8,6 +8,22 @@ import CannotDefineAssociationWithBothDependentAndRequiredAndClause from '../../
|
|
|
8
8
|
import camelize from '../../../helpers/camelize.js';
|
|
9
9
|
import freezeBaseClassArrayMap from '../../helpers/freezeBaseClassArrayMap.js';
|
|
10
10
|
import associationToGetterSetterProp from './associationToGetterSetterProp.js';
|
|
11
|
+
export const ASSOCIATION_DECLARATION_METADATA_KEY = Symbol('dream:associationDeclarationNames');
|
|
12
|
+
export function markAssociationDeclaration(context) {
|
|
13
|
+
const metadata = context.metadata;
|
|
14
|
+
if (!metadata)
|
|
15
|
+
return;
|
|
16
|
+
const existingDeclarationNames = Object.getOwnPropertyDescriptor(metadata, ASSOCIATION_DECLARATION_METADATA_KEY)?.value || [];
|
|
17
|
+
Object.defineProperty(metadata, ASSOCIATION_DECLARATION_METADATA_KEY, {
|
|
18
|
+
configurable: true,
|
|
19
|
+
value: [...existingDeclarationNames, context.name],
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
export function associationDeclarationNamesFromMetadata(metadata) {
|
|
23
|
+
if (!metadata)
|
|
24
|
+
return [];
|
|
25
|
+
return (Object.getOwnPropertyDescriptor(metadata, ASSOCIATION_DECLARATION_METADATA_KEY)?.value || []);
|
|
26
|
+
}
|
|
11
27
|
export function blankAssociationsFactory(dreamClass, { freeze = false, } = {}) {
|
|
12
28
|
// This pattern allows associations to be defined on a base STI class and on
|
|
13
29
|
// child STI classes. The new `associationsMap` property will be created
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const primaryKeyTypes = ['uuid7', 'uuid4', '
|
|
1
|
+
export const primaryKeyTypes = ['uuid7', 'uuid4', 'bigint', 'integer'];
|
|
2
2
|
export const TRIGRAM_OPERATORS = ['%', '<%', '<<%'];
|
|
3
3
|
export const RECURSIVE_SERIALIZATION_MAX_REPEATS = 4;
|
|
4
4
|
export const RECURSIVE_DESTROY_PRELOAD_MAX_REPEATS = RECURSIVE_SERIALIZATION_MAX_REPEATS;
|
|
@@ -3,9 +3,18 @@ import DreamMissingRequiredOverride from '../../../errors/DreamMissingRequiredOv
|
|
|
3
3
|
import DreamImporter from '../DreamImporter.js';
|
|
4
4
|
import globalModelKeyFromPath from '../globalModelKeyFromPath.js';
|
|
5
5
|
let _models;
|
|
6
|
+
let _importModelsPromise;
|
|
6
7
|
export default async function importModels(modelsPath, modelImportCb) {
|
|
7
8
|
if (_models)
|
|
8
9
|
return _models;
|
|
10
|
+
if (_importModelsPromise)
|
|
11
|
+
return await _importModelsPromise;
|
|
12
|
+
_importModelsPromise = importModelsUncached(modelsPath, modelImportCb).finally(() => {
|
|
13
|
+
_importModelsPromise = undefined;
|
|
14
|
+
});
|
|
15
|
+
return await _importModelsPromise;
|
|
16
|
+
}
|
|
17
|
+
async function importModelsUncached(modelsPath, modelImportCb) {
|
|
9
18
|
const modelClasses = await DreamImporter.importDreams(modelsPath, modelImportCb);
|
|
10
19
|
/**
|
|
11
20
|
* Certain features (e.g. passing a Dream instance to `create` so that it automatically destructures polymorphic type and primary key)
|
|
@@ -14,58 +23,64 @@ export default async function importModels(modelsPath, modelImportCb) {
|
|
|
14
23
|
* to only apply static values once, on boot, `globallyInitializingDecorators` is set to true on Dream, and all Dream models are instantiated.
|
|
15
24
|
*/
|
|
16
25
|
Dream['globallyInitializingDecorators'] = true;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
modelClass
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
const models = {};
|
|
27
|
+
try {
|
|
28
|
+
for (const [modelPath, modelClass] of modelClasses) {
|
|
29
|
+
// `?` in case modelClass is undefined (e.g. a file without a default export exists in the models directory hierarchy)
|
|
30
|
+
if (modelClass?.isDream) {
|
|
31
|
+
try {
|
|
32
|
+
// Don't create a global lookup for ApplicationModel
|
|
33
|
+
// ApplicationModel does not have a table
|
|
34
|
+
if (modelClass.table) {
|
|
35
|
+
modelClass['defineAttributeAccessors']();
|
|
36
|
+
const modelKey = globalModelKeyFromPath(modelPath, modelsPath);
|
|
37
|
+
modelClass['setGlobalName'](modelKey);
|
|
38
|
+
models[modelKey] = modelClass;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
// ApplicationModel will automatically raise an exception here,
|
|
43
|
+
// since it does not have a table.
|
|
44
|
+
if (!(error instanceof DreamMissingRequiredOverride))
|
|
45
|
+
throw error;
|
|
29
46
|
}
|
|
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
47
|
}
|
|
37
48
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
for (const [, modelClass] of modelClasses) {
|
|
50
|
+
// `?` in case modelClass is undefined (e.g. a file without a default export exists in the models directory hierarchy)
|
|
51
|
+
if (modelClass?.isDream) {
|
|
52
|
+
try {
|
|
53
|
+
/**
|
|
54
|
+
* Certain features (e.g. passing a Dream instance to `create` so that it automatically destructures polymorphic type and primary key)
|
|
55
|
+
* need static access to things set up by decorators (e.g. associations). Stage 3 Decorators change the context that is available
|
|
56
|
+
* at decoration time such that the class of a property being decorated is only avilable during instance instantiation. In order
|
|
57
|
+
* to only apply static values once, on boot, `globallyInitializingDecorators` is set to true on Dream, and all Dream models are instantiated.
|
|
58
|
+
*/
|
|
59
|
+
new modelClass({}, { _internalUseOnly: true });
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
// ApplicationModel will automatically raise an exception here,
|
|
63
|
+
// since it does not have a table.
|
|
64
|
+
if (!(error instanceof DreamMissingRequiredOverride))
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
56
67
|
}
|
|
57
68
|
}
|
|
69
|
+
_models = models;
|
|
70
|
+
return _models;
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
/**
|
|
74
|
+
* Certain features (e.g. passing a Dream instance to `create` so that it automatically destructures polymorphic type and primary key)
|
|
75
|
+
* need static access to things set up by decorators (e.g. associations). Stage 3 Decorators change the context that is available
|
|
76
|
+
* at decoration time such that the class of a property being decorated is only avilable during instance instantiation. In order
|
|
77
|
+
* to only apply static values once, on boot, `globallyInitializingDecorators` is set to true on Dream, and all Dream models are instantiated.
|
|
78
|
+
*/
|
|
79
|
+
Dream['globallyInitializingDecorators'] = false;
|
|
58
80
|
}
|
|
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
81
|
}
|
|
68
82
|
export function setCachedModels(models) {
|
|
83
|
+
_importModelsPromise = undefined;
|
|
69
84
|
_models = models;
|
|
70
85
|
}
|
|
71
86
|
export function getModelsOrFail() {
|
|
@@ -218,7 +218,7 @@ A new key can also be generated from the CLI:
|
|
|
218
218
|
get paginationPageSize() {
|
|
219
219
|
return this._paginationPageSize;
|
|
220
220
|
}
|
|
221
|
-
_primaryKeyType = '
|
|
221
|
+
_primaryKeyType = 'bigint';
|
|
222
222
|
get primaryKeyType() {
|
|
223
223
|
return this._primaryKeyType;
|
|
224
224
|
}
|
|
@@ -361,8 +361,12 @@ function generateIdStr({ primaryKeyType }) {
|
|
|
361
361
|
.primaryKey()
|
|
362
362
|
.defaultTo(sql\`uuid_generate_v4()\`),
|
|
363
363
|
)`;
|
|
364
|
+
case 'integer':
|
|
365
|
+
return `.addColumn('id', 'integer', col => col.primaryKey().generatedByDefaultAsIdentity())`;
|
|
366
|
+
case 'bigint':
|
|
367
|
+
case 'bigserial':
|
|
364
368
|
default:
|
|
365
|
-
return `.addColumn('id', '
|
|
369
|
+
return `.addColumn('id', 'bigint', col => col.primaryKey().generatedByDefaultAsIdentity())`;
|
|
366
370
|
}
|
|
367
371
|
}
|
|
368
372
|
/**
|
|
@@ -7,9 +7,12 @@ export default class DreamMigrationHelpers {
|
|
|
7
7
|
* This method renames the table, its primary key index (`{tablename}_pkey`),
|
|
8
8
|
* and its primary key sequence (`{tablename}_id_seq`) to keep them in sync.
|
|
9
9
|
*
|
|
10
|
-
* The sequence rename
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* The sequence rename applies to both legacy `serial`/`bigserial` columns and
|
|
11
|
+
* modern `GENERATED ... AS IDENTITY` columns: identity columns are also backed
|
|
12
|
+
* by a `{tablename}_id_seq` sequence, so they need the same rename. It is
|
|
13
|
+
* skipped only for tables with UUID primary keys (which have no associated
|
|
14
|
+
* sequence). The primary key index is always renamed since PostgreSQL does not
|
|
15
|
+
* automatically rename it when the table is renamed.
|
|
13
16
|
*
|
|
14
17
|
* @param db - The Kysely database object passed into the migration up/down function
|
|
15
18
|
* @param from - The current name of the table to rename
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import StiChildCannotDefineNewAssociations from '../../errors/sti/StiChildCannotDefineNewAssociations.js';
|
|
2
2
|
import StiChildIncompatibleWithReplicaSafeDecorator from '../../errors/sti/StiChildIncompatibleWithReplicaSafeDecorator.js';
|
|
3
3
|
import StiChildIncompatibleWithSoftDeleteDecorator from '../../errors/sti/StiChildIncompatibleWithSoftDeleteDecorator.js';
|
|
4
|
+
import { associationDeclarationNamesFromMetadata } from '../field/association/shared.js';
|
|
4
5
|
import { scopeImplementation } from '../static-method/Scope.js';
|
|
5
6
|
export const STI_SCOPE_NAME = 'dream:STI';
|
|
6
7
|
export default function STI(dreamClass) {
|
|
7
|
-
return function (stiChildClass) {
|
|
8
|
+
return function (stiChildClass, context) {
|
|
8
9
|
const baseClass = dreamClass['sti'].baseClass || dreamClass;
|
|
9
|
-
if (
|
|
10
|
+
if (associationDeclarationNamesFromMetadata(context?.metadata).length)
|
|
10
11
|
throw new StiChildCannotDefineNewAssociations(baseClass, stiChildClass);
|
|
11
12
|
if (Object.getOwnPropertyDescriptor(stiChildClass, 'replicaSafe'))
|
|
12
13
|
throw new StiChildIncompatibleWithReplicaSafeDecorator(stiChildClass);
|
|
@@ -14,7 +14,7 @@ export const SOFT_DELETE_SCOPE_NAME = 'dream:SoftDelete';
|
|
|
14
14
|
* export async function up(db: Kysely<any>): Promise<void> {
|
|
15
15
|
* await db.schema
|
|
16
16
|
* .createTable('posts')
|
|
17
|
-
* .addColumn('id', '
|
|
17
|
+
* .addColumn('id', 'bigint', col => col.primaryKey().generatedByDefaultAsIdentity())
|
|
18
18
|
* .addColumn('deleted_at', 'timestamp', col => col.defaultTo(null))
|
|
19
19
|
* .addColumn('created_at', 'timestamp', col => col.notNull())
|
|
20
20
|
* .addColumn('updated_at', 'timestamp', col => col.notNull())
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import lookupModelByGlobalNameOrNames from '../../../dream-app/helpers/lookupModelByGlobalNameOrNames.js';
|
|
2
2
|
import ArrayTargetOnlyOnPolymorphicBelongsTo from '../../../errors/associations/ArrayTargetOnlyOnPolymorphicBelongsTo.js';
|
|
3
3
|
import { validatesImplementation } from '../validation/Validates.js';
|
|
4
|
-
import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociationsFactory, finalForeignKey, foreignKeyTypeField, } from './shared.js';
|
|
4
|
+
import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociationsFactory, finalForeignKey, foreignKeyTypeField, markAssociationDeclaration, } from './shared.js';
|
|
5
5
|
/**
|
|
6
6
|
* Establishes a "BelongsTo" association between the base dream
|
|
7
7
|
* and the child dream, where the base dream has a foreign key
|
|
@@ -56,6 +56,7 @@ import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociations
|
|
|
56
56
|
export default function BelongsTo(globalAssociationNameOrNames, opts = {}) {
|
|
57
57
|
const { on: foreignKey, optional = false, polymorphic = false, primaryKeyOverride = null, withoutDefaultScopes, } = opts;
|
|
58
58
|
return function (_, context) {
|
|
59
|
+
markAssociationDeclaration(context);
|
|
59
60
|
const key = context.name;
|
|
60
61
|
context.addInitializer(function () {
|
|
61
62
|
const target = this;
|
|
@@ -93,6 +94,10 @@ export default function BelongsTo(globalAssociationNameOrNames, opts = {}) {
|
|
|
93
94
|
return foreignKeyTypeField(foreignKey, dreamClass, partialAssociation);
|
|
94
95
|
},
|
|
95
96
|
};
|
|
97
|
+
if (dreamClass['isSTIChild']) {
|
|
98
|
+
applyGetterAndSetter(target, association, { isBelongsTo: true, foreignKeyBase: foreignKey });
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
96
101
|
if (!Object.getOwnPropertyDescriptor(dreamClass, 'associationMetadataByType'))
|
|
97
102
|
dreamClass['associationMetadataByType'] = blankAssociationsFactory(dreamClass);
|
|
98
103
|
dreamClass['associationMetadataByType']['belongsTo'].push(association);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import lookupModelByGlobalNameOrNames from '../../../dream-app/helpers/lookupModelByGlobalNameOrNames.js';
|
|
2
|
-
import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociationsFactory, finalForeignKey, foreignKeyTypeField, validateHasStatementArgs, } from './shared.js';
|
|
2
|
+
import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociationsFactory, finalForeignKey, foreignKeyTypeField, markAssociationDeclaration, validateHasStatementArgs, } from './shared.js';
|
|
3
3
|
/**
|
|
4
4
|
* Establishes a "HasMany" association between the base dream
|
|
5
5
|
* and the child dream, where the child dream has a foreign key
|
|
@@ -36,6 +36,7 @@ import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociations
|
|
|
36
36
|
export default function HasMany(globalAssociationNameOrNames, opts = {}) {
|
|
37
37
|
const { dependent, distinct, on: foreignKey, and, andNot, andAny, order, polymorphic = false, primaryKeyOverride = null, selfAnd, selfAndNot, source, through, withoutDefaultScopes, } = opts;
|
|
38
38
|
return function (_, context) {
|
|
39
|
+
markAssociationDeclaration(context);
|
|
39
40
|
const key = context.name;
|
|
40
41
|
context.addInitializer(function () {
|
|
41
42
|
const target = this;
|
|
@@ -86,6 +87,10 @@ export default function HasMany(globalAssociationNameOrNames, opts = {}) {
|
|
|
86
87
|
return foreignKeyTypeField(foreignKey, dreamClass, partialAssociation);
|
|
87
88
|
},
|
|
88
89
|
};
|
|
90
|
+
if (dreamClass['isSTIChild']) {
|
|
91
|
+
applyGetterAndSetter(target, association);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
89
94
|
if (!Object.getOwnPropertyDescriptor(dreamClass, 'associationMetadataByType'))
|
|
90
95
|
dreamClass['associationMetadataByType'] = blankAssociationsFactory(dreamClass);
|
|
91
96
|
dreamClass['associationMetadataByType']['hasMany'].push(association);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import lookupModelByGlobalNameOrNames from '../../../dream-app/helpers/lookupModelByGlobalNameOrNames.js';
|
|
2
|
-
import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociationsFactory, finalForeignKey, foreignKeyTypeField, validateHasStatementArgs, } from './shared.js';
|
|
2
|
+
import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociationsFactory, finalForeignKey, foreignKeyTypeField, markAssociationDeclaration, validateHasStatementArgs, } from './shared.js';
|
|
3
3
|
/**
|
|
4
4
|
* Establishes a "HasOne" association between the base dream
|
|
5
5
|
* and the child dream, where the child dream has a foreign key
|
|
@@ -34,6 +34,7 @@ import { applyGetterAndSetter, associationPrimaryKeyAccessors, blankAssociations
|
|
|
34
34
|
export default function HasOne(globalAssociationNameOrNames, opts = {}) {
|
|
35
35
|
const { dependent, on: foreignKey, and, andNot, andAny, polymorphic = false, primaryKeyOverride = null, selfAnd, selfAndNot, source, through, withoutDefaultScopes, } = opts;
|
|
36
36
|
return function (_, context) {
|
|
37
|
+
markAssociationDeclaration(context);
|
|
37
38
|
const key = context.name;
|
|
38
39
|
context.addInitializer(function () {
|
|
39
40
|
const target = this;
|
|
@@ -82,6 +83,10 @@ export default function HasOne(globalAssociationNameOrNames, opts = {}) {
|
|
|
82
83
|
return foreignKeyTypeField(foreignKey, dreamClass, partialAssociation);
|
|
83
84
|
},
|
|
84
85
|
};
|
|
86
|
+
if (dreamClass['isSTIChild']) {
|
|
87
|
+
applyGetterAndSetter(target, association);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
85
90
|
if (!Object.getOwnPropertyDescriptor(dreamClass, 'associationMetadataByType'))
|
|
86
91
|
dreamClass['associationMetadataByType'] = blankAssociationsFactory(dreamClass);
|
|
87
92
|
dreamClass['associationMetadataByType']['hasOne'].push(association);
|
|
@@ -8,6 +8,22 @@ import CannotDefineAssociationWithBothDependentAndRequiredAndClause from '../../
|
|
|
8
8
|
import camelize from '../../../helpers/camelize.js';
|
|
9
9
|
import freezeBaseClassArrayMap from '../../helpers/freezeBaseClassArrayMap.js';
|
|
10
10
|
import associationToGetterSetterProp from './associationToGetterSetterProp.js';
|
|
11
|
+
export const ASSOCIATION_DECLARATION_METADATA_KEY = Symbol('dream:associationDeclarationNames');
|
|
12
|
+
export function markAssociationDeclaration(context) {
|
|
13
|
+
const metadata = context.metadata;
|
|
14
|
+
if (!metadata)
|
|
15
|
+
return;
|
|
16
|
+
const existingDeclarationNames = Object.getOwnPropertyDescriptor(metadata, ASSOCIATION_DECLARATION_METADATA_KEY)?.value || [];
|
|
17
|
+
Object.defineProperty(metadata, ASSOCIATION_DECLARATION_METADATA_KEY, {
|
|
18
|
+
configurable: true,
|
|
19
|
+
value: [...existingDeclarationNames, context.name],
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
export function associationDeclarationNamesFromMetadata(metadata) {
|
|
23
|
+
if (!metadata)
|
|
24
|
+
return [];
|
|
25
|
+
return (Object.getOwnPropertyDescriptor(metadata, ASSOCIATION_DECLARATION_METADATA_KEY)?.value || []);
|
|
26
|
+
}
|
|
11
27
|
export function blankAssociationsFactory(dreamClass, { freeze = false, } = {}) {
|
|
12
28
|
// This pattern allows associations to be defined on a base STI class and on
|
|
13
29
|
// child STI classes. The new `associationsMap` property will be created
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const primaryKeyTypes = ['uuid7', 'uuid4', '
|
|
1
|
+
export const primaryKeyTypes = ['uuid7', 'uuid4', 'bigint', 'integer'];
|
|
2
2
|
export const TRIGRAM_OPERATORS = ['%', '<%', '<<%'];
|
|
3
3
|
export const RECURSIVE_SERIALIZATION_MAX_REPEATS = 4;
|
|
4
4
|
export const RECURSIVE_DESTROY_PRELOAD_MAX_REPEATS = RECURSIVE_SERIALIZATION_MAX_REPEATS;
|
|
@@ -3,9 +3,18 @@ import DreamMissingRequiredOverride from '../../../errors/DreamMissingRequiredOv
|
|
|
3
3
|
import DreamImporter from '../DreamImporter.js';
|
|
4
4
|
import globalModelKeyFromPath from '../globalModelKeyFromPath.js';
|
|
5
5
|
let _models;
|
|
6
|
+
let _importModelsPromise;
|
|
6
7
|
export default async function importModels(modelsPath, modelImportCb) {
|
|
7
8
|
if (_models)
|
|
8
9
|
return _models;
|
|
10
|
+
if (_importModelsPromise)
|
|
11
|
+
return await _importModelsPromise;
|
|
12
|
+
_importModelsPromise = importModelsUncached(modelsPath, modelImportCb).finally(() => {
|
|
13
|
+
_importModelsPromise = undefined;
|
|
14
|
+
});
|
|
15
|
+
return await _importModelsPromise;
|
|
16
|
+
}
|
|
17
|
+
async function importModelsUncached(modelsPath, modelImportCb) {
|
|
9
18
|
const modelClasses = await DreamImporter.importDreams(modelsPath, modelImportCb);
|
|
10
19
|
/**
|
|
11
20
|
* Certain features (e.g. passing a Dream instance to `create` so that it automatically destructures polymorphic type and primary key)
|
|
@@ -14,58 +23,64 @@ export default async function importModels(modelsPath, modelImportCb) {
|
|
|
14
23
|
* to only apply static values once, on boot, `globallyInitializingDecorators` is set to true on Dream, and all Dream models are instantiated.
|
|
15
24
|
*/
|
|
16
25
|
Dream['globallyInitializingDecorators'] = true;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
modelClass
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
const models = {};
|
|
27
|
+
try {
|
|
28
|
+
for (const [modelPath, modelClass] of modelClasses) {
|
|
29
|
+
// `?` in case modelClass is undefined (e.g. a file without a default export exists in the models directory hierarchy)
|
|
30
|
+
if (modelClass?.isDream) {
|
|
31
|
+
try {
|
|
32
|
+
// Don't create a global lookup for ApplicationModel
|
|
33
|
+
// ApplicationModel does not have a table
|
|
34
|
+
if (modelClass.table) {
|
|
35
|
+
modelClass['defineAttributeAccessors']();
|
|
36
|
+
const modelKey = globalModelKeyFromPath(modelPath, modelsPath);
|
|
37
|
+
modelClass['setGlobalName'](modelKey);
|
|
38
|
+
models[modelKey] = modelClass;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
// ApplicationModel will automatically raise an exception here,
|
|
43
|
+
// since it does not have a table.
|
|
44
|
+
if (!(error instanceof DreamMissingRequiredOverride))
|
|
45
|
+
throw error;
|
|
29
46
|
}
|
|
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
47
|
}
|
|
37
48
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
for (const [, modelClass] of modelClasses) {
|
|
50
|
+
// `?` in case modelClass is undefined (e.g. a file without a default export exists in the models directory hierarchy)
|
|
51
|
+
if (modelClass?.isDream) {
|
|
52
|
+
try {
|
|
53
|
+
/**
|
|
54
|
+
* Certain features (e.g. passing a Dream instance to `create` so that it automatically destructures polymorphic type and primary key)
|
|
55
|
+
* need static access to things set up by decorators (e.g. associations). Stage 3 Decorators change the context that is available
|
|
56
|
+
* at decoration time such that the class of a property being decorated is only avilable during instance instantiation. In order
|
|
57
|
+
* to only apply static values once, on boot, `globallyInitializingDecorators` is set to true on Dream, and all Dream models are instantiated.
|
|
58
|
+
*/
|
|
59
|
+
new modelClass({}, { _internalUseOnly: true });
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
// ApplicationModel will automatically raise an exception here,
|
|
63
|
+
// since it does not have a table.
|
|
64
|
+
if (!(error instanceof DreamMissingRequiredOverride))
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
56
67
|
}
|
|
57
68
|
}
|
|
69
|
+
_models = models;
|
|
70
|
+
return _models;
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
/**
|
|
74
|
+
* Certain features (e.g. passing a Dream instance to `create` so that it automatically destructures polymorphic type and primary key)
|
|
75
|
+
* need static access to things set up by decorators (e.g. associations). Stage 3 Decorators change the context that is available
|
|
76
|
+
* at decoration time such that the class of a property being decorated is only avilable during instance instantiation. In order
|
|
77
|
+
* to only apply static values once, on boot, `globallyInitializingDecorators` is set to true on Dream, and all Dream models are instantiated.
|
|
78
|
+
*/
|
|
79
|
+
Dream['globallyInitializingDecorators'] = false;
|
|
58
80
|
}
|
|
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
81
|
}
|
|
68
82
|
export function setCachedModels(models) {
|
|
83
|
+
_importModelsPromise = undefined;
|
|
69
84
|
_models = models;
|
|
70
85
|
}
|
|
71
86
|
export function getModelsOrFail() {
|
|
@@ -218,7 +218,7 @@ A new key can also be generated from the CLI:
|
|
|
218
218
|
get paginationPageSize() {
|
|
219
219
|
return this._paginationPageSize;
|
|
220
220
|
}
|
|
221
|
-
_primaryKeyType = '
|
|
221
|
+
_primaryKeyType = 'bigint';
|
|
222
222
|
get primaryKeyType() {
|
|
223
223
|
return this._primaryKeyType;
|
|
224
224
|
}
|