@rvoh/dream 2.5.7 → 2.5.8

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 (215) hide show
  1. package/dist/cjs/src/Dream.js +25 -10
  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 +15 -9
  5. package/dist/cjs/src/dream/Query.js +1 -1
  6. package/dist/cjs/src/serializer/builders/DreamSerializerBuilder.js +110 -52
  7. package/dist/cjs/src/serializer/builders/ObjectSerializerBuilder.js +111 -41
  8. package/dist/esm/src/Dream.js +25 -10
  9. package/dist/esm/src/decorators/class/STI.js +2 -2
  10. package/dist/esm/src/dream/LeftJoinLoadBuilder.js +16 -10
  11. package/dist/esm/src/dream/LoadBuilder.js +15 -9
  12. package/dist/esm/src/dream/Query.js +1 -1
  13. package/dist/esm/src/serializer/builders/DreamSerializerBuilder.js +110 -52
  14. package/dist/esm/src/serializer/builders/ObjectSerializerBuilder.js +111 -41
  15. package/dist/types/src/Dream.d.ts +25 -10
  16. package/dist/types/src/decorators/Decorators.d.ts +8 -0
  17. package/dist/types/src/decorators/class/STI.d.ts +1 -3
  18. package/dist/types/src/decorators/field/sortable/Sortable.d.ts +9 -0
  19. package/dist/types/src/decorators/field/validation/Validates.d.ts +4 -0
  20. package/dist/types/src/decorators/static-method/Scope.d.ts +4 -0
  21. package/dist/types/src/dream/LeftJoinLoadBuilder.d.ts +16 -10
  22. package/dist/types/src/dream/LoadBuilder.d.ts +15 -9
  23. package/dist/types/src/dream/Query.d.ts +1 -1
  24. package/dist/types/src/serializer/builders/DreamSerializerBuilder.d.ts +151 -59
  25. package/dist/types/src/serializer/builders/ObjectSerializerBuilder.d.ts +123 -41
  26. package/dist/types/src/types/associations/belongsTo.d.ts +34 -0
  27. package/dist/types/src/types/associations/belongsTo.ts +41 -0
  28. package/dist/types/src/types/associations/hasMany.d.ts +18 -0
  29. package/dist/types/src/types/associations/hasMany.ts +18 -0
  30. package/dist/types/src/types/associations/shared.d.ts +71 -0
  31. package/dist/types/src/types/associations/shared.ts +74 -0
  32. package/dist/types/src/types/dream.d.ts +16 -0
  33. package/dist/types/src/types/dream.ts +18 -0
  34. package/dist/types/src/types/lifecycle.d.ts +18 -0
  35. package/dist/types/src/types/lifecycle.ts +18 -0
  36. package/dist/types/src/types/query.d.ts +3 -0
  37. package/dist/types/src/types/query.ts +3 -0
  38. package/docs/classes/db.DreamMigrationHelpers.html +9 -9
  39. package/docs/classes/db.KyselyQueryDriver.html +32 -32
  40. package/docs/classes/db.PostgresQueryDriver.html +33 -33
  41. package/docs/classes/db.QueryDriverBase.html +31 -31
  42. package/docs/classes/errors.CheckConstraintViolation.html +3 -3
  43. package/docs/classes/errors.ColumnOverflow.html +3 -3
  44. package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
  45. package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +3 -3
  46. package/docs/classes/errors.DataTypeColumnTypeMismatch.html +3 -3
  47. package/docs/classes/errors.GlobalNameNotSet.html +3 -3
  48. package/docs/classes/errors.InvalidCalendarDate.html +2 -2
  49. package/docs/classes/errors.InvalidClockTime.html +2 -2
  50. package/docs/classes/errors.InvalidClockTimeTz.html +2 -2
  51. package/docs/classes/errors.InvalidDateTime.html +2 -2
  52. package/docs/classes/errors.MissingSerializersDefinition.html +3 -3
  53. package/docs/classes/errors.NonLoadedAssociation.html +3 -3
  54. package/docs/classes/errors.NotNullViolation.html +3 -3
  55. package/docs/classes/errors.RecordNotFound.html +3 -3
  56. package/docs/classes/errors.ValidationError.html +3 -3
  57. package/docs/classes/index.CalendarDate.html +33 -33
  58. package/docs/classes/index.ClockTime.html +32 -32
  59. package/docs/classes/index.ClockTimeTz.html +35 -35
  60. package/docs/classes/index.DateTime.html +86 -86
  61. package/docs/classes/index.Decorators.html +21 -20
  62. package/docs/classes/index.Dream.html +133 -126
  63. package/docs/classes/index.DreamApp.html +5 -5
  64. package/docs/classes/index.DreamTransaction.html +2 -2
  65. package/docs/classes/index.Env.html +2 -2
  66. package/docs/classes/index.Query.html +57 -57
  67. package/docs/classes/system.CliFileWriter.html +4 -4
  68. package/docs/classes/system.DreamBin.html +2 -2
  69. package/docs/classes/system.DreamCLI.html +6 -6
  70. package/docs/classes/system.DreamImporter.html +2 -2
  71. package/docs/classes/system.DreamLogos.html +2 -2
  72. package/docs/classes/system.DreamSerializerBuilder.html +172 -58
  73. package/docs/classes/system.ObjectSerializerBuilder.html +109 -33
  74. package/docs/classes/system.PathHelpers.html +3 -3
  75. package/docs/classes/utils.Encrypt.html +2 -2
  76. package/docs/classes/utils.Range.html +2 -2
  77. package/docs/functions/db.closeAllDbConnections.html +1 -1
  78. package/docs/functions/db.dreamDbConnections.html +1 -1
  79. package/docs/functions/db.untypedDb.html +1 -1
  80. package/docs/functions/db.validateColumn.html +1 -1
  81. package/docs/functions/db.validateTable.html +1 -1
  82. package/docs/functions/errors.pgErrorType.html +1 -1
  83. package/docs/functions/index.DreamSerializer.html +1 -1
  84. package/docs/functions/index.ObjectSerializer.html +1 -1
  85. package/docs/functions/index.ReplicaSafe.html +1 -1
  86. package/docs/functions/index.STI.html +1 -1
  87. package/docs/functions/index.SoftDelete.html +1 -1
  88. package/docs/functions/utils.camelize.html +1 -1
  89. package/docs/functions/utils.capitalize.html +1 -1
  90. package/docs/functions/utils.cloneDeepSafe.html +1 -1
  91. package/docs/functions/utils.compact.html +1 -1
  92. package/docs/functions/utils.groupBy.html +1 -1
  93. package/docs/functions/utils.hyphenize.html +1 -1
  94. package/docs/functions/utils.intersection.html +1 -1
  95. package/docs/functions/utils.isEmpty.html +1 -1
  96. package/docs/functions/utils.normalizeUnicode.html +1 -1
  97. package/docs/functions/utils.pascalize.html +1 -1
  98. package/docs/functions/utils.percent.html +1 -1
  99. package/docs/functions/utils.range.html +1 -1
  100. package/docs/functions/utils.round.html +1 -1
  101. package/docs/functions/utils.sanitizeString.html +1 -1
  102. package/docs/functions/utils.snakeify.html +1 -1
  103. package/docs/functions/utils.sort.html +1 -1
  104. package/docs/functions/utils.sortBy.html +1 -1
  105. package/docs/functions/utils.sortObjectByKey.html +1 -1
  106. package/docs/functions/utils.sortObjectByValue.html +1 -1
  107. package/docs/functions/utils.uncapitalize.html +1 -1
  108. package/docs/functions/utils.uniq.html +1 -1
  109. package/docs/interfaces/openapi.OpenapiDescription.html +2 -2
  110. package/docs/interfaces/openapi.OpenapiSchemaProperties.html +1 -1
  111. package/docs/interfaces/openapi.OpenapiSchemaPropertiesShorthand.html +1 -1
  112. package/docs/interfaces/openapi.OpenapiTypeFieldObject.html +1 -1
  113. package/docs/interfaces/types.BelongsToStatement.html +2 -2
  114. package/docs/interfaces/types.DecoratorContext.html +2 -2
  115. package/docs/interfaces/types.DreamAppInitOptions.html +2 -2
  116. package/docs/interfaces/types.DreamAppOpts.html +2 -2
  117. package/docs/interfaces/types.DurationObject.html +2 -2
  118. package/docs/interfaces/types.EncryptOptions.html +2 -2
  119. package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
  120. package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
  121. package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
  122. package/docs/types/openapi.CommonOpenapiSchemaObjectFields.html +1 -1
  123. package/docs/types/openapi.OpenapiAllTypes.html +1 -1
  124. package/docs/types/openapi.OpenapiFormats.html +1 -1
  125. package/docs/types/openapi.OpenapiNumberFormats.html +1 -1
  126. package/docs/types/openapi.OpenapiPrimitiveBaseTypes.html +1 -1
  127. package/docs/types/openapi.OpenapiPrimitiveTypes.html +1 -1
  128. package/docs/types/openapi.OpenapiSchemaArray.html +1 -1
  129. package/docs/types/openapi.OpenapiSchemaArrayShorthand.html +1 -1
  130. package/docs/types/openapi.OpenapiSchemaBase.html +1 -1
  131. package/docs/types/openapi.OpenapiSchemaBody.html +1 -1
  132. package/docs/types/openapi.OpenapiSchemaBodyShorthand.html +1 -1
  133. package/docs/types/openapi.OpenapiSchemaCommonFields.html +1 -1
  134. package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +2 -2
  135. package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +2 -2
  136. package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +2 -2
  137. package/docs/types/openapi.OpenapiSchemaExpressionRef.html +2 -2
  138. package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +2 -2
  139. package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
  140. package/docs/types/openapi.OpenapiSchemaNull.html +2 -2
  141. package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
  142. package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
  143. package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +1 -1
  144. package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +1 -1
  145. package/docs/types/openapi.OpenapiSchemaObjectAnyOf.html +1 -1
  146. package/docs/types/openapi.OpenapiSchemaObjectAnyOfShorthand.html +1 -1
  147. package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
  148. package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
  149. package/docs/types/openapi.OpenapiSchemaObjectOneOf.html +1 -1
  150. package/docs/types/openapi.OpenapiSchemaObjectOneOfShorthand.html +1 -1
  151. package/docs/types/openapi.OpenapiSchemaObjectShorthand.html +1 -1
  152. package/docs/types/openapi.OpenapiSchemaPrimitiveGeneric.html +1 -1
  153. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAllOf.html +2 -2
  154. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +2 -2
  155. package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +2 -2
  156. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +2 -2
  157. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +2 -2
  158. package/docs/types/openapi.OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
  159. package/docs/types/openapi.OpenapiSchemaString.html +1 -1
  160. package/docs/types/openapi.OpenapiShorthandAllTypes.html +1 -1
  161. package/docs/types/openapi.OpenapiShorthandPrimitiveBaseTypes.html +1 -1
  162. package/docs/types/openapi.OpenapiShorthandPrimitiveTypes.html +1 -1
  163. package/docs/types/openapi.OpenapiTypeField.html +1 -1
  164. package/docs/types/system.DreamAppAllowedPackageManagersEnum.html +1 -1
  165. package/docs/types/types.CalendarDateDurationUnit.html +1 -1
  166. package/docs/types/types.CalendarDateObject.html +1 -1
  167. package/docs/types/types.Camelized.html +1 -1
  168. package/docs/types/types.ClockTimeObject.html +1 -1
  169. package/docs/types/types.DbConnectionType.html +1 -1
  170. package/docs/types/types.DbTypes.html +1 -1
  171. package/docs/types/types.DreamAssociationMetadata.html +1 -1
  172. package/docs/types/types.DreamAttributes.html +1 -1
  173. package/docs/types/types.DreamClassAssociationAndStatement.html +1 -1
  174. package/docs/types/types.DreamClassColumn.html +1 -1
  175. package/docs/types/types.DreamColumn.html +1 -1
  176. package/docs/types/types.DreamColumnNames.html +1 -1
  177. package/docs/types/types.DreamLogLevel.html +1 -1
  178. package/docs/types/types.DreamLogger.html +2 -2
  179. package/docs/types/types.DreamModelSerializerType.html +1 -1
  180. package/docs/types/types.DreamOrViewModelClassSerializerKey.html +1 -1
  181. package/docs/types/types.DreamOrViewModelSerializerKey.html +1 -1
  182. package/docs/types/types.DreamParamSafeAttributes.html +1 -1
  183. package/docs/types/types.DreamParamSafeColumnNames.html +1 -1
  184. package/docs/types/types.DreamSerializable.html +1 -1
  185. package/docs/types/types.DreamSerializableArray.html +1 -1
  186. package/docs/types/types.DreamSerializerKey.html +1 -1
  187. package/docs/types/types.DreamSerializers.html +1 -1
  188. package/docs/types/types.DreamVirtualColumns.html +1 -1
  189. package/docs/types/types.DurationUnit.html +1 -1
  190. package/docs/types/types.EncryptAlgorithm.html +1 -1
  191. package/docs/types/types.HasManyStatement.html +1 -1
  192. package/docs/types/types.HasOneStatement.html +1 -1
  193. package/docs/types/types.Hyphenized.html +1 -1
  194. package/docs/types/types.Pascalized.html +1 -1
  195. package/docs/types/types.PrimaryKeyType.html +1 -1
  196. package/docs/types/types.RoundingPrecision.html +1 -1
  197. package/docs/types/types.SerializerCasing.html +1 -1
  198. package/docs/types/types.SimpleObjectSerializerType.html +1 -1
  199. package/docs/types/types.Snakeified.html +1 -1
  200. package/docs/types/types.StrictInterface.html +1 -1
  201. package/docs/types/types.UpdateableAssociationProperties.html +1 -1
  202. package/docs/types/types.UpdateableProperties.html +1 -1
  203. package/docs/types/types.ValidationType.html +1 -1
  204. package/docs/types/types.ViewModel.html +2 -2
  205. package/docs/types/types.ViewModelClass.html +1 -1
  206. package/docs/types/types.WeekdayName.html +1 -1
  207. package/docs/types/types.WhereStatementForDream.html +1 -1
  208. package/docs/types/types.WhereStatementForDreamClass.html +1 -1
  209. package/docs/variables/index.DreamConst.html +1 -1
  210. package/docs/variables/index.ops.html +1 -1
  211. package/docs/variables/openapi.openapiPrimitiveTypes.html +1 -1
  212. package/docs/variables/openapi.openapiShorthandPrimitiveTypes.html +1 -1
  213. package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
  214. package/docs/variables/system.primaryKeyTypes.html +1 -1
  215. package/package.json +1 -1
