@rvoh/dream 0.45.0 → 0.45.2
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 +118 -36
- package/dist/cjs/src/bin/index.js +6 -2
- package/dist/cjs/src/cli/index.js +41 -5
- package/dist/cjs/src/dream/DreamClassTransactionBuilder.js +92 -0
- package/dist/cjs/src/dream/DreamInstanceTransactionBuilder.js +98 -0
- package/dist/cjs/src/dream/LeftJoinLoadBuilder.js +52 -1
- package/dist/cjs/src/dream/LoadBuilder.js +49 -0
- package/dist/cjs/src/dream/Query.js +31 -57
- package/dist/cjs/src/dream/internal/convertDreamClassAndAssociationNameTupleArrayToPreloadArgs.js +18 -0
- package/dist/cjs/src/dream/internal/unaliasTableName.js +7 -0
- package/dist/cjs/src/helpers/cli/generateDream.js +2 -0
- package/dist/cjs/src/helpers/cli/generateDreamContent.js +6 -2
- package/dist/cjs/src/helpers/cli/generateFactoryContent.js +27 -17
- package/dist/cjs/src/helpers/cli/generateMigrationContent.js +45 -39
- package/dist/cjs/src/helpers/cli/generateSerializer.js +2 -1
- package/dist/cjs/src/helpers/cli/generateSerializerContent.js +20 -8
- package/dist/esm/src/Dream.js +118 -36
- package/dist/esm/src/bin/index.js +6 -2
- package/dist/esm/src/cli/index.js +41 -5
- package/dist/esm/src/dream/DreamClassTransactionBuilder.js +92 -0
- package/dist/esm/src/dream/DreamInstanceTransactionBuilder.js +98 -0
- package/dist/esm/src/dream/LeftJoinLoadBuilder.js +52 -1
- package/dist/esm/src/dream/LoadBuilder.js +49 -0
- package/dist/esm/src/dream/Query.js +31 -57
- package/dist/esm/src/dream/internal/convertDreamClassAndAssociationNameTupleArrayToPreloadArgs.js +15 -0
- package/dist/esm/src/dream/internal/unaliasTableName.js +4 -0
- package/dist/esm/src/helpers/cli/generateDream.js +2 -0
- package/dist/esm/src/helpers/cli/generateDreamContent.js +6 -2
- package/dist/esm/src/helpers/cli/generateFactoryContent.js +27 -17
- package/dist/esm/src/helpers/cli/generateMigrationContent.js +45 -39
- package/dist/esm/src/helpers/cli/generateSerializer.js +2 -1
- package/dist/esm/src/helpers/cli/generateSerializerContent.js +20 -8
- package/dist/types/src/Dream.d.ts +113 -49
- package/dist/types/src/dream/DreamClassTransactionBuilder.d.ts +108 -2
- package/dist/types/src/dream/DreamInstanceTransactionBuilder.d.ts +96 -2
- package/dist/types/src/dream/LeftJoinLoadBuilder.d.ts +48 -1
- package/dist/types/src/dream/LoadBuilder.d.ts +48 -1
- package/dist/types/src/dream/Query.d.ts +32 -59
- package/dist/types/src/dream/internal/convertDreamClassAndAssociationNameTupleArrayToPreloadArgs.d.ts +9 -0
- package/dist/types/src/dream/internal/unaliasTableName.d.ts +1 -0
- package/dist/types/src/helpers/cli/generateDream.d.ts +1 -0
- package/dist/types/src/helpers/cli/generateDreamContent.d.ts +2 -1
- package/dist/types/src/helpers/cli/generateSerializer.d.ts +2 -1
- package/dist/types/src/helpers/cli/generateSerializerContent.d.ts +3 -2
- package/dist/types/src/types/query.d.ts +5 -0
- package/dist/types/src/types/query.ts +5 -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 +220 -186
- 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/DreamSerializerBuilder.html +8 -8
- 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/ObjectSerializerBuilder.html +8 -8
- package/docs/classes/Query.html +70 -66
- package/docs/classes/Range.html +2 -2
- package/docs/classes/RecordNotFound.html +3 -3
- package/docs/classes/ValidationError.html +3 -3
- package/docs/functions/DreamSerializer.html +1 -1
- package/docs/functions/ObjectSerializer.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/cloneDeepSafe.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/expandStiClasses.html +1 -1
- package/docs/functions/generateDream.html +1 -1
- package/docs/functions/globalClassNameFromFullyQualifiedModelName.html +1 -1
- package/docs/functions/groupBy.html +1 -1
- package/docs/functions/hyphenize.html +1 -1
- package/docs/functions/inferSerializerFromDreamOrViewModel.html +1 -1
- package/docs/functions/inferSerializersFromDreamClassOrViewModelClass.html +1 -1
- package/docs/functions/intersection.html +1 -1
- package/docs/functions/isDreamSerializer.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/normalizeUnicode.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/sortObjectByKey.html +1 -1
- package/docs/functions/sortObjectByValue.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/BelongsToStatement.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/EncryptOptions.html +2 -2
- package/docs/interfaces/InternalAnyTypedSerializerRendersMany.html +2 -2
- package/docs/interfaces/InternalAnyTypedSerializerRendersOne.html +2 -2
- package/docs/interfaces/OpenapiDescription.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/interfaces/SerializerRendererOpts.html +2 -2
- 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/DbTypes.html +1 -1
- package/docs/types/DreamAssociationMetadata.html +1 -1
- package/docs/types/DreamAttributes.html +1 -1
- package/docs/types/DreamClassAssociationAndStatement.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/DreamModelSerializerType.html +1 -1
- package/docs/types/DreamOrViewModelClassSerializerKey.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/DreamSerializable.html +1 -1
- package/docs/types/DreamSerializableArray.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/HasManyStatement.html +1 -1
- package/docs/types/HasOneStatement.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/OpenapiPrimitiveBaseTypes.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/OpenapiShorthandPrimitiveBaseTypes.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/SerializerCasing.html +1 -1
- package/docs/types/SimpleObjectSerializerType.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/ViewModel.html +1 -1
- package/docs/types/ViewModelClass.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 +2 -2
package/dist/cjs/src/Dream.js
CHANGED
|
@@ -1148,38 +1148,31 @@ class Dream {
|
|
|
1148
1148
|
* await User.preload('posts', 'comments', 'replies').all()
|
|
1149
1149
|
*
|
|
1150
1150
|
* // Automatically preload everything needed for serialization:
|
|
1151
|
-
* await User.
|
|
1151
|
+
* await User.preloadFor('summary').all()
|
|
1152
1152
|
*
|
|
1153
1153
|
* // Add where conditions to specific associations during preloading:
|
|
1154
|
-
* await User.
|
|
1155
|
-
*
|
|
1156
|
-
*
|
|
1157
|
-
* if (dreamClass.typeof(Post) && associationName === 'comments') {
|
|
1158
|
-
* return { and: { published: true } }
|
|
1159
|
-
* }
|
|
1154
|
+
* await User.preloadFor('default', (dreamClass, associationName) => {
|
|
1155
|
+
* if (dreamClass.typeof(Post) && associationName === 'comments') {
|
|
1156
|
+
* return { and: { published: true } }
|
|
1160
1157
|
* }
|
|
1161
1158
|
* }).all()
|
|
1162
1159
|
*
|
|
1163
1160
|
* // Skip preloading specific associations to handle them manually:
|
|
1164
|
-
* await User.
|
|
1165
|
-
*
|
|
1166
|
-
*
|
|
1167
|
-
* if (dreamClass.typeof(User) && associationName === 'posts') {
|
|
1168
|
-
* return 'omit' // Handle posts preloading separately with custom logic
|
|
1169
|
-
* }
|
|
1161
|
+
* await User.preloadFor('summary', (dreamClass, associationName) => {
|
|
1162
|
+
* if (dreamClass.typeof(User) && associationName === 'posts') {
|
|
1163
|
+
* return 'omit' // Handle posts preloading separately with custom logic
|
|
1170
1164
|
* }
|
|
1171
1165
|
* })
|
|
1172
1166
|
* .preload('posts', { and: { featured: true } }) // Custom preloading
|
|
1173
1167
|
* .all()
|
|
1174
1168
|
* ```
|
|
1175
1169
|
*
|
|
1176
|
-
* @param
|
|
1177
|
-
* @param
|
|
1178
|
-
* @param opts.modifierFn - Optional callback function to modify or omit specific associations during preloading. Called for each association with the Dream class and association name. Return an object with `and`, `andAny`, or `andNot` properties to add where conditions, return 'omit' to skip preloading that association (useful when you want to handle it manually), or return undefined to use default preloading
|
|
1170
|
+
* @param serializerKey - The serializer key to use for determining which associations to preload.
|
|
1171
|
+
* @param modifierFn - Optional callback function to modify or omit specific associations during preloading. Called for each association with the Dream class and association name. Return an object with `and`, `andAny`, or `andNot` properties to add where conditions, return 'omit' to skip preloading that association (useful when you want to handle it manually), or return undefined to use default preloading
|
|
1179
1172
|
* @returns A Query with all serialization associations preloaded
|
|
1180
1173
|
*/
|
|
1181
|
-
static
|
|
1182
|
-
return this.query().
|
|
1174
|
+
static preloadFor(serializerKey, modifierFn) {
|
|
1175
|
+
return this.query().preloadFor(serializerKey, modifierFn);
|
|
1183
1176
|
}
|
|
1184
1177
|
/**
|
|
1185
1178
|
* Recursively preloads all Dream associations referenced by `rendersOne` and `rendersMany`
|
|
@@ -1205,38 +1198,31 @@ class Dream {
|
|
|
1205
1198
|
* await User.leftJoinPreload('posts', 'comments', 'replies').all()
|
|
1206
1199
|
*
|
|
1207
1200
|
* // Automatically left join preload everything needed for serialization:
|
|
1208
|
-
* await User.
|
|
1201
|
+
* await User.leftJoinPreloadFor('summary').all()
|
|
1209
1202
|
*
|
|
1210
1203
|
* // Add where conditions to specific associations during left join preloading:
|
|
1211
|
-
* await User.
|
|
1212
|
-
*
|
|
1213
|
-
*
|
|
1214
|
-
* if (dreamClass.typeof(Post) && associationName === 'comments') {
|
|
1215
|
-
* return { and: { published: true } }
|
|
1216
|
-
* }
|
|
1204
|
+
* await User.leftJoinPreloadFor('detailed', (dreamClass, associationName) => {
|
|
1205
|
+
* if (dreamClass.typeof(Post) && associationName === 'comments') {
|
|
1206
|
+
* return { and: { published: true } }
|
|
1217
1207
|
* }
|
|
1218
1208
|
* }).all()
|
|
1219
1209
|
*
|
|
1220
1210
|
* // Skip left join preloading specific associations to handle them manually:
|
|
1221
|
-
* await User.
|
|
1222
|
-
*
|
|
1223
|
-
*
|
|
1224
|
-
* if (dreamClass.typeof(User) && associationName === 'posts') {
|
|
1225
|
-
* return 'omit' // Handle posts preloading separately with custom logic
|
|
1226
|
-
* }
|
|
1211
|
+
* await User.leftJoinPreloadFor('summary', (dreamClass, associationName) => {
|
|
1212
|
+
* if (dreamClass.typeof(User) && associationName === 'posts') {
|
|
1213
|
+
* return 'omit' // Handle posts preloading separately with custom logic
|
|
1227
1214
|
* }
|
|
1228
1215
|
* })
|
|
1229
1216
|
* .preload('posts', { and: { featured: true } }) // Custom preloading instead
|
|
1230
1217
|
* .all()
|
|
1231
1218
|
* ```
|
|
1232
1219
|
*
|
|
1233
|
-
* @param
|
|
1234
|
-
* @param
|
|
1235
|
-
* @param opts.modifierFn - Optional callback function to modify or omit specific associations during preloading. Called for each association with the Dream class and association name. Return an object with `and`, `andAny`, or `andNot` properties to add where conditions, return 'omit' to skip preloading that association (useful when you want to handle it manually), or return undefined to use default preloading
|
|
1220
|
+
* @param serializerKey - The serializer key to use for determining which associations to preload.
|
|
1221
|
+
* @param modifierFn - Optional callback function to modify or omit specific associations during preloading. Called for each association with the Dream class and association name. Return an object with `and`, `andAny`, or `andNot` properties to add where conditions, return 'omit' to skip preloading that association (useful when you want to handle it manually), or return undefined to use default preloading
|
|
1236
1222
|
* @returns A Query with all serialization associations left join preloaded
|
|
1237
1223
|
*/
|
|
1238
|
-
static
|
|
1239
|
-
return this.query().
|
|
1224
|
+
static leftJoinPreloadFor(serializerKey, modifierFn) {
|
|
1225
|
+
return this.query().leftJoinPreloadFor(serializerKey, modifierFn);
|
|
1240
1226
|
}
|
|
1241
1227
|
/**
|
|
1242
1228
|
* Returns a new Query instance with the provided
|
|
@@ -3083,6 +3069,54 @@ class Dream {
|
|
|
3083
3069
|
load(...args) {
|
|
3084
3070
|
return new LoadBuilder_js_1.default(this).load(...args);
|
|
3085
3071
|
}
|
|
3072
|
+
/**
|
|
3073
|
+
* Recursively loads all Dream associations referenced by `rendersOne` and `rendersMany`
|
|
3074
|
+
* in a DreamSerializer. This traverses the entire content tree of serializers to automatically
|
|
3075
|
+
* load all necessary associations, eliminating N+1 query problems and removing the need to
|
|
3076
|
+
* manually remember which associations to preload for serialization.
|
|
3077
|
+
*
|
|
3078
|
+
* This method decouples data loading code from data rendering code by having the serializer
|
|
3079
|
+
* (rendering code) inform the query (loading code) about which associations are needed.
|
|
3080
|
+
* As serializers evolve over time - adding new `rendersOne` and `rendersMany` calls or
|
|
3081
|
+
* modifying existing ones - the loading code automatically adapts without requiring
|
|
3082
|
+
* corresponding modifications to preload statements.
|
|
3083
|
+
*
|
|
3084
|
+
* This method analyzes the serializer (specified by `serializerKey` or 'default') and
|
|
3085
|
+
* automatically preloads all associations that will be needed during serialization.
|
|
3086
|
+
*
|
|
3087
|
+
* ```ts
|
|
3088
|
+
* // Instead of manually specifying all associations:
|
|
3089
|
+
* await User.preload('posts', 'comments', 'replies').all()
|
|
3090
|
+
*
|
|
3091
|
+
* // Automatically preload everything needed for serialization:
|
|
3092
|
+
* await user.loadFor('summary').execute()
|
|
3093
|
+
*
|
|
3094
|
+
* // Add where conditions to specific associations during preloading:
|
|
3095
|
+
* await user.loadFor('detailed', (dreamClass, associationName) => {
|
|
3096
|
+
* if (dreamClass.typeof(Post) && associationName === 'comments') {
|
|
3097
|
+
* return { and: { published: true } }
|
|
3098
|
+
* }
|
|
3099
|
+
* })
|
|
3100
|
+
* .execute()
|
|
3101
|
+
*
|
|
3102
|
+
* // Skip preloading specific associations to handle them manually:
|
|
3103
|
+
* await user
|
|
3104
|
+
* .loadFor('summary', (dreamClass, associationName) => {
|
|
3105
|
+
* if (dreamClass.typeof(User) && associationName === 'posts') {
|
|
3106
|
+
* return 'omit' // Handle posts preloading separately with custom logic
|
|
3107
|
+
* }
|
|
3108
|
+
* })
|
|
3109
|
+
* .load('posts', { and: { featured: true } }) // Custom preloading
|
|
3110
|
+
* .execute()
|
|
3111
|
+
* ```
|
|
3112
|
+
*
|
|
3113
|
+
* @param serializerKey - The serializer key to use for determining which associations to preload.
|
|
3114
|
+
* @param modifierFn - Optional callback function to modify or omit specific associations during preloading. Called for each association with the Dream class and association name. Return an object with `and`, `andAny`, or `andNot` properties to add where conditions, return 'omit' to skip preloading that association (useful when you want to handle it manually), or return undefined to use default preloading
|
|
3115
|
+
* @returns A Query with all serialization associations preloaded
|
|
3116
|
+
*/
|
|
3117
|
+
loadFor(serializerKey, modifierFn) {
|
|
3118
|
+
return new LoadBuilder_js_1.default(this)['loadFor'](serializerKey, modifierFn);
|
|
3119
|
+
}
|
|
3086
3120
|
/**
|
|
3087
3121
|
* Load each specified association using a single SQL query.
|
|
3088
3122
|
* See {@link Dream.load} for loading in separate queries.
|
|
@@ -3117,6 +3151,54 @@ class Dream {
|
|
|
3117
3151
|
leftJoinLoad(...args) {
|
|
3118
3152
|
return new LeftJoinLoadBuilder_js_1.default(this).leftJoinLoad(...args);
|
|
3119
3153
|
}
|
|
3154
|
+
/**
|
|
3155
|
+
* Recursively loads all Dream associations referenced by `rendersOne` and `rendersMany`
|
|
3156
|
+
* in a DreamSerializer. This traverses the entire content tree of serializers to automatically
|
|
3157
|
+
* load all necessary associations, eliminating N+1 query problems and removing the need to
|
|
3158
|
+
* manually remember which associations to preload for serialization.
|
|
3159
|
+
*
|
|
3160
|
+
* This method decouples data loading code from data rendering code by having the serializer
|
|
3161
|
+
* (rendering code) inform the query (loading code) about which associations are needed.
|
|
3162
|
+
* As serializers evolve over time - adding new `rendersOne` and `rendersMany` calls or
|
|
3163
|
+
* modifying existing ones - the loading code automatically adapts without requiring
|
|
3164
|
+
* corresponding modifications to preload statements.
|
|
3165
|
+
*
|
|
3166
|
+
* This method analyzes the serializer (specified by `serializerKey` or 'default') and
|
|
3167
|
+
* automatically preloads all associations that will be needed during serialization.
|
|
3168
|
+
*
|
|
3169
|
+
* ```ts
|
|
3170
|
+
* // Instead of manually specifying all associations:
|
|
3171
|
+
* await User.preload('posts', 'comments', 'replies').all()
|
|
3172
|
+
*
|
|
3173
|
+
* // Automatically preload everything needed for serialization:
|
|
3174
|
+
* await user.leftJoinLoadFor('summary').execute()
|
|
3175
|
+
*
|
|
3176
|
+
* // Add where conditions to specific associations during preloading:
|
|
3177
|
+
* await user.leftJoinLoadFor('detailed', (dreamClass, associationName) => {
|
|
3178
|
+
* if (dreamClass.typeof(Post) && associationName === 'comments') {
|
|
3179
|
+
* return { and: { published: true } }
|
|
3180
|
+
* }
|
|
3181
|
+
* })
|
|
3182
|
+
* .execute()
|
|
3183
|
+
*
|
|
3184
|
+
* // Skip preloading specific associations to handle them manually:
|
|
3185
|
+
* await user
|
|
3186
|
+
* .loadFor('summary', (dreamClass, associationName) => {
|
|
3187
|
+
* if (dreamClass.typeof(User) && associationName === 'posts') {
|
|
3188
|
+
* return 'omit' // Handle posts preloading separately with custom logic
|
|
3189
|
+
* }
|
|
3190
|
+
* })
|
|
3191
|
+
* .load('posts', { and: { featured: true } }) // Custom preloading
|
|
3192
|
+
* .execute()
|
|
3193
|
+
* ```
|
|
3194
|
+
*
|
|
3195
|
+
* @param serializerKey - The serializer key to use for determining which associations to preload.
|
|
3196
|
+
* @param modifierFn - Optional callback function to modify or omit specific associations during preloading. Called for each association with the Dream class and association name. Return an object with `and`, `andAny`, or `andNot` properties to add where conditions, return 'omit' to skip preloading that association (useful when you want to handle it manually), or return undefined to use default preloading
|
|
3197
|
+
* @returns A Query with all serialization associations preloaded
|
|
3198
|
+
*/
|
|
3199
|
+
leftJoinLoadFor(serializerKey, modifierFn) {
|
|
3200
|
+
return new LeftJoinLoadBuilder_js_1.default(this)['leftJoinLoadFor'](serializerKey, modifierFn);
|
|
3201
|
+
}
|
|
3120
3202
|
/**
|
|
3121
3203
|
* Returns true if the association specified has
|
|
3122
3204
|
* been loaded on this instance
|
|
@@ -21,13 +21,17 @@ class DreamBin {
|
|
|
21
21
|
await Query_js_1.default.dbDriverClass().rollback(opts);
|
|
22
22
|
}
|
|
23
23
|
static async generateDream(fullyQualifiedModelName, columnsWithTypes, options) {
|
|
24
|
-
await (0, generateDream_js_1.default)({
|
|
24
|
+
await (0, generateDream_js_1.default)({
|
|
25
|
+
fullyQualifiedModelName,
|
|
26
|
+
columnsWithTypes,
|
|
27
|
+
options: { includeAdminSerializers: false, ...options },
|
|
28
|
+
});
|
|
25
29
|
}
|
|
26
30
|
static async generateStiChild(fullyQualifiedModelName, fullyQualifiedParentName, columnsWithTypes, options) {
|
|
27
31
|
await (0, generateDream_js_1.default)({
|
|
28
32
|
fullyQualifiedModelName,
|
|
29
33
|
columnsWithTypes,
|
|
30
|
-
options: { ...options, stiBaseSerializer: false },
|
|
34
|
+
options: { includeAdminSerializers: false, ...options, stiBaseSerializer: false },
|
|
31
35
|
fullyQualifiedParentName,
|
|
32
36
|
});
|
|
33
37
|
}
|
|
@@ -6,6 +6,40 @@ const index_js_2 = require("../dream-app/index.js");
|
|
|
6
6
|
const EnvInternal_js_1 = require("../helpers/EnvInternal.js");
|
|
7
7
|
const sspawn_js_1 = require("../helpers/sspawn.js");
|
|
8
8
|
const DreamCliLogger_js_1 = require("./logger/DreamCliLogger.js");
|
|
9
|
+
const INDENT = ' ';
|
|
10
|
+
const columnsWithTypesDescription = `space separated snake-case (except for belongs_to model name) properties like this:
|
|
11
|
+
${INDENT} title:citext subtitle:string body_markdown:text style:enum:post_styles:formal,informal User:belongs_to
|
|
12
|
+
${INDENT}
|
|
13
|
+
${INDENT}all properties default to not nullable; null can be allowed by appending ':optional':
|
|
14
|
+
${INDENT} subtitle:string:optional
|
|
15
|
+
${INDENT}
|
|
16
|
+
${INDENT}supported types:
|
|
17
|
+
${INDENT} - citext:
|
|
18
|
+
${INDENT} case insensitive text (indexes and queries are automatically case insensitive)
|
|
19
|
+
${INDENT}
|
|
20
|
+
${INDENT} - string:
|
|
21
|
+
${INDENT} varchar; allowed length defaults to 255, but may be customized, e.g.: subtitle:string:128 or subtitle:string:128:optional
|
|
22
|
+
${INDENT}
|
|
23
|
+
${INDENT} - text
|
|
24
|
+
${INDENT}
|
|
25
|
+
${INDENT} - integer
|
|
26
|
+
${INDENT}
|
|
27
|
+
${INDENT} - decimal:
|
|
28
|
+
${INDENT} scale,precision is required, e.g.: volume:decimal:3,2 or volume:decimal:3,2:optional
|
|
29
|
+
${INDENT}
|
|
30
|
+
${INDENT} - enum:
|
|
31
|
+
${INDENT} include the enum name to automatically create the enum:
|
|
32
|
+
${INDENT} type:enum:room_types:bathroom,kitchen,bedroom or type:enum:room_types:bathroom,kitchen,bedroom:optional
|
|
33
|
+
${INDENT}
|
|
34
|
+
${INDENT} omit the enum values to leverage an existing enum (omits the enum type creation):
|
|
35
|
+
${INDENT} type:enum:room_types or type:enum:room_types:optional
|
|
36
|
+
${INDENT}
|
|
37
|
+
${INDENT} - belongs_to:
|
|
38
|
+
${INDENT} Not only updates the migration but also adds a BelongsTo association to the generated model:
|
|
39
|
+
${INDENT} Place:belongs_to
|
|
40
|
+
${INDENT}
|
|
41
|
+
${INDENT} Include the full Path to the model. E.g., if the Coach model is in src/app/models/Health/Coach:
|
|
42
|
+
${INDENT} Health/Coach:belongs_to`;
|
|
9
43
|
class DreamCLI {
|
|
10
44
|
/**
|
|
11
45
|
* use this method for initializing a standalone dream application. If using Psychic and Dream together,
|
|
@@ -35,7 +69,7 @@ class DreamCLI {
|
|
|
35
69
|
.alias('g:migration')
|
|
36
70
|
.description('create a new migration')
|
|
37
71
|
.argument('<migrationName>', 'end with -to-table-name to prepopulate with an alterTable command')
|
|
38
|
-
.argument('[columnsWithTypes...]',
|
|
72
|
+
.argument('[columnsWithTypes...]', columnsWithTypesDescription)
|
|
39
73
|
.action(async (migrationName, columnsWithTypes) => {
|
|
40
74
|
await initializeDreamApp();
|
|
41
75
|
await index_js_1.default.generateMigration(migrationName, columnsWithTypes);
|
|
@@ -47,7 +81,7 @@ class DreamCLI {
|
|
|
47
81
|
.alias('generate:dream')
|
|
48
82
|
.alias('g:dream')
|
|
49
83
|
.option('--no-serializer')
|
|
50
|
-
.option('--sti-base-serializer', '
|
|
84
|
+
.option('--sti-base-serializer', 'omits the serializer from the dream model, but does create the serializer so it can be extended by STI children')
|
|
51
85
|
.description('create a new Dream model')
|
|
52
86
|
.argument('<modelName>', 'the name of the model to create, e.g. Post or Settings/CommunicationPreferences')
|
|
53
87
|
.argument('[columnsWithTypes...]', 'properties of the model property1:text/string/enum/etc. property2:text/string/enum/etc. ... propertyN:text/string/enum/etc.')
|
|
@@ -62,9 +96,11 @@ class DreamCLI {
|
|
|
62
96
|
.description('create a new Dream model that extends another Dream model, leveraging STI (single table inheritance)')
|
|
63
97
|
.option('--no-serializer')
|
|
64
98
|
.argument('<childModelName>', 'the name of the model to create, e.g. Post or Settings/CommunicationPreferences')
|
|
65
|
-
.argument('<extends>', 'just the word extends')
|
|
66
|
-
.argument('<parentModelName>',
|
|
67
|
-
|
|
99
|
+
.argument('<extends>', 'just the word "extends"')
|
|
100
|
+
.argument('<parentModelName>', `fully qualified name of the parent model, e.g.:
|
|
101
|
+
${INDENT} to extend the Room model in src/app/models/Room: Room
|
|
102
|
+
${INDENT} to extend the Coach model in src/app/models/Health/Coach: Health/Coach`)
|
|
103
|
+
.argument('[columnsWithTypes...]', columnsWithTypesDescription)
|
|
68
104
|
.action(async (childModelName, extendsWord, parentModelName, columnsWithTypes, options) => {
|
|
69
105
|
await initializeDreamApp();
|
|
70
106
|
if (extendsWord !== 'extends')
|
|
@@ -370,6 +370,52 @@ class DreamClassTransactionBuilder {
|
|
|
370
370
|
leftJoinPreload(...args) {
|
|
371
371
|
return this.queryInstance().leftJoinPreload(...args);
|
|
372
372
|
}
|
|
373
|
+
/**
|
|
374
|
+
* Recursively left-join-preloads all Dream associations referenced by `rendersOne` and `rendersMany`
|
|
375
|
+
* in a DreamSerializer. This traverses the entire content tree of serializers to automatically
|
|
376
|
+
* load all necessary associations, eliminating N+1 query problems and removing the need to
|
|
377
|
+
* manually remember which associations to preload for serialization.
|
|
378
|
+
*
|
|
379
|
+
* This method decouples data loading code from data rendering code by having the serializer
|
|
380
|
+
* (rendering code) inform the query (loading code) about which associations are needed.
|
|
381
|
+
* As serializers evolve over time - adding new `rendersOne` and `rendersMany` calls or
|
|
382
|
+
* modifying existing ones - the loading code automatically adapts without requiring
|
|
383
|
+
* corresponding modifications to preload statements.
|
|
384
|
+
*
|
|
385
|
+
* This method analyzes the serializer (specified by `serializerKey` or 'default') and
|
|
386
|
+
* automatically preloads all associations that will be needed during serialization.
|
|
387
|
+
*
|
|
388
|
+
* ```ts
|
|
389
|
+
* // Instead of manually specifying all associations:
|
|
390
|
+
* await User.preload('posts', 'comments', 'replies').all()
|
|
391
|
+
*
|
|
392
|
+
* // Automatically preload everything needed for serialization:
|
|
393
|
+
* await User.preloadFor('summary').all()
|
|
394
|
+
*
|
|
395
|
+
* // Add where conditions to specific associations during preloading:
|
|
396
|
+
* await User.txn(txn).leftJoinPreloadFor('detailed', (dreamClass, associationName) => {
|
|
397
|
+
* if (dreamClass.typeof(Post) && associationName === 'comments') {
|
|
398
|
+
* return { and: { published: true } }
|
|
399
|
+
* }
|
|
400
|
+
* }).all()
|
|
401
|
+
*
|
|
402
|
+
* // Skip preloading specific associations to handle them manually:
|
|
403
|
+
* await User.txn(txn).leftJoinPreloadFor('summary', (dreamClass, associationName) => {
|
|
404
|
+
* if (dreamClass.typeof(User) && associationName === 'posts') {
|
|
405
|
+
* return 'omit' // Handle posts preloading separately with custom logic
|
|
406
|
+
* }
|
|
407
|
+
* })
|
|
408
|
+
* .preload('posts', { and: { featured: true } }) // Custom preloading
|
|
409
|
+
* .all()
|
|
410
|
+
* ```
|
|
411
|
+
*
|
|
412
|
+
* @param serializerKey - The serializer key to use for determining which associations to preload.
|
|
413
|
+
* @param modifierFn - Optional callback function to modify or omit specific associations during preloading. Called for each association with the Dream class and association name. Return an object with `and`, `andAny`, or `andNot` properties to add where conditions, return 'omit' to skip preloading that association (useful when you want to handle it manually), or return undefined to use default preloading
|
|
414
|
+
* @returns A Query with all serialization associations preloaded
|
|
415
|
+
*/
|
|
416
|
+
leftJoinPreloadFor(serializerKey, modifierFn) {
|
|
417
|
+
return this.queryInstance().leftJoinPreloadFor(serializerKey, modifierFn);
|
|
418
|
+
}
|
|
373
419
|
/**
|
|
374
420
|
* Applies preload statement to a Query scoped to this model.
|
|
375
421
|
* Upon instantiating records of this model type,
|
|
@@ -394,6 +440,52 @@ class DreamClassTransactionBuilder {
|
|
|
394
440
|
preload(...args) {
|
|
395
441
|
return this.queryInstance().preload(...args);
|
|
396
442
|
}
|
|
443
|
+
/**
|
|
444
|
+
* Recursively preloads all Dream associations referenced by `rendersOne` and `rendersMany`
|
|
445
|
+
* in a DreamSerializer. This traverses the entire content tree of serializers to automatically
|
|
446
|
+
* load all necessary associations, eliminating N+1 query problems and removing the need to
|
|
447
|
+
* manually remember which associations to preload for serialization.
|
|
448
|
+
*
|
|
449
|
+
* This method decouples data loading code from data rendering code by having the serializer
|
|
450
|
+
* (rendering code) inform the query (loading code) about which associations are needed.
|
|
451
|
+
* As serializers evolve over time - adding new `rendersOne` and `rendersMany` calls or
|
|
452
|
+
* modifying existing ones - the loading code automatically adapts without requiring
|
|
453
|
+
* corresponding modifications to preload statements.
|
|
454
|
+
*
|
|
455
|
+
* This method analyzes the serializer (specified by `serializerKey` or 'default') and
|
|
456
|
+
* automatically preloads all associations that will be needed during serialization.
|
|
457
|
+
*
|
|
458
|
+
* ```ts
|
|
459
|
+
* // Instead of manually specifying all associations:
|
|
460
|
+
* await User.preload('posts', 'comments', 'replies').all()
|
|
461
|
+
*
|
|
462
|
+
* // Automatically preload everything needed for serialization:
|
|
463
|
+
* await User.preloadFor('summary').all()
|
|
464
|
+
*
|
|
465
|
+
* // Add where conditions to specific associations during preloading:
|
|
466
|
+
* await User.txn(txn).preloadFor('detailed', (dreamClass, associationName) => {
|
|
467
|
+
* if (dreamClass.typeof(Post) && associationName === 'comments') {
|
|
468
|
+
* return { and: { published: true } }
|
|
469
|
+
* }
|
|
470
|
+
* }).all()
|
|
471
|
+
*
|
|
472
|
+
* // Skip preloading specific associations to handle them manually:
|
|
473
|
+
* await User.txn(txn).preloadFor('summary', (dreamClass, associationName) => {
|
|
474
|
+
* if (dreamClass.typeof(User) && associationName === 'posts') {
|
|
475
|
+
* return 'omit' // Handle posts preloading separately with custom logic
|
|
476
|
+
* }
|
|
477
|
+
* })
|
|
478
|
+
* .preload('posts', { and: { featured: true } }) // Custom preloading
|
|
479
|
+
* .all()
|
|
480
|
+
* ```
|
|
481
|
+
*
|
|
482
|
+
* @param serializerKey - The serializer key to use for determining which associations to preload.
|
|
483
|
+
* @param modifierFn - Optional callback function to modify or omit specific associations during preloading. Called for each association with the Dream class and association name. Return an object with `and`, `andAny`, or `andNot` properties to add where conditions, return 'omit' to skip preloading that association (useful when you want to handle it manually), or return undefined to use default preloading
|
|
484
|
+
* @returns A Query with all serialization associations preloaded
|
|
485
|
+
*/
|
|
486
|
+
preloadFor(serializerKey, modifierFn) {
|
|
487
|
+
return this.queryInstance().preloadFor(serializerKey, modifierFn);
|
|
488
|
+
}
|
|
397
489
|
/**
|
|
398
490
|
* Returns a new Query instance with the provided
|
|
399
491
|
* inner join statement attached
|
|
@@ -55,6 +55,55 @@ class DreamInstanceTransactionBuilder {
|
|
|
55
55
|
load(...args) {
|
|
56
56
|
return new LoadBuilder_js_1.default(this.dreamInstance, this.dreamTransaction).load(...args);
|
|
57
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Recursively loads all Dream associations referenced by `rendersOne` and `rendersMany`
|
|
60
|
+
* in a DreamSerializer. This traverses the entire content tree of serializers to automatically
|
|
61
|
+
* load all necessary associations, eliminating N+1 query problems and removing the need to
|
|
62
|
+
* manually remember which associations to preload for serialization.
|
|
63
|
+
*
|
|
64
|
+
* This method decouples data loading code from data rendering code by having the serializer
|
|
65
|
+
* (rendering code) inform the query (loading code) about which associations are needed.
|
|
66
|
+
* As serializers evolve over time - adding new `rendersOne` and `rendersMany` calls or
|
|
67
|
+
* modifying existing ones - the loading code automatically adapts without requiring
|
|
68
|
+
* corresponding modifications to preload statements.
|
|
69
|
+
*
|
|
70
|
+
* This method analyzes the serializer (specified by `serializerKey` or 'default') and
|
|
71
|
+
* automatically preloads all associations that will be needed during serialization.
|
|
72
|
+
*
|
|
73
|
+
* ```ts
|
|
74
|
+
* // Instead of manually specifying all associations:
|
|
75
|
+
* await User.preload('posts', 'comments', 'replies').all()
|
|
76
|
+
*
|
|
77
|
+
* // Automatically preload everything needed for serialization:
|
|
78
|
+
* await user.loadFor('summary').execute()
|
|
79
|
+
*
|
|
80
|
+
* // Add where conditions to specific associations during preloading:
|
|
81
|
+
* await user.txn(txn).loadFor('detailed', (dreamClass, associationName) => {
|
|
82
|
+
* if (dreamClass.typeof(Post) && associationName === 'comments') {
|
|
83
|
+
* return { and: { published: true } }
|
|
84
|
+
* }
|
|
85
|
+
* })
|
|
86
|
+
* .execute()
|
|
87
|
+
*
|
|
88
|
+
* // Skip preloading specific associations to handle them manually:
|
|
89
|
+
* await user
|
|
90
|
+
* .txn(txn)
|
|
91
|
+
* .loadFor('summary', (dreamClass, associationName) => {
|
|
92
|
+
* if (dreamClass.typeof(User) && associationName === 'posts') {
|
|
93
|
+
* return 'omit' // Handle posts preloading separately with custom logic
|
|
94
|
+
* }
|
|
95
|
+
* })
|
|
96
|
+
* .load('posts', { and: { featured: true } }) // Custom preloading
|
|
97
|
+
* .execute()
|
|
98
|
+
* ```
|
|
99
|
+
*
|
|
100
|
+
* @param serializerKey - The serializer key to use for determining which associations to preload.
|
|
101
|
+
* @param modifierFn - Optional callback function to modify or omit specific associations during preloading. Called for each association with the Dream class and association name. Return an object with `and`, `andAny`, or `andNot` properties to add where conditions, return 'omit' to skip preloading that association (useful when you want to handle it manually), or return undefined to use default preloading
|
|
102
|
+
* @returns A Query with all serialization associations preloaded
|
|
103
|
+
*/
|
|
104
|
+
loadFor(serializerKey, modifierFn) {
|
|
105
|
+
return new LoadBuilder_js_1.default(this.dreamInstance, this.dreamTransaction)['loadFor'](serializerKey, modifierFn);
|
|
106
|
+
}
|
|
58
107
|
/**
|
|
59
108
|
* Load each specified association using a single SQL query.
|
|
60
109
|
* See {@link #load} for loading in separate queries.
|
|
@@ -90,6 +139,55 @@ class DreamInstanceTransactionBuilder {
|
|
|
90
139
|
leftJoinLoad(...args) {
|
|
91
140
|
return new LeftJoinLoadBuilder_js_1.default(this.dreamInstance, this.dreamTransaction).leftJoinLoad(...args);
|
|
92
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Recursively loads all Dream associations referenced by `rendersOne` and `rendersMany`
|
|
144
|
+
* in a DreamSerializer. This traverses the entire content tree of serializers to automatically
|
|
145
|
+
* load all necessary associations, eliminating N+1 query problems and removing the need to
|
|
146
|
+
* manually remember which associations to preload for serialization.
|
|
147
|
+
*
|
|
148
|
+
* This method decouples data loading code from data rendering code by having the serializer
|
|
149
|
+
* (rendering code) inform the query (loading code) about which associations are needed.
|
|
150
|
+
* As serializers evolve over time - adding new `rendersOne` and `rendersMany` calls or
|
|
151
|
+
* modifying existing ones - the loading code automatically adapts without requiring
|
|
152
|
+
* corresponding modifications to preload statements.
|
|
153
|
+
*
|
|
154
|
+
* This method analyzes the serializer (specified by `serializerKey` or 'default') and
|
|
155
|
+
* automatically preloads all associations that will be needed during serialization.
|
|
156
|
+
*
|
|
157
|
+
* ```ts
|
|
158
|
+
* // Instead of manually specifying all associations:
|
|
159
|
+
* await User.preload('posts', 'comments', 'replies').all()
|
|
160
|
+
*
|
|
161
|
+
* // Automatically preload everything needed for serialization:
|
|
162
|
+
* await user.leftJoinLoadFor('summary').execute()
|
|
163
|
+
*
|
|
164
|
+
* // Add where conditions to specific associations during preloading:
|
|
165
|
+
* await user.txn(txn).leftJoinLoadFor('detailed', (dreamClass, associationName) => {
|
|
166
|
+
* if (dreamClass.typeof(Post) && associationName === 'comments') {
|
|
167
|
+
* return { and: { published: true } }
|
|
168
|
+
* }
|
|
169
|
+
* })
|
|
170
|
+
* .execute()
|
|
171
|
+
*
|
|
172
|
+
* // Skip preloading specific associations to handle them manually:
|
|
173
|
+
* await user
|
|
174
|
+
* .txn(txn)
|
|
175
|
+
* .leftJoinLoadFor('summary', (dreamClass, associationName) => {
|
|
176
|
+
* if (dreamClass.typeof(User) && associationName === 'posts') {
|
|
177
|
+
* return 'omit' // Handle posts preloading separately with custom logic
|
|
178
|
+
* }
|
|
179
|
+
* })
|
|
180
|
+
* .load('posts', { and: { featured: true } }) // Custom preloading
|
|
181
|
+
* .execute()
|
|
182
|
+
* ```
|
|
183
|
+
*
|
|
184
|
+
* @param serializerKey - The serializer key to use for determining which associations to preload.
|
|
185
|
+
* @param modifierFn - Optional callback function to modify or omit specific associations during preloading. Called for each association with the Dream class and association name. Return an object with `and`, `andAny`, or `andNot` properties to add where conditions, return 'omit' to skip preloading that association (useful when you want to handle it manually), or return undefined to use default preloading
|
|
186
|
+
* @returns A Query with all serialization associations preloaded
|
|
187
|
+
*/
|
|
188
|
+
leftJoinLoadFor(serializerKey, modifierFn) {
|
|
189
|
+
return new LeftJoinLoadBuilder_js_1.default(this.dreamInstance, this.dreamTransaction)['leftJoinLoadFor'](serializerKey, modifierFn);
|
|
190
|
+
}
|
|
93
191
|
/**
|
|
94
192
|
* Returns a new Query instance with the provided
|
|
95
193
|
* inner join statement attached
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const UnexpectedUndefined_js_1 = require("../errors/UnexpectedUndefined.js");
|
|
4
|
+
const unaliasTableName_js_1 = require("./internal/unaliasTableName.js");
|
|
4
5
|
class LeftJoinLoadBuilder {
|
|
5
6
|
dreamTransaction;
|
|
6
7
|
dream;
|
|
@@ -45,6 +46,55 @@ class LeftJoinLoadBuilder {
|
|
|
45
46
|
this.query = this.query.leftJoinPreload(...args);
|
|
46
47
|
return this;
|
|
47
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Recursively loads all Dream associations referenced by `rendersOne` and `rendersMany`
|
|
51
|
+
* in a DreamSerializer. This traverses the entire content tree of serializers to automatically
|
|
52
|
+
* load all necessary associations, eliminating N+1 query problems and removing the need to
|
|
53
|
+
* manually remember which associations to preload for serialization.
|
|
54
|
+
*
|
|
55
|
+
* This method decouples data loading code from data rendering code by having the serializer
|
|
56
|
+
* (rendering code) inform the query (loading code) about which associations are needed.
|
|
57
|
+
* As serializers evolve over time - adding new `rendersOne` and `rendersMany` calls or
|
|
58
|
+
* modifying existing ones - the loading code automatically adapts without requiring
|
|
59
|
+
* corresponding modifications to preload statements.
|
|
60
|
+
*
|
|
61
|
+
* This method analyzes the serializer (specified by `serializerKey` or 'default') and
|
|
62
|
+
* automatically preloads all associations that will be needed during serialization.
|
|
63
|
+
*
|
|
64
|
+
* ```ts
|
|
65
|
+
* // Instead of manually specifying all associations:
|
|
66
|
+
* await User.preload('posts', 'comments', 'replies').all()
|
|
67
|
+
*
|
|
68
|
+
* // Automatically preload everything needed for serialization:
|
|
69
|
+
* await user.leftJoinLoadFor('summary').execute()
|
|
70
|
+
*
|
|
71
|
+
* // Add where conditions to specific associations during preloading:
|
|
72
|
+
* await user.leftJoinLoadFor('detailed', (dreamClass, associationName) => {
|
|
73
|
+
* if (dreamClass.typeof(Post) && associationName === 'comments') {
|
|
74
|
+
* return { and: { published: true } }
|
|
75
|
+
* }
|
|
76
|
+
* })
|
|
77
|
+
* .execute()
|
|
78
|
+
*
|
|
79
|
+
* // Skip preloading specific associations to handle them manually:
|
|
80
|
+
* await user
|
|
81
|
+
* .leftJoinLoadFor('summary', (dreamClass, associationName) => {
|
|
82
|
+
* if (dreamClass.typeof(User) && associationName === 'posts') {
|
|
83
|
+
* return 'omit' // Handle posts preloading separately with custom logic
|
|
84
|
+
* }
|
|
85
|
+
* })
|
|
86
|
+
* .load('posts', { and: { featured: true } }) // Custom preloading
|
|
87
|
+
* .execute()
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* @param serializerKey - The serializer key to use for determining which associations to preload.
|
|
91
|
+
* @param modifierFn - Optional callback function to modify or omit specific associations during preloading. Called for each association with the Dream class and association name. Return an object with `and`, `andAny`, or `andNot` properties to add where conditions, return 'omit' to skip preloading that association (useful when you want to handle it manually), or return undefined to use default preloading
|
|
92
|
+
* @returns A Query with all serialization associations preloaded
|
|
93
|
+
*/
|
|
94
|
+
leftJoinLoadFor(serializerKey, modifierFn) {
|
|
95
|
+
this.query = this.query.leftJoinPreloadFor(serializerKey, modifierFn);
|
|
96
|
+
return this;
|
|
97
|
+
}
|
|
48
98
|
/**
|
|
49
99
|
* executes a load builder query, binding
|
|
50
100
|
* all associations to their respective model
|
|
@@ -63,7 +113,8 @@ class LeftJoinLoadBuilder {
|
|
|
63
113
|
this.query = this.query.txn(this.dreamTransaction);
|
|
64
114
|
}
|
|
65
115
|
const dreamWithLoadedAssociations = await this.query.firstOrFail();
|
|
66
|
-
Object.keys(this.query['leftJoinStatements']).forEach(
|
|
116
|
+
Object.keys(this.query['leftJoinStatements']).forEach(aliasedAssociationName => {
|
|
117
|
+
const associationName = (0, unaliasTableName_js_1.default)(aliasedAssociationName);
|
|
67
118
|
const associationMetadata = this.dream['getAssociationMetadata'](associationName);
|
|
68
119
|
if (associationMetadata === undefined)
|
|
69
120
|
throw new UnexpectedUndefined_js_1.default();
|