@rvoh/dream 2.33.0 → 2.34.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/README.md +1 -1
- package/dist/cjs/src/Dream.js +14 -1
- package/dist/cjs/src/decorators/Decorators.js +20 -0
- package/dist/cjs/src/decorators/field/lifecycle/AfterCreateCommit.js +4 -0
- package/dist/cjs/src/decorators/field/lifecycle/AfterDestroyCommit.js +4 -0
- package/dist/cjs/src/decorators/field/lifecycle/AfterSaveCommit.js +4 -0
- package/dist/cjs/src/decorators/field/lifecycle/AfterUpdateCommit.js +4 -0
- package/dist/cjs/src/dream/DreamTransaction.js +14 -3
- package/dist/cjs/src/dream/QueryDriver/Kysely.js +1 -1
- package/dist/cjs/src/dream/internal/runHooksFor.js +16 -5
- package/dist/cjs/src/dream/internal/withConcurrentWriterRetry.js +6 -1
- package/dist/esm/src/Dream.js +14 -1
- package/dist/esm/src/decorators/Decorators.js +20 -0
- package/dist/esm/src/decorators/field/lifecycle/AfterCreateCommit.js +4 -0
- package/dist/esm/src/decorators/field/lifecycle/AfterDestroyCommit.js +4 -0
- package/dist/esm/src/decorators/field/lifecycle/AfterSaveCommit.js +4 -0
- package/dist/esm/src/decorators/field/lifecycle/AfterUpdateCommit.js +4 -0
- package/dist/esm/src/dream/DreamTransaction.js +14 -3
- package/dist/esm/src/dream/QueryDriver/Kysely.js +1 -1
- package/dist/esm/src/dream/internal/runHooksFor.js +16 -5
- package/dist/esm/src/dream/internal/withConcurrentWriterRetry.js +6 -1
- package/dist/types/src/Dream.d.ts +14 -1
- package/dist/types/src/decorators/Decorators.d.ts +24 -4
- package/dist/types/src/decorators/field/lifecycle/AfterCreateCommit.d.ts +6 -2
- package/dist/types/src/decorators/field/lifecycle/AfterDestroyCommit.d.ts +6 -1
- package/dist/types/src/decorators/field/lifecycle/AfterSaveCommit.d.ts +6 -2
- package/dist/types/src/decorators/field/lifecycle/AfterUpdateCommit.d.ts +6 -2
- package/dist/types/src/dream/DreamTransaction.d.ts +8 -1
- package/dist/types/src/dream/internal/runHooksFor.d.ts +5 -0
- package/dist/types/src/dream/internal/withConcurrentWriterRetry.d.ts +2 -1
- package/dist/types/src/types/lifecycle.d.ts +29 -0
- package/dist/types/src/types/types/lifecycle.ts +46 -0
- package/docs/classes/db.DreamMigrationHelpers.html +11 -11
- package/docs/classes/db.KyselyQueryDriver.html +46 -46
- package/docs/classes/db.PostgresQueryDriver.html +47 -47
- package/docs/classes/db.QueryDriverBase.html +45 -45
- package/docs/classes/errors.CannotSaveMissingDream.html +5 -5
- package/docs/classes/errors.CheckConstraintViolation.html +5 -5
- package/docs/classes/errors.ColumnOverflow.html +5 -5
- package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +5 -5
- package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +5 -5
- package/docs/classes/errors.DataTypeColumnTypeMismatch.html +5 -5
- package/docs/classes/errors.DecryptionError.html +4 -4
- package/docs/classes/errors.DecryptionParseError.html +4 -4
- package/docs/classes/errors.DecryptionRotationError.html +5 -5
- package/docs/classes/errors.GlobalNameNotSet.html +5 -5
- package/docs/classes/errors.InvalidCalendarDate.html +5 -5
- package/docs/classes/errors.InvalidClockTime.html +5 -5
- package/docs/classes/errors.InvalidClockTimeTz.html +5 -5
- package/docs/classes/errors.InvalidDateTime.html +5 -5
- package/docs/classes/errors.MissingSerializersDefinition.html +5 -5
- package/docs/classes/errors.NonLoadedAssociation.html +5 -5
- package/docs/classes/errors.NotNullViolation.html +5 -5
- package/docs/classes/errors.RecordNotFound.html +5 -5
- package/docs/classes/errors.SortableScopeDidNotStabilize.html +5 -5
- package/docs/classes/errors.SortableScopeLockWaitTimedOut.html +5 -5
- package/docs/classes/errors.ValidationError.html +5 -5
- 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 +39 -23
- package/docs/classes/index.Dream.html +135 -125
- package/docs/classes/index.DreamApp.html +10 -10
- package/docs/classes/index.DreamTransaction.html +6 -2
- package/docs/classes/index.Env.html +2 -2
- package/docs/classes/index.Query.html +65 -65
- 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 +3 -3
- 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/index.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 +6 -6
- 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 +5 -2
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Dream is a typescript-driven, esm-first ORM built on top of [kysely](http://kysely.dev). It is built to operate within the [Psychic web framework](https://psychicframework.com/docs/intro), but can be brought into other projects and used without the encapsulating framework (though this is theoretical, and we do not encourage it at this time). It is actively being developed to support production-grade applications in use within the [RVOHealth organization](https://www.rvohealth.com), who has kindly sponsored the continued development of this ORM, as well as the Psychic web framework as a whole.
|
|
1
|
+
Dream is a typescript-driven, esm-first ORM built on top of [kysely](http://kysely.dev). It supports Node.js 24 and newer, with Node.js 26 as the primary development and CI runtime. It is built to operate within the [Psychic web framework](https://psychicframework.com/docs/intro), but can be brought into other projects and used without the encapsulating framework (though this is theoretical, and we do not encourage it at this time). It is actively being developed to support production-grade applications in use within the [RVOHealth organization](https://www.rvohealth.com), who has kindly sponsored the continued development of this ORM, as well as the Psychic web framework as a whole.
|
|
2
2
|
|
|
3
3
|
Documentation: [https://psychicframework.com/docs/intro](https://psychicframework.com/docs/intro)
|
|
4
4
|
Psychic web framework github: [https://github.com/rvohealth/psychic](https://github.com/rvohealth/psychic)
|
package/dist/cjs/src/Dream.js
CHANGED
|
@@ -2946,6 +2946,10 @@ export default class Dream {
|
|
|
2946
2946
|
* being persisted to the database, with the values
|
|
2947
2947
|
* that were last persisted to the database.
|
|
2948
2948
|
*
|
|
2949
|
+
* On a record that has not been persisted, every
|
|
2950
|
+
* column counts as changed: the object has a key
|
|
2951
|
+
* for every column.
|
|
2952
|
+
*
|
|
2949
2953
|
* ```ts
|
|
2950
2954
|
* const user = User.new({ email: 'original@email', password: 'howyadoin' })
|
|
2951
2955
|
* await user.save()
|
|
@@ -3077,6 +3081,10 @@ export default class Dream {
|
|
|
3077
3081
|
* Returns true if the columnName provided has
|
|
3078
3082
|
* changes that have not yet been persisted.
|
|
3079
3083
|
*
|
|
3084
|
+
* On a record that has not been persisted, every
|
|
3085
|
+
* column counts as changed, so this returns true
|
|
3086
|
+
* for every column, whether or not it was assigned.
|
|
3087
|
+
*
|
|
3080
3088
|
* @param attribute - the column name to check
|
|
3081
3089
|
* @returns A boolean
|
|
3082
3090
|
*/
|
|
@@ -3096,10 +3104,15 @@ export default class Dream {
|
|
|
3096
3104
|
* of columns that have changed since last persist,
|
|
3097
3105
|
* and their current values.
|
|
3098
3106
|
*
|
|
3107
|
+
* On a record that has not been persisted, every
|
|
3108
|
+
* column counts as changed: the object has a key
|
|
3109
|
+
* for every column, including those never assigned,
|
|
3110
|
+
* whose value is `undefined`.
|
|
3111
|
+
*
|
|
3099
3112
|
* ```ts
|
|
3100
3113
|
* const user = User.new({ email: 'hello@world' })
|
|
3101
3114
|
* user.dirtyAttributes()
|
|
3102
|
-
* // { email: 'hello@world' }
|
|
3115
|
+
* // { id: undefined, email: 'hello@world', name: undefined, ...every other column: undefined }
|
|
3103
3116
|
*
|
|
3104
3117
|
* await user.save()
|
|
3105
3118
|
*
|
|
@@ -491,6 +491,11 @@ export default class Decorators {
|
|
|
491
491
|
* }
|
|
492
492
|
* ```
|
|
493
493
|
*
|
|
494
|
+
* The decorated method is called with no argument, once the
|
|
495
|
+
* transaction has committed, so declaring a parameter on it is a
|
|
496
|
+
* compile error. A subclass override of the method that is not itself
|
|
497
|
+
* decorated is not checked; it is still called with no argument.
|
|
498
|
+
*
|
|
494
499
|
* @returns The AfterCreateCommit decorator
|
|
495
500
|
*/
|
|
496
501
|
AfterCreateCommit(opts) {
|
|
@@ -526,6 +531,11 @@ export default class Decorators {
|
|
|
526
531
|
* }
|
|
527
532
|
* ```
|
|
528
533
|
*
|
|
534
|
+
* The decorated method is called with no argument, once the
|
|
535
|
+
* transaction has committed, so declaring a parameter on it is a
|
|
536
|
+
* compile error. A subclass override of the method that is not itself
|
|
537
|
+
* decorated is not checked; it is still called with no argument.
|
|
538
|
+
*
|
|
529
539
|
* @returns The AfterSaveCommit decorator
|
|
530
540
|
*
|
|
531
541
|
*/
|
|
@@ -562,6 +572,11 @@ export default class Decorators {
|
|
|
562
572
|
* }
|
|
563
573
|
* ```
|
|
564
574
|
*
|
|
575
|
+
* The decorated method is called with no argument, once the
|
|
576
|
+
* transaction has committed, so declaring a parameter on it is a
|
|
577
|
+
* compile error. A subclass override of the method that is not itself
|
|
578
|
+
* decorated is not checked; it is still called with no argument.
|
|
579
|
+
*
|
|
565
580
|
* @returns The AfterUpdateCommit decorator
|
|
566
581
|
*
|
|
567
582
|
*/
|
|
@@ -598,6 +613,11 @@ export default class Decorators {
|
|
|
598
613
|
* }
|
|
599
614
|
* ```
|
|
600
615
|
*
|
|
616
|
+
* The decorated method is called with no argument, once the
|
|
617
|
+
* transaction has committed, so declaring a parameter on it is a
|
|
618
|
+
* compile error. A subclass override of the method that is not itself
|
|
619
|
+
* decorated is not checked; it is still called with no argument.
|
|
620
|
+
*
|
|
601
621
|
* @returns The AfterDestroyCommit decorator
|
|
602
622
|
*
|
|
603
623
|
*/
|
|
@@ -7,6 +7,10 @@ import { blankHooksFactory } from './shared.js';
|
|
|
7
7
|
* a transaction, the method will be run after the save
|
|
8
8
|
* is complete.
|
|
9
9
|
*
|
|
10
|
+
* The method is called with no argument: the transaction has already
|
|
11
|
+
* committed, so there is none to hand it. Decorating a method that
|
|
12
|
+
* declares a parameter is a compile error (see {@link CommitHookDecorator}).
|
|
13
|
+
*
|
|
10
14
|
* class User extends ApplicationModel {
|
|
11
15
|
* @deco.AfterCreateCommit()
|
|
12
16
|
* public doSomething() {
|
|
@@ -7,6 +7,10 @@ import { blankHooksFactory } from './shared.js';
|
|
|
7
7
|
* a transaction, the method will be run after the save
|
|
8
8
|
* is complete.
|
|
9
9
|
*
|
|
10
|
+
* The method is called with no argument: the transaction has already
|
|
11
|
+
* committed, so there is none to hand it. Decorating a method that
|
|
12
|
+
* declares a parameter is a compile error (see {@link CommitHookDecorator}).
|
|
13
|
+
*
|
|
10
14
|
* class User extends ApplicationModel {
|
|
11
15
|
* @deco.AfterDestroyCommit()
|
|
12
16
|
* public doSomething() {
|
|
@@ -7,6 +7,10 @@ import { blankHooksFactory } from './shared.js';
|
|
|
7
7
|
* a transaction, the method will be run after the save
|
|
8
8
|
* is complete.
|
|
9
9
|
*
|
|
10
|
+
* The method is called with no argument: the transaction has already
|
|
11
|
+
* committed, so there is none to hand it. Decorating a method that
|
|
12
|
+
* declares a parameter is a compile error (see {@link CommitHookDecorator}).
|
|
13
|
+
*
|
|
10
14
|
* class User extends ApplicationModel {
|
|
11
15
|
* @deco.AfterSaveCommit()
|
|
12
16
|
* public doSomething() {
|
|
@@ -7,6 +7,10 @@ import { blankHooksFactory } from './shared.js';
|
|
|
7
7
|
* a transaction, the method will be run after the save
|
|
8
8
|
* is complete.
|
|
9
9
|
*
|
|
10
|
+
* The method is called with no argument: the transaction has already
|
|
11
|
+
* committed, so there is none to hand it. Decorating a method that
|
|
12
|
+
* declares a parameter is a compile error (see {@link CommitHookDecorator}).
|
|
13
|
+
*
|
|
10
14
|
* class User extends ApplicationModel {
|
|
11
15
|
* @deco.AfterUpdateCommit()
|
|
12
16
|
* public doSomething() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { runCommitHook } from './internal/runHooksFor.js';
|
|
2
2
|
// though this class is called `DreamTransaction`, it is not itself
|
|
3
3
|
// a transaction class, as much as a collector for various callbacks
|
|
4
4
|
// that must be run after the underlying transaction is commited (i.e.
|
|
@@ -6,6 +6,10 @@ import { runHook } from './internal/runHooksFor.js';
|
|
|
6
6
|
export default class DreamTransaction {
|
|
7
7
|
_kyselyTransaction;
|
|
8
8
|
commitHooks = [];
|
|
9
|
+
// Set when the query driver starts the commit hooks, which it does only once
|
|
10
|
+
// the transaction has committed. `withConcurrentWriterRetry` reads it to
|
|
11
|
+
// never run a committed operation again.
|
|
12
|
+
committed = false;
|
|
9
13
|
get kyselyTransaction() {
|
|
10
14
|
return this._kyselyTransaction;
|
|
11
15
|
}
|
|
@@ -15,9 +19,16 @@ export default class DreamTransaction {
|
|
|
15
19
|
addCommitHook(hookStatement, dreamInstance) {
|
|
16
20
|
this.commitHooks.push({ dreamInstance, hookStatement });
|
|
17
21
|
}
|
|
18
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Runs the commit hooks queued during the transaction, in the order they
|
|
24
|
+
* were queued. A query driver calls this once the transaction has
|
|
25
|
+
* committed. Each hook is called with no argument, since the transaction
|
|
26
|
+
* it would otherwise receive can no longer run queries.
|
|
27
|
+
*/
|
|
28
|
+
async runAfterCommitHooks() {
|
|
29
|
+
this.committed = true;
|
|
19
30
|
for (const hook of this.commitHooks) {
|
|
20
|
-
await
|
|
31
|
+
await runCommitHook(hook.hookStatement, hook.dreamInstance);
|
|
21
32
|
}
|
|
22
33
|
}
|
|
23
34
|
}
|
|
@@ -351,7 +351,7 @@ export default class KyselyQueryDriver extends QueryDriverBase {
|
|
|
351
351
|
dreamTransaction.kyselyTransaction = kyselyTransaction;
|
|
352
352
|
callbackResponse = (await callback(dreamTransaction));
|
|
353
353
|
});
|
|
354
|
-
await dreamTransaction.runAfterCommitHooks(
|
|
354
|
+
await dreamTransaction.runAfterCommitHooks();
|
|
355
355
|
return callbackResponse;
|
|
356
356
|
}
|
|
357
357
|
/**
|
|
@@ -35,7 +35,7 @@ export default async function runHooksFor(key, dream, alreadyPersisted, beforeSa
|
|
|
35
35
|
if (txn)
|
|
36
36
|
txn.addCommitHook(hook, dream);
|
|
37
37
|
else
|
|
38
|
-
await
|
|
38
|
+
await runCommitHook(hook, dream);
|
|
39
39
|
}
|
|
40
40
|
break;
|
|
41
41
|
case 'afterSave':
|
|
@@ -50,7 +50,7 @@ export default async function runHooksFor(key, dream, alreadyPersisted, beforeSa
|
|
|
50
50
|
if (txn)
|
|
51
51
|
txn.addCommitHook(hook, dream);
|
|
52
52
|
else
|
|
53
|
-
await
|
|
53
|
+
await runCommitHook(hook, dream);
|
|
54
54
|
}
|
|
55
55
|
break;
|
|
56
56
|
case 'afterUpdate':
|
|
@@ -63,7 +63,7 @@ export default async function runHooksFor(key, dream, alreadyPersisted, beforeSa
|
|
|
63
63
|
if (txn)
|
|
64
64
|
txn.addCommitHook(hook, dream);
|
|
65
65
|
else
|
|
66
|
-
await
|
|
66
|
+
await runCommitHook(hook, dream);
|
|
67
67
|
}
|
|
68
68
|
break;
|
|
69
69
|
default:
|
|
@@ -79,7 +79,7 @@ export default async function runHooksFor(key, dream, alreadyPersisted, beforeSa
|
|
|
79
79
|
if (txn)
|
|
80
80
|
txn.addCommitHook(hook, dream);
|
|
81
81
|
else
|
|
82
|
-
await
|
|
82
|
+
await runCommitHook(hook, dream);
|
|
83
83
|
break;
|
|
84
84
|
default:
|
|
85
85
|
await runHook(hook, dream, txn);
|
|
@@ -88,6 +88,18 @@ export default async function runHooksFor(key, dream, alreadyPersisted, beforeSa
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
export async function runHook(statement, dream, txn) {
|
|
91
|
+
assertHookMethodExists(statement, dream);
|
|
92
|
+
await dream[statement.method](txn);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Commit hooks run after the transaction has committed, so they are called
|
|
96
|
+
* with no argument.
|
|
97
|
+
*/
|
|
98
|
+
export async function runCommitHook(statement, dream) {
|
|
99
|
+
assertHookMethodExists(statement, dream);
|
|
100
|
+
await dream[statement.method]();
|
|
101
|
+
}
|
|
102
|
+
function assertHookMethodExists(statement, dream) {
|
|
91
103
|
if (typeof dream[statement.method] !== 'function') {
|
|
92
104
|
throw new Error(`
|
|
93
105
|
Attempting to run ${statement.method} as part of the ${statement.type}
|
|
@@ -96,7 +108,6 @@ Dream model hook sequence, but we encountered a method that does not exist.
|
|
|
96
108
|
Please make sure "${statement.method}" is defined on ${dream['sanitizedConstructorName']}
|
|
97
109
|
`);
|
|
98
110
|
}
|
|
99
|
-
await dream[statement.method](txn);
|
|
100
111
|
}
|
|
101
112
|
function shouldRunBeforeCreateHook(dream, statement) {
|
|
102
113
|
let shouldRun = false;
|
|
@@ -22,7 +22,8 @@ export const MAX_CONCURRENT_WRITER_ATTEMPTS = 3;
|
|
|
22
22
|
* rows mid-statement as well. Either way the database has undone the whole
|
|
23
23
|
* transaction, nothing has committed and no commit hook has run, so running
|
|
24
24
|
* the operation again reads the rows as the other writer left them. The last
|
|
25
|
-
* attempt's error is the adapter's own.
|
|
25
|
+
* attempt's error is the adapter's own. An error raised after COMMIT, such as a
|
|
26
|
+
* commit hook's, is never retried.
|
|
26
27
|
*
|
|
27
28
|
* A unique violation raised by a statement inside the callback is not a
|
|
28
29
|
* collision but a write that violates a constraint outright, and is not
|
|
@@ -46,15 +47,19 @@ export const MAX_CONCURRENT_WRITER_ATTEMPTS = 3;
|
|
|
46
47
|
export default async function withConcurrentWriterRetry(dreamClass, callback) {
|
|
47
48
|
const queryDriverClass = DreamApp.getOrFail().dbConnectionQueryDriverClass(dreamClass.prototype.connectionName);
|
|
48
49
|
for (let attempt = 1;; attempt++) {
|
|
50
|
+
let attemptTransaction = null;
|
|
49
51
|
let callbackResolved = false;
|
|
50
52
|
try {
|
|
51
53
|
return await dreamClass.transaction(async (txn) => {
|
|
54
|
+
attemptTransaction = txn;
|
|
52
55
|
const result = await callback(txn);
|
|
53
56
|
callbackResolved = true;
|
|
54
57
|
return result;
|
|
55
58
|
});
|
|
56
59
|
}
|
|
57
60
|
catch (error) {
|
|
61
|
+
if (attemptTransaction?.['committed'])
|
|
62
|
+
throw error;
|
|
58
63
|
const undoneByConcurrentWriter = queryDriverClass.isDeadlock(error) ||
|
|
59
64
|
(callbackResolved && queryDriverClass.isUniqueConstraintViolation(error));
|
|
60
65
|
if (!undoneByConcurrentWriter || attempt === MAX_CONCURRENT_WRITER_ATTEMPTS)
|
package/dist/esm/src/Dream.js
CHANGED
|
@@ -2946,6 +2946,10 @@ export default class Dream {
|
|
|
2946
2946
|
* being persisted to the database, with the values
|
|
2947
2947
|
* that were last persisted to the database.
|
|
2948
2948
|
*
|
|
2949
|
+
* On a record that has not been persisted, every
|
|
2950
|
+
* column counts as changed: the object has a key
|
|
2951
|
+
* for every column.
|
|
2952
|
+
*
|
|
2949
2953
|
* ```ts
|
|
2950
2954
|
* const user = User.new({ email: 'original@email', password: 'howyadoin' })
|
|
2951
2955
|
* await user.save()
|
|
@@ -3077,6 +3081,10 @@ export default class Dream {
|
|
|
3077
3081
|
* Returns true if the columnName provided has
|
|
3078
3082
|
* changes that have not yet been persisted.
|
|
3079
3083
|
*
|
|
3084
|
+
* On a record that has not been persisted, every
|
|
3085
|
+
* column counts as changed, so this returns true
|
|
3086
|
+
* for every column, whether or not it was assigned.
|
|
3087
|
+
*
|
|
3080
3088
|
* @param attribute - the column name to check
|
|
3081
3089
|
* @returns A boolean
|
|
3082
3090
|
*/
|
|
@@ -3096,10 +3104,15 @@ export default class Dream {
|
|
|
3096
3104
|
* of columns that have changed since last persist,
|
|
3097
3105
|
* and their current values.
|
|
3098
3106
|
*
|
|
3107
|
+
* On a record that has not been persisted, every
|
|
3108
|
+
* column counts as changed: the object has a key
|
|
3109
|
+
* for every column, including those never assigned,
|
|
3110
|
+
* whose value is `undefined`.
|
|
3111
|
+
*
|
|
3099
3112
|
* ```ts
|
|
3100
3113
|
* const user = User.new({ email: 'hello@world' })
|
|
3101
3114
|
* user.dirtyAttributes()
|
|
3102
|
-
* // { email: 'hello@world' }
|
|
3115
|
+
* // { id: undefined, email: 'hello@world', name: undefined, ...every other column: undefined }
|
|
3103
3116
|
*
|
|
3104
3117
|
* await user.save()
|
|
3105
3118
|
*
|
|
@@ -491,6 +491,11 @@ export default class Decorators {
|
|
|
491
491
|
* }
|
|
492
492
|
* ```
|
|
493
493
|
*
|
|
494
|
+
* The decorated method is called with no argument, once the
|
|
495
|
+
* transaction has committed, so declaring a parameter on it is a
|
|
496
|
+
* compile error. A subclass override of the method that is not itself
|
|
497
|
+
* decorated is not checked; it is still called with no argument.
|
|
498
|
+
*
|
|
494
499
|
* @returns The AfterCreateCommit decorator
|
|
495
500
|
*/
|
|
496
501
|
AfterCreateCommit(opts) {
|
|
@@ -526,6 +531,11 @@ export default class Decorators {
|
|
|
526
531
|
* }
|
|
527
532
|
* ```
|
|
528
533
|
*
|
|
534
|
+
* The decorated method is called with no argument, once the
|
|
535
|
+
* transaction has committed, so declaring a parameter on it is a
|
|
536
|
+
* compile error. A subclass override of the method that is not itself
|
|
537
|
+
* decorated is not checked; it is still called with no argument.
|
|
538
|
+
*
|
|
529
539
|
* @returns The AfterSaveCommit decorator
|
|
530
540
|
*
|
|
531
541
|
*/
|
|
@@ -562,6 +572,11 @@ export default class Decorators {
|
|
|
562
572
|
* }
|
|
563
573
|
* ```
|
|
564
574
|
*
|
|
575
|
+
* The decorated method is called with no argument, once the
|
|
576
|
+
* transaction has committed, so declaring a parameter on it is a
|
|
577
|
+
* compile error. A subclass override of the method that is not itself
|
|
578
|
+
* decorated is not checked; it is still called with no argument.
|
|
579
|
+
*
|
|
565
580
|
* @returns The AfterUpdateCommit decorator
|
|
566
581
|
*
|
|
567
582
|
*/
|
|
@@ -598,6 +613,11 @@ export default class Decorators {
|
|
|
598
613
|
* }
|
|
599
614
|
* ```
|
|
600
615
|
*
|
|
616
|
+
* The decorated method is called with no argument, once the
|
|
617
|
+
* transaction has committed, so declaring a parameter on it is a
|
|
618
|
+
* compile error. A subclass override of the method that is not itself
|
|
619
|
+
* decorated is not checked; it is still called with no argument.
|
|
620
|
+
*
|
|
601
621
|
* @returns The AfterDestroyCommit decorator
|
|
602
622
|
*
|
|
603
623
|
*/
|
|
@@ -7,6 +7,10 @@ import { blankHooksFactory } from './shared.js';
|
|
|
7
7
|
* a transaction, the method will be run after the save
|
|
8
8
|
* is complete.
|
|
9
9
|
*
|
|
10
|
+
* The method is called with no argument: the transaction has already
|
|
11
|
+
* committed, so there is none to hand it. Decorating a method that
|
|
12
|
+
* declares a parameter is a compile error (see {@link CommitHookDecorator}).
|
|
13
|
+
*
|
|
10
14
|
* class User extends ApplicationModel {
|
|
11
15
|
* @deco.AfterCreateCommit()
|
|
12
16
|
* public doSomething() {
|
|
@@ -7,6 +7,10 @@ import { blankHooksFactory } from './shared.js';
|
|
|
7
7
|
* a transaction, the method will be run after the save
|
|
8
8
|
* is complete.
|
|
9
9
|
*
|
|
10
|
+
* The method is called with no argument: the transaction has already
|
|
11
|
+
* committed, so there is none to hand it. Decorating a method that
|
|
12
|
+
* declares a parameter is a compile error (see {@link CommitHookDecorator}).
|
|
13
|
+
*
|
|
10
14
|
* class User extends ApplicationModel {
|
|
11
15
|
* @deco.AfterDestroyCommit()
|
|
12
16
|
* public doSomething() {
|
|
@@ -7,6 +7,10 @@ import { blankHooksFactory } from './shared.js';
|
|
|
7
7
|
* a transaction, the method will be run after the save
|
|
8
8
|
* is complete.
|
|
9
9
|
*
|
|
10
|
+
* The method is called with no argument: the transaction has already
|
|
11
|
+
* committed, so there is none to hand it. Decorating a method that
|
|
12
|
+
* declares a parameter is a compile error (see {@link CommitHookDecorator}).
|
|
13
|
+
*
|
|
10
14
|
* class User extends ApplicationModel {
|
|
11
15
|
* @deco.AfterSaveCommit()
|
|
12
16
|
* public doSomething() {
|
|
@@ -7,6 +7,10 @@ import { blankHooksFactory } from './shared.js';
|
|
|
7
7
|
* a transaction, the method will be run after the save
|
|
8
8
|
* is complete.
|
|
9
9
|
*
|
|
10
|
+
* The method is called with no argument: the transaction has already
|
|
11
|
+
* committed, so there is none to hand it. Decorating a method that
|
|
12
|
+
* declares a parameter is a compile error (see {@link CommitHookDecorator}).
|
|
13
|
+
*
|
|
10
14
|
* class User extends ApplicationModel {
|
|
11
15
|
* @deco.AfterUpdateCommit()
|
|
12
16
|
* public doSomething() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { runCommitHook } from './internal/runHooksFor.js';
|
|
2
2
|
// though this class is called `DreamTransaction`, it is not itself
|
|
3
3
|
// a transaction class, as much as a collector for various callbacks
|
|
4
4
|
// that must be run after the underlying transaction is commited (i.e.
|
|
@@ -6,6 +6,10 @@ import { runHook } from './internal/runHooksFor.js';
|
|
|
6
6
|
export default class DreamTransaction {
|
|
7
7
|
_kyselyTransaction;
|
|
8
8
|
commitHooks = [];
|
|
9
|
+
// Set when the query driver starts the commit hooks, which it does only once
|
|
10
|
+
// the transaction has committed. `withConcurrentWriterRetry` reads it to
|
|
11
|
+
// never run a committed operation again.
|
|
12
|
+
committed = false;
|
|
9
13
|
get kyselyTransaction() {
|
|
10
14
|
return this._kyselyTransaction;
|
|
11
15
|
}
|
|
@@ -15,9 +19,16 @@ export default class DreamTransaction {
|
|
|
15
19
|
addCommitHook(hookStatement, dreamInstance) {
|
|
16
20
|
this.commitHooks.push({ dreamInstance, hookStatement });
|
|
17
21
|
}
|
|
18
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Runs the commit hooks queued during the transaction, in the order they
|
|
24
|
+
* were queued. A query driver calls this once the transaction has
|
|
25
|
+
* committed. Each hook is called with no argument, since the transaction
|
|
26
|
+
* it would otherwise receive can no longer run queries.
|
|
27
|
+
*/
|
|
28
|
+
async runAfterCommitHooks() {
|
|
29
|
+
this.committed = true;
|
|
19
30
|
for (const hook of this.commitHooks) {
|
|
20
|
-
await
|
|
31
|
+
await runCommitHook(hook.hookStatement, hook.dreamInstance);
|
|
21
32
|
}
|
|
22
33
|
}
|
|
23
34
|
}
|
|
@@ -351,7 +351,7 @@ export default class KyselyQueryDriver extends QueryDriverBase {
|
|
|
351
351
|
dreamTransaction.kyselyTransaction = kyselyTransaction;
|
|
352
352
|
callbackResponse = (await callback(dreamTransaction));
|
|
353
353
|
});
|
|
354
|
-
await dreamTransaction.runAfterCommitHooks(
|
|
354
|
+
await dreamTransaction.runAfterCommitHooks();
|
|
355
355
|
return callbackResponse;
|
|
356
356
|
}
|
|
357
357
|
/**
|
|
@@ -35,7 +35,7 @@ export default async function runHooksFor(key, dream, alreadyPersisted, beforeSa
|
|
|
35
35
|
if (txn)
|
|
36
36
|
txn.addCommitHook(hook, dream);
|
|
37
37
|
else
|
|
38
|
-
await
|
|
38
|
+
await runCommitHook(hook, dream);
|
|
39
39
|
}
|
|
40
40
|
break;
|
|
41
41
|
case 'afterSave':
|
|
@@ -50,7 +50,7 @@ export default async function runHooksFor(key, dream, alreadyPersisted, beforeSa
|
|
|
50
50
|
if (txn)
|
|
51
51
|
txn.addCommitHook(hook, dream);
|
|
52
52
|
else
|
|
53
|
-
await
|
|
53
|
+
await runCommitHook(hook, dream);
|
|
54
54
|
}
|
|
55
55
|
break;
|
|
56
56
|
case 'afterUpdate':
|
|
@@ -63,7 +63,7 @@ export default async function runHooksFor(key, dream, alreadyPersisted, beforeSa
|
|
|
63
63
|
if (txn)
|
|
64
64
|
txn.addCommitHook(hook, dream);
|
|
65
65
|
else
|
|
66
|
-
await
|
|
66
|
+
await runCommitHook(hook, dream);
|
|
67
67
|
}
|
|
68
68
|
break;
|
|
69
69
|
default:
|
|
@@ -79,7 +79,7 @@ export default async function runHooksFor(key, dream, alreadyPersisted, beforeSa
|
|
|
79
79
|
if (txn)
|
|
80
80
|
txn.addCommitHook(hook, dream);
|
|
81
81
|
else
|
|
82
|
-
await
|
|
82
|
+
await runCommitHook(hook, dream);
|
|
83
83
|
break;
|
|
84
84
|
default:
|
|
85
85
|
await runHook(hook, dream, txn);
|
|
@@ -88,6 +88,18 @@ export default async function runHooksFor(key, dream, alreadyPersisted, beforeSa
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
export async function runHook(statement, dream, txn) {
|
|
91
|
+
assertHookMethodExists(statement, dream);
|
|
92
|
+
await dream[statement.method](txn);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Commit hooks run after the transaction has committed, so they are called
|
|
96
|
+
* with no argument.
|
|
97
|
+
*/
|
|
98
|
+
export async function runCommitHook(statement, dream) {
|
|
99
|
+
assertHookMethodExists(statement, dream);
|
|
100
|
+
await dream[statement.method]();
|
|
101
|
+
}
|
|
102
|
+
function assertHookMethodExists(statement, dream) {
|
|
91
103
|
if (typeof dream[statement.method] !== 'function') {
|
|
92
104
|
throw new Error(`
|
|
93
105
|
Attempting to run ${statement.method} as part of the ${statement.type}
|
|
@@ -96,7 +108,6 @@ Dream model hook sequence, but we encountered a method that does not exist.
|
|
|
96
108
|
Please make sure "${statement.method}" is defined on ${dream['sanitizedConstructorName']}
|
|
97
109
|
`);
|
|
98
110
|
}
|
|
99
|
-
await dream[statement.method](txn);
|
|
100
111
|
}
|
|
101
112
|
function shouldRunBeforeCreateHook(dream, statement) {
|
|
102
113
|
let shouldRun = false;
|
|
@@ -22,7 +22,8 @@ export const MAX_CONCURRENT_WRITER_ATTEMPTS = 3;
|
|
|
22
22
|
* rows mid-statement as well. Either way the database has undone the whole
|
|
23
23
|
* transaction, nothing has committed and no commit hook has run, so running
|
|
24
24
|
* the operation again reads the rows as the other writer left them. The last
|
|
25
|
-
* attempt's error is the adapter's own.
|
|
25
|
+
* attempt's error is the adapter's own. An error raised after COMMIT, such as a
|
|
26
|
+
* commit hook's, is never retried.
|
|
26
27
|
*
|
|
27
28
|
* A unique violation raised by a statement inside the callback is not a
|
|
28
29
|
* collision but a write that violates a constraint outright, and is not
|
|
@@ -46,15 +47,19 @@ export const MAX_CONCURRENT_WRITER_ATTEMPTS = 3;
|
|
|
46
47
|
export default async function withConcurrentWriterRetry(dreamClass, callback) {
|
|
47
48
|
const queryDriverClass = DreamApp.getOrFail().dbConnectionQueryDriverClass(dreamClass.prototype.connectionName);
|
|
48
49
|
for (let attempt = 1;; attempt++) {
|
|
50
|
+
let attemptTransaction = null;
|
|
49
51
|
let callbackResolved = false;
|
|
50
52
|
try {
|
|
51
53
|
return await dreamClass.transaction(async (txn) => {
|
|
54
|
+
attemptTransaction = txn;
|
|
52
55
|
const result = await callback(txn);
|
|
53
56
|
callbackResolved = true;
|
|
54
57
|
return result;
|
|
55
58
|
});
|
|
56
59
|
}
|
|
57
60
|
catch (error) {
|
|
61
|
+
if (attemptTransaction?.['committed'])
|
|
62
|
+
throw error;
|
|
58
63
|
const undoneByConcurrentWriter = queryDriverClass.isDeadlock(error) ||
|
|
59
64
|
(callbackResolved && queryDriverClass.isUniqueConstraintViolation(error));
|
|
60
65
|
if (!undoneByConcurrentWriter || attempt === MAX_CONCURRENT_WRITER_ATTEMPTS)
|
|
@@ -2312,6 +2312,10 @@ export default class Dream {
|
|
|
2312
2312
|
* being persisted to the database, with the values
|
|
2313
2313
|
* that were last persisted to the database.
|
|
2314
2314
|
*
|
|
2315
|
+
* On a record that has not been persisted, every
|
|
2316
|
+
* column counts as changed: the object has a key
|
|
2317
|
+
* for every column.
|
|
2318
|
+
*
|
|
2315
2319
|
* ```ts
|
|
2316
2320
|
* const user = User.new({ email: 'original@email', password: 'howyadoin' })
|
|
2317
2321
|
* await user.save()
|
|
@@ -2421,6 +2425,10 @@ export default class Dream {
|
|
|
2421
2425
|
* Returns true if the columnName provided has
|
|
2422
2426
|
* changes that have not yet been persisted.
|
|
2423
2427
|
*
|
|
2428
|
+
* On a record that has not been persisted, every
|
|
2429
|
+
* column counts as changed, so this returns true
|
|
2430
|
+
* for every column, whether or not it was assigned.
|
|
2431
|
+
*
|
|
2424
2432
|
* @param attribute - the column name to check
|
|
2425
2433
|
* @returns A boolean
|
|
2426
2434
|
*/
|
|
@@ -2436,10 +2444,15 @@ export default class Dream {
|
|
|
2436
2444
|
* of columns that have changed since last persist,
|
|
2437
2445
|
* and their current values.
|
|
2438
2446
|
*
|
|
2447
|
+
* On a record that has not been persisted, every
|
|
2448
|
+
* column counts as changed: the object has a key
|
|
2449
|
+
* for every column, including those never assigned,
|
|
2450
|
+
* whose value is `undefined`.
|
|
2451
|
+
*
|
|
2439
2452
|
* ```ts
|
|
2440
2453
|
* const user = User.new({ email: 'hello@world' })
|
|
2441
2454
|
* user.dirtyAttributes()
|
|
2442
|
-
* // { email: 'hello@world' }
|
|
2455
|
+
* // { id: undefined, email: 'hello@world', name: undefined, ...every other column: undefined }
|
|
2443
2456
|
*
|
|
2444
2457
|
* await user.save()
|
|
2445
2458
|
*
|
|
@@ -399,9 +399,14 @@ export default class Decorators<TD extends typeof Dream, T extends Dream = Insta
|
|
|
399
399
|
* }
|
|
400
400
|
* ```
|
|
401
401
|
*
|
|
402
|
+
* The decorated method is called with no argument, once the
|
|
403
|
+
* transaction has committed, so declaring a parameter on it is a
|
|
404
|
+
* compile error. A subclass override of the method that is not itself
|
|
405
|
+
* decorated is not checked; it is still called with no argument.
|
|
406
|
+
*
|
|
402
407
|
* @returns The AfterCreateCommit decorator
|
|
403
408
|
*/
|
|
404
|
-
AfterCreateCommit(this: Decorators<TD>, opts?: AfterHookOpts<T>):
|
|
409
|
+
AfterCreateCommit(this: Decorators<TD>, opts?: AfterHookOpts<T>): import("../types/lifecycle.js").CommitHookDecorator;
|
|
405
410
|
/**
|
|
406
411
|
* AfterSave decorator
|
|
407
412
|
*
|
|
@@ -430,10 +435,15 @@ export default class Decorators<TD extends typeof Dream, T extends Dream = Insta
|
|
|
430
435
|
* }
|
|
431
436
|
* ```
|
|
432
437
|
*
|
|
438
|
+
* The decorated method is called with no argument, once the
|
|
439
|
+
* transaction has committed, so declaring a parameter on it is a
|
|
440
|
+
* compile error. A subclass override of the method that is not itself
|
|
441
|
+
* decorated is not checked; it is still called with no argument.
|
|
442
|
+
*
|
|
433
443
|
* @returns The AfterSaveCommit decorator
|
|
434
444
|
*
|
|
435
445
|
*/
|
|
436
|
-
AfterSaveCommit(this: Decorators<TD>, opts?: AfterHookOpts<T>):
|
|
446
|
+
AfterSaveCommit(this: Decorators<TD>, opts?: AfterHookOpts<T>): import("../types/lifecycle.js").CommitHookDecorator;
|
|
437
447
|
/**
|
|
438
448
|
* AfterUpdate decorator
|
|
439
449
|
*
|
|
@@ -462,10 +472,15 @@ export default class Decorators<TD extends typeof Dream, T extends Dream = Insta
|
|
|
462
472
|
* }
|
|
463
473
|
* ```
|
|
464
474
|
*
|
|
475
|
+
* The decorated method is called with no argument, once the
|
|
476
|
+
* transaction has committed, so declaring a parameter on it is a
|
|
477
|
+
* compile error. A subclass override of the method that is not itself
|
|
478
|
+
* decorated is not checked; it is still called with no argument.
|
|
479
|
+
*
|
|
465
480
|
* @returns The AfterUpdateCommit decorator
|
|
466
481
|
*
|
|
467
482
|
*/
|
|
468
|
-
AfterUpdateCommit(this: Decorators<TD>, opts?: AfterHookOpts<T>):
|
|
483
|
+
AfterUpdateCommit(this: Decorators<TD>, opts?: AfterHookOpts<T>): import("../types/lifecycle.js").CommitHookDecorator;
|
|
469
484
|
/**
|
|
470
485
|
* AfterDestroy decorator
|
|
471
486
|
*
|
|
@@ -494,8 +509,13 @@ export default class Decorators<TD extends typeof Dream, T extends Dream = Insta
|
|
|
494
509
|
* }
|
|
495
510
|
* ```
|
|
496
511
|
*
|
|
512
|
+
* The decorated method is called with no argument, once the
|
|
513
|
+
* transaction has committed, so declaring a parameter on it is a
|
|
514
|
+
* compile error. A subclass override of the method that is not itself
|
|
515
|
+
* decorated is not checked; it is still called with no argument.
|
|
516
|
+
*
|
|
497
517
|
* @returns The AfterDestroyCommit decorator
|
|
498
518
|
*
|
|
499
519
|
*/
|
|
500
|
-
AfterDestroyCommit(this: Decorators<TD>):
|
|
520
|
+
AfterDestroyCommit(this: Decorators<TD>): import("../types/lifecycle.js").CommitHookDecorator;
|
|
501
521
|
}
|