@rvoh/dream 0.40.4 → 0.40.6
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 +64 -12
- package/dist/cjs/src/dream/DreamClassTransactionBuilder.js +46 -6
- package/dist/cjs/src/dream/DreamInstanceTransactionBuilder.js +2 -2
- package/dist/cjs/src/dream/LeftJoinLoadBuilder.js +3 -3
- package/dist/cjs/src/dream/LoadBuilder.js +3 -3
- package/dist/cjs/src/dream/internal/associations/createAssociation.js +1 -6
- package/dist/cjs/src/dream/internal/destroyDream.js +1 -1
- package/dist/cjs/src/dream/internal/findOrCreateBy.js +16 -0
- package/dist/cjs/src/dream/internal/runHooksFor.js +4 -4
- package/dist/cjs/src/dream/internal/saveDream.js +1 -1
- package/dist/cjs/src/dream/internal/updateOrCreateBy.js +18 -0
- package/dist/cjs/src/errors/CreateOrUpdateByFailedToCreateAndUpdate.js +18 -0
- package/dist/esm/src/Dream.js +64 -12
- package/dist/esm/src/dream/DreamClassTransactionBuilder.js +46 -6
- package/dist/esm/src/dream/DreamInstanceTransactionBuilder.js +2 -2
- package/dist/esm/src/dream/LeftJoinLoadBuilder.js +3 -3
- package/dist/esm/src/dream/LoadBuilder.js +3 -3
- package/dist/esm/src/dream/internal/associations/createAssociation.js +1 -6
- package/dist/esm/src/dream/internal/destroyDream.js +1 -1
- package/dist/esm/src/dream/internal/findOrCreateBy.js +13 -0
- package/dist/esm/src/dream/internal/runHooksFor.js +4 -4
- package/dist/esm/src/dream/internal/saveDream.js +1 -1
- package/dist/esm/src/dream/internal/updateOrCreateBy.js +15 -0
- package/dist/esm/src/errors/CreateOrUpdateByFailedToCreateAndUpdate.js +15 -0
- package/dist/types/src/Dream.d.ts +42 -9
- package/dist/types/src/dream/DreamClassTransactionBuilder.d.ts +72 -37
- package/dist/types/src/dream/DreamInstanceTransactionBuilder.d.ts +3 -3
- package/dist/types/src/dream/LeftJoinLoadBuilder.d.ts +2 -2
- package/dist/types/src/dream/LoadBuilder.d.ts +2 -2
- package/dist/types/src/dream/Query.d.ts +1 -1
- package/dist/types/src/dream/internal/findOrCreateBy.d.ts +4 -0
- package/dist/types/src/dream/internal/runHooksFor.d.ts +2 -2
- package/dist/types/src/dream/internal/updateOrCreateBy.d.ts +4 -0
- package/dist/types/src/errors/CreateOrUpdateByFailedToCreateAndUpdate.d.ts +6 -0
- package/dist/types/src/types/dream.d.ts +7 -0
- package/dist/types/src/types/dream.ts +9 -0
- package/docs/assets/search.js +1 -1
- package/docs/classes/Benchmark.html +2 -2
- package/docs/classes/CalendarDate.html +2 -2
- package/docs/classes/CreateOrFindByFailedToCreateAndFind.html +3 -3
- package/docs/classes/Decorators.html +19 -19
- package/docs/classes/Dream.html +205 -185
- package/docs/classes/DreamApp.html +4 -4
- package/docs/classes/DreamBin.html +2 -2
- package/docs/classes/DreamCLI.html +4 -4
- package/docs/classes/DreamImporter.html +2 -2
- package/docs/classes/DreamLogos.html +2 -2
- package/docs/classes/DreamMigrationHelpers.html +7 -7
- package/docs/classes/DreamSerializer.html +2 -2
- package/docs/classes/DreamTransaction.html +2 -2
- package/docs/classes/Encrypt.html +2 -2
- package/docs/classes/Env.html +2 -2
- package/docs/classes/GlobalNameNotSet.html +3 -3
- package/docs/classes/NonLoadedAssociation.html +3 -3
- package/docs/classes/Query.html +51 -51
- package/docs/classes/Range.html +2 -2
- package/docs/classes/RecordNotFound.html +3 -3
- package/docs/classes/ValidationError.html +3 -3
- package/docs/functions/Attribute.html +1 -1
- package/docs/functions/RendersMany.html +1 -1
- package/docs/functions/RendersOne.html +1 -1
- package/docs/functions/ReplicaSafe.html +1 -1
- package/docs/functions/STI.html +1 -1
- package/docs/functions/SoftDelete.html +1 -1
- package/docs/functions/camelize.html +1 -1
- package/docs/functions/capitalize.html +1 -1
- package/docs/functions/closeAllDbConnections.html +1 -1
- package/docs/functions/compact.html +1 -1
- package/docs/functions/dreamDbConnections.html +1 -1
- package/docs/functions/dreamPath.html +1 -1
- package/docs/functions/generateDream.html +1 -1
- package/docs/functions/globalClassNameFromFullyQualifiedModelName.html +1 -1
- package/docs/functions/hyphenize.html +1 -1
- package/docs/functions/inferSerializerFromDreamClassOrViewModelClass.html +1 -1
- package/docs/functions/inferSerializerFromDreamOrViewModel.html +1 -1
- package/docs/functions/isEmpty.html +1 -1
- package/docs/functions/loadRepl.html +1 -1
- package/docs/functions/lookupClassByGlobalName.html +1 -1
- package/docs/functions/pascalize.html +1 -1
- package/docs/functions/pgErrorType.html +1 -1
- package/docs/functions/range-1.html +1 -1
- package/docs/functions/relativeDreamPath.html +1 -1
- package/docs/functions/round.html +1 -1
- package/docs/functions/serializerNameFromFullyQualifiedModelName.html +1 -1
- package/docs/functions/sharedPathPrefix.html +1 -1
- package/docs/functions/snakeify.html +1 -1
- package/docs/functions/sort.html +1 -1
- package/docs/functions/sortBy.html +1 -1
- package/docs/functions/standardizeFullyQualifiedModelName.html +1 -1
- package/docs/functions/uncapitalize.html +1 -1
- package/docs/functions/uniq.html +1 -1
- package/docs/functions/untypedDb.html +1 -1
- package/docs/functions/validateColumn.html +1 -1
- package/docs/functions/validateTable.html +1 -1
- package/docs/interfaces/AttributeStatement.html +2 -2
- package/docs/interfaces/DecoratorContext.html +2 -2
- package/docs/interfaces/DreamAppInitOptions.html +2 -2
- package/docs/interfaces/DreamAppOpts.html +2 -2
- package/docs/interfaces/DreamSerializerAssociationStatement.html +2 -2
- package/docs/interfaces/EncryptOptions.html +2 -2
- package/docs/interfaces/OpenapiSchemaProperties.html +1 -1
- package/docs/interfaces/OpenapiSchemaPropertiesShorthand.html +1 -1
- package/docs/interfaces/OpenapiTypeFieldObject.html +1 -1
- package/docs/types/Camelized.html +1 -1
- package/docs/types/CommonOpenapiSchemaObjectFields.html +1 -1
- package/docs/types/DateTime.html +1 -1
- package/docs/types/DbConnectionType.html +1 -1
- package/docs/types/DreamAssociationMetadata.html +1 -1
- package/docs/types/DreamAttributes.html +1 -1
- package/docs/types/DreamClassColumn.html +1 -1
- package/docs/types/DreamColumn.html +1 -1
- package/docs/types/DreamColumnNames.html +1 -1
- package/docs/types/DreamLogLevel.html +1 -1
- package/docs/types/DreamLogger.html +1 -1
- package/docs/types/DreamOrViewModelSerializerKey.html +1 -1
- package/docs/types/DreamParamSafeAttributes.html +1 -1
- package/docs/types/DreamParamSafeColumnNames.html +1 -1
- package/docs/types/DreamSerializerKey.html +1 -1
- package/docs/types/DreamSerializers.html +1 -1
- package/docs/types/DreamTableSchema.html +1 -1
- package/docs/types/DreamVirtualColumns.html +1 -1
- package/docs/types/EncryptAlgorithm.html +1 -1
- package/docs/types/Hyphenized.html +1 -1
- package/docs/types/IdType.html +1 -1
- package/docs/types/OpenapiAllTypes.html +1 -1
- package/docs/types/OpenapiFormats.html +1 -1
- package/docs/types/OpenapiNumberFormats.html +1 -1
- package/docs/types/OpenapiPrimitiveTypes.html +1 -1
- package/docs/types/OpenapiSchemaArray.html +1 -1
- package/docs/types/OpenapiSchemaArrayShorthand.html +1 -1
- package/docs/types/OpenapiSchemaBase.html +1 -1
- package/docs/types/OpenapiSchemaBody.html +1 -1
- package/docs/types/OpenapiSchemaBodyShorthand.html +1 -1
- package/docs/types/OpenapiSchemaCommonFields.html +1 -1
- package/docs/types/OpenapiSchemaExpressionAllOf.html +1 -1
- package/docs/types/OpenapiSchemaExpressionAnyOf.html +1 -1
- package/docs/types/OpenapiSchemaExpressionOneOf.html +1 -1
- package/docs/types/OpenapiSchemaExpressionRef.html +1 -1
- package/docs/types/OpenapiSchemaExpressionRefSchemaShorthand.html +1 -1
- package/docs/types/OpenapiSchemaInteger.html +1 -1
- package/docs/types/OpenapiSchemaNull.html +1 -1
- package/docs/types/OpenapiSchemaNumber.html +1 -1
- package/docs/types/OpenapiSchemaObject.html +1 -1
- package/docs/types/OpenapiSchemaObjectAllOf.html +1 -1
- package/docs/types/OpenapiSchemaObjectAllOfShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectAnyOf.html +1 -1
- package/docs/types/OpenapiSchemaObjectAnyOfShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectBase.html +1 -1
- package/docs/types/OpenapiSchemaObjectBaseShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectOneOf.html +1 -1
- package/docs/types/OpenapiSchemaObjectOneOfShorthand.html +1 -1
- package/docs/types/OpenapiSchemaObjectShorthand.html +1 -1
- package/docs/types/OpenapiSchemaPrimitiveGeneric.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionAllOf.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionAnyOf.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionOneOf.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionSerializableRef.html +1 -1
- package/docs/types/OpenapiSchemaShorthandExpressionSerializerRef.html +1 -1
- package/docs/types/OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
- package/docs/types/OpenapiSchemaString.html +1 -1
- package/docs/types/OpenapiShorthandAllTypes.html +1 -1
- package/docs/types/OpenapiShorthandPrimitiveTypes.html +1 -1
- package/docs/types/OpenapiTypeField.html +1 -1
- package/docs/types/Pascalized.html +1 -1
- package/docs/types/PrimaryKeyType.html +1 -1
- package/docs/types/RoundingPrecision.html +1 -1
- package/docs/types/SerializableClassOrSerializerCallback.html +1 -1
- package/docs/types/SerializableDreamClassOrViewModelClass.html +1 -1
- package/docs/types/SerializableDreamOrViewModel.html +1 -1
- package/docs/types/SerializableTypes.html +1 -1
- package/docs/types/Snakeified.html +1 -1
- package/docs/types/Timestamp.html +1 -1
- package/docs/types/UpdateableAssociationProperties.html +1 -1
- package/docs/types/UpdateableProperties.html +1 -1
- package/docs/types/ValidationType.html +1 -1
- package/docs/types/ViewModelSerializerKey.html +1 -1
- package/docs/types/WhereStatementForDream.html +1 -1
- package/docs/types/WhereStatementForDreamClass.html +1 -1
- package/docs/variables/DateTime-1.html +1 -1
- package/docs/variables/DreamConst.html +1 -1
- package/docs/variables/TRIGRAM_OPERATORS.html +1 -1
- package/docs/variables/openapiPrimitiveTypes-1.html +1 -1
- package/docs/variables/openapiShorthandPrimitiveTypes-1.html +1 -1
- package/docs/variables/ops.html +1 -1
- package/docs/variables/primaryKeyTypes.html +1 -1
- package/package.json +1 -1
package/dist/cjs/src/Dream.js
CHANGED
|
@@ -18,11 +18,13 @@ const destroyDream_js_1 = require("./dream/internal/destroyDream.js");
|
|
|
18
18
|
const destroyOptions_js_1 = require("./dream/internal/destroyOptions.js");
|
|
19
19
|
const ensureSTITypeFieldIsSet_js_1 = require("./dream/internal/ensureSTITypeFieldIsSet.js");
|
|
20
20
|
const extractAssociationMetadataFromAssociationName_js_1 = require("./dream/internal/extractAssociationMetadataFromAssociationName.js");
|
|
21
|
+
const findOrCreateBy_js_1 = require("./dream/internal/findOrCreateBy.js");
|
|
21
22
|
const reload_js_1 = require("./dream/internal/reload.js");
|
|
22
23
|
const runValidations_js_1 = require("./dream/internal/runValidations.js");
|
|
23
24
|
const saveDream_js_1 = require("./dream/internal/saveDream.js");
|
|
24
25
|
const scopeHelpers_js_1 = require("./dream/internal/scopeHelpers.js");
|
|
25
26
|
const undestroyDream_js_1 = require("./dream/internal/undestroyDream.js");
|
|
27
|
+
const updateOrCreateBy_js_1 = require("./dream/internal/updateOrCreateBy.js");
|
|
26
28
|
const LeftJoinLoadBuilder_js_1 = require("./dream/LeftJoinLoadBuilder.js");
|
|
27
29
|
const LoadBuilder_js_1 = require("./dream/LoadBuilder.js");
|
|
28
30
|
const Query_js_1 = require("./dream/Query.js");
|
|
@@ -36,6 +38,7 @@ const NonLoadedAssociation_js_1 = require("./errors/associations/NonLoadedAssoci
|
|
|
36
38
|
const CannotCallUndestroyOnANonSoftDeleteModel_js_1 = require("./errors/CannotCallUndestroyOnANonSoftDeleteModel.js");
|
|
37
39
|
const ConstructorOnlyForInternalUse_js_1 = require("./errors/ConstructorOnlyForInternalUse.js");
|
|
38
40
|
const CreateOrFindByFailedToCreateAndFind_js_1 = require("./errors/CreateOrFindByFailedToCreateAndFind.js");
|
|
41
|
+
const CreateOrUpdateByFailedToCreateAndUpdate_js_1 = require("./errors/CreateOrUpdateByFailedToCreateAndUpdate.js");
|
|
39
42
|
const GlobalNameNotSet_js_1 = require("./errors/dream-app/GlobalNameNotSet.js");
|
|
40
43
|
const DreamMissingRequiredOverride_js_1 = require("./errors/DreamMissingRequiredOverride.js");
|
|
41
44
|
const MissingSerializersDefinition_js_1 = require("./errors/MissingSerializersDefinition.js");
|
|
@@ -656,11 +659,12 @@ class Dream {
|
|
|
656
659
|
* ```
|
|
657
660
|
*
|
|
658
661
|
* @param attributes - attributes or belongs to associations you wish to set on this model before persisting
|
|
662
|
+
* @param opts.skipHooks - if true, will skip applying model hooks. Defaults to false
|
|
659
663
|
* @returns A newly persisted dream instance
|
|
660
664
|
*/
|
|
661
|
-
static async create(attributes) {
|
|
665
|
+
static async create(attributes, { skipHooks } = {}) {
|
|
662
666
|
const dreamModel = this.new(attributes);
|
|
663
|
-
await dreamModel.save();
|
|
667
|
+
await dreamModel.save(skipHooks ? { skipHooks } : undefined);
|
|
664
668
|
return dreamModel;
|
|
665
669
|
}
|
|
666
670
|
/**
|
|
@@ -701,6 +705,62 @@ class Dream {
|
|
|
701
705
|
throw err;
|
|
702
706
|
}
|
|
703
707
|
}
|
|
708
|
+
/**
|
|
709
|
+
* Attempt to update the model with the given attributes.
|
|
710
|
+
* If no record is found, then a new record is created.
|
|
711
|
+
* All lifecycle hooks are run for whichever action is taken.
|
|
712
|
+
*
|
|
713
|
+
* ```ts
|
|
714
|
+
* const user = await User.updateOrCreateBy({ email }, { with: { name: 'Alice' })
|
|
715
|
+
* ```
|
|
716
|
+
*
|
|
717
|
+
* @param attributes - The base attributes for finding which record to update, also used when creating
|
|
718
|
+
* @param extraOpts.with - additional attributes to persist when updating and creating, but not used for finding
|
|
719
|
+
* @param extraOpts.skipHooks - if true, will skip applying model hooks. Defaults to false
|
|
720
|
+
* @returns A dream instance
|
|
721
|
+
*/
|
|
722
|
+
static async updateOrCreateBy(attributes, extraOpts = {}) {
|
|
723
|
+
return await (0, updateOrCreateBy_js_1.default)(this, null, attributes, extraOpts);
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Attempt to create the model with the given attributes.
|
|
727
|
+
* If creation fails due to uniqueness constraint, then find and update
|
|
728
|
+
* the existing model. All lifecycle hooks are run for whichever
|
|
729
|
+
* action is taken.
|
|
730
|
+
*
|
|
731
|
+
* This is useful in situations where we want to avoid
|
|
732
|
+
* a race condition creating duplicate records.
|
|
733
|
+
*
|
|
734
|
+
* IMPORTANT: A unique index/uniqueness constraint must exist on
|
|
735
|
+
* at least one of the provided attributes
|
|
736
|
+
*
|
|
737
|
+
* @param attributes - The base attributes for finding which record to update, also used when creating
|
|
738
|
+
* @param extraOpts.with - additional attributes to persist when updating and creating, but not used for finding
|
|
739
|
+
* @param extraOpts.skipHooks - if true, will skip applying model hooks. Defaults to false
|
|
740
|
+
* @returns A dream instance
|
|
741
|
+
*/
|
|
742
|
+
static async createOrUpdateBy(attributes, extraOpts = {}) {
|
|
743
|
+
const { skipHooks } = extraOpts;
|
|
744
|
+
try {
|
|
745
|
+
return await this.create({
|
|
746
|
+
...attributes,
|
|
747
|
+
...(extraOpts?.with || {}),
|
|
748
|
+
}, skipHooks ? { skipHooks } : undefined);
|
|
749
|
+
}
|
|
750
|
+
catch (err) {
|
|
751
|
+
if ((0, errors_js_1.pgErrorType)(err) === 'UNIQUE_CONSTRAINT_VIOLATION') {
|
|
752
|
+
const existingRecord = await this.findBy(this.extractAttributesFromUpdateableProperties(attributes));
|
|
753
|
+
if (!existingRecord)
|
|
754
|
+
throw new CreateOrUpdateByFailedToCreateAndUpdate_js_1.default(this);
|
|
755
|
+
const { with: attrs } = extraOpts;
|
|
756
|
+
if (existingRecord) {
|
|
757
|
+
existingRecord.assignAttributes(attrs ?? {});
|
|
758
|
+
return await (0, saveDream_js_1.default)(existingRecord, null, skipHooks ? { skipHooks } : undefined);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
throw err;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
704
764
|
/**
|
|
705
765
|
* Returns a new query instance with the distinct query applied.
|
|
706
766
|
* If no columnName is provided, then distinct will apply to the
|
|
@@ -852,15 +912,7 @@ class Dream {
|
|
|
852
912
|
* @returns A dream instance
|
|
853
913
|
*/
|
|
854
914
|
static async findOrCreateBy(attributes, extraOpts = {}) {
|
|
855
|
-
|
|
856
|
-
if (existingRecord)
|
|
857
|
-
return existingRecord;
|
|
858
|
-
const dreamModel = this.new({
|
|
859
|
-
...attributes,
|
|
860
|
-
...(extraOpts?.createWith || {}),
|
|
861
|
-
});
|
|
862
|
-
await dreamModel.save();
|
|
863
|
-
return dreamModel;
|
|
915
|
+
return await (0, findOrCreateBy_js_1.default)(this, null, attributes, extraOpts);
|
|
864
916
|
}
|
|
865
917
|
/**
|
|
866
918
|
* Returns true if a record exists for the given
|
|
@@ -1254,7 +1306,7 @@ class Dream {
|
|
|
1254
1306
|
* @returns A Query scoped to this model with the transaction applied
|
|
1255
1307
|
*/
|
|
1256
1308
|
static txn(txn) {
|
|
1257
|
-
return new DreamClassTransactionBuilder_js_1.default(this
|
|
1309
|
+
return new DreamClassTransactionBuilder_js_1.default(this, txn);
|
|
1258
1310
|
}
|
|
1259
1311
|
/**
|
|
1260
1312
|
* Builds a new DreamTransaction instance, provides
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const findOrCreateBy_js_1 = require("./internal/findOrCreateBy.js");
|
|
3
4
|
const saveDream_js_1 = require("./internal/saveDream.js");
|
|
5
|
+
const updateOrCreateBy_js_1 = require("./internal/updateOrCreateBy.js");
|
|
4
6
|
const Query_js_1 = require("./Query.js");
|
|
5
7
|
class DreamClassTransactionBuilder {
|
|
6
|
-
|
|
8
|
+
dreamClass;
|
|
7
9
|
dreamTransaction;
|
|
10
|
+
dreamInstance;
|
|
8
11
|
/**
|
|
9
12
|
* Constructs a new DreamClassTransactionBuilder.
|
|
10
13
|
*
|
|
11
14
|
* @param dreamInstance - The Dream instance to build the transaction for
|
|
12
15
|
* @param txn - The DreamTransaction instance
|
|
13
16
|
*/
|
|
14
|
-
constructor(
|
|
15
|
-
this.
|
|
17
|
+
constructor(dreamClass, dreamTransaction) {
|
|
18
|
+
this.dreamClass = dreamClass;
|
|
16
19
|
this.dreamTransaction = dreamTransaction;
|
|
20
|
+
this.dreamInstance = dreamClass.prototype;
|
|
17
21
|
}
|
|
18
22
|
/**
|
|
19
23
|
* Retrieves an array containing all records corresponding to
|
|
@@ -122,9 +126,9 @@ class DreamClassTransactionBuilder {
|
|
|
122
126
|
* @param attributes - Attributes or belongs to associations you wish to set on this model before persisting
|
|
123
127
|
* @returns A newly persisted dream instance
|
|
124
128
|
*/
|
|
125
|
-
async create(attributes) {
|
|
126
|
-
const dream = this.
|
|
127
|
-
return (0, saveDream_js_1.default)(dream, this.dreamTransaction);
|
|
129
|
+
async create(attributes, { skipHooks } = {}) {
|
|
130
|
+
const dream = this.dreamClass.new(attributes);
|
|
131
|
+
return (0, saveDream_js_1.default)(dream, this.dreamTransaction, skipHooks ? { skipHooks } : undefined);
|
|
128
132
|
}
|
|
129
133
|
/**
|
|
130
134
|
* Finds a record for the corresponding model with the
|
|
@@ -196,6 +200,42 @@ class DreamClassTransactionBuilder {
|
|
|
196
200
|
async findOrFailBy(whereStatement) {
|
|
197
201
|
return await this.queryInstance().findOrFailBy(whereStatement);
|
|
198
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* Attempt to find the model with the given attributes.
|
|
205
|
+
* If no record is found, then a new record is created.
|
|
206
|
+
*
|
|
207
|
+
* ```ts
|
|
208
|
+
* await ApplicationModel.transaction(async txn => {
|
|
209
|
+
* await User.txn(txn).findOrCreateBy({ email }, { createWith: params })
|
|
210
|
+
* })
|
|
211
|
+
* ```
|
|
212
|
+
*
|
|
213
|
+
* @param attributes - The base attributes for finding, but also the attributes to use when creating
|
|
214
|
+
* @param extraOpts.createWith - additional attributes to persist when creating, but not used for finding
|
|
215
|
+
* @returns A dream instance
|
|
216
|
+
*/
|
|
217
|
+
async findOrCreateBy(attributes, extraOpts = {}) {
|
|
218
|
+
return await (0, findOrCreateBy_js_1.default)(this.dreamClass, this.dreamTransaction, attributes, extraOpts);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Attempt to update the model with the given attributes.
|
|
222
|
+
* If no record is found, then a new record is created.
|
|
223
|
+
* All lifecycle hooks are run for whichever action is taken.
|
|
224
|
+
*
|
|
225
|
+
* ```ts
|
|
226
|
+
* await ApplicationModel.transaction(async txn => {
|
|
227
|
+
* await User.txn(txn).updateOrCreateBy({ email }, { with: { name: 'Alice' })
|
|
228
|
+
* })
|
|
229
|
+
* ```
|
|
230
|
+
*
|
|
231
|
+
* @param attributes - The base attributes for finding, but also the attributes to use when creating
|
|
232
|
+
* @param extraOpts.with - additional attributes to persist when updating and creating, but not used for finding
|
|
233
|
+
* @param extraOpts.skipHooks - if true, will skip applying model hooks. Defaults to false
|
|
234
|
+
* @returns A dream instance
|
|
235
|
+
*/
|
|
236
|
+
async updateOrCreateBy(attributes, extraOpts = {}) {
|
|
237
|
+
return await (0, updateOrCreateBy_js_1.default)(this.dreamClass, this.dreamTransaction, attributes, extraOpts);
|
|
238
|
+
}
|
|
199
239
|
/**
|
|
200
240
|
* Finds all records for the corresponding model in batches,
|
|
201
241
|
* and then calls the provided callback for each found record.
|
|
@@ -26,9 +26,9 @@ class DreamInstanceTransactionBuilder {
|
|
|
26
26
|
* @param dreamInstance - The Dream instance to build the transaction for
|
|
27
27
|
* @param txn - The DreamTransaction instance
|
|
28
28
|
*/
|
|
29
|
-
constructor(dreamInstance,
|
|
29
|
+
constructor(dreamInstance, dreamTransaction) {
|
|
30
30
|
this.dreamInstance = dreamInstance;
|
|
31
|
-
this.dreamTransaction =
|
|
31
|
+
this.dreamTransaction = dreamTransaction;
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
34
|
* Loads the requested associations upon execution
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const UnexpectedUndefined_js_1 = require("../errors/UnexpectedUndefined.js");
|
|
4
4
|
class LeftJoinLoadBuilder {
|
|
5
|
-
dream;
|
|
6
5
|
dreamTransaction;
|
|
6
|
+
dream;
|
|
7
7
|
query;
|
|
8
8
|
/**
|
|
9
9
|
* An intermediate class on the way to executing a load
|
|
@@ -15,7 +15,8 @@ class LeftJoinLoadBuilder {
|
|
|
15
15
|
* await user.load('settings').execute()
|
|
16
16
|
* ```
|
|
17
17
|
*/
|
|
18
|
-
constructor(dream,
|
|
18
|
+
constructor(dream, dreamTransaction) {
|
|
19
|
+
this.dreamTransaction = dreamTransaction;
|
|
19
20
|
this.dream = dream['clone']();
|
|
20
21
|
// Load queries start from the table corresponding to an instance
|
|
21
22
|
// of a Dream. However, the Dream may have default scopes that would
|
|
@@ -24,7 +25,6 @@ class LeftJoinLoadBuilder {
|
|
|
24
25
|
// to other associations (thus the use of `removeAllDefaultScopesExceptOnAssociations`
|
|
25
26
|
// instead of `removeAllDefaultScopes`).
|
|
26
27
|
this.query = this.dream.query()['removeAllDefaultScopesExceptOnAssociations']();
|
|
27
|
-
this.dreamTransaction = txn;
|
|
28
28
|
}
|
|
29
29
|
passthrough(passthroughWhereStatement) {
|
|
30
30
|
this.query = this.query.passthrough(passthroughWhereStatement);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
class LoadBuilder {
|
|
4
|
-
dream;
|
|
5
4
|
dreamTransaction;
|
|
5
|
+
dream;
|
|
6
6
|
query;
|
|
7
7
|
/**
|
|
8
8
|
* An intermediate class on the way to executing a load
|
|
@@ -14,7 +14,8 @@ class LoadBuilder {
|
|
|
14
14
|
* await user.load('settings').execute()
|
|
15
15
|
* ```
|
|
16
16
|
*/
|
|
17
|
-
constructor(dream,
|
|
17
|
+
constructor(dream, dreamTransaction) {
|
|
18
|
+
this.dreamTransaction = dreamTransaction;
|
|
18
19
|
this.dream = dream['clone']();
|
|
19
20
|
// Load queries start from the table corresponding to an instance
|
|
20
21
|
// of a Dream. However, the Dream may have default scopes that would
|
|
@@ -23,7 +24,6 @@ class LoadBuilder {
|
|
|
23
24
|
// to other associations (thus the use of `removeAllDefaultScopesExceptOnAssociations`
|
|
24
25
|
// instead of `removeAllDefaultScopes`).
|
|
25
26
|
this.query = this.dream.query()['removeAllDefaultScopesExceptOnAssociations']();
|
|
26
|
-
this.dreamTransaction = txn;
|
|
27
27
|
}
|
|
28
28
|
passthrough(passthroughWhereStatement) {
|
|
29
29
|
this.query = this.query.passthrough(passthroughWhereStatement);
|
|
@@ -33,12 +33,7 @@ async function createAssociation(dream, txn = null, associationName, opts = {})
|
|
|
33
33
|
if (hasAssociation.polymorphic) {
|
|
34
34
|
modifiedOpts[hasAssociation.foreignKeyTypeField()] = dream['stiBaseClassOrOwnClassName'];
|
|
35
35
|
}
|
|
36
|
-
|
|
37
|
-
hasresult = await associationClass.txn(txn).create(modifiedOpts);
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
hasresult = await associationClass.create(modifiedOpts);
|
|
41
|
-
}
|
|
36
|
+
hasresult = await associationClass.txn(txn).create(modifiedOpts);
|
|
42
37
|
return hasresult;
|
|
43
38
|
case 'BelongsTo':
|
|
44
39
|
belongstoFn = async (txn) => {
|
|
@@ -40,7 +40,7 @@ async function destroyDreamWithTransaction(dream, txn, options) {
|
|
|
40
40
|
}
|
|
41
41
|
await maybeDestroyDream(dream, txn, reallyDestroy);
|
|
42
42
|
if (!skipHooks) {
|
|
43
|
-
await (0, runHooksFor_js_1.default)('afterDestroy', dream, true, null, txn
|
|
43
|
+
await (0, runHooksFor_js_1.default)('afterDestroy', dream, true, null, txn);
|
|
44
44
|
await (0, runHooksFor_js_1.default)('afterDestroyCommit', dream, true, null, txn);
|
|
45
45
|
}
|
|
46
46
|
if (shouldSoftDelete(dream, reallyDestroy)) {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = findOrCreateBy;
|
|
4
|
+
async function findOrCreateBy(dreamClass, txn = null, attributes, extraOpts = {}) {
|
|
5
|
+
const existingRecord = await dreamClass
|
|
6
|
+
.txn(txn)
|
|
7
|
+
.findBy(dreamClass['extractAttributesFromUpdateableProperties'](attributes));
|
|
8
|
+
if (existingRecord)
|
|
9
|
+
return existingRecord;
|
|
10
|
+
const dreamModel = dreamClass.new({
|
|
11
|
+
...attributes,
|
|
12
|
+
...(extraOpts?.createWith || {}),
|
|
13
|
+
});
|
|
14
|
+
await dreamModel.txn(txn).save();
|
|
15
|
+
return dreamModel;
|
|
16
|
+
}
|
|
@@ -39,7 +39,7 @@ async function runHooksFor(key, dream, alreadyPersisted, beforeSaveChanges, txn)
|
|
|
39
39
|
if (txn)
|
|
40
40
|
txn.addCommitHook(hook, dream);
|
|
41
41
|
else
|
|
42
|
-
await runHook(hook, dream);
|
|
42
|
+
await runHook(hook, dream, null);
|
|
43
43
|
}
|
|
44
44
|
break;
|
|
45
45
|
case 'afterSave':
|
|
@@ -54,7 +54,7 @@ async function runHooksFor(key, dream, alreadyPersisted, beforeSaveChanges, txn)
|
|
|
54
54
|
if (txn)
|
|
55
55
|
txn.addCommitHook(hook, dream);
|
|
56
56
|
else
|
|
57
|
-
await runHook(hook, dream);
|
|
57
|
+
await runHook(hook, dream, null);
|
|
58
58
|
}
|
|
59
59
|
break;
|
|
60
60
|
case 'afterUpdate':
|
|
@@ -67,7 +67,7 @@ async function runHooksFor(key, dream, alreadyPersisted, beforeSaveChanges, txn)
|
|
|
67
67
|
if (txn)
|
|
68
68
|
txn.addCommitHook(hook, dream);
|
|
69
69
|
else
|
|
70
|
-
await runHook(hook, dream);
|
|
70
|
+
await runHook(hook, dream, null);
|
|
71
71
|
}
|
|
72
72
|
break;
|
|
73
73
|
default:
|
|
@@ -83,7 +83,7 @@ async function runHooksFor(key, dream, alreadyPersisted, beforeSaveChanges, txn)
|
|
|
83
83
|
if (txn)
|
|
84
84
|
txn.addCommitHook(hook, dream);
|
|
85
85
|
else
|
|
86
|
-
await runHook(hook, dream);
|
|
86
|
+
await runHook(hook, dream, null);
|
|
87
87
|
break;
|
|
88
88
|
default:
|
|
89
89
|
await runHook(hook, dream, txn);
|
|
@@ -9,7 +9,7 @@ const sqlAttributes_js_1 = require("../../helpers/sqlAttributes.js");
|
|
|
9
9
|
const executeDatabaseQuery_js_1 = require("./executeDatabaseQuery.js");
|
|
10
10
|
const runHooksFor_js_1 = require("./runHooksFor.js");
|
|
11
11
|
async function saveDream(dream, txn = null, { skipHooks = false } = {}) {
|
|
12
|
-
const db = txn?.kyselyTransaction
|
|
12
|
+
const db = txn?.kyselyTransaction ?? (0, index_js_1.default)('primary');
|
|
13
13
|
const alreadyPersisted = dream.isPersisted;
|
|
14
14
|
if (!skipHooks) {
|
|
15
15
|
if (alreadyPersisted)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = updateOrCreateBy;
|
|
4
|
+
const saveDream_js_1 = require("./saveDream.js");
|
|
5
|
+
async function updateOrCreateBy(dreamClass, txn = null, attributes, extraOpts = {}) {
|
|
6
|
+
const existingRecord = await dreamClass
|
|
7
|
+
.txn(txn)
|
|
8
|
+
.findBy(dreamClass['extractAttributesFromUpdateableProperties'](attributes));
|
|
9
|
+
const { with: attrs, skipHooks } = extraOpts;
|
|
10
|
+
if (existingRecord) {
|
|
11
|
+
existingRecord.assignAttributes(attrs ?? {});
|
|
12
|
+
return await (0, saveDream_js_1.default)(existingRecord, txn, skipHooks ? { skipHooks } : undefined);
|
|
13
|
+
}
|
|
14
|
+
return await dreamClass.txn(txn).create({
|
|
15
|
+
...attributes,
|
|
16
|
+
...(extraOpts?.with || {}),
|
|
17
|
+
}, skipHooks ? { skipHooks } : undefined);
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class CreateOrUpdateByFailedToCreateAndUpdate extends Error {
|
|
4
|
+
dreamClass;
|
|
5
|
+
constructor(dreamClass) {
|
|
6
|
+
super();
|
|
7
|
+
this.dreamClass = dreamClass;
|
|
8
|
+
}
|
|
9
|
+
get message() {
|
|
10
|
+
return `
|
|
11
|
+
Failed to create instance of ${this.dreamClass.sanitizedName} and no matching model exists to update.
|
|
12
|
+
|
|
13
|
+
The likely cause is that one of the \`with\` fields violates
|
|
14
|
+
a uniqueness constraint.
|
|
15
|
+
`;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.default = CreateOrUpdateByFailedToCreateAndUpdate;
|
package/dist/esm/src/Dream.js
CHANGED
|
@@ -16,11 +16,13 @@ import destroyDream from './dream/internal/destroyDream.js';
|
|
|
16
16
|
import { destroyOptions, reallyDestroyOptions, undestroyOptions, } from './dream/internal/destroyOptions.js';
|
|
17
17
|
import ensureSTITypeFieldIsSet from './dream/internal/ensureSTITypeFieldIsSet.js';
|
|
18
18
|
import extractAssociationMetadataFromAssociationName from './dream/internal/extractAssociationMetadataFromAssociationName.js';
|
|
19
|
+
import findOrCreateBy from './dream/internal/findOrCreateBy.js';
|
|
19
20
|
import reload from './dream/internal/reload.js';
|
|
20
21
|
import runValidations from './dream/internal/runValidations.js';
|
|
21
22
|
import saveDream from './dream/internal/saveDream.js';
|
|
22
23
|
import { DEFAULT_BYPASS_ALL_DEFAULT_SCOPES, DEFAULT_DEFAULT_SCOPES_TO_BYPASS, DEFAULT_SKIP_HOOKS, } from './dream/internal/scopeHelpers.js';
|
|
23
24
|
import undestroyDream from './dream/internal/undestroyDream.js';
|
|
25
|
+
import updateOrCreateBy from './dream/internal/updateOrCreateBy.js';
|
|
24
26
|
import LeftJoinLoadBuilder from './dream/LeftJoinLoadBuilder.js';
|
|
25
27
|
import LoadBuilder from './dream/LoadBuilder.js';
|
|
26
28
|
import Query from './dream/Query.js';
|
|
@@ -34,6 +36,7 @@ import NonLoadedAssociation from './errors/associations/NonLoadedAssociation.js'
|
|
|
34
36
|
import CannotCallUndestroyOnANonSoftDeleteModel from './errors/CannotCallUndestroyOnANonSoftDeleteModel.js';
|
|
35
37
|
import ConstructorOnlyForInternalUse from './errors/ConstructorOnlyForInternalUse.js';
|
|
36
38
|
import CreateOrFindByFailedToCreateAndFind from './errors/CreateOrFindByFailedToCreateAndFind.js';
|
|
39
|
+
import CreateOrUpdateByFailedToCreateAndUpdate from './errors/CreateOrUpdateByFailedToCreateAndUpdate.js';
|
|
37
40
|
import GlobalNameNotSet from './errors/dream-app/GlobalNameNotSet.js';
|
|
38
41
|
import DreamMissingRequiredOverride from './errors/DreamMissingRequiredOverride.js';
|
|
39
42
|
import MissingSerializer from './errors/MissingSerializersDefinition.js';
|
|
@@ -654,11 +657,12 @@ export default class Dream {
|
|
|
654
657
|
* ```
|
|
655
658
|
*
|
|
656
659
|
* @param attributes - attributes or belongs to associations you wish to set on this model before persisting
|
|
660
|
+
* @param opts.skipHooks - if true, will skip applying model hooks. Defaults to false
|
|
657
661
|
* @returns A newly persisted dream instance
|
|
658
662
|
*/
|
|
659
|
-
static async create(attributes) {
|
|
663
|
+
static async create(attributes, { skipHooks } = {}) {
|
|
660
664
|
const dreamModel = this.new(attributes);
|
|
661
|
-
await dreamModel.save();
|
|
665
|
+
await dreamModel.save(skipHooks ? { skipHooks } : undefined);
|
|
662
666
|
return dreamModel;
|
|
663
667
|
}
|
|
664
668
|
/**
|
|
@@ -699,6 +703,62 @@ export default class Dream {
|
|
|
699
703
|
throw err;
|
|
700
704
|
}
|
|
701
705
|
}
|
|
706
|
+
/**
|
|
707
|
+
* Attempt to update the model with the given attributes.
|
|
708
|
+
* If no record is found, then a new record is created.
|
|
709
|
+
* All lifecycle hooks are run for whichever action is taken.
|
|
710
|
+
*
|
|
711
|
+
* ```ts
|
|
712
|
+
* const user = await User.updateOrCreateBy({ email }, { with: { name: 'Alice' })
|
|
713
|
+
* ```
|
|
714
|
+
*
|
|
715
|
+
* @param attributes - The base attributes for finding which record to update, also used when creating
|
|
716
|
+
* @param extraOpts.with - additional attributes to persist when updating and creating, but not used for finding
|
|
717
|
+
* @param extraOpts.skipHooks - if true, will skip applying model hooks. Defaults to false
|
|
718
|
+
* @returns A dream instance
|
|
719
|
+
*/
|
|
720
|
+
static async updateOrCreateBy(attributes, extraOpts = {}) {
|
|
721
|
+
return await updateOrCreateBy(this, null, attributes, extraOpts);
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* Attempt to create the model with the given attributes.
|
|
725
|
+
* If creation fails due to uniqueness constraint, then find and update
|
|
726
|
+
* the existing model. All lifecycle hooks are run for whichever
|
|
727
|
+
* action is taken.
|
|
728
|
+
*
|
|
729
|
+
* This is useful in situations where we want to avoid
|
|
730
|
+
* a race condition creating duplicate records.
|
|
731
|
+
*
|
|
732
|
+
* IMPORTANT: A unique index/uniqueness constraint must exist on
|
|
733
|
+
* at least one of the provided attributes
|
|
734
|
+
*
|
|
735
|
+
* @param attributes - The base attributes for finding which record to update, also used when creating
|
|
736
|
+
* @param extraOpts.with - additional attributes to persist when updating and creating, but not used for finding
|
|
737
|
+
* @param extraOpts.skipHooks - if true, will skip applying model hooks. Defaults to false
|
|
738
|
+
* @returns A dream instance
|
|
739
|
+
*/
|
|
740
|
+
static async createOrUpdateBy(attributes, extraOpts = {}) {
|
|
741
|
+
const { skipHooks } = extraOpts;
|
|
742
|
+
try {
|
|
743
|
+
return await this.create({
|
|
744
|
+
...attributes,
|
|
745
|
+
...(extraOpts?.with || {}),
|
|
746
|
+
}, skipHooks ? { skipHooks } : undefined);
|
|
747
|
+
}
|
|
748
|
+
catch (err) {
|
|
749
|
+
if (pgErrorType(err) === 'UNIQUE_CONSTRAINT_VIOLATION') {
|
|
750
|
+
const existingRecord = await this.findBy(this.extractAttributesFromUpdateableProperties(attributes));
|
|
751
|
+
if (!existingRecord)
|
|
752
|
+
throw new CreateOrUpdateByFailedToCreateAndUpdate(this);
|
|
753
|
+
const { with: attrs } = extraOpts;
|
|
754
|
+
if (existingRecord) {
|
|
755
|
+
existingRecord.assignAttributes(attrs ?? {});
|
|
756
|
+
return await saveDream(existingRecord, null, skipHooks ? { skipHooks } : undefined);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
throw err;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
702
762
|
/**
|
|
703
763
|
* Returns a new query instance with the distinct query applied.
|
|
704
764
|
* If no columnName is provided, then distinct will apply to the
|
|
@@ -850,15 +910,7 @@ export default class Dream {
|
|
|
850
910
|
* @returns A dream instance
|
|
851
911
|
*/
|
|
852
912
|
static async findOrCreateBy(attributes, extraOpts = {}) {
|
|
853
|
-
|
|
854
|
-
if (existingRecord)
|
|
855
|
-
return existingRecord;
|
|
856
|
-
const dreamModel = this.new({
|
|
857
|
-
...attributes,
|
|
858
|
-
...(extraOpts?.createWith || {}),
|
|
859
|
-
});
|
|
860
|
-
await dreamModel.save();
|
|
861
|
-
return dreamModel;
|
|
913
|
+
return await findOrCreateBy(this, null, attributes, extraOpts);
|
|
862
914
|
}
|
|
863
915
|
/**
|
|
864
916
|
* Returns true if a record exists for the given
|
|
@@ -1252,7 +1304,7 @@ export default class Dream {
|
|
|
1252
1304
|
* @returns A Query scoped to this model with the transaction applied
|
|
1253
1305
|
*/
|
|
1254
1306
|
static txn(txn) {
|
|
1255
|
-
return new DreamClassTransactionBuilder(this
|
|
1307
|
+
return new DreamClassTransactionBuilder(this, txn);
|
|
1256
1308
|
}
|
|
1257
1309
|
/**
|
|
1258
1310
|
* Builds a new DreamTransaction instance, provides
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
+
import findOrCreateBy from './internal/findOrCreateBy.js';
|
|
1
2
|
import saveDream from './internal/saveDream.js';
|
|
3
|
+
import updateOrCreateBy from './internal/updateOrCreateBy.js';
|
|
2
4
|
import Query from './Query.js';
|
|
3
5
|
export default class DreamClassTransactionBuilder {
|
|
4
|
-
|
|
6
|
+
dreamClass;
|
|
5
7
|
dreamTransaction;
|
|
8
|
+
dreamInstance;
|
|
6
9
|
/**
|
|
7
10
|
* Constructs a new DreamClassTransactionBuilder.
|
|
8
11
|
*
|
|
9
12
|
* @param dreamInstance - The Dream instance to build the transaction for
|
|
10
13
|
* @param txn - The DreamTransaction instance
|
|
11
14
|
*/
|
|
12
|
-
constructor(
|
|
13
|
-
this.
|
|
15
|
+
constructor(dreamClass, dreamTransaction) {
|
|
16
|
+
this.dreamClass = dreamClass;
|
|
14
17
|
this.dreamTransaction = dreamTransaction;
|
|
18
|
+
this.dreamInstance = dreamClass.prototype;
|
|
15
19
|
}
|
|
16
20
|
/**
|
|
17
21
|
* Retrieves an array containing all records corresponding to
|
|
@@ -120,9 +124,9 @@ export default class DreamClassTransactionBuilder {
|
|
|
120
124
|
* @param attributes - Attributes or belongs to associations you wish to set on this model before persisting
|
|
121
125
|
* @returns A newly persisted dream instance
|
|
122
126
|
*/
|
|
123
|
-
async create(attributes) {
|
|
124
|
-
const dream = this.
|
|
125
|
-
return saveDream(dream, this.dreamTransaction);
|
|
127
|
+
async create(attributes, { skipHooks } = {}) {
|
|
128
|
+
const dream = this.dreamClass.new(attributes);
|
|
129
|
+
return saveDream(dream, this.dreamTransaction, skipHooks ? { skipHooks } : undefined);
|
|
126
130
|
}
|
|
127
131
|
/**
|
|
128
132
|
* Finds a record for the corresponding model with the
|
|
@@ -194,6 +198,42 @@ export default class DreamClassTransactionBuilder {
|
|
|
194
198
|
async findOrFailBy(whereStatement) {
|
|
195
199
|
return await this.queryInstance().findOrFailBy(whereStatement);
|
|
196
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* Attempt to find the model with the given attributes.
|
|
203
|
+
* If no record is found, then a new record is created.
|
|
204
|
+
*
|
|
205
|
+
* ```ts
|
|
206
|
+
* await ApplicationModel.transaction(async txn => {
|
|
207
|
+
* await User.txn(txn).findOrCreateBy({ email }, { createWith: params })
|
|
208
|
+
* })
|
|
209
|
+
* ```
|
|
210
|
+
*
|
|
211
|
+
* @param attributes - The base attributes for finding, but also the attributes to use when creating
|
|
212
|
+
* @param extraOpts.createWith - additional attributes to persist when creating, but not used for finding
|
|
213
|
+
* @returns A dream instance
|
|
214
|
+
*/
|
|
215
|
+
async findOrCreateBy(attributes, extraOpts = {}) {
|
|
216
|
+
return await findOrCreateBy(this.dreamClass, this.dreamTransaction, attributes, extraOpts);
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Attempt to update the model with the given attributes.
|
|
220
|
+
* If no record is found, then a new record is created.
|
|
221
|
+
* All lifecycle hooks are run for whichever action is taken.
|
|
222
|
+
*
|
|
223
|
+
* ```ts
|
|
224
|
+
* await ApplicationModel.transaction(async txn => {
|
|
225
|
+
* await User.txn(txn).updateOrCreateBy({ email }, { with: { name: 'Alice' })
|
|
226
|
+
* })
|
|
227
|
+
* ```
|
|
228
|
+
*
|
|
229
|
+
* @param attributes - The base attributes for finding, but also the attributes to use when creating
|
|
230
|
+
* @param extraOpts.with - additional attributes to persist when updating and creating, but not used for finding
|
|
231
|
+
* @param extraOpts.skipHooks - if true, will skip applying model hooks. Defaults to false
|
|
232
|
+
* @returns A dream instance
|
|
233
|
+
*/
|
|
234
|
+
async updateOrCreateBy(attributes, extraOpts = {}) {
|
|
235
|
+
return await updateOrCreateBy(this.dreamClass, this.dreamTransaction, attributes, extraOpts);
|
|
236
|
+
}
|
|
197
237
|
/**
|
|
198
238
|
* Finds all records for the corresponding model in batches,
|
|
199
239
|
* and then calls the provided callback for each found record.
|
|
@@ -24,9 +24,9 @@ export default class DreamInstanceTransactionBuilder {
|
|
|
24
24
|
* @param dreamInstance - The Dream instance to build the transaction for
|
|
25
25
|
* @param txn - The DreamTransaction instance
|
|
26
26
|
*/
|
|
27
|
-
constructor(dreamInstance,
|
|
27
|
+
constructor(dreamInstance, dreamTransaction) {
|
|
28
28
|
this.dreamInstance = dreamInstance;
|
|
29
|
-
this.dreamTransaction =
|
|
29
|
+
this.dreamTransaction = dreamTransaction;
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
32
|
* Loads the requested associations upon execution
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import UnexpectedUndefined from '../errors/UnexpectedUndefined.js';
|
|
2
2
|
export default class LeftJoinLoadBuilder {
|
|
3
|
-
dream;
|
|
4
3
|
dreamTransaction;
|
|
4
|
+
dream;
|
|
5
5
|
query;
|
|
6
6
|
/**
|
|
7
7
|
* An intermediate class on the way to executing a load
|
|
@@ -13,7 +13,8 @@ export default class LeftJoinLoadBuilder {
|
|
|
13
13
|
* await user.load('settings').execute()
|
|
14
14
|
* ```
|
|
15
15
|
*/
|
|
16
|
-
constructor(dream,
|
|
16
|
+
constructor(dream, dreamTransaction) {
|
|
17
|
+
this.dreamTransaction = dreamTransaction;
|
|
17
18
|
this.dream = dream['clone']();
|
|
18
19
|
// Load queries start from the table corresponding to an instance
|
|
19
20
|
// of a Dream. However, the Dream may have default scopes that would
|
|
@@ -22,7 +23,6 @@ export default class LeftJoinLoadBuilder {
|
|
|
22
23
|
// to other associations (thus the use of `removeAllDefaultScopesExceptOnAssociations`
|
|
23
24
|
// instead of `removeAllDefaultScopes`).
|
|
24
25
|
this.query = this.dream.query()['removeAllDefaultScopesExceptOnAssociations']();
|
|
25
|
-
this.dreamTransaction = txn;
|
|
26
26
|
}
|
|
27
27
|
passthrough(passthroughWhereStatement) {
|
|
28
28
|
this.query = this.query.passthrough(passthroughWhereStatement);
|