@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
@@ -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();
@@ -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