@rvoh/dream 2.5.7 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. package/dist/cjs/src/Dream.js +37 -66
  2. package/dist/cjs/src/decorators/class/STI.js +2 -2
  3. package/dist/cjs/src/dream/LeftJoinLoadBuilder.js +16 -10
  4. package/dist/cjs/src/dream/LoadBuilder.js +70 -9
  5. package/dist/cjs/src/dream/Query.js +5 -6
  6. package/dist/cjs/src/dream/constants.js +2 -0
  7. package/dist/cjs/src/dream/internal/buildAssociationPaths.js +33 -0
  8. package/dist/cjs/src/dream/internal/buildDependentDestroyPreloadPaths.js +43 -0
  9. package/dist/cjs/src/dream/internal/buildSerializerPreloadPaths.js +38 -0
  10. package/dist/cjs/src/dream/internal/destroyAssociatedRecords.js +14 -6
  11. package/dist/cjs/src/dream/internal/destroyDream.js +7 -1
  12. package/dist/cjs/src/dream/internal/loadDependentDestroyTree.js +35 -0
  13. package/dist/cjs/src/dream/internal/resolveSerializerAssociationEdges.js +53 -0
  14. package/dist/cjs/src/serializer/SerializerRenderer.js +1 -1
  15. package/dist/cjs/src/serializer/builders/DreamSerializerBuilder.js +114 -52
  16. package/dist/cjs/src/serializer/builders/ObjectSerializerBuilder.js +111 -41
  17. package/dist/cjs/src/types/recursiveSerialization.js +1 -0
  18. package/dist/esm/src/Dream.js +37 -66
  19. package/dist/esm/src/decorators/class/STI.js +2 -2
  20. package/dist/esm/src/dream/LeftJoinLoadBuilder.js +16 -10
  21. package/dist/esm/src/dream/LoadBuilder.js +70 -9
  22. package/dist/esm/src/dream/Query.js +5 -6
  23. package/dist/esm/src/dream/constants.js +2 -0
  24. package/dist/esm/src/dream/internal/buildAssociationPaths.js +33 -0
  25. package/dist/esm/src/dream/internal/buildDependentDestroyPreloadPaths.js +43 -0
  26. package/dist/esm/src/dream/internal/buildSerializerPreloadPaths.js +38 -0
  27. package/dist/esm/src/dream/internal/destroyAssociatedRecords.js +14 -6
  28. package/dist/esm/src/dream/internal/destroyDream.js +7 -1
  29. package/dist/esm/src/dream/internal/loadDependentDestroyTree.js +35 -0
  30. package/dist/esm/src/dream/internal/resolveSerializerAssociationEdges.js +53 -0
  31. package/dist/esm/src/serializer/SerializerRenderer.js +1 -1
  32. package/dist/esm/src/serializer/builders/DreamSerializerBuilder.js +114 -52
  33. package/dist/esm/src/serializer/builders/ObjectSerializerBuilder.js +111 -41
  34. package/dist/esm/src/types/recursiveSerialization.js +1 -0
  35. package/dist/types/src/Dream.d.ts +25 -10
  36. package/dist/types/src/decorators/Decorators.d.ts +8 -0
  37. package/dist/types/src/decorators/class/STI.d.ts +1 -3
  38. package/dist/types/src/decorators/field/sortable/Sortable.d.ts +9 -0
  39. package/dist/types/src/decorators/field/validation/Validates.d.ts +4 -0
  40. package/dist/types/src/decorators/static-method/Scope.d.ts +4 -0
  41. package/dist/types/src/dream/LeftJoinLoadBuilder.d.ts +16 -10
  42. package/dist/types/src/dream/LoadBuilder.d.ts +63 -10
  43. package/dist/types/src/dream/Query.d.ts +1 -1
  44. package/dist/types/src/dream/constants.d.ts +2 -0
  45. package/dist/types/src/dream/internal/buildAssociationPaths.d.ts +12 -0
  46. package/dist/types/src/dream/internal/buildDependentDestroyPreloadPaths.d.ts +17 -0
  47. package/dist/types/src/dream/internal/buildSerializerPreloadPaths.d.ts +3 -0
  48. package/dist/types/src/dream/internal/convertDreamClassAndAssociationNameTupleArrayToPreloadArgs.d.ts +1 -1
  49. package/dist/types/src/dream/internal/destroyAssociatedRecords.d.ts +5 -1
  50. package/dist/types/src/dream/internal/loadDependentDestroyTree.d.ts +17 -0
  51. package/dist/types/src/dream/internal/resolveSerializerAssociationEdges.d.ts +13 -0
  52. package/dist/types/src/serializer/builders/DreamSerializerBuilder.d.ts +164 -63
  53. package/dist/types/src/serializer/builders/ObjectSerializerBuilder.d.ts +126 -43
  54. package/dist/types/src/types/associations/belongsTo.d.ts +34 -0
  55. package/dist/types/src/types/associations/belongsTo.ts +41 -0
  56. package/dist/types/src/types/associations/hasMany.d.ts +18 -0
  57. package/dist/types/src/types/associations/hasMany.ts +18 -0
  58. package/dist/types/src/types/associations/shared.d.ts +71 -0
  59. package/dist/types/src/types/associations/shared.ts +74 -0
  60. package/dist/types/src/types/dream.d.ts +16 -0
  61. package/dist/types/src/types/dream.ts +18 -0
  62. package/dist/types/src/types/lifecycle.d.ts +18 -0
  63. package/dist/types/src/types/lifecycle.ts +18 -0
  64. package/dist/types/src/types/query.d.ts +3 -0
  65. package/dist/types/src/types/query.ts +3 -0
  66. package/dist/types/src/types/recursiveSerialization.d.ts +8 -0
  67. package/dist/types/src/types/recursiveSerialization.ts +10 -0
  68. package/dist/types/src/types/serializer.d.ts +8 -1
  69. package/dist/types/src/types/serializer.ts +8 -1
  70. package/docs/classes/db.DreamMigrationHelpers.html +9 -9
  71. package/docs/classes/db.KyselyQueryDriver.html +32 -32
  72. package/docs/classes/db.PostgresQueryDriver.html +33 -33
  73. package/docs/classes/db.QueryDriverBase.html +31 -31
  74. package/docs/classes/errors.CheckConstraintViolation.html +3 -3
  75. package/docs/classes/errors.ColumnOverflow.html +3 -3
  76. package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
  77. package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +3 -3
  78. package/docs/classes/errors.DataTypeColumnTypeMismatch.html +3 -3
  79. package/docs/classes/errors.GlobalNameNotSet.html +3 -3
  80. package/docs/classes/errors.InvalidCalendarDate.html +2 -2
  81. package/docs/classes/errors.InvalidClockTime.html +2 -2
  82. package/docs/classes/errors.InvalidClockTimeTz.html +2 -2
  83. package/docs/classes/errors.InvalidDateTime.html +2 -2
  84. package/docs/classes/errors.MissingSerializersDefinition.html +3 -3
  85. package/docs/classes/errors.NonLoadedAssociation.html +3 -3
  86. package/docs/classes/errors.NotNullViolation.html +3 -3
  87. package/docs/classes/errors.RecordNotFound.html +3 -3
  88. package/docs/classes/errors.ValidationError.html +3 -3
  89. package/docs/classes/index.CalendarDate.html +33 -33
  90. package/docs/classes/index.ClockTime.html +32 -32
  91. package/docs/classes/index.ClockTimeTz.html +35 -35
  92. package/docs/classes/index.DateTime.html +86 -86
  93. package/docs/classes/index.Decorators.html +21 -20
  94. package/docs/classes/index.Dream.html +133 -126
  95. package/docs/classes/index.DreamApp.html +5 -5
  96. package/docs/classes/index.DreamTransaction.html +2 -2
  97. package/docs/classes/index.Env.html +2 -2
  98. package/docs/classes/index.Query.html +57 -57
  99. package/docs/classes/system.CliFileWriter.html +4 -4
  100. package/docs/classes/system.DreamBin.html +2 -2
  101. package/docs/classes/system.DreamCLI.html +6 -6
  102. package/docs/classes/system.DreamImporter.html +2 -2
  103. package/docs/classes/system.DreamLogos.html +2 -2
  104. package/docs/classes/system.DreamSerializerBuilder.html +177 -59
  105. package/docs/classes/system.ObjectSerializerBuilder.html +110 -34
  106. package/docs/classes/system.PathHelpers.html +3 -3
  107. package/docs/classes/utils.Encrypt.html +2 -2
  108. package/docs/classes/utils.Range.html +2 -2
  109. package/docs/functions/db.closeAllDbConnections.html +1 -1
  110. package/docs/functions/db.dreamDbConnections.html +1 -1
  111. package/docs/functions/db.untypedDb.html +1 -1
  112. package/docs/functions/db.validateColumn.html +1 -1
  113. package/docs/functions/db.validateTable.html +1 -1
  114. package/docs/functions/errors.pgErrorType.html +1 -1
  115. package/docs/functions/index.DreamSerializer.html +1 -1
  116. package/docs/functions/index.ObjectSerializer.html +1 -1
  117. package/docs/functions/index.ReplicaSafe.html +1 -1
  118. package/docs/functions/index.STI.html +1 -1
  119. package/docs/functions/index.SoftDelete.html +1 -1
  120. package/docs/functions/utils.camelize.html +1 -1
  121. package/docs/functions/utils.capitalize.html +1 -1
  122. package/docs/functions/utils.cloneDeepSafe.html +1 -1
  123. package/docs/functions/utils.compact.html +1 -1
  124. package/docs/functions/utils.groupBy.html +1 -1
  125. package/docs/functions/utils.hyphenize.html +1 -1
  126. package/docs/functions/utils.intersection.html +1 -1
  127. package/docs/functions/utils.isEmpty.html +1 -1
  128. package/docs/functions/utils.normalizeUnicode.html +1 -1
  129. package/docs/functions/utils.pascalize.html +1 -1
  130. package/docs/functions/utils.percent.html +1 -1
  131. package/docs/functions/utils.range.html +1 -1
  132. package/docs/functions/utils.round.html +1 -1
  133. package/docs/functions/utils.sanitizeString.html +1 -1
  134. package/docs/functions/utils.snakeify.html +1 -1
  135. package/docs/functions/utils.sort.html +1 -1
  136. package/docs/functions/utils.sortBy.html +1 -1
  137. package/docs/functions/utils.sortObjectByKey.html +1 -1
  138. package/docs/functions/utils.sortObjectByValue.html +1 -1
  139. package/docs/functions/utils.uncapitalize.html +1 -1
  140. package/docs/functions/utils.uniq.html +1 -1
  141. package/docs/interfaces/openapi.OpenapiDescription.html +2 -2
  142. package/docs/interfaces/openapi.OpenapiSchemaProperties.html +1 -1
  143. package/docs/interfaces/openapi.OpenapiSchemaPropertiesShorthand.html +1 -1
  144. package/docs/interfaces/openapi.OpenapiTypeFieldObject.html +1 -1
  145. package/docs/interfaces/types.BelongsToStatement.html +2 -2
  146. package/docs/interfaces/types.DecoratorContext.html +2 -2
  147. package/docs/interfaces/types.DreamAppInitOptions.html +2 -2
  148. package/docs/interfaces/types.DreamAppOpts.html +2 -2
  149. package/docs/interfaces/types.DurationObject.html +2 -2
  150. package/docs/interfaces/types.EncryptOptions.html +2 -2
  151. package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
  152. package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
  153. package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
  154. package/docs/types/openapi.CommonOpenapiSchemaObjectFields.html +1 -1
  155. package/docs/types/openapi.OpenapiAllTypes.html +1 -1
  156. package/docs/types/openapi.OpenapiFormats.html +1 -1
  157. package/docs/types/openapi.OpenapiNumberFormats.html +1 -1
  158. package/docs/types/openapi.OpenapiPrimitiveBaseTypes.html +1 -1
  159. package/docs/types/openapi.OpenapiPrimitiveTypes.html +1 -1
  160. package/docs/types/openapi.OpenapiSchemaArray.html +1 -1
  161. package/docs/types/openapi.OpenapiSchemaArrayShorthand.html +1 -1
  162. package/docs/types/openapi.OpenapiSchemaBase.html +1 -1
  163. package/docs/types/openapi.OpenapiSchemaBody.html +1 -1
  164. package/docs/types/openapi.OpenapiSchemaBodyShorthand.html +1 -1
  165. package/docs/types/openapi.OpenapiSchemaCommonFields.html +1 -1
  166. package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +2 -2
  167. package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +2 -2
  168. package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +2 -2
  169. package/docs/types/openapi.OpenapiSchemaExpressionRef.html +2 -2
  170. package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +2 -2
  171. package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
  172. package/docs/types/openapi.OpenapiSchemaNull.html +2 -2
  173. package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
  174. package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
  175. package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +1 -1
  176. package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +1 -1
  177. package/docs/types/openapi.OpenapiSchemaObjectAnyOf.html +1 -1
  178. package/docs/types/openapi.OpenapiSchemaObjectAnyOfShorthand.html +1 -1
  179. package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
  180. package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
  181. package/docs/types/openapi.OpenapiSchemaObjectOneOf.html +1 -1
  182. package/docs/types/openapi.OpenapiSchemaObjectOneOfShorthand.html +1 -1
  183. package/docs/types/openapi.OpenapiSchemaObjectShorthand.html +1 -1
  184. package/docs/types/openapi.OpenapiSchemaPrimitiveGeneric.html +1 -1
  185. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAllOf.html +2 -2
  186. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +2 -2
  187. package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +2 -2
  188. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +2 -2
  189. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +2 -2
  190. package/docs/types/openapi.OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
  191. package/docs/types/openapi.OpenapiSchemaString.html +1 -1
  192. package/docs/types/openapi.OpenapiShorthandAllTypes.html +1 -1
  193. package/docs/types/openapi.OpenapiShorthandPrimitiveBaseTypes.html +1 -1
  194. package/docs/types/openapi.OpenapiShorthandPrimitiveTypes.html +1 -1
  195. package/docs/types/openapi.OpenapiTypeField.html +1 -1
  196. package/docs/types/system.DreamAppAllowedPackageManagersEnum.html +1 -1
  197. package/docs/types/types.CalendarDateDurationUnit.html +1 -1
  198. package/docs/types/types.CalendarDateObject.html +1 -1
  199. package/docs/types/types.Camelized.html +1 -1
  200. package/docs/types/types.ClockTimeObject.html +1 -1
  201. package/docs/types/types.DbConnectionType.html +1 -1
  202. package/docs/types/types.DbTypes.html +1 -1
  203. package/docs/types/types.DreamAssociationMetadata.html +1 -1
  204. package/docs/types/types.DreamAttributes.html +1 -1
  205. package/docs/types/types.DreamClassAssociationAndStatement.html +1 -1
  206. package/docs/types/types.DreamClassColumn.html +1 -1
  207. package/docs/types/types.DreamColumn.html +1 -1
  208. package/docs/types/types.DreamColumnNames.html +1 -1
  209. package/docs/types/types.DreamLogLevel.html +1 -1
  210. package/docs/types/types.DreamLogger.html +2 -2
  211. package/docs/types/types.DreamModelSerializerType.html +1 -1
  212. package/docs/types/types.DreamOrViewModelClassSerializerKey.html +1 -1
  213. package/docs/types/types.DreamOrViewModelSerializerKey.html +1 -1
  214. package/docs/types/types.DreamParamSafeAttributes.html +1 -1
  215. package/docs/types/types.DreamParamSafeColumnNames.html +1 -1
  216. package/docs/types/types.DreamSerializable.html +1 -1
  217. package/docs/types/types.DreamSerializableArray.html +1 -1
  218. package/docs/types/types.DreamSerializerKey.html +1 -1
  219. package/docs/types/types.DreamSerializers.html +1 -1
  220. package/docs/types/types.DreamVirtualColumns.html +1 -1
  221. package/docs/types/types.DurationUnit.html +1 -1
  222. package/docs/types/types.EncryptAlgorithm.html +1 -1
  223. package/docs/types/types.HasManyStatement.html +1 -1
  224. package/docs/types/types.HasOneStatement.html +1 -1
  225. package/docs/types/types.Hyphenized.html +1 -1
  226. package/docs/types/types.Pascalized.html +1 -1
  227. package/docs/types/types.PrimaryKeyType.html +1 -1
  228. package/docs/types/types.RoundingPrecision.html +1 -1
  229. package/docs/types/types.SerializerCasing.html +1 -1
  230. package/docs/types/types.SimpleObjectSerializerType.html +1 -1
  231. package/docs/types/types.Snakeified.html +1 -1
  232. package/docs/types/types.StrictInterface.html +1 -1
  233. package/docs/types/types.UpdateableAssociationProperties.html +1 -1
  234. package/docs/types/types.UpdateableProperties.html +1 -1
  235. package/docs/types/types.ValidationType.html +1 -1
  236. package/docs/types/types.ViewModel.html +2 -2
  237. package/docs/types/types.ViewModelClass.html +1 -1
  238. package/docs/types/types.WeekdayName.html +1 -1
  239. package/docs/types/types.WhereStatementForDream.html +1 -1
  240. package/docs/types/types.WhereStatementForDreamClass.html +1 -1
  241. package/docs/variables/index.DreamConst.html +1 -1
  242. package/docs/variables/index.ops.html +1 -1
  243. package/docs/variables/openapi.openapiPrimitiveTypes.html +1 -1
  244. package/docs/variables/openapi.openapiShorthandPrimitiveTypes.html +1 -1
  245. package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
  246. package/docs/variables/system.primaryKeyTypes.html +1 -1
  247. package/package.json +1 -1
  248. package/dist/cjs/src/dream/internal/extractNestedPaths.js +0 -34
  249. package/dist/esm/src/dream/internal/extractNestedPaths.js +0 -34
  250. package/dist/types/src/dream/internal/extractNestedPaths.d.ts +0 -21
@@ -0,0 +1,53 @@
1
+ import MissingSerializersDefinition from '../../errors/serializers/MissingSerializersDefinition.js';
2
+ import compact from '../../helpers/compact.js';
3
+ import { inferSerializersFromDreamClassOrViewModelClass } from '../../serializer/helpers/inferSerializerFromDreamOrViewModel.js';
4
+ export default function resolveSerializerAssociationEdges(dreamClass, serializer) {
5
+ const serializerBuilder = serializer(undefined, undefined);
6
+ const serializerAssociations = serializerBuilder['attributes'].filter(attribute => ['rendersOne', 'rendersMany', 'delegatedAttribute'].includes(attribute.type));
7
+ return compact(serializerAssociations.map(serializerAssociation => {
8
+ const serializerAssociationName = serializerAssociation.targetName ??
9
+ serializerAssociation.name;
10
+ const association = dreamClass['getAssociationMetadata'](serializerAssociationName);
11
+ if (!association)
12
+ return null;
13
+ if (serializerAssociation.type === 'delegatedAttribute') {
14
+ return {
15
+ associationAs: association.as,
16
+ sourceDreamClass: dreamClass,
17
+ type: serializerAssociation.type,
18
+ serializerAssociationName,
19
+ targets: [],
20
+ };
21
+ }
22
+ const maybeAssociatedClasses = association.modelCB();
23
+ if (!maybeAssociatedClasses)
24
+ throw new Error(`No class defined on ${serializerAssociationName} association on ${dreamClass.sanitizedName}`);
25
+ const associatedClasses = Array.isArray(maybeAssociatedClasses)
26
+ ? maybeAssociatedClasses
27
+ : [maybeAssociatedClasses];
28
+ const targets = associatedClasses.flatMap(associatedClass => {
29
+ let serializers = [];
30
+ try {
31
+ serializers = serializerAssociation.options.serializer
32
+ ? compact([serializerAssociation.options.serializer])
33
+ : compact(inferSerializersFromDreamClassOrViewModelClass(associatedClass, serializerAssociation.options.serializerKey));
34
+ }
35
+ catch (error) {
36
+ if (!(error instanceof MissingSerializersDefinition))
37
+ throw error;
38
+ serializers = [];
39
+ }
40
+ return serializers.map(associatedSerializer => ({
41
+ dreamClass: associatedClass,
42
+ serializer: associatedSerializer,
43
+ }));
44
+ });
45
+ return {
46
+ associationAs: association.as,
47
+ sourceDreamClass: dreamClass,
48
+ type: serializerAssociation.type,
49
+ serializerAssociationName,
50
+ targets,
51
+ };
52
+ }));
53
+ }
@@ -158,7 +158,7 @@ export default class SerializerRenderer {
158
158
  // does not pass it into the call to DreamSerializer/ObjectSerializer,
159
159
  // then it would be lost to serializers rendered via rendersOne/Many, and SerializerRenderer
160
160
  // handles passing its passthrough data into those
161
- .render(passthroughData));
161
+ .render(passthroughData, this.renderOpts));
162
162
  });
163
163
  return accumulator;
164
164
  }
@@ -20,30 +20,50 @@ export default class DreamSerializerBuilder {
20
20
  /**
21
21
  * Includes an attribute from a nested object in the serialized output.
22
22
  *
23
- * Serializes an attribute from a target object. If the target object or
24
- * the delegated attribute is null/undefined, the `default` option value
23
+ * Accesses `targetName.name` on the data object. If the target object
24
+ * or the delegated attribute is null/undefined, the `default` option value
25
25
  * will be used if provided.
26
26
  *
27
- * @param targetName - The property name containing the target object
27
+ * When the target is a Dream model, OpenAPI types may be automatically inferred
28
+ * for standard database columns. For json/jsonb columns or non-Dream targets,
29
+ * the `openapi` option is required.
30
+ *
31
+ * @param targetName - The property name containing the target object (e.g., an association name)
28
32
  * @param name - The attribute name within the target object
29
- * @param options - Configuration options including OpenAPI schema, default value, and output customization
33
+ * @param options - Configuration options:
34
+ * - `as` - Rename the attribute key in the serialized output and OpenAPI shape
35
+ * (e.g., delegating `'user', 'email'` with `as: 'userEmail'` outputs the value
36
+ * under `userEmail`)
37
+ * - `default` - Value to use when the target object or its attribute is null/undefined
38
+ * - `openapi` - OpenAPI schema definition; required for non-Dream targets and json/jsonb
39
+ * columns, optional for standard Dream columns (where types are inferred)
40
+ * - `optional` - Set to `true` to indicate the value can be null in the OpenAPI schema
41
+ * (wraps the type in `anyOf: [schema, { type: 'null' }]`). For Dream models, this is
42
+ * auto-inferred from optional BelongsTo associations. Use this when delegating through
43
+ * a HasOne or other nullable association.
44
+ * - `precision` - Round decimal values to the specified number of decimal places (0–9)
45
+ * during rendering; does not affect the OpenAPI shape
46
+ * - `required` - Set to `false` to mark the attribute as optional in the OpenAPI schema;
47
+ * when omitted, attributes are required by default
30
48
  * @returns The serializer builder for method chaining
31
49
  *
32
50
  * @example
33
51
  * ```typescript
34
- * // Delegate to user.email
35
- * .delegatedAttribute('user', 'email', {
36
- * openapi: { type: 'string', format: 'email' }
37
- * })
52
+ * // Delegate to a Dream association's column (type inferred)
53
+ * .delegatedAttribute('currentLocalizedText', 'title', { openapi: 'string' })
38
54
  *
39
55
  * // With default value for null target or attribute
40
56
  * .delegatedAttribute('user', 'displayName', {
41
57
  * openapi: { type: 'string' },
42
58
  * default: 'Unknown User'
43
59
  * })
44
- * ```
45
60
  *
46
- * See: {@link https://your-docs-url.com/docs/serializers/attributes | Serializer Attributes Documentation}
61
+ * // Rename the output key
62
+ * .delegatedAttribute('profile', 'avatarUrl', {
63
+ * openapi: 'string',
64
+ * as: 'avatar'
65
+ * })
66
+ * ```
47
67
  */
48
68
  delegatedAttribute(targetName, name, options) {
49
69
  this.attributes.push({
@@ -62,7 +82,17 @@ export default class DreamSerializerBuilder {
62
82
  *
63
83
  * @param name - The attribute name for the computed value
64
84
  * @param fn - Callback function that returns the computed value
65
- * @param options - Configuration options including required OpenAPI schema and optional flattening
85
+ * @param options - Configuration options:
86
+ * - `openapi` - (required) OpenAPI schema definition for the computed value
87
+ * - `as` - Rename the attribute key in the serialized output and OpenAPI shape
88
+ * - `default` - Value to use when the callback returns undefined
89
+ * - `flatten` - When `true`, spreads the returned object's properties directly into the
90
+ * parent serialized output instead of nesting them under `name`; the `openapi` option
91
+ * should then define each flattened property individually
92
+ * - `precision` - Round decimal values to the specified number of decimal places (0–9)
93
+ * during rendering; does not affect the OpenAPI shape
94
+ * - `required` - Set to `false` to mark the attribute as optional in the OpenAPI schema;
95
+ * when omitted, attributes are required by default
66
96
  * @returns The serializer builder for method chaining
67
97
  *
68
98
  * @example
@@ -74,16 +104,20 @@ export default class DreamSerializerBuilder {
74
104
  * )
75
105
  *
76
106
  * // Flattened object properties
77
- * .customAttribute('metadata', () => ({ age: 30, city: 'NYC' }), {
107
+ * .customAttribute('coordinates', () => ({ lat: 40.7, lng: -74.0 }), {
78
108
  * flatten: true,
79
109
  * openapi: {
80
- * age: { type: 'integer' },
81
- * city: { type: 'string' }
110
+ * lat: { type: 'number' },
111
+ * lng: { type: 'number' }
82
112
  * }
83
113
  * })
84
- * ```
85
114
  *
86
- * See: {@link https://your-docs-url.com/docs/serializers/attributes | Serializer Attributes Documentation}
115
+ * // With decimal precision
116
+ * .customAttribute('averageRating', () => calculateAverage(ratings), {
117
+ * openapi: 'decimal',
118
+ * precision: 2
119
+ * })
120
+ * ```
87
121
  */
88
122
  customAttribute(name, fn, options) {
89
123
  this.attributes.push({
@@ -97,28 +131,50 @@ export default class DreamSerializerBuilder {
97
131
  /**
98
132
  * Includes a single associated object in the serialized output.
99
133
  *
100
- * When rendering a Dream association, the OpenAPI shape is automatically
101
- * inferred from that associated Dream's serializer.
134
+ * When rendering a Dream association, the serializer and OpenAPI shape are automatically
135
+ * inferred from that associated Dream model's registered serializers.
102
136
  *
103
137
  * @param name - The association property name
104
- * @param options - Configuration options for serialization and schema definition
138
+ * @param options - Configuration options:
139
+ * - `as` - Rename the association key in the serialized output
140
+ * - `flatten` - When `true`, spreads the rendered association's attributes directly into
141
+ * the parent serialized output instead of nesting them under `name`. Be aware of
142
+ * attribute shadowing: if the parent and flattened association share attribute names
143
+ * (e.g., `id`), the flattened association's values overwrite the parent's
144
+ * - `optional` - When `true`, allows the association to be null/missing without causing
145
+ * an `OpenapiResponseValidationFailure` during Psychic controller unit specs. By default,
146
+ * `rendersOne` expects the association to be present (mirroring the `optional` option on
147
+ * `@deco.BelongsTo`). Set this to `true` when the association is genuinely nullable
148
+ * - `serializerKey` - Use a specific serializer key from the associated Dream model's
149
+ * registered serializers (e.g., `'summary'`)
150
+ * - `serializer` - Provide an explicit serializer function instead of using the
151
+ * associated model's registered serializers
152
+ *
153
+ * For ViewModel associations, one of these is required:
154
+ * - `viewModelClass` + optional `serializerKey`
155
+ * - `serializer`
156
+ *
157
+ * For non-Dream/non-ViewModel associations:
158
+ * - `serializer` is required
105
159
  * @returns The serializer builder for method chaining
106
160
  *
107
161
  * @example
108
162
  * ```typescript
109
- * // DreamSerializer with inference
110
- * .rendersOne('user') // Infers from Dream association
163
+ * // Auto-infer serializer from Dream association
164
+ * .rendersOne('profile')
111
165
  *
112
- * // With specific serializer
166
+ * // With specific serializer key
113
167
  * .rendersOne('user', { serializerKey: 'summary' })
114
168
  *
115
- * // ObjectSerializer (explicit configuration required)
116
- * .rendersOne('owner', UserSerializer, {
117
- * openapi: { $ref: '#/components/schemas/User' }
118
- * })
119
- * ```
169
+ * // Allow null association
170
+ * .rendersOne('approver', { optional: true })
120
171
  *
121
- * See: {@link https://your-docs-url.com/docs/serializers/associations | Serializer Associations Documentation}
172
+ * // Flatten into parent object
173
+ * .rendersOne('candidate', { serializerKey: 'summary', flatten: true })
174
+ *
175
+ * // Explicit serializer function
176
+ * .rendersOne('owner', { serializer: CustomOwnerSerializer })
177
+ * ```
122
178
  */
123
179
  rendersOne(name, options) {
124
180
  this.attributes.push({
@@ -131,31 +187,39 @@ export default class DreamSerializerBuilder {
131
187
  /**
132
188
  * Includes an array of associated objects in the serialized output.
133
189
  *
134
- * When rendering a Dream association, the OpenAPI shape is automatically
135
- * inferred from that associated Dream's serializer.
190
+ * When rendering a Dream association, the serializer and OpenAPI shape are automatically
191
+ * inferred from that associated Dream model's registered serializers.
192
+ *
193
+ * @param name - The association property name (should resolve to an array)
194
+ * @param options - Configuration options:
195
+ * - `as` - Rename the association key in the serialized output
196
+ * - `serializerKey` - Use a specific serializer key from the associated Dream model's
197
+ * registered serializers (e.g., `'summary'`)
198
+ * - `serializer` - Provide an explicit serializer function instead of using the
199
+ * associated model's registered serializers
136
200
  *
137
- * @param name - The association property name (should be an array)
138
- * @param options - Configuration options for serialization and schema definition
201
+ * For ViewModel associations, one of these is required:
202
+ * - `viewModelClass` + optional `serializerKey`
203
+ * - `serializer`
204
+ *
205
+ * For non-Dream/non-ViewModel associations:
206
+ * - `serializer` is required
139
207
  * @returns The serializer builder for method chaining
140
208
  *
141
209
  * @example
142
210
  * ```typescript
143
- * // DreamSerializer with inference
144
- * .rendersMany('posts') // Infers from Dream association
211
+ * // Auto-infer serializer from Dream association
212
+ * .rendersMany('rooms')
145
213
  *
146
- * // With specific serializer
147
- * .rendersMany('posts', { serializerKey: 'summary' })
214
+ * // With specific serializer key
215
+ * .rendersMany('rooms', { serializerKey: 'summary' })
148
216
  *
149
- * // ObjectSerializer (explicit configuration required)
150
- * .rendersMany('articles', ArticleSerializer, {
151
- * openapi: {
152
- * type: 'array',
153
- * items: { $ref: '#/components/schemas/Article' }
154
- * }
155
- * })
156
- * ```
217
+ * // Explicit serializer function (for non-Dream objects)
218
+ * .rendersMany('bedTypes', { serializer: BedTypeSerializer })
157
219
  *
158
- * See: {@link https://your-docs-url.com/docs/serializers/associations | Serializer Associations Documentation}
220
+ * // Rename output key
221
+ * .rendersMany('rooms', { serializerKey: 'forGuests', as: 'guestRooms' })
222
+ * ```
159
223
  */
160
224
  rendersMany(name, options) {
161
225
  this.attributes.push({
@@ -168,24 +232,22 @@ export default class DreamSerializerBuilder {
168
232
  /**
169
233
  * Executes the serializer and returns the serialized output.
170
234
  *
171
- * This method processes all defined attributes, custom attributes, delegated attributes,
172
- * and associations to produce the final serialized object. The result is suitable for
173
- * JSON.stringify() and API responses.
235
+ * Processes all defined attributes, custom attributes, delegated attributes,
236
+ * and associations to produce the final serialized object.
174
237
  *
175
238
  * @param passthrough - Additional data to pass through to nested serializers
239
+ * (e.g., locale, current user context)
176
240
  * @param opts - Rendering options for customizing the serialization process
177
- * @returns The serialized object
241
+ * @returns The serialized object, suitable for JSON responses
178
242
  *
179
243
  * @example
180
244
  * ```typescript
181
245
  * const result = UserSerializer(user).render()
182
246
  * // Returns: { id: 1, email: 'user@example.com', ... }
183
247
  *
184
- * // With passthrough data
248
+ * // With passthrough data for nested serializers
185
249
  * const result = UserSerializer(user).render({ currentUserId: 123 })
186
250
  * ```
187
- *
188
- * See: {@link https://your-docs-url.com/docs/serializers/render | Serializer Rendering Documentation}
189
251
  */
190
252
  render(passthrough = {}, opts = {}) {
191
253
  return new SerializerRenderer(this, passthrough, opts).render();
@@ -14,7 +14,15 @@ export default class ObjectSerializerBuilder {
14
14
  * inference is not available for plain objects or ViewModels.
15
15
  *
16
16
  * @param name - The attribute name from the data object
17
- * @param options - Configuration options including required OpenAPI schema, default value, and output customization
17
+ * @param options - Configuration options:
18
+ * - `openapi` - (required) OpenAPI schema definition for the attribute
19
+ * - `as` - Rename the attribute key in the serialized output and OpenAPI shape
20
+ * - `default` - Value to use when the attribute is undefined
21
+ * - `precision` - Round decimal values to the specified number of decimal places (0–9)
22
+ * during rendering; does not affect the OpenAPI shape
23
+ * - `required` - Set to `false` to mark the attribute as optional in the OpenAPI schema;
24
+ * when omitted, attributes are required by default, meaning `undefined` values will
25
+ * serialize as `null`
18
26
  * @returns The serializer builder for method chaining
19
27
  *
20
28
  * @example
@@ -35,9 +43,19 @@ export default class ObjectSerializerBuilder {
35
43
  * openapi: { type: 'string' },
36
44
  * as: 'userEmail'
37
45
  * })
38
- * ```
39
46
  *
40
- * See: {@link https://your-docs-url.com/docs/serializers/attributes | Serializer Attributes Documentation}
47
+ * // Round decimal to 2 places
48
+ * .attribute('price', {
49
+ * openapi: 'decimal',
50
+ * precision: 2
51
+ * })
52
+ *
53
+ * // Mark as optional in OpenAPI (omitted from response when undefined)
54
+ * .attribute('nickname', {
55
+ * openapi: 'string',
56
+ * required: false
57
+ * })
58
+ * ```
41
59
  */
42
60
  attribute(name, options) {
43
61
  this.attributes.push({
@@ -50,13 +68,22 @@ export default class ObjectSerializerBuilder {
50
68
  /**
51
69
  * Includes an attribute from a nested object in the serialized output.
52
70
  *
53
- * Pulls up an attribute from a target object property. The `openapi` option
54
- * is always required. If the target object or the delegated attribute
55
- * is null/undefined, the `default` option value will be used if provided.
71
+ * Accesses `targetName.name` on the data object. The `openapi` option is always
72
+ * required. If the target object or the delegated attribute is null/undefined,
73
+ * the `default` option value will be used if provided.
56
74
  *
57
75
  * @param targetName - The property name containing the target object
58
76
  * @param name - The attribute name within the target object
59
- * @param options - Configuration options including required OpenAPI schema, default value, and output customization
77
+ * @param options - Configuration options:
78
+ * - `openapi` - (required) OpenAPI schema definition for the attribute
79
+ * - `as` - Rename the attribute key in the serialized output and OpenAPI shape
80
+ * (e.g., delegating `'profile', 'avatarUrl'` with `as: 'avatar'` outputs the value
81
+ * under `avatar`)
82
+ * - `default` - Value to use when the target object or its attribute is null/undefined
83
+ * - `precision` - Round decimal values to the specified number of decimal places (0–9)
84
+ * during rendering; does not affect the OpenAPI shape
85
+ * - `required` - Set to `false` to mark the attribute as optional in the OpenAPI schema;
86
+ * when omitted, attributes are required by default
60
87
  * @returns The serializer builder for method chaining
61
88
  *
62
89
  * @example
@@ -71,9 +98,13 @@ export default class ObjectSerializerBuilder {
71
98
  * openapi: { type: 'string' },
72
99
  * default: 'Anonymous User'
73
100
  * })
74
- * ```
75
101
  *
76
- * See: {@link https://your-docs-url.com/docs/serializers/attributes | Serializer Attributes Documentation}
102
+ * // Rename the output key
103
+ * .delegatedAttribute('profile', 'avatarUrl', {
104
+ * openapi: 'string',
105
+ * as: 'avatar'
106
+ * })
107
+ * ```
77
108
  */
78
109
  delegatedAttribute(targetName, name, options) {
79
110
  this.attributes.push({
@@ -90,9 +121,19 @@ export default class ObjectSerializerBuilder {
90
121
  * Executes a callback function to generate a custom attribute value.
91
122
  * The `openapi` option is always required since the return type cannot be inferred.
92
123
  *
124
+ * Unlike DreamSerializerBuilder's `customAttribute`, this version does not support `as`
125
+ * or `precision`.
126
+ *
93
127
  * @param name - The attribute name for the computed value
94
128
  * @param fn - Callback function that returns the computed value
95
- * @param options - Configuration options including required OpenAPI schema and optional flattening
129
+ * @param options - Configuration options:
130
+ * - `openapi` - (required) OpenAPI schema definition for the computed value
131
+ * - `default` - Value to use when the callback returns undefined
132
+ * - `flatten` - When `true`, spreads the returned object's properties directly into the
133
+ * parent serialized output instead of nesting them under `name`; the `openapi` option
134
+ * should then define each flattened property individually
135
+ * - `required` - Set to `false` to mark the attribute as optional in the OpenAPI schema;
136
+ * when omitted, attributes are required by default
96
137
  * @returns The serializer builder for method chaining
97
138
  *
98
139
  * @example
@@ -112,8 +153,6 @@ export default class ObjectSerializerBuilder {
112
153
  * }
113
154
  * })
114
155
  * ```
115
- *
116
- * See: {@link https://your-docs-url.com/docs/serializers/attributes | Serializer Attributes Documentation}
117
156
  */
118
157
  customAttribute(name, fn, options) {
119
158
  this.attributes.push({
@@ -131,25 +170,47 @@ export default class ObjectSerializerBuilder {
131
170
  * since association schemas cannot be inferred from plain objects.
132
171
  *
133
172
  * @param name - The association property name
134
- * @param options - Configuration options including required serializer and OpenAPI schema
173
+ * @param options - Configuration options:
174
+ * - `as` - Rename the association key in the serialized output
175
+ * - `flatten` - When `true`, spreads the rendered association's attributes directly into
176
+ * the parent serialized output instead of nesting them under `name`. Be aware of
177
+ * attribute shadowing: if the parent and flattened association share attribute names
178
+ * (e.g., `id`), the flattened association's values overwrite the parent's
179
+ * - `optional` - When `true`, allows the association to be null/missing without causing
180
+ * an `OpenapiResponseValidationFailure` during Psychic controller unit specs. By default,
181
+ * `rendersOne` expects the association to be present (mirroring the `optional` option on
182
+ * `@deco.BelongsTo`). Set this to `true` when the association is genuinely nullable
183
+ *
184
+ * For Dream associations:
185
+ * - `dreamClass` - The Dream model class, enabling serializer inference; when specified,
186
+ * `serializerKey` may also be provided to select a specific registered serializer
187
+ * - `serializer` - Provide an explicit serializer function
188
+ *
189
+ * For ViewModel associations:
190
+ * - `viewModelClass` + optional `serializerKey`
191
+ * - `serializer`
192
+ *
193
+ * For non-Dream/non-ViewModel associations:
194
+ * - `serializer` is required
135
195
  * @returns The serializer builder for method chaining
136
196
  *
137
197
  * @example
138
198
  * ```typescript
139
199
  * // With explicit serializer function
140
- * .rendersOne('owner', UserSerializer, {
141
- * openapi: { $ref: '#/components/schemas/User' }
142
- * })
200
+ * .rendersOne('owner', { serializer: CustomOwnerSerializer })
143
201
  *
144
- * // With Dream class reference
202
+ * // With Dream class reference and serializer key
145
203
  * .rendersOne('creator', {
146
204
  * dreamClass: User,
147
- * serializerKey: 'summary',
148
- * openapi: { $ref: '#/components/schemas/UserSummary' }
205
+ * serializerKey: 'summary'
149
206
  * })
150
- * ```
151
207
  *
152
- * See: {@link https://your-docs-url.com/docs/serializers/associations | Serializer Associations Documentation}
208
+ * // Allow null association
209
+ * .rendersOne('approver', { serializer: UserSerializer, optional: true })
210
+ *
211
+ * // Flatten into parent object
212
+ * .rendersOne('profile', { serializer: ProfileSerializer, flatten: true })
213
+ * ```
153
214
  */
154
215
  rendersOne(name, options) {
155
216
  this.attributes.push({
@@ -165,32 +226,43 @@ export default class ObjectSerializerBuilder {
165
226
  * For ObjectSerializer, explicit serializer configuration is always required
166
227
  * since association schemas cannot be inferred from plain objects.
167
228
  *
168
- * @param name - The association property name (should be an array)
169
- * @param options - Configuration options including required serializer and OpenAPI schema
229
+ * @param name - The association property name (should resolve to an array)
230
+ * @param options - Configuration options:
231
+ * - `as` - Rename the association key in the serialized output
232
+ *
233
+ * For Dream associations:
234
+ * - `dreamClass` - The Dream model class, enabling serializer inference; when specified,
235
+ * `serializerKey` may also be provided to select a specific registered serializer
236
+ * - `serializer` - Provide an explicit serializer function
237
+ *
238
+ * For ViewModel associations:
239
+ * - `viewModelClass` + optional `serializerKey`
240
+ * - `serializer`
241
+ *
242
+ * For non-Dream/non-ViewModel associations:
243
+ * - `serializer` is required
170
244
  * @returns The serializer builder for method chaining
171
245
  *
172
246
  * @example
173
247
  * ```typescript
174
248
  * // With explicit serializer function
175
- * .rendersMany('articles', ArticleSerializer, {
176
- * openapi: {
177
- * type: 'array',
178
- * items: { $ref: '#/components/schemas/Article' }
179
- * }
249
+ * .rendersMany('articles', { serializer: ArticleSerializer })
250
+ *
251
+ * // With Dream class reference and serializer key
252
+ * .rendersMany('posts', {
253
+ * dreamClass: Post,
254
+ * serializerKey: 'summary'
180
255
  * })
181
256
  *
182
257
  * // With ViewModel class reference
183
258
  * .rendersMany('comments', {
184
259
  * viewModelClass: CommentViewModel,
185
- * serializer: CommentViewModelSerializer,
186
- * openapi: {
187
- * type: 'array',
188
- * items: { $ref: '#/components/schemas/Comment' }
189
- * }
260
+ * serializer: CommentViewModelSerializer
190
261
  * })
191
- * ```
192
262
  *
193
- * See: {@link https://your-docs-url.com/docs/serializers/associations | Serializer Associations Documentation}
263
+ * // Rename output key
264
+ * .rendersMany('articles', { serializer: ArticleSerializer, as: 'posts' })
265
+ * ```
194
266
  */
195
267
  rendersMany(name, options) {
196
268
  this.attributes.push({
@@ -203,13 +275,13 @@ export default class ObjectSerializerBuilder {
203
275
  /**
204
276
  * Executes the serializer and returns the serialized output.
205
277
  *
206
- * This method processes all defined attributes, custom attributes, delegated attributes,
207
- * and associations to produce the final serialized object. The result is suitable for
208
- * JSON.stringify() and API responses.
278
+ * Processes all defined attributes, custom attributes, delegated attributes,
279
+ * and associations to produce the final serialized object.
209
280
  *
210
281
  * @param passthrough - Additional data to pass through to nested serializers
282
+ * (e.g., locale, current user context)
211
283
  * @param opts - Rendering options for customizing the serialization process
212
- * @returns The serialized object
284
+ * @returns The serialized object, suitable for JSON responses
213
285
  *
214
286
  * @example
215
287
  * ```typescript
@@ -219,8 +291,6 @@ export default class ObjectSerializerBuilder {
219
291
  * // With passthrough data for nested serializers
220
292
  * const result = UserViewModelSerializer(userVm).render({ currentUserId: '456' })
221
293
  * ```
222
- *
223
- * See: {@link https://your-docs-url.com/docs/serializers/render | Serializer Rendering Documentation}
224
294
  */
225
295
  render(passthrough = {}, opts = {}) {
226
296
  return new SerializerRenderer(this, passthrough, opts).render();
@@ -0,0 +1 @@
1
+ export {};
@@ -2368,13 +2368,28 @@ export default class Dream {
2368
2368
  */
2369
2369
  passthrough<I extends Dream, PassthroughColumns extends PassthroughColumnNames<I>>(this: I, passthroughWhereStatement: PassthroughOnClause<PassthroughColumns>): LoadBuilder<I>;
2370
2370
  /**
2371
- * Loads the requested associations upon execution
2371
+ * Loads the requested associations upon execution.
2372
+ *
2373
+ * **IMPORTANT:** `load().execute()` returns a **new clone** of the model with the
2374
+ * associations loaded. It does NOT modify the original instance. You must use the
2375
+ * returned value:
2376
+ *
2377
+ * ```ts
2378
+ * // CORRECT — use the returned clone:
2379
+ * const loaded = await user.load('posts').execute()
2380
+ * loaded.posts // works
2381
+ *
2382
+ * // WRONG — original is not modified:
2383
+ * await user.load('posts').execute()
2384
+ * user.posts // association not loaded!
2385
+ * ```
2372
2386
  *
2373
2387
  * NOTE: {@link Dream.preload} is often a preferrable way of achieving the
2374
- * same goal.
2388
+ * same goal. Alternatively, `await model.association('posts')` loads only
2389
+ * if the association is not already loaded.
2375
2390
  *
2376
2391
  * ```ts
2377
- * await user
2392
+ * const user = await user
2378
2393
  * .load('posts', { body: ops.ilike('%hello world%') }, 'comments', 'replies')
2379
2394
  * .load('images')
2380
2395
  * .execute()
@@ -2387,7 +2402,7 @@ export default class Dream {
2387
2402
  * ```
2388
2403
  *
2389
2404
  * @param args - A list of associations (and optional where clauses) to load
2390
- * @returns A chainable LoadBuilder instance
2405
+ * @returns A chainable LoadBuilder instance. Call `.execute()` to get the cloned model with associations loaded.
2391
2406
  */
2392
2407
  load<I extends Dream, DB extends I['DB'], TableName extends I['table'], Schema extends I['schema'], const Arr extends readonly unknown[]>(this: I, ...args: [...Arr, VariadicLoadArgs<I, DB, Schema, TableName, Arr>]): LoadBuilder<I>;
2393
2408
  /**
@@ -2557,19 +2572,19 @@ export default class Dream {
2557
2572
  * Load each specified association using a single SQL query.
2558
2573
  * See {@link Dream.load} for loading in separate queries.
2559
2574
  *
2575
+ * **IMPORTANT:** Like `load()`, `leftJoinLoad().execute()` returns a **new clone** of the
2576
+ * model with associations loaded. It does NOT modify the original instance.
2577
+ *
2560
2578
  * Note: since leftJoinLoad loads via single query, it has
2561
- * some downsides and that may be avoided using {@link Dream.load}:
2579
+ * some downsides that may be avoided using {@link Dream.load}:
2562
2580
  * 1. `limit` and `offset` will be automatically removed
2563
2581
  * 2. `through` associations will bring additional namespaces into the query that can conflict with through associations from other associations, creating an invalid query
2564
2582
  * 3. each nested association will result in an additional record which duplicates data from the outer record. E.g., given `.leftJoinLoad('a', 'b', 'c')`, if each `a` has 10 `b` and each `b` has 10 `c`, then for one `a`, 100 records will be returned, each of which has all of the columns of `a`. `.load('a', 'b', 'c')` would perform three separate SQL queries, but the data for a single `a` would only be returned once.
2565
2583
  * 4. the individual query becomes more complex the more associations are included
2566
2584
  * 5. associations loading associations loading associations could result in exponential amounts of data; in those cases, `.load(...).findEach(...)` avoids instantiating massive amounts of data at once
2567
2585
  *
2568
- * Note: Left join loading loads all data in a single SQL query but has trade-offs compared
2569
- * to regular preloading. See {@link Dream.leftJoinPreload} for details about limitations.
2570
- *
2571
2586
  * ```ts
2572
- * await user
2587
+ * const user = await user
2573
2588
  * .leftJoinLoad('posts', { body: ops.ilike('%hello world%') }, 'comments', 'replies')
2574
2589
  * .leftJoinLoad('images')
2575
2590
  * .execute()
@@ -2582,7 +2597,7 @@ export default class Dream {
2582
2597
  * ```
2583
2598
  *
2584
2599
  * @param args - A list of associations (and optional where clauses) to load
2585
- * @returns A chainable LeftJoinLoadBuilder instance
2600
+ * @returns A chainable LeftJoinLoadBuilder instance. Call `.execute()` to get the cloned model with associations loaded.
2586
2601
  */
2587
2602
  leftJoinLoad<I extends Dream, DB extends I['DB'], TableName extends I['table'], Schema extends I['schema'], const Arr extends readonly unknown[]>(this: I, ...args: [...Arr, VariadicLeftJoinLoadArgs<I, DB, Schema, TableName, Arr>]): LeftJoinLoadBuilder<I>;
2588
2603
  /**