@@ -3238,13 +3238,28 @@ export default class Dream {
3238
3238
  return new LoadBuilder(this).passthrough(passthroughWhereStatement);
3239
3239
  }
3240
3240
  /**
3241
- * Loads the requested associations upon execution
3241
+ * Loads the requested associations upon execution.
3242
+ *
3243
+ * **IMPORTANT:** `load().execute()` returns a **new clone** of the model with the
3244
+ * associations loaded. It does NOT modify the original instance. You must use the
3245
+ * returned value:
3246
+ *
3247
+ * ```ts
3248
+ * // CORRECT — use the returned clone:
3249
+ * const loaded = await user.load('posts').execute()
3250
+ * loaded.posts // works
3251
+ *
3252
+ * // WRONG — original is not modified:
3253
+ * await user.load('posts').execute()
3254
+ * user.posts // association not loaded!
3255
+ * ```
3242
3256
  *
3243
3257
  * NOTE: {@link Dream.preload} is often a preferrable way of achieving the
3244
- * same goal.
3258
+ * same goal. Alternatively, `await model.association('posts')` loads only
3259
+ * if the association is not already loaded.
3245
3260
  *
3246
3261
  * ```ts
3247
- * await user
3262
+ * const user = await user
3248
3263
  * .load('posts', { body: ops.ilike('%hello world%') }, 'comments', 'replies')
3249
3264
  * .load('images')
3250
3265
  * .execute()
@@ -3257,7 +3272,7 @@ export default class Dream {
3257
3272
  * ```
3258
3273
  *
3259
3274
  * @param args - A list of associations (and optional where clauses) to load
3260
- * @returns A chainable LoadBuilder instance
3275
+ * @returns A chainable LoadBuilder instance. Call `.execute()` to get the cloned model with associations loaded.
3261
3276
  */
3262
3277
  load(...args) {
3263
3278
  return new LoadBuilder(this).load(...args);
@@ -3326,19 +3341,19 @@ export default class Dream {
3326
3341
  * Load each specified association using a single SQL query.
3327
3342
  * See {@link Dream.load} for loading in separate queries.
3328
3343
  *
3344
+ * **IMPORTANT:** Like `load()`, `leftJoinLoad().execute()` returns a **new clone** of the
3345
+ * model with associations loaded. It does NOT modify the original instance.
3346
+ *
3329
3347
  * Note: since leftJoinLoad loads via single query, it has
3330
- * some downsides and that may be avoided using {@link Dream.load}:
3348
+ * some downsides that may be avoided using {@link Dream.load}:
3331
3349
  * 1. `limit` and `offset` will be automatically removed
3332
3350
  * 2. `through` associations will bring additional namespaces into the query that can conflict with through associations from other associations, creating an invalid query
3333
3351
  * 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.
3334
3352
  * 4. the individual query becomes more complex the more associations are included
3335
3353
  * 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
3336
3354
  *
3337
- * Note: Left join loading loads all data in a single SQL query but has trade-offs compared
3338
- * to regular preloading. See {@link Dream.leftJoinPreload} for details about limitations.
3339
- *
3340
3355
  * ```ts
3341
- * await user
3356
+ * const user = await user
3342
3357
  * .leftJoinLoad('posts', { body: ops.ilike('%hello world%') }, 'comments', 'replies')
3343
3358
  * .leftJoinLoad('images')
3344
3359
  * .execute()
@@ -3351,7 +3366,7 @@ export default class Dream {
3351
3366
  * ```
3352
3367
  *
3353
3368
  * @param args - A list of associations (and optional where clauses) to load
3354
- * @returns A chainable LeftJoinLoadBuilder instance
3369
+ * @returns A chainable LeftJoinLoadBuilder instance. Call `.execute()` to get the cloned model with associations loaded.
3355
3370
  */
3356
3371
  leftJoinLoad(...args) {
3357
3372
  return new LeftJoinLoadBuilder(this).leftJoinLoad(...args);
@@ -3,7 +3,7 @@ import StiChildIncompatibleWithReplicaSafeDecorator from '../../errors/sti/StiCh
3
3
  import StiChildIncompatibleWithSoftDeleteDecorator from '../../errors/sti/StiChildIncompatibleWithSoftDeleteDecorator.js';
4
4
  import { scopeImplementation } from '../static-method/Scope.js';
5
5
  export const STI_SCOPE_NAME = 'dream:STI';
6
- export default function STI(dreamClass, { value } = {}) {
6
+ export default function STI(dreamClass) {
7
7
  return function (target) {
8
8
  const stiChildClass = target;
9
9
  const baseClass = dreamClass['sti'].baseClass || dreamClass;
@@ -21,7 +21,7 @@ export default function STI(dreamClass, { value } = {}) {
21
21
  stiChildClass['sti'] = {
22
22
  active: true,
23
23
  baseClass,
24
- value: value || stiChildClass.sanitizedName,
24
+ value: stiChildClass.sanitizedName,
25
25
  };
26
26
  stiChildClass[STI_SCOPE_NAME] = function (query) {
27
27
  return query.where({ type: stiChildClass['sti'].value });
@@ -5,13 +5,16 @@ export default class LeftJoinLoadBuilder {
5
5
  dream;
6
6
  query;
7
7
  /**
8
- * An intermediate class on the way to executing a load
9
- * query. this can be accessed on an instance of a dream
10
- * model by using the `#load` method:
8
+ * An intermediate builder for loading associations onto a Dream model
9
+ * via a single left-join SQL query. Accessed via `#leftJoinLoad`.
10
+ *
11
+ * **Note:** The LeftJoinLoadBuilder works on a clone of the original model.
12
+ * Call `.execute()` to get the clone with associations loaded.
11
13
  *
12
14
  * ```ts
13
15
  * const user = await User.firstOrFail()
14
- * await user.load('settings').execute()
16
+ * const loaded = await user.leftJoinLoad('settings').execute()
17
+ * loaded.settings // association is loaded on the returned clone
15
18
  * ```
16
19
  */
17
20
  constructor(dream, dreamTransaction) {
@@ -39,17 +42,20 @@ export default class LeftJoinLoadBuilder {
39
42
  return this;
40
43
  }
41
44
  /**
42
- * executes a load builder query, binding
43
- * all associations to their respective model
44
- * instances.
45
+ * Executes the left-join load query, returning a **clone** of the original model
46
+ * with all requested associations loaded. The original instance is not modified.
45
47
  *
46
48
  * ```ts
47
49
  * const user = await User.firstOrFail()
48
- * await user
49
- * .load('settings')
50
- * .load('posts', 'comments', 'replies', ['image', 'localizedText'])
50
+ * const loaded = await user
51
+ * .leftJoinLoad('settings')
52
+ * .leftJoinLoad('posts', 'comments', 'replies')
51
53
  * .execute()
54
+ *
55
+ * loaded.settings // works — associations are on the returned clone
52
56
  * ```
57
+ *
58
+ * @returns A clone of the Dream instance with all requested associations loaded
53
59
  */
54
60
  async execute() {
55
61
  if (this.dreamTransaction) {
@@ -3,13 +3,16 @@ export default class LoadBuilder {
3
3
  dream;
4
4
  query;
5
5
  /**
6
- * An intermediate class on the way to executing a load
7
- * query. this can be accessed on an instance of a dream
8
- * model by using the `#load` method:
6
+ * An intermediate builder for loading associations onto a Dream model.
7
+ * Accessed via the `#load` method on a Dream instance.
8
+ *
9
+ * **Note:** The LoadBuilder works on a clone of the original model.
10
+ * Call `.execute()` to get the clone with associations loaded.
9
11
  *
10
12
  * ```ts
11
13
  * const user = await User.firstOrFail()
12
- * await user.load('settings').execute()
14
+ * const loaded = await user.load('settings').execute()
15
+ * loaded.settings // association is loaded on the returned clone
13
16
  * ```
14
17
  */
15
18
  constructor(dream, dreamTransaction) {
@@ -89,19 +92,22 @@ export default class LoadBuilder {
89
92
  return this;
90
93
  }
91
94
  /**
92
- * Executes a load builder query, binding
93
- * all associations to their respective model
94
- * instances.
95
+ * Executes the load query, binding all associations to a **clone** of the
96
+ * original model instance. The original instance is not modified.
97
+ *
98
+ * You must use the returned value to access the loaded associations:
95
99
  *
96
100
  * ```ts
97
101
  * const user = await User.firstOrFail()
98
- * await user
102
+ * const loaded = await user
99
103
  * .load('settings')
100
104
  * .load('posts', 'comments', 'replies', ['image', 'localizedText'])
101
105
  * .execute()
106
+ *
107
+ * loaded.settings // works — associations are on the returned clone
102
108
  * ```
103
109
  *
104
- * @returns The Dream instance with all associations loaded
110
+ * @returns A clone of the Dream instance with all requested associations loaded
105
111
  */
106
112
  async execute() {
107
113
  if (this.dreamTransaction) {
@@ -1698,7 +1698,7 @@ export default class Query {
1698
1698
  * Updates all records matching the Query
1699
1699
  *
1700
1700
  * ```ts
1701
- * await User.where({ email: ops.ilike('%burpcollaborator%') }).updateAll({ email: null })
1701
+ * await User.where({ email: ops.ilike('%burpcollaborator%') }).update({ email: null })
1702
1702
  * // 12
1703
1703
  * ```
1704
1704
  * @param attributes - The attributes used to update the records
@@ -20,30 +20,46 @@ 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
+ * - `precision` - Round decimal values to the specified number of decimal places (0–9)
41
+ * during rendering; does not affect the OpenAPI shape
42
+ * - `required` - Set to `false` to mark the attribute as optional in the OpenAPI schema;
43
+ * when omitted, attributes are required by default
30
44
  * @returns The serializer builder for method chaining
31
45
  *
32
46
  * @example
33
47
  * ```typescript
34
- * // Delegate to user.email
35
- * .delegatedAttribute('user', 'email', {
36
- * openapi: { type: 'string', format: 'email' }
37
- * })
48
+ * // Delegate to a Dream association's column (type inferred)
49
+ * .delegatedAttribute('currentLocalizedText', 'title', { openapi: 'string' })
38
50
  *
39
51
  * // With default value for null target or attribute
40
52
  * .delegatedAttribute('user', 'displayName', {
41
53
  * openapi: { type: 'string' },
42
54
  * default: 'Unknown User'
43
55
  * })
44
- * ```
45
56
  *
46
- * See: {@link https://your-docs-url.com/docs/serializers/attributes | Serializer Attributes Documentation}
57
+ * // Rename the output key
58
+ * .delegatedAttribute('profile', 'avatarUrl', {
59
+ * openapi: 'string',
60
+ * as: 'avatar'
61
+ * })
62
+ * ```
47
63
  */
48
64
  delegatedAttribute(targetName, name, options) {
49
65
  this.attributes.push({
@@ -62,7 +78,17 @@ export default class DreamSerializerBuilder {
62
78
  *
63
79
  * @param name - The attribute name for the computed value
64
80
  * @param fn - Callback function that returns the computed value
65
- * @param options - Configuration options including required OpenAPI schema and optional flattening
81
+ * @param options - Configuration options:
82
+ * - `openapi` - (required) OpenAPI schema definition for the computed value
83
+ * - `as` - Rename the attribute key in the serialized output and OpenAPI shape
84
+ * - `default` - Value to use when the callback returns undefined
85
+ * - `flatten` - When `true`, spreads the returned object's properties directly into the
86
+ * parent serialized output instead of nesting them under `name`; the `openapi` option
87
+ * should then define each flattened property individually
88
+ * - `precision` - Round decimal values to the specified number of decimal places (0–9)
89
+ * during rendering; does not affect the OpenAPI shape
90
+ * - `required` - Set to `false` to mark the attribute as optional in the OpenAPI schema;
91
+ * when omitted, attributes are required by default
66
92
  * @returns The serializer builder for method chaining
67
93
  *
68
94
  * @example
@@ -74,16 +100,20 @@ export default class DreamSerializerBuilder {
74
100
  * )
75
101
  *
76
102
  * // Flattened object properties
77
- * .customAttribute('metadata', () => ({ age: 30, city: 'NYC' }), {
103
+ * .customAttribute('coordinates', () => ({ lat: 40.7, lng: -74.0 }), {
78
104
  * flatten: true,
79
105
  * openapi: {
80
- * age: { type: 'integer' },
81
- * city: { type: 'string' }
106
+ * lat: { type: 'number' },
107
+ * lng: { type: 'number' }
82
108
  * }
83
109
  * })
84
- * ```
85
110
  *
86
- * See: {@link https://your-docs-url.com/docs/serializers/attributes | Serializer Attributes Documentation}
111
+ * // With decimal precision
112
+ * .customAttribute('averageRating', () => calculateAverage(ratings), {
113
+ * openapi: 'decimal',
114
+ * precision: 2
115
+ * })
116
+ * ```
87
117
  */
88
118
  customAttribute(name, fn, options) {
89
119
  this.attributes.push({
@@ -97,28 +127,50 @@ export default class DreamSerializerBuilder {
97
127
  /**
98
128
  * Includes a single associated object in the serialized output.
99
129
  *
100
- * When rendering a Dream association, the OpenAPI shape is automatically
101
- * inferred from that associated Dream's serializer.
130
+ * When rendering a Dream association, the serializer and OpenAPI shape are automatically
131
+ * inferred from that associated Dream model's registered serializers.
102
132
  *
103
133
  * @param name - The association property name
104
- * @param options - Configuration options for serialization and schema definition
134
+ * @param options - Configuration options:
135
+ * - `as` - Rename the association key in the serialized output
136
+ * - `flatten` - When `true`, spreads the rendered association's attributes directly into
137
+ * the parent serialized output instead of nesting them under `name`. Be aware of
138
+ * attribute shadowing: if the parent and flattened association share attribute names
139
+ * (e.g., `id`), the flattened association's values overwrite the parent's
140
+ * - `optional` - When `true`, allows the association to be null/missing without causing
141
+ * an `OpenapiResponseValidationFailure` during Psychic controller unit specs. By default,
142
+ * `rendersOne` expects the association to be present (mirroring the `optional` option on
143
+ * `@deco.BelongsTo`). Set this to `true` when the association is genuinely nullable
144
+ * - `serializerKey` - Use a specific serializer key from the associated Dream model's
145
+ * registered serializers (e.g., `'summary'`)
146
+ * - `serializer` - Provide an explicit serializer function instead of using the
147
+ * associated model's registered serializers
148
+ *
149
+ * For ViewModel associations, one of these is required:
150
+ * - `viewModelClass` + optional `serializerKey`
151
+ * - `serializer`
152
+ *
153
+ * For non-Dream/non-ViewModel associations:
154
+ * - `serializer` is required
105
155
  * @returns The serializer builder for method chaining
106
156
  *
107
157
  * @example
108
158
  * ```typescript
109
- * // DreamSerializer with inference
110
- * .rendersOne('user') // Infers from Dream association
159
+ * // Auto-infer serializer from Dream association
160
+ * .rendersOne('profile')
111
161
  *
112
- * // With specific serializer
162
+ * // With specific serializer key
113
163
  * .rendersOne('user', { serializerKey: 'summary' })
114
164
  *
115
- * // ObjectSerializer (explicit configuration required)
116
- * .rendersOne('owner', UserSerializer, {
117
- * openapi: { $ref: '#/components/schemas/User' }
118
- * })
119
- * ```
165
+ * // Allow null association
166
+ * .rendersOne('approver', { optional: true })
120
167
  *
121
- * See: {@link https://your-docs-url.com/docs/serializers/associations | Serializer Associations Documentation}
168
+ * // Flatten into parent object
169
+ * .rendersOne('candidate', { serializerKey: 'summary', flatten: true })
170
+ *
171
+ * // Explicit serializer function
172
+ * .rendersOne('owner', { serializer: CustomOwnerSerializer })
173
+ * ```
122
174
  */
123
175
  rendersOne(name, options) {
124
176
  this.attributes.push({
@@ -131,31 +183,39 @@ export default class DreamSerializerBuilder {
131
183
  /**
132
184
  * Includes an array of associated objects in the serialized output.
133
185
  *
134
- * When rendering a Dream association, the OpenAPI shape is automatically
135
- * inferred from that associated Dream's serializer.
186
+ * When rendering a Dream association, the serializer and OpenAPI shape are automatically
187
+ * inferred from that associated Dream model's registered serializers.
188
+ *
189
+ * @param name - The association property name (should resolve to an array)
190
+ * @param options - Configuration options:
191
+ * - `as` - Rename the association key in the serialized output
192
+ * - `serializerKey` - Use a specific serializer key from the associated Dream model's
193
+ * registered serializers (e.g., `'summary'`)
194
+ * - `serializer` - Provide an explicit serializer function instead of using the
195
+ * associated model's registered serializers
136
196
  *
137
- * @param name - The association property name (should be an array)
138
- * @param options - Configuration options for serialization and schema definition
197
+ * For ViewModel associations, one of these is required:
198
+ * - `viewModelClass` + optional `serializerKey`
199
+ * - `serializer`
200
+ *
201
+ * For non-Dream/non-ViewModel associations:
202
+ * - `serializer` is required
139
203
  * @returns The serializer builder for method chaining
140
204
  *
141
205
  * @example
142
206
  * ```typescript
143
- * // DreamSerializer with inference
144
- * .rendersMany('posts') // Infers from Dream association
207
+ * // Auto-infer serializer from Dream association
208
+ * .rendersMany('rooms')
145
209
  *
146
- * // With specific serializer
147
- * .rendersMany('posts', { serializerKey: 'summary' })
210
+ * // With specific serializer key
211
+ * .rendersMany('rooms', { serializerKey: 'summary' })
148
212
  *
149
- * // ObjectSerializer (explicit configuration required)
150
- * .rendersMany('articles', ArticleSerializer, {
151
- * openapi: {
152
- * type: 'array',
153
- * items: { $ref: '#/components/schemas/Article' }
154
- * }
155
- * })
156
- * ```
213
+ * // Explicit serializer function (for non-Dream objects)
214
+ * .rendersMany('bedTypes', { serializer: BedTypeSerializer })
157
215
  *
158
- * See: {@link https://your-docs-url.com/docs/serializers/associations | Serializer Associations Documentation}
216
+ * // Rename output key
217
+ * .rendersMany('rooms', { serializerKey: 'forGuests', as: 'guestRooms' })
218
+ * ```
159
219
  */
160
220
  rendersMany(name, options) {
161
221
  this.attributes.push({
@@ -168,24 +228,22 @@ export default class DreamSerializerBuilder {
168
228
  /**
169
229
  * Executes the serializer and returns the serialized output.
170
230
  *
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.
231
+ * Processes all defined attributes, custom attributes, delegated attributes,
232
+ * and associations to produce the final serialized object.
174
233
  *
175
234
  * @param passthrough - Additional data to pass through to nested serializers
235
+ * (e.g., locale, current user context)
176
236
  * @param opts - Rendering options for customizing the serialization process
177
- * @returns The serialized object
237
+ * @returns The serialized object, suitable for JSON responses
178
238
  *
179
239
  * @example
180
240
  * ```typescript
181
241
  * const result = UserSerializer(user).render()
182
242
  * // Returns: { id: 1, email: 'user@example.com', ... }
183
243
  *
184
- * // With passthrough data
244
+ * // With passthrough data for nested serializers
185
245
  * const result = UserSerializer(user).render({ currentUserId: 123 })
186
246
  * ```
187
- *
188
- * See: {@link https://your-docs-url.com/docs/serializers/render | Serializer Rendering Documentation}
189
247
  */
190
248
  render(passthrough = {}, opts = {}) {
191
249
  return new SerializerRenderer(this, passthrough, opts).render();