@rvoh/dream 2.28.1 → 2.28.3
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/Dream.js +11 -9
- package/dist/cjs/src/decorators/field/sortable/Sortable.js +10 -0
- package/dist/cjs/src/dream/DreamClassTransactionBuilder.js +4 -2
- package/dist/cjs/src/dream/DreamInstanceTransactionBuilder.js +7 -7
- package/dist/cjs/src/dream/LoadBuilder.js +3 -2
- package/dist/cjs/src/dream/Query.js +24 -11
- package/dist/cjs/src/dream/QueryDriver/Base.js +12 -0
- package/dist/cjs/src/dream/QueryDriver/Kysely.js +11 -2
- package/dist/cjs/src/dream/internal/shouldBypassDefaultScope.js +3 -4
- package/dist/cjs/src/dream/internal/sqlResultToDreamInstance.js +4 -1
- package/dist/cjs/src/errors/NoUpdateOnAssociationQuery.js +1 -1
- package/dist/cjs/src/errors/sti/STIChildTypeMismatch.js +28 -0
- package/dist/cjs/src/helpers/cli/generateMigration.js +1 -1
- package/dist/cjs/src/helpers/cli/resolveIgnoredColumns.js +2 -2
- package/dist/cjs/src/helpers/cli/writeGeneratedFile.js +1 -1
- package/dist/esm/src/Dream.js +11 -9
- package/dist/esm/src/decorators/field/sortable/Sortable.js +10 -0
- package/dist/esm/src/dream/DreamClassTransactionBuilder.js +4 -2
- package/dist/esm/src/dream/DreamInstanceTransactionBuilder.js +7 -7
- package/dist/esm/src/dream/LoadBuilder.js +3 -2
- package/dist/esm/src/dream/Query.js +24 -11
- package/dist/esm/src/dream/QueryDriver/Base.js +12 -0
- package/dist/esm/src/dream/QueryDriver/Kysely.js +11 -2
- package/dist/esm/src/dream/internal/shouldBypassDefaultScope.js +3 -4
- package/dist/esm/src/dream/internal/sqlResultToDreamInstance.js +4 -1
- package/dist/esm/src/errors/NoUpdateOnAssociationQuery.js +1 -1
- package/dist/esm/src/errors/sti/STIChildTypeMismatch.js +28 -0
- package/dist/esm/src/helpers/cli/generateMigration.js +1 -1
- package/dist/esm/src/helpers/cli/resolveIgnoredColumns.js +2 -2
- package/dist/esm/src/helpers/cli/writeGeneratedFile.js +1 -1
- package/dist/types/src/Dream.d.ts +7 -5
- package/dist/types/src/dream/DreamClassTransactionBuilder.d.ts +4 -2
- package/dist/types/src/dream/DreamInstanceTransactionBuilder.d.ts +3 -3
- package/dist/types/src/dream/LoadBuilder.d.ts +3 -2
- package/dist/types/src/dream/Query.d.ts +16 -8
- package/dist/types/src/dream/QueryDriver/Base.d.ts +6 -0
- package/dist/types/src/dream/internal/destroyOptions.d.ts +3 -2
- package/dist/types/src/errors/sti/STIChildTypeMismatch.d.ts +11 -0
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/db.DreamMigrationHelpers.html +11 -11
- package/docs/classes/db.KyselyQueryDriver.html +44 -42
- package/docs/classes/db.PostgresQueryDriver.html +45 -43
- package/docs/classes/db.QueryDriverBase.html +43 -41
- 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.SortableBatchRequiresTooManyScopeLocks.html +3 -3
- package/docs/classes/errors.SortableScopeDidNotStabilize.html +3 -3
- package/docs/classes/errors.SortableScopeLockWaitTimedOut.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 +130 -128
- 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 +69 -67
- 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/hierarchy.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 +3 -3
package/dist/cjs/src/Dream.js
CHANGED
|
@@ -878,9 +878,11 @@ export default class Dream {
|
|
|
878
878
|
});
|
|
879
879
|
}
|
|
880
880
|
/**
|
|
881
|
-
* Returns a query
|
|
881
|
+
* Returns a query which bypasses user-removable default scopes, including on
|
|
882
|
+
* association loads. An STI child's reserved type discriminator remains
|
|
883
|
+
* enforced; query the STI base model to span its registered children.
|
|
882
884
|
*
|
|
883
|
-
* @returns A query
|
|
885
|
+
* @returns A query which bypasses user-removable default scopes
|
|
884
886
|
*/
|
|
885
887
|
static removeAllDefaultScopes() {
|
|
886
888
|
return this.query().removeAllDefaultScopes();
|
|
@@ -3141,7 +3143,7 @@ export default class Dream {
|
|
|
3141
3143
|
* @param options - Options for destroying the instance
|
|
3142
3144
|
* @param options.skipHooks - If true, skips applying model hooks during the destroy operation. Defaults to false
|
|
3143
3145
|
* @param options.cascade - If false, skips destroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
3144
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
3146
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when cascade destroying; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
3145
3147
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when cascade destroying. Defaults to an empty array
|
|
3146
3148
|
* @returns The instance that was destroyed
|
|
3147
3149
|
*/
|
|
@@ -3166,7 +3168,7 @@ export default class Dream {
|
|
|
3166
3168
|
* @param options - Options for destroying the instance
|
|
3167
3169
|
* @param options.skipHooks - If true, skips applying model hooks during the destroy operation. Defaults to false
|
|
3168
3170
|
* @param options.cascade - If false, skips destroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
3169
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
3171
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when cascade destroying; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
3170
3172
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when cascade destroying. Defaults to an empty array
|
|
3171
3173
|
* @returns The instance that was destroyed
|
|
3172
3174
|
*/
|
|
@@ -3188,7 +3190,7 @@ export default class Dream {
|
|
|
3188
3190
|
* @param options - Options for undestroying the instance
|
|
3189
3191
|
* @param options.skipHooks - If true, skips applying model hooks during the undestroy operation. Defaults to false
|
|
3190
3192
|
* @param options.cascade - If false, skips undestroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
3191
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
3193
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when cascade undestroying; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
3192
3194
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when cascade undestroying (soft delete is always bypassed). Defaults to an empty array
|
|
3193
3195
|
* @returns The undestroyed record
|
|
3194
3196
|
*/
|
|
@@ -3297,7 +3299,7 @@ export default class Dream {
|
|
|
3297
3299
|
* @param options.andAny - Optional andAny statement to apply to query before destroying
|
|
3298
3300
|
* @param options.skipHooks - If true, skips applying model hooks during the destroy operation. Defaults to false
|
|
3299
3301
|
* @param options.cascade - If false, skips destroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
3300
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
3302
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when destroying the association; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
3301
3303
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when destroying the association. Defaults to an empty array
|
|
3302
3304
|
* @returns The number of records deleted
|
|
3303
3305
|
*/
|
|
@@ -3333,7 +3335,7 @@ export default class Dream {
|
|
|
3333
3335
|
* @param options.andAny - Optional andAny statement to apply to query before destroying
|
|
3334
3336
|
* @param options.skipHooks - If true, skips applying model hooks during the destroy operation. Defaults to false
|
|
3335
3337
|
* @param options.cascade - If true, cascades the destroy operation to associations marked with `dependent: 'destroy'`. Defaults to true
|
|
3336
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
3338
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when destroying the association; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
3337
3339
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when destroying the association. Defaults to an empty array
|
|
3338
3340
|
* @returns The number of records deleted
|
|
3339
3341
|
*/
|
|
@@ -3366,7 +3368,7 @@ export default class Dream {
|
|
|
3366
3368
|
* @param options.andAny - Optional andAny statement to apply to query before undestroying
|
|
3367
3369
|
* @param options.skipHooks - If true, skips applying model hooks during the undestroy operation. Defaults to false
|
|
3368
3370
|
* @param options.cascade - If false, skips undestroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
3369
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
3371
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when undestroying the association; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
3370
3372
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when undestroying the association. Defaults to an empty array
|
|
3371
3373
|
* @returns The number of records undestroyed
|
|
3372
3374
|
*/
|
|
@@ -3419,7 +3421,7 @@ export default class Dream {
|
|
|
3419
3421
|
* @param options - Options for updating the association
|
|
3420
3422
|
* @param options.and - Optional on statement to apply to query before updating
|
|
3421
3423
|
* @param options.skipHooks - If true, skips applying model hooks during the update operation. Defaults to false
|
|
3422
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
3424
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when updating the association; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
3423
3425
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when updating the association. Defaults to an empty array
|
|
3424
3426
|
* @returns The number of updated records
|
|
3425
3427
|
*/
|
|
@@ -47,6 +47,16 @@ export default function Sortable(opts = {}) {
|
|
|
47
47
|
// already declared on the base STI class.
|
|
48
48
|
dreamClass['sortableFields'] = [...dreamClass['sortableFields']];
|
|
49
49
|
}
|
|
50
|
+
// an STI child inherits its base's sortable fields via the copy above, and
|
|
51
|
+
// the base's field initializers run again while the child is globally
|
|
52
|
+
// initialized, so without this guard the child registers a second config
|
|
53
|
+
// for the same position field whenever the base is initialized first
|
|
54
|
+
// (models are globally initialized in filesystem order). Every duplicate
|
|
55
|
+
// config repeats the child's position work on each save, so positions
|
|
56
|
+
// advance by the number of duplicates instead of by 1
|
|
57
|
+
if (dreamClass['sortableFields'].some(conf => conf.positionField === key)) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
50
60
|
// the decorator registers nothing but this metadata: none of a sortable
|
|
51
61
|
// field's runtime work runs as hooks. A save's preparation and position
|
|
52
62
|
// write run as phases in `saveDream` (`prepareSortableFieldsForSave`,
|
|
@@ -629,9 +629,11 @@ export default class DreamClassTransactionBuilder {
|
|
|
629
629
|
return new Query(this.dreamInstance).txn(this.dreamTransaction);
|
|
630
630
|
}
|
|
631
631
|
/**
|
|
632
|
-
* Returns a query
|
|
632
|
+
* Returns a query which bypasses user-removable default scopes, including on
|
|
633
|
+
* association loads. An STI child's reserved type discriminator remains
|
|
634
|
+
* enforced; query the STI base model to span its registered children.
|
|
633
635
|
*
|
|
634
|
-
* @returns A query
|
|
636
|
+
* @returns A query which bypasses user-removable default scopes
|
|
635
637
|
*/
|
|
636
638
|
removeAllDefaultScopes() {
|
|
637
639
|
return this.queryInstance().removeAllDefaultScopes();
|
|
@@ -190,7 +190,7 @@ export default class DreamInstanceTransactionBuilder {
|
|
|
190
190
|
* @param options - Options for destroying the instance
|
|
191
191
|
* @param options.skipHooks - If true, skips applying model hooks during the destroy operation. Defaults to false
|
|
192
192
|
* @param options.cascade - If false, skips destroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
193
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
193
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when cascade destroying; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
194
194
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when cascade destroying. Defaults to an empty array
|
|
195
195
|
* @returns The instance that was destroyed
|
|
196
196
|
*/
|
|
@@ -212,7 +212,7 @@ export default class DreamInstanceTransactionBuilder {
|
|
|
212
212
|
* @param options - Options for destroying the instance
|
|
213
213
|
* @param options.skipHooks - If true, skips applying model hooks during the destroy operation. Defaults to false
|
|
214
214
|
* @param options.cascade - If false, skips destroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
215
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
215
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when cascade destroying; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
216
216
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when cascade destroying. Defaults to an empty array
|
|
217
217
|
* @returns The instance that was destroyed
|
|
218
218
|
*/
|
|
@@ -234,7 +234,7 @@ export default class DreamInstanceTransactionBuilder {
|
|
|
234
234
|
* @param options - Options for undestroying the instance
|
|
235
235
|
* @param options.skipHooks - If true, skips applying model hooks during the undestroy operation. Defaults to false
|
|
236
236
|
* @param options.cascade - If false, skips undestroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
237
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
237
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when cascade undestroying; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
238
238
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when cascade undestroying (soft delete is always bypassed). Defaults to an empty array
|
|
239
239
|
* @returns The undestroyed instance
|
|
240
240
|
*/
|
|
@@ -403,7 +403,7 @@ export default class DreamInstanceTransactionBuilder {
|
|
|
403
403
|
* @param attributes - The attributes to update on the association
|
|
404
404
|
* @param updateAssociationOptions - Options for updating the association
|
|
405
405
|
* @param updateAssociationOptions.where - Optional where statement to apply to query before updating
|
|
406
|
-
* @param updateAssociationOptions.bypassAllDefaultScopes - If true, bypasses
|
|
406
|
+
* @param updateAssociationOptions.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when updating the association; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
407
407
|
* @param updateAssociationOptions.defaultScopesToBypass - An array of default scope names to bypass when updating the association. Defaults to an empty array
|
|
408
408
|
* @param updateAssociationOptions.skipHooks - If true, skips applying model hooks during the update operation. Defaults to false
|
|
409
409
|
* @returns The number of updated records
|
|
@@ -460,7 +460,7 @@ export default class DreamInstanceTransactionBuilder {
|
|
|
460
460
|
* @param options.andAny - Optional andAny statement to apply to query before destroying
|
|
461
461
|
* @param options.skipHooks - If true, skips applying model hooks during the destroy operation. Defaults to false
|
|
462
462
|
* @param options.cascade - If false, skips destroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
463
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
463
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when destroying the association; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
464
464
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when destroying the association. Defaults to an empty array
|
|
465
465
|
* @returns The number of records deleted
|
|
466
466
|
*/
|
|
@@ -498,7 +498,7 @@ export default class DreamInstanceTransactionBuilder {
|
|
|
498
498
|
* @param options.andAny - Optional andAny statement to apply to query before destroying
|
|
499
499
|
* @param options.skipHooks - If true, skips applying model hooks during the destroy operation. Defaults to false
|
|
500
500
|
* @param options.cascade - If true, cascades the destroy operation to associations marked with `dependent: 'destroy'`. Defaults to true
|
|
501
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
501
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when destroying the association; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
502
502
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when destroying the association. Defaults to an empty array
|
|
503
503
|
* @returns The number of records deleted
|
|
504
504
|
*/
|
|
@@ -531,7 +531,7 @@ export default class DreamInstanceTransactionBuilder {
|
|
|
531
531
|
* @param options.andAny - Optional andAny statement to apply to query before undestroying
|
|
532
532
|
* @param options.skipHooks - If true, skips applying model hooks during the undestroy operation. Defaults to false
|
|
533
533
|
* @param options.cascade - If false, skips undestroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
534
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
534
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when undestroying the association; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
535
535
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when undestroying the association. Defaults to an empty array
|
|
536
536
|
* @returns The number of records undestroyed
|
|
537
537
|
*/
|
|
@@ -44,8 +44,9 @@ export default class LoadBuilder {
|
|
|
44
44
|
return this;
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
47
|
-
* Prevents
|
|
48
|
-
*
|
|
47
|
+
* Prevents user-removable default scopes from applying when loading
|
|
48
|
+
* associations. An associated STI child's reserved type discriminator remains
|
|
49
|
+
* enforced; loading through its STI base still spans registered children.
|
|
49
50
|
*
|
|
50
51
|
* ```ts
|
|
51
52
|
* const user = await User.firstOrFail()
|
|
@@ -177,13 +177,13 @@ export default class Query {
|
|
|
177
177
|
/**
|
|
178
178
|
* @internal
|
|
179
179
|
*
|
|
180
|
-
* Whether or not to bypass all default scopes for this Query
|
|
180
|
+
* Whether or not to bypass all user-removable default scopes for this Query
|
|
181
181
|
*/
|
|
182
182
|
bypassAllDefaultScopes = false;
|
|
183
183
|
/**
|
|
184
184
|
* @internal
|
|
185
185
|
*
|
|
186
|
-
* Whether or not to bypass all default scopes for this Query, but not associations
|
|
186
|
+
* Whether or not to bypass all user-removable default scopes for this Query, but not associations
|
|
187
187
|
*/
|
|
188
188
|
bypassAllDefaultScopesExceptOnAssociations = false;
|
|
189
189
|
/**
|
|
@@ -778,10 +778,12 @@ export default class Query {
|
|
|
778
778
|
});
|
|
779
779
|
}
|
|
780
780
|
/**
|
|
781
|
-
* Prevents default scopes from applying when
|
|
782
|
-
*
|
|
781
|
+
* Prevents user-removable default scopes from applying when the Query is
|
|
782
|
+
* executed, including when associations are loaded. An STI child's reserved
|
|
783
|
+
* type discriminator remains enforced; query the STI base model to span its
|
|
784
|
+
* registered children.
|
|
783
785
|
*
|
|
784
|
-
* @returns A new Query which
|
|
786
|
+
* @returns A new Query which bypasses user-removable default scopes
|
|
785
787
|
*/
|
|
786
788
|
removeAllDefaultScopes() {
|
|
787
789
|
return this.clone({
|
|
@@ -1044,8 +1046,19 @@ export default class Query {
|
|
|
1044
1046
|
* @returns A Kysely query. Depending on the type passed, it will return either a SelectQueryBuilder, DeleteQueryBuilder, or an UpdateQueryBuilder
|
|
1045
1047
|
*/
|
|
1046
1048
|
toKysely(type) {
|
|
1049
|
+
if (type !== 'select')
|
|
1050
|
+
this.assertMutationPreservesAssociationQuery();
|
|
1047
1051
|
return this.dbDriverInstance().toKysely(type);
|
|
1048
1052
|
}
|
|
1053
|
+
/**
|
|
1054
|
+
* @internal
|
|
1055
|
+
*
|
|
1056
|
+
* Prevents mutation paths that discard an association query's ownership constraint.
|
|
1057
|
+
*/
|
|
1058
|
+
assertMutationPreservesAssociationQuery() {
|
|
1059
|
+
if (this.baseSelectQuery)
|
|
1060
|
+
throw new NoUpdateOnAssociationQuery();
|
|
1061
|
+
}
|
|
1049
1062
|
/**
|
|
1050
1063
|
* Applies transaction to the Query instance
|
|
1051
1064
|
*
|
|
@@ -1904,7 +1917,7 @@ export default class Query {
|
|
|
1904
1917
|
* @param options.cascade - If false, skips destroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
1905
1918
|
* @param options.lock - If true, each batch is re-selected with an exclusive row lock inside its own transaction before being destroyed, making the destroy a compare-and-set. Defaults to false
|
|
1906
1919
|
* @param options.batchSize - The number of records to process per batch. Must be a positive integer. Defaults to 10 when `lock` is true, and to 1000 otherwise
|
|
1907
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
1920
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when cascade destroying; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
1908
1921
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when cascade destroying. Defaults to an empty array
|
|
1909
1922
|
* @returns The number of records that were removed
|
|
1910
1923
|
* @throws InvalidBatchSize if `batchSize` is not a positive integer
|
|
@@ -2057,7 +2070,7 @@ export default class Query {
|
|
|
2057
2070
|
// truthiness, since a primary key of 0 is a legitimate cursor value that
|
|
2058
2071
|
// would otherwise reset the window to the start of the set
|
|
2059
2072
|
let lastId = undefined;
|
|
2060
|
-
let attemptedCount
|
|
2073
|
+
let attemptedCount;
|
|
2061
2074
|
do {
|
|
2062
2075
|
const batchQuery = lastId === undefined
|
|
2063
2076
|
? orderedQuery
|
|
@@ -2126,7 +2139,7 @@ export default class Query {
|
|
|
2126
2139
|
* @param options.cascade - If false, skips destroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
2127
2140
|
* @param options.lock - If true, each batch is re-selected with an exclusive row lock inside its own transaction before being destroyed, making the destroy a compare-and-set. See {@link Query.destroy} for the full semantics. Defaults to false
|
|
2128
2141
|
* @param options.batchSize - The number of records to process per batch. Must be a positive integer. Defaults to 10 when `lock` is true, and to 1000 otherwise
|
|
2129
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
2142
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when cascade destroying; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
2130
2143
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when cascade destroying. Defaults to an empty array
|
|
2131
2144
|
* @returns The number of records that were removed
|
|
2132
2145
|
* @throws InvalidBatchSize if `batchSize` is not a positive integer
|
|
@@ -2156,7 +2169,7 @@ export default class Query {
|
|
|
2156
2169
|
* @param options - Options for undestroying the instance
|
|
2157
2170
|
* @param options.skipHooks - If true, skips applying model hooks during the undestroy operation. Defaults to false
|
|
2158
2171
|
* @param options.cascade - If false, skips undestroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
2159
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
2172
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when cascade undestroying; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
2160
2173
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when cascade undestroying (soft delete is always bypassed). Defaults to an empty array
|
|
2161
2174
|
* @returns The number of records that were removed
|
|
2162
2175
|
* @throws BatchingIncompatibleWithLimitOrOffset if the query carries a `limit` or `offset`
|
|
@@ -2196,11 +2209,11 @@ export default class Query {
|
|
|
2196
2209
|
* @returns The number of records that were removed
|
|
2197
2210
|
*/
|
|
2198
2211
|
async delete() {
|
|
2212
|
+
this.assertMutationPreservesAssociationQuery();
|
|
2199
2213
|
return await this.dbDriverInstance().delete();
|
|
2200
2214
|
}
|
|
2201
2215
|
async update(attributesOrCb, { skipHooks, lock, batchSize } = {}) {
|
|
2202
|
-
|
|
2203
|
-
throw new NoUpdateOnAssociationQuery();
|
|
2216
|
+
this.assertMutationPreservesAssociationQuery();
|
|
2204
2217
|
if (Object.keys(this.innerJoinStatements).length)
|
|
2205
2218
|
throw new NoUpdateAllOnJoins();
|
|
2206
2219
|
if (Object.keys(this.leftJoinStatements).length)
|
|
@@ -18,6 +18,14 @@ export default class QueryDriverBase {
|
|
|
18
18
|
this.connectionOverride = query['originalOpts'].connection;
|
|
19
19
|
this.innerJoinDreamClasses = Object.freeze(query['originalOpts'].innerJoinDreamClasses || []);
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* @internal
|
|
23
|
+
*
|
|
24
|
+
* Prevents mutation paths that discard an association query's ownership constraint.
|
|
25
|
+
*/
|
|
26
|
+
assertMutationPreservesAssociationQuery() {
|
|
27
|
+
this.query['assertMutationPreservesAssociationQuery']();
|
|
28
|
+
}
|
|
21
29
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
22
30
|
static async ensureAllMigrationsHaveBeenRun(
|
|
23
31
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -110,6 +118,8 @@ export default class QueryDriverBase {
|
|
|
110
118
|
* @returns A Kysely query. Depending on the type passed, it will return either a SelectQueryBuilder, DeleteQueryBuilder, or an UpdateQueryBuilder
|
|
111
119
|
*/
|
|
112
120
|
toKysely(type) {
|
|
121
|
+
if (type !== 'select')
|
|
122
|
+
this.assertMutationPreservesAssociationQuery();
|
|
113
123
|
throw new Error('implement toKysely in child class (if it makes sense)');
|
|
114
124
|
}
|
|
115
125
|
/**
|
|
@@ -543,6 +553,7 @@ export default class QueryDriverBase {
|
|
|
543
553
|
*/
|
|
544
554
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
545
555
|
async delete() {
|
|
556
|
+
this.assertMutationPreservesAssociationQuery();
|
|
546
557
|
throw new Error('implement delete in child class');
|
|
547
558
|
}
|
|
548
559
|
/**
|
|
@@ -551,6 +562,7 @@ export default class QueryDriverBase {
|
|
|
551
562
|
*/
|
|
552
563
|
// eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-unused-vars
|
|
553
564
|
async update(attributes) {
|
|
565
|
+
this.assertMutationPreservesAssociationQuery();
|
|
554
566
|
throw new Error('implement update in child class');
|
|
555
567
|
}
|
|
556
568
|
/**
|
|
@@ -301,6 +301,8 @@ export default class KyselyQueryDriver extends QueryDriverBase {
|
|
|
301
301
|
* @returns A Kysely query. Depending on the type passed, it will return either a SelectQueryBuilder, DeleteQueryBuilder, or an UpdateQueryBuilder
|
|
302
302
|
*/
|
|
303
303
|
toKysely(type) {
|
|
304
|
+
if (type !== 'select')
|
|
305
|
+
this.assertMutationPreservesAssociationQuery();
|
|
304
306
|
switch (type) {
|
|
305
307
|
case 'select':
|
|
306
308
|
return this.buildSelect();
|
|
@@ -740,6 +742,7 @@ export default class KyselyQueryDriver extends QueryDriverBase {
|
|
|
740
742
|
* @returns the number of deleted rows
|
|
741
743
|
*/
|
|
742
744
|
async delete() {
|
|
745
|
+
this.assertMutationPreservesAssociationQuery();
|
|
743
746
|
const deletionResult = await executeDatabaseQuery(this.buildDelete(), 'executeTakeFirst');
|
|
744
747
|
return Number(deletionResult?.numDeletedRows || 0);
|
|
745
748
|
}
|
|
@@ -748,6 +751,7 @@ export default class KyselyQueryDriver extends QueryDriverBase {
|
|
|
748
751
|
* @returns the number of updated rows
|
|
749
752
|
*/
|
|
750
753
|
async update(attributes) {
|
|
754
|
+
this.assertMutationPreservesAssociationQuery();
|
|
751
755
|
const kyselyQuery = this.buildUpdate(attributes);
|
|
752
756
|
const res = await executeDatabaseQuery(kyselyQuery, 'execute');
|
|
753
757
|
const resultData = Array.from(res.entries())?.[0]?.[1];
|
|
@@ -1014,7 +1018,11 @@ export default class KyselyQueryDriver extends QueryDriverBase {
|
|
|
1014
1018
|
return { kyselyQuery, clone: this.query };
|
|
1015
1019
|
}
|
|
1016
1020
|
columnsWithRequiredLoadColumns(columns) {
|
|
1017
|
-
return uniq(compact([
|
|
1021
|
+
return uniq(compact([
|
|
1022
|
+
this.dreamClass.primaryKey,
|
|
1023
|
+
this.dreamClass['isSTIBase'] || this.dreamClass['isSTIChild'] ? 'type' : null,
|
|
1024
|
+
...columns,
|
|
1025
|
+
]));
|
|
1018
1026
|
}
|
|
1019
1027
|
/**
|
|
1020
1028
|
* @internal
|
|
@@ -1784,12 +1792,13 @@ export default class KyselyQueryDriver extends QueryDriverBase {
|
|
|
1784
1792
|
}, {});
|
|
1785
1793
|
}
|
|
1786
1794
|
conditionallyApplyDefaultScopes() {
|
|
1787
|
-
if (this.query['
|
|
1795
|
+
if (this.query['bypassAllDefaultScopesExceptOnAssociations'])
|
|
1788
1796
|
return this.query;
|
|
1789
1797
|
const thisScopes = this.dreamClass['scopes'].default;
|
|
1790
1798
|
let query = this.query;
|
|
1791
1799
|
for (const scope of thisScopes) {
|
|
1792
1800
|
if (!shouldBypassDefaultScope(scope.method, {
|
|
1801
|
+
bypassAllDefaultScopes: this.query['bypassAllDefaultScopes'],
|
|
1793
1802
|
defaultScopesToBypass: [
|
|
1794
1803
|
...this.query['defaultScopesToBypass'],
|
|
1795
1804
|
...this.query['defaultScopesToBypassExceptOnAssociations'],
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
+
import { STI_SCOPE_NAME } from '../../decorators/class/STI.js';
|
|
1
2
|
export default function shouldBypassDefaultScope(scopeName, { bypassAllDefaultScopes = false, defaultScopesToBypass, }) {
|
|
2
|
-
if (bypassAllDefaultScopes)
|
|
3
|
-
return true;
|
|
4
|
-
if (!defaultScopesToBypass.length)
|
|
5
|
-
return false;
|
|
6
3
|
if (defaultScopesToBypass.includes(scopeName))
|
|
7
4
|
return true;
|
|
5
|
+
if (bypassAllDefaultScopes)
|
|
6
|
+
return scopeName !== STI_SCOPE_NAME;
|
|
8
7
|
return false;
|
|
9
8
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import STIChildMissing from '../../errors/sti/STIChildMissing.js';
|
|
2
|
+
import STIChildTypeMismatch from '../../errors/sti/STIChildTypeMismatch.js';
|
|
2
3
|
import filterRowToKnownColumns from './filterRowToKnownColumns.js';
|
|
3
4
|
export default function sqlResultToDreamInstance(dreamClass, sqlResult) {
|
|
5
|
+
if (dreamClass['isSTIChild'] && sqlResult.type !== dreamClass['sti'].value)
|
|
6
|
+
throw new STIChildTypeMismatch(dreamClass, sqlResult.type, sqlResult[dreamClass.primaryKey]);
|
|
4
7
|
// base-model reads select `*`, so under schema/image skew (or with a
|
|
5
8
|
// column declared in ignoredColumns but not yet dropped) the row can
|
|
6
9
|
// contain columns the compiled schema doesn't know about. Passing such
|
|
@@ -32,7 +35,7 @@ export default function sqlResultToDreamInstance(dreamClass, sqlResult) {
|
|
|
32
35
|
export function findExtendingDreamClass(dreamClass, type) {
|
|
33
36
|
if (!dreamClass['extendedBy'])
|
|
34
37
|
return undefined;
|
|
35
|
-
const extendingDreamClass = dreamClass['extendedBy'].find(extendingDreamClass => extendingDreamClass.
|
|
38
|
+
const extendingDreamClass = dreamClass['extendedBy'].find(extendingDreamClass => extendingDreamClass['sti'].value === type);
|
|
36
39
|
if (extendingDreamClass)
|
|
37
40
|
return extendingDreamClass;
|
|
38
41
|
return dreamClass['extendedBy']
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export default class NoUpdateOnAssociationQuery extends Error {
|
|
2
2
|
get message() {
|
|
3
3
|
return `
|
|
4
|
-
|
|
4
|
+
Mutations may not be called on an associationQuery because its ownership constraint cannot be preserved. Use an association-specific mutation method or query the associated model with explicit conditions.
|
|
5
5
|
`;
|
|
6
6
|
}
|
|
7
7
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export default class STIChildTypeMismatch extends Error {
|
|
2
|
+
expectedDreamClass;
|
|
3
|
+
expectedType;
|
|
4
|
+
actualType;
|
|
5
|
+
baseDreamClass;
|
|
6
|
+
table;
|
|
7
|
+
primaryKeyValue;
|
|
8
|
+
constructor(expectedDreamClass, actualType, primaryKeyValue) {
|
|
9
|
+
super();
|
|
10
|
+
this.expectedDreamClass = expectedDreamClass;
|
|
11
|
+
this.expectedType = expectedDreamClass['sti'].value;
|
|
12
|
+
this.actualType = actualType;
|
|
13
|
+
this.baseDreamClass = expectedDreamClass['sti'].baseClass;
|
|
14
|
+
this.table = this.baseDreamClass.table;
|
|
15
|
+
this.primaryKeyValue = primaryKeyValue;
|
|
16
|
+
}
|
|
17
|
+
get message() {
|
|
18
|
+
return `
|
|
19
|
+
Cannot hydrate STI child from a row with a different discriminator.
|
|
20
|
+
Expected Dream class: ${this.expectedDreamClass.sanitizedName}
|
|
21
|
+
Expected type: ${this.expectedType}
|
|
22
|
+
Type specified in DB record: ${String(this.actualType)}
|
|
23
|
+
STI base Dream class: ${this.baseDreamClass.sanitizedName}
|
|
24
|
+
Table: ${this.table}
|
|
25
|
+
Primary key value: ${String(this.primaryKeyValue)}
|
|
26
|
+
`;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -52,7 +52,7 @@ export default async function generateMigration({ migrationName, columnsWithType
|
|
|
52
52
|
: path.join(dreamPath('db'), 'migrations', connectionName);
|
|
53
53
|
const fileName = `${migrationVersion()}-${hyphenize(migrationName).replace(/\//g, '-')}.ts`;
|
|
54
54
|
const isSTI = !!fullyQualifiedParentName;
|
|
55
|
-
let content
|
|
55
|
+
let content;
|
|
56
56
|
if (isSTI) {
|
|
57
57
|
content = generateStiMigrationContent({
|
|
58
58
|
table: validTableNameOrThrow(migrationName, snakeify(pluralize(pascalizePath(fullyQualifiedParentName)))),
|
|
@@ -137,8 +137,8 @@ function guardAssociationColumns(ignoredColumns, tableName, allModels) {
|
|
|
137
137
|
// pass too, and these guards never see the association's foreign key;
|
|
138
138
|
// the InvalidComputedForeignKey / ExplicitForeignKeyRequired errors
|
|
139
139
|
// swallowed here resurface at runtime as the backstop.
|
|
140
|
-
let foreignKey
|
|
141
|
-
let foreignKeyTypeColumn
|
|
140
|
+
let foreignKey;
|
|
141
|
+
let foreignKeyTypeColumn;
|
|
142
142
|
try {
|
|
143
143
|
foreignKey = associationMetaData.foreignKey();
|
|
144
144
|
foreignKeyTypeColumn = associationMetaData.polymorphic
|
package/dist/esm/src/Dream.js
CHANGED
|
@@ -878,9 +878,11 @@ export default class Dream {
|
|
|
878
878
|
});
|
|
879
879
|
}
|
|
880
880
|
/**
|
|
881
|
-
* Returns a query
|
|
881
|
+
* Returns a query which bypasses user-removable default scopes, including on
|
|
882
|
+
* association loads. An STI child's reserved type discriminator remains
|
|
883
|
+
* enforced; query the STI base model to span its registered children.
|
|
882
884
|
*
|
|
883
|
-
* @returns A query
|
|
885
|
+
* @returns A query which bypasses user-removable default scopes
|
|
884
886
|
*/
|
|
885
887
|
static removeAllDefaultScopes() {
|
|
886
888
|
return this.query().removeAllDefaultScopes();
|
|
@@ -3141,7 +3143,7 @@ export default class Dream {
|
|
|
3141
3143
|
* @param options - Options for destroying the instance
|
|
3142
3144
|
* @param options.skipHooks - If true, skips applying model hooks during the destroy operation. Defaults to false
|
|
3143
3145
|
* @param options.cascade - If false, skips destroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
3144
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
3146
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when cascade destroying; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
3145
3147
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when cascade destroying. Defaults to an empty array
|
|
3146
3148
|
* @returns The instance that was destroyed
|
|
3147
3149
|
*/
|
|
@@ -3166,7 +3168,7 @@ export default class Dream {
|
|
|
3166
3168
|
* @param options - Options for destroying the instance
|
|
3167
3169
|
* @param options.skipHooks - If true, skips applying model hooks during the destroy operation. Defaults to false
|
|
3168
3170
|
* @param options.cascade - If false, skips destroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
3169
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
3171
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when cascade destroying; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
3170
3172
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when cascade destroying. Defaults to an empty array
|
|
3171
3173
|
* @returns The instance that was destroyed
|
|
3172
3174
|
*/
|
|
@@ -3188,7 +3190,7 @@ export default class Dream {
|
|
|
3188
3190
|
* @param options - Options for undestroying the instance
|
|
3189
3191
|
* @param options.skipHooks - If true, skips applying model hooks during the undestroy operation. Defaults to false
|
|
3190
3192
|
* @param options.cascade - If false, skips undestroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
3191
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
3193
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when cascade undestroying; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
3192
3194
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when cascade undestroying (soft delete is always bypassed). Defaults to an empty array
|
|
3193
3195
|
* @returns The undestroyed record
|
|
3194
3196
|
*/
|
|
@@ -3297,7 +3299,7 @@ export default class Dream {
|
|
|
3297
3299
|
* @param options.andAny - Optional andAny statement to apply to query before destroying
|
|
3298
3300
|
* @param options.skipHooks - If true, skips applying model hooks during the destroy operation. Defaults to false
|
|
3299
3301
|
* @param options.cascade - If false, skips destroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
3300
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
3302
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when destroying the association; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
3301
3303
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when destroying the association. Defaults to an empty array
|
|
3302
3304
|
* @returns The number of records deleted
|
|
3303
3305
|
*/
|
|
@@ -3333,7 +3335,7 @@ export default class Dream {
|
|
|
3333
3335
|
* @param options.andAny - Optional andAny statement to apply to query before destroying
|
|
3334
3336
|
* @param options.skipHooks - If true, skips applying model hooks during the destroy operation. Defaults to false
|
|
3335
3337
|
* @param options.cascade - If true, cascades the destroy operation to associations marked with `dependent: 'destroy'`. Defaults to true
|
|
3336
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
3338
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when destroying the association; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
3337
3339
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when destroying the association. Defaults to an empty array
|
|
3338
3340
|
* @returns The number of records deleted
|
|
3339
3341
|
*/
|
|
@@ -3366,7 +3368,7 @@ export default class Dream {
|
|
|
3366
3368
|
* @param options.andAny - Optional andAny statement to apply to query before undestroying
|
|
3367
3369
|
* @param options.skipHooks - If true, skips applying model hooks during the undestroy operation. Defaults to false
|
|
3368
3370
|
* @param options.cascade - If false, skips undestroying associations marked `dependent: 'destroy'`. Defaults to true
|
|
3369
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
3371
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when undestroying the association; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
3370
3372
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when undestroying the association. Defaults to an empty array
|
|
3371
3373
|
* @returns The number of records undestroyed
|
|
3372
3374
|
*/
|
|
@@ -3419,7 +3421,7 @@ export default class Dream {
|
|
|
3419
3421
|
* @param options - Options for updating the association
|
|
3420
3422
|
* @param options.and - Optional on statement to apply to query before updating
|
|
3421
3423
|
* @param options.skipHooks - If true, skips applying model hooks during the update operation. Defaults to false
|
|
3422
|
-
* @param options.bypassAllDefaultScopes - If true, bypasses
|
|
3424
|
+
* @param options.bypassAllDefaultScopes - If true, bypasses user-removable default scopes when updating the association; an STI child's reserved discriminator remains enforced, including when associations are loaded. Defaults to false
|
|
3423
3425
|
* @param options.defaultScopesToBypass - An array of default scope names to bypass when updating the association. Defaults to an empty array
|
|
3424
3426
|
* @returns The number of updated records
|
|
3425
3427
|
*/
|
|
@@ -47,6 +47,16 @@ export default function Sortable(opts = {}) {
|
|
|
47
47
|
// already declared on the base STI class.
|
|
48
48
|
dreamClass['sortableFields'] = [...dreamClass['sortableFields']];
|
|
49
49
|
}
|
|
50
|
+
// an STI child inherits its base's sortable fields via the copy above, and
|
|
51
|
+
// the base's field initializers run again while the child is globally
|
|
52
|
+
// initialized, so without this guard the child registers a second config
|
|
53
|
+
// for the same position field whenever the base is initialized first
|
|
54
|
+
// (models are globally initialized in filesystem order). Every duplicate
|
|
55
|
+
// config repeats the child's position work on each save, so positions
|
|
56
|
+
// advance by the number of duplicates instead of by 1
|
|
57
|
+
if (dreamClass['sortableFields'].some(conf => conf.positionField === key)) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
50
60
|
// the decorator registers nothing but this metadata: none of a sortable
|
|
51
61
|
// field's runtime work runs as hooks. A save's preparation and position
|
|
52
62
|
// write run as phases in `saveDream` (`prepareSortableFieldsForSave`,
|
|
@@ -629,9 +629,11 @@ export default class DreamClassTransactionBuilder {
|
|
|
629
629
|
return new Query(this.dreamInstance).txn(this.dreamTransaction);
|
|
630
630
|
}
|
|
631
631
|
/**
|
|
632
|
-
* Returns a query
|
|
632
|
+
* Returns a query which bypasses user-removable default scopes, including on
|
|
633
|
+
* association loads. An STI child's reserved type discriminator remains
|
|
634
|
+
* enforced; query the STI base model to span its registered children.
|
|
633
635
|
*
|
|
634
|
-
* @returns A query
|
|
636
|
+
* @returns A query which bypasses user-removable default scopes
|
|
635
637
|
*/
|
|
636
638
|
removeAllDefaultScopes() {
|
|
637
639
|
return this.queryInstance().removeAllDefaultScopes();
|