@rvoh/dream 0.44.9 → 0.45.1

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 (227) hide show
  1. package/dist/cjs/src/Dream.js +328 -23
  2. package/dist/cjs/src/cli/index.js +16 -0
  3. package/dist/cjs/src/db/migration-helpers/DreamMigrationHelpers.js +18 -14
  4. package/dist/cjs/src/decorators/Decorators.js +2 -1
  5. package/dist/cjs/src/dream/DreamClassTransactionBuilder.js +92 -0
  6. package/dist/cjs/src/dream/DreamInstanceTransactionBuilder.js +98 -0
  7. package/dist/cjs/src/dream/LeftJoinLoadBuilder.js +52 -1
  8. package/dist/cjs/src/dream/LoadBuilder.js +49 -0
  9. package/dist/cjs/src/dream/Query.js +136 -24
  10. package/dist/cjs/src/dream/internal/convertDreamClassAndAssociationNameTupleArrayToPreloadArgs.js +18 -0
  11. package/dist/cjs/src/dream/internal/extractNestedPaths.js +37 -0
  12. package/dist/cjs/src/dream/internal/unaliasTableName.js +7 -0
  13. package/dist/cjs/src/helpers/indent.js +18 -0
  14. package/dist/cjs/src/serializer/SerializerRenderer.js +2 -17
  15. package/dist/cjs/src/serializer/builders/DreamSerializerBuilder.js +139 -3
  16. package/dist/cjs/src/serializer/builders/ObjectSerializerBuilder.js +176 -3
  17. package/dist/cjs/src/serializer/helpers/serializerForAssociatedClass.js +20 -0
  18. package/dist/esm/src/Dream.js +328 -23
  19. package/dist/esm/src/cli/index.js +16 -0
  20. package/dist/esm/src/db/migration-helpers/DreamMigrationHelpers.js +18 -14
  21. package/dist/esm/src/decorators/Decorators.js +2 -1
  22. package/dist/esm/src/dream/DreamClassTransactionBuilder.js +92 -0
  23. package/dist/esm/src/dream/DreamInstanceTransactionBuilder.js +98 -0
  24. package/dist/esm/src/dream/LeftJoinLoadBuilder.js +52 -1
  25. package/dist/esm/src/dream/LoadBuilder.js +49 -0
  26. package/dist/esm/src/dream/Query.js +136 -24
  27. package/dist/esm/src/dream/internal/convertDreamClassAndAssociationNameTupleArrayToPreloadArgs.js +15 -0
  28. package/dist/esm/src/dream/internal/extractNestedPaths.js +34 -0
  29. package/dist/esm/src/dream/internal/unaliasTableName.js +4 -0
  30. package/dist/esm/src/helpers/indent.js +15 -0
  31. package/dist/esm/src/serializer/SerializerRenderer.js +2 -17
  32. package/dist/esm/src/serializer/builders/DreamSerializerBuilder.js +139 -3
  33. package/dist/esm/src/serializer/builders/ObjectSerializerBuilder.js +176 -3
  34. package/dist/esm/src/serializer/helpers/serializerForAssociatedClass.js +17 -0
  35. package/dist/types/src/Dream.d.ts +283 -25
  36. package/dist/types/src/db/migration-helpers/DreamMigrationHelpers.d.ts +18 -14
  37. package/dist/types/src/decorators/Decorators.d.ts +2 -1
  38. package/dist/types/src/dream/DreamClassTransactionBuilder.d.ts +108 -2
  39. package/dist/types/src/dream/DreamInstanceTransactionBuilder.d.ts +96 -2
  40. package/dist/types/src/dream/LeftJoinLoadBuilder.d.ts +48 -1
  41. package/dist/types/src/dream/LoadBuilder.d.ts +48 -1
  42. package/dist/types/src/dream/Query.d.ts +128 -26
  43. package/dist/types/src/dream/internal/convertDreamClassAndAssociationNameTupleArrayToPreloadArgs.d.ts +9 -0
  44. package/dist/types/src/dream/internal/extractNestedPaths.d.ts +21 -0
  45. package/dist/types/src/dream/internal/unaliasTableName.d.ts +1 -0
  46. package/dist/types/src/helpers/indent.d.ts +3 -0
  47. package/dist/types/src/index.d.ts +1 -1
  48. package/dist/types/src/serializer/builders/DreamSerializerBuilder.d.ts +176 -5
  49. package/dist/types/src/serializer/builders/ObjectSerializerBuilder.d.ts +176 -3
  50. package/dist/types/src/serializer/helpers/serializerForAssociatedClass.d.ts +9 -0
  51. package/dist/types/src/types/dream.d.ts +2 -1
  52. package/dist/types/src/types/dream.ts +26 -1
  53. package/dist/types/src/types/query.d.ts +5 -0
  54. package/dist/types/src/types/query.ts +5 -0
  55. package/docs/assets/highlight.css +7 -0
  56. package/docs/assets/navigation.js +1 -1
  57. package/docs/assets/search.js +1 -1
  58. package/docs/classes/Benchmark.html +2 -2
  59. package/docs/classes/CalendarDate.html +2 -2
  60. package/docs/classes/CreateOrFindByFailedToCreateAndFind.html +3 -3
  61. package/docs/classes/Decorators.html +21 -20
  62. package/docs/classes/Dream.html +339 -226
  63. package/docs/classes/DreamApp.html +4 -4
  64. package/docs/classes/DreamBin.html +2 -2
  65. package/docs/classes/DreamCLI.html +4 -4
  66. package/docs/classes/DreamImporter.html +2 -2
  67. package/docs/classes/DreamLogos.html +2 -2
  68. package/docs/classes/DreamMigrationHelpers.html +21 -8
  69. package/docs/classes/DreamSerializerBuilder.html +66 -2
  70. package/docs/classes/DreamTransaction.html +2 -2
  71. package/docs/classes/Encrypt.html +2 -2
  72. package/docs/classes/Env.html +2 -2
  73. package/docs/classes/GlobalNameNotSet.html +3 -3
  74. package/docs/classes/NonLoadedAssociation.html +3 -3
  75. package/docs/classes/ObjectSerializerBuilder.html +66 -2
  76. package/docs/classes/Query.html +122 -78
  77. package/docs/classes/Range.html +2 -2
  78. package/docs/classes/RecordNotFound.html +3 -3
  79. package/docs/classes/ValidationError.html +3 -3
  80. package/docs/functions/DreamSerializer.html +1 -1
  81. package/docs/functions/ObjectSerializer.html +1 -1
  82. package/docs/functions/ReplicaSafe.html +1 -1
  83. package/docs/functions/STI.html +1 -1
  84. package/docs/functions/SoftDelete.html +1 -1
  85. package/docs/functions/camelize.html +1 -1
  86. package/docs/functions/capitalize.html +1 -1
  87. package/docs/functions/cloneDeepSafe.html +1 -1
  88. package/docs/functions/closeAllDbConnections.html +1 -1
  89. package/docs/functions/compact.html +1 -1
  90. package/docs/functions/dreamDbConnections.html +1 -1
  91. package/docs/functions/dreamPath.html +1 -1
  92. package/docs/functions/expandStiClasses.html +1 -1
  93. package/docs/functions/generateDream.html +1 -1
  94. package/docs/functions/globalClassNameFromFullyQualifiedModelName.html +1 -1
  95. package/docs/functions/groupBy.html +1 -1
  96. package/docs/functions/hyphenize.html +1 -1
  97. package/docs/functions/inferSerializerFromDreamOrViewModel.html +1 -1
  98. package/docs/functions/inferSerializersFromDreamClassOrViewModelClass.html +1 -1
  99. package/docs/functions/intersection.html +1 -1
  100. package/docs/functions/isDreamSerializer.html +1 -1
  101. package/docs/functions/isEmpty.html +1 -1
  102. package/docs/functions/loadRepl.html +1 -1
  103. package/docs/functions/lookupClassByGlobalName.html +1 -1
  104. package/docs/functions/normalizeUnicode.html +1 -1
  105. package/docs/functions/pascalize.html +1 -1
  106. package/docs/functions/pgErrorType.html +1 -1
  107. package/docs/functions/range-1.html +1 -1
  108. package/docs/functions/relativeDreamPath.html +1 -1
  109. package/docs/functions/round.html +1 -1
  110. package/docs/functions/serializerNameFromFullyQualifiedModelName.html +1 -1
  111. package/docs/functions/sharedPathPrefix.html +1 -1
  112. package/docs/functions/snakeify.html +1 -1
  113. package/docs/functions/sort.html +1 -1
  114. package/docs/functions/sortBy.html +1 -1
  115. package/docs/functions/sortObjectByKey.html +1 -1
  116. package/docs/functions/sortObjectByValue.html +1 -1
  117. package/docs/functions/standardizeFullyQualifiedModelName.html +1 -1
  118. package/docs/functions/uncapitalize.html +1 -1
  119. package/docs/functions/uniq.html +1 -1
  120. package/docs/functions/untypedDb.html +1 -1
  121. package/docs/functions/validateColumn.html +1 -1
  122. package/docs/functions/validateTable.html +1 -1
  123. package/docs/interfaces/BelongsToStatement.html +2 -2
  124. package/docs/interfaces/DecoratorContext.html +2 -2
  125. package/docs/interfaces/DreamAppInitOptions.html +2 -2
  126. package/docs/interfaces/DreamAppOpts.html +2 -2
  127. package/docs/interfaces/EncryptOptions.html +2 -2
  128. package/docs/interfaces/InternalAnyTypedSerializerRendersMany.html +2 -2
  129. package/docs/interfaces/InternalAnyTypedSerializerRendersOne.html +2 -2
  130. package/docs/interfaces/OpenapiDescription.html +2 -2
  131. package/docs/interfaces/OpenapiSchemaProperties.html +1 -1
  132. package/docs/interfaces/OpenapiSchemaPropertiesShorthand.html +1 -1
  133. package/docs/interfaces/OpenapiTypeFieldObject.html +1 -1
  134. package/docs/interfaces/SerializerRendererOpts.html +2 -2
  135. package/docs/modules.html +1 -0
  136. package/docs/types/Camelized.html +1 -1
  137. package/docs/types/CommonOpenapiSchemaObjectFields.html +1 -1
  138. package/docs/types/DateTime.html +1 -1
  139. package/docs/types/DbConnectionType.html +1 -1
  140. package/docs/types/DbTypes.html +1 -1
  141. package/docs/types/DreamAssociationMetadata.html +1 -1
  142. package/docs/types/DreamAttributes.html +1 -1
  143. package/docs/types/DreamClassAssociationAndStatement.html +1 -0
  144. package/docs/types/DreamClassColumn.html +1 -1
  145. package/docs/types/DreamColumn.html +1 -1
  146. package/docs/types/DreamColumnNames.html +1 -1
  147. package/docs/types/DreamLogLevel.html +1 -1
  148. package/docs/types/DreamLogger.html +1 -1
  149. package/docs/types/DreamModelSerializerType.html +1 -1
  150. package/docs/types/DreamOrViewModelClassSerializerKey.html +1 -1
  151. package/docs/types/DreamOrViewModelSerializerKey.html +1 -1
  152. package/docs/types/DreamParamSafeAttributes.html +1 -1
  153. package/docs/types/DreamParamSafeColumnNames.html +1 -1
  154. package/docs/types/DreamSerializable.html +1 -1
  155. package/docs/types/DreamSerializableArray.html +1 -1
  156. package/docs/types/DreamSerializerKey.html +1 -1
  157. package/docs/types/DreamSerializers.html +1 -1
  158. package/docs/types/DreamTableSchema.html +1 -1
  159. package/docs/types/DreamVirtualColumns.html +1 -1
  160. package/docs/types/EncryptAlgorithm.html +1 -1
  161. package/docs/types/HasManyStatement.html +1 -1
  162. package/docs/types/HasOneStatement.html +1 -1
  163. package/docs/types/Hyphenized.html +1 -1
  164. package/docs/types/IdType.html +1 -1
  165. package/docs/types/OpenapiAllTypes.html +1 -1
  166. package/docs/types/OpenapiFormats.html +1 -1
  167. package/docs/types/OpenapiNumberFormats.html +1 -1
  168. package/docs/types/OpenapiPrimitiveBaseTypes.html +1 -1
  169. package/docs/types/OpenapiPrimitiveTypes.html +1 -1
  170. package/docs/types/OpenapiSchemaArray.html +1 -1
  171. package/docs/types/OpenapiSchemaArrayShorthand.html +1 -1
  172. package/docs/types/OpenapiSchemaBase.html +1 -1
  173. package/docs/types/OpenapiSchemaBody.html +1 -1
  174. package/docs/types/OpenapiSchemaBodyShorthand.html +1 -1
  175. package/docs/types/OpenapiSchemaCommonFields.html +1 -1
  176. package/docs/types/OpenapiSchemaExpressionAllOf.html +1 -1
  177. package/docs/types/OpenapiSchemaExpressionAnyOf.html +1 -1
  178. package/docs/types/OpenapiSchemaExpressionOneOf.html +1 -1
  179. package/docs/types/OpenapiSchemaExpressionRef.html +1 -1
  180. package/docs/types/OpenapiSchemaExpressionRefSchemaShorthand.html +1 -1
  181. package/docs/types/OpenapiSchemaInteger.html +1 -1
  182. package/docs/types/OpenapiSchemaNull.html +1 -1
  183. package/docs/types/OpenapiSchemaNumber.html +1 -1
  184. package/docs/types/OpenapiSchemaObject.html +1 -1
  185. package/docs/types/OpenapiSchemaObjectAllOf.html +1 -1
  186. package/docs/types/OpenapiSchemaObjectAllOfShorthand.html +1 -1
  187. package/docs/types/OpenapiSchemaObjectAnyOf.html +1 -1
  188. package/docs/types/OpenapiSchemaObjectAnyOfShorthand.html +1 -1
  189. package/docs/types/OpenapiSchemaObjectBase.html +1 -1
  190. package/docs/types/OpenapiSchemaObjectBaseShorthand.html +1 -1
  191. package/docs/types/OpenapiSchemaObjectOneOf.html +1 -1
  192. package/docs/types/OpenapiSchemaObjectOneOfShorthand.html +1 -1
  193. package/docs/types/OpenapiSchemaObjectShorthand.html +1 -1
  194. package/docs/types/OpenapiSchemaPrimitiveGeneric.html +1 -1
  195. package/docs/types/OpenapiSchemaShorthandExpressionAllOf.html +1 -1
  196. package/docs/types/OpenapiSchemaShorthandExpressionAnyOf.html +1 -1
  197. package/docs/types/OpenapiSchemaShorthandExpressionOneOf.html +1 -1
  198. package/docs/types/OpenapiSchemaShorthandExpressionSerializableRef.html +1 -1
  199. package/docs/types/OpenapiSchemaShorthandExpressionSerializerRef.html +1 -1
  200. package/docs/types/OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
  201. package/docs/types/OpenapiSchemaString.html +1 -1
  202. package/docs/types/OpenapiShorthandAllTypes.html +1 -1
  203. package/docs/types/OpenapiShorthandPrimitiveBaseTypes.html +1 -1
  204. package/docs/types/OpenapiShorthandPrimitiveTypes.html +1 -1
  205. package/docs/types/OpenapiTypeField.html +1 -1
  206. package/docs/types/Pascalized.html +1 -1
  207. package/docs/types/PrimaryKeyType.html +1 -1
  208. package/docs/types/RoundingPrecision.html +1 -1
  209. package/docs/types/SerializerCasing.html +1 -1
  210. package/docs/types/SimpleObjectSerializerType.html +1 -1
  211. package/docs/types/Snakeified.html +1 -1
  212. package/docs/types/Timestamp.html +1 -1
  213. package/docs/types/UpdateableAssociationProperties.html +1 -1
  214. package/docs/types/UpdateableProperties.html +1 -1
  215. package/docs/types/ValidationType.html +1 -1
  216. package/docs/types/ViewModel.html +1 -1
  217. package/docs/types/ViewModelClass.html +1 -1
  218. package/docs/types/WhereStatementForDream.html +1 -1
  219. package/docs/types/WhereStatementForDreamClass.html +1 -1
  220. package/docs/variables/DateTime-1.html +1 -1
  221. package/docs/variables/DreamConst.html +1 -1
  222. package/docs/variables/TRIGRAM_OPERATORS.html +1 -1
  223. package/docs/variables/openapiPrimitiveTypes-1.html +1 -1
  224. package/docs/variables/openapiShorthandPrimitiveTypes-1.html +1 -1
  225. package/docs/variables/ops.html +1 -1
  226. package/docs/variables/primaryKeyTypes.html +1 -1
  227. package/package.json +2 -2
@@ -0,0 +1,15 @@
1
+ export function indent(number, { tabWidth = 2 } = {}) {
2
+ let spacesString = '';
3
+ const indentationUnit = indentationUnitString(tabWidth);
4
+ for (let i = 0; i < number; i++) {
5
+ spacesString += indentationUnit;
6
+ }
7
+ return spacesString;
8
+ }
9
+ function indentationUnitString(number) {
10
+ let spacesString = '';
11
+ for (let i = 0; i < number; i++) {
12
+ spacesString += ' ';
13
+ }
14
+ return spacesString;
15
+ }
@@ -6,7 +6,8 @@ import round from '../helpers/round.js';
6
6
  import snakeify from '../helpers/snakeify.js';
7
7
  import DreamSerializerBuilder from './builders/DreamSerializerBuilder.js';
8
8
  import ObjectSerializerBuilder from './builders/ObjectSerializerBuilder.js';
9
- import inferSerializerFromDreamOrViewModel, { inferSerializersFromDreamClassOrViewModelClass, } from './helpers/inferSerializerFromDreamOrViewModel.js';
9
+ import inferSerializerFromDreamOrViewModel from './helpers/inferSerializerFromDreamOrViewModel.js';
10
+ import { serializerForAssociatedClass } from './helpers/serializerForAssociatedClass.js';
10
11
  export default class SerializerRenderer {
11
12
  serializerBuilder;
12
13
  passthroughData;
@@ -201,19 +202,3 @@ function serializerForAssociatedObject(associatedObject, options) {
201
202
  return options.serializer;
202
203
  return inferSerializerFromDreamOrViewModel(associatedObject, options.serializerKey);
203
204
  }
204
- /**
205
- * Only used when flatten: true, and the associated model is null, in which case,
206
- * we need something to determine the keys that will be flattened into the
207
- * rendering serializer
208
- */
209
- function serializerForAssociatedClass(object, associationName, options) {
210
- if (options.serializer)
211
- return options.serializer;
212
- if (!object.isDreamInstance)
213
- return null;
214
- const dream = object;
215
- const association = dream['getAssociationMetadata'](associationName);
216
- const associatedClasses = association.modelCB();
217
- const associatedClass = Array.isArray(associatedClasses) ? associatedClasses[0] : associatedClasses;
218
- return inferSerializersFromDreamClassOrViewModelClass(associatedClass, options.serializerKey)[0] ?? null;
219
- }
@@ -20,15 +20,74 @@ export default class DreamSerializerBuilder {
20
20
  });
21
21
  return this;
22
22
  }
23
+ /**
24
+ * Includes an attribute from a nested object in the serialized output.
25
+ *
26
+ * Serializes an attribute from a target object. If the target object or
27
+ * the delegated attribute is null/undefined, the `default` option value
28
+ * will be used if provided.
29
+ *
30
+ * @param targetName - The property name containing the target object
31
+ * @param name - The attribute name within the target object
32
+ * @param options - Configuration options including OpenAPI schema, default value, and output customization
33
+ * @returns The serializer builder for method chaining
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * // Delegate to user.email
38
+ * .delegatedAttribute('user', 'email', {
39
+ * openapi: { type: 'string', format: 'email' }
40
+ * })
41
+ *
42
+ * // With default value for null target or attribute
43
+ * .delegatedAttribute('user', 'displayName', {
44
+ * openapi: { type: 'string' },
45
+ * default: 'Unknown User'
46
+ * })
47
+ * ```
48
+ *
49
+ * See: {@link https://your-docs-url.com/docs/serializers/attributes | Serializer Attributes Documentation}
50
+ */
23
51
  delegatedAttribute(targetName, name, options) {
24
52
  this.attributes.push({
25
53
  type: 'delegatedAttribute',
26
- targetName,
54
+ targetName: targetName,
27
55
  name: name,
28
56
  options: options ?? {},
29
57
  });
30
58
  return this;
31
59
  }
60
+ /**
61
+ * Includes a computed value in the serialized output.
62
+ *
63
+ * Executes a callback function to generate a custom attribute value.
64
+ * The `openapi` option is always required since the return type cannot be inferred.
65
+ *
66
+ * @param name - The attribute name for the computed value
67
+ * @param fn - Callback function that returns the computed value
68
+ * @param options - Configuration options including required OpenAPI schema and optional flattening
69
+ * @returns The serializer builder for method chaining
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * // Simple computed value
74
+ * .customAttribute('initials', () =>
75
+ * `${user.firstName?.[0]}${user.lastName?.[0]}`.toUpperCase(),
76
+ * { openapi: { type: 'string' } }
77
+ * )
78
+ *
79
+ * // Flattened object properties
80
+ * .customAttribute('metadata', () => ({ age: 30, city: 'NYC' }), {
81
+ * flatten: true,
82
+ * openapi: {
83
+ * age: { type: 'integer' },
84
+ * city: { type: 'string' }
85
+ * }
86
+ * })
87
+ * ```
88
+ *
89
+ * See: {@link https://your-docs-url.com/docs/serializers/attributes | Serializer Attributes Documentation}
90
+ */
32
91
  customAttribute(name, fn, options) {
33
92
  this.attributes.push({
34
93
  type: 'customAttribute',
@@ -38,22 +97,99 @@ export default class DreamSerializerBuilder {
38
97
  });
39
98
  return this;
40
99
  }
100
+ /**
101
+ * Includes a single associated object in the serialized output.
102
+ *
103
+ * When rendering a Dream association, the OpenAPI shape is automatically
104
+ * inferred from that associated Dream's serializer.
105
+ *
106
+ * @param name - The association property name
107
+ * @param options - Configuration options for serialization and schema definition
108
+ * @returns The serializer builder for method chaining
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * // DreamSerializer with inference
113
+ * .rendersOne('user') // Infers from Dream association
114
+ *
115
+ * // With specific serializer
116
+ * .rendersOne('user', { serializerKey: 'summary' })
117
+ *
118
+ * // ObjectSerializer (explicit configuration required)
119
+ * .rendersOne('owner', UserSerializer, {
120
+ * openapi: { $ref: '#/components/schemas/User' }
121
+ * })
122
+ * ```
123
+ *
124
+ * See: {@link https://your-docs-url.com/docs/serializers/associations | Serializer Associations Documentation}
125
+ */
41
126
  rendersOne(name, options) {
42
127
  this.attributes.push({
43
128
  type: 'rendersOne',
44
- name,
129
+ name: name,
45
130
  options: options ?? {},
46
131
  });
47
132
  return this;
48
133
  }
134
+ /**
135
+ * Includes an array of associated objects in the serialized output.
136
+ *
137
+ * When rendering a Dream association, the OpenAPI shape is automatically
138
+ * inferred from that associated Dream's serializer.
139
+ *
140
+ * @param name - The association property name (should be an array)
141
+ * @param options - Configuration options for serialization and schema definition
142
+ * @returns The serializer builder for method chaining
143
+ *
144
+ * @example
145
+ * ```typescript
146
+ * // DreamSerializer with inference
147
+ * .rendersMany('posts') // Infers from Dream association
148
+ *
149
+ * // With specific serializer
150
+ * .rendersMany('posts', { serializerKey: 'summary' })
151
+ *
152
+ * // ObjectSerializer (explicit configuration required)
153
+ * .rendersMany('articles', ArticleSerializer, {
154
+ * openapi: {
155
+ * type: 'array',
156
+ * items: { $ref: '#/components/schemas/Article' }
157
+ * }
158
+ * })
159
+ * ```
160
+ *
161
+ * See: {@link https://your-docs-url.com/docs/serializers/associations | Serializer Associations Documentation}
162
+ */
49
163
  rendersMany(name, options) {
50
164
  this.attributes.push({
51
165
  type: 'rendersMany',
52
- name,
166
+ name: name,
53
167
  options: options ?? {},
54
168
  });
55
169
  return this;
56
170
  }
171
+ /**
172
+ * Executes the serializer and returns the serialized output.
173
+ *
174
+ * This method processes all defined attributes, custom attributes, delegated attributes,
175
+ * and associations to produce the final serialized object. The result is suitable for
176
+ * JSON.stringify() and API responses.
177
+ *
178
+ * @param passthrough - Additional data to pass through to nested serializers
179
+ * @param opts - Rendering options for customizing the serialization process
180
+ * @returns The serialized object
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * const result = UserSerializer(user).render()
185
+ * // Returns: { id: 1, email: 'user@example.com', ... }
186
+ *
187
+ * // With passthrough data
188
+ * const result = UserSerializer(user).render({ currentUserId: 123 })
189
+ * ```
190
+ *
191
+ * See: {@link https://your-docs-url.com/docs/serializers/render | Serializer Rendering Documentation}
192
+ */
57
193
  render(passthrough = {}, opts = {}) {
58
194
  return new SerializerRenderer(this, passthrough, opts).render();
59
195
  }
@@ -10,6 +10,38 @@ export default class ObjectSerializerBuilder {
10
10
  this.data = data;
11
11
  this.passthroughData = passthroughData;
12
12
  }
13
+ /**
14
+ * Includes an attribute from the data object in the serialized output.
15
+ *
16
+ * For ObjectSerializer, the `openapi` option is always required since type
17
+ * inference is not available for plain objects or ViewModels.
18
+ *
19
+ * @param name - The attribute name from the data object
20
+ * @param options - Configuration options including required OpenAPI schema, default value, and output customization
21
+ * @returns The serializer builder for method chaining
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * // Required OpenAPI schema
26
+ * .attribute('email', {
27
+ * openapi: { type: 'string', format: 'email' }
28
+ * })
29
+ *
30
+ * // With default value
31
+ * .attribute('status', {
32
+ * openapi: { type: 'string' },
33
+ * default: 'active'
34
+ * })
35
+ *
36
+ * // Rename output key
37
+ * .attribute('email', {
38
+ * openapi: { type: 'string' },
39
+ * as: 'userEmail'
40
+ * })
41
+ * ```
42
+ *
43
+ * See: {@link https://your-docs-url.com/docs/serializers/attributes | Serializer Attributes Documentation}
44
+ */
13
45
  attribute(name, options) {
14
46
  this.attributes.push({
15
47
  type: 'attribute',
@@ -18,15 +50,74 @@ export default class ObjectSerializerBuilder {
18
50
  });
19
51
  return this;
20
52
  }
53
+ /**
54
+ * Includes an attribute from a nested object in the serialized output.
55
+ *
56
+ * Pulls up an attribute from a target object property. The `openapi` option
57
+ * is always required. If the target object or the delegated attribute
58
+ * is null/undefined, the `default` option value will be used if provided.
59
+ *
60
+ * @param targetName - The property name containing the target object
61
+ * @param name - The attribute name within the target object
62
+ * @param options - Configuration options including required OpenAPI schema, default value, and output customization
63
+ * @returns The serializer builder for method chaining
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * // Delegate to user.email
68
+ * .delegatedAttribute('user', 'email', {
69
+ * openapi: { type: 'string', format: 'email' }
70
+ * })
71
+ *
72
+ * // With default value for null target or attribute
73
+ * .delegatedAttribute('profile', 'displayName', {
74
+ * openapi: { type: 'string' },
75
+ * default: 'Anonymous User'
76
+ * })
77
+ * ```
78
+ *
79
+ * See: {@link https://your-docs-url.com/docs/serializers/attributes | Serializer Attributes Documentation}
80
+ */
21
81
  delegatedAttribute(targetName, name, options) {
22
82
  this.attributes.push({
23
83
  type: 'delegatedAttribute',
24
- targetName,
84
+ targetName: targetName,
25
85
  name: name,
26
86
  options: options ?? {},
27
87
  });
28
88
  return this;
29
89
  }
90
+ /**
91
+ * Includes a computed value in the serialized output.
92
+ *
93
+ * Executes a callback function to generate a custom attribute value.
94
+ * The `openapi` option is always required since the return type cannot be inferred.
95
+ *
96
+ * @param name - The attribute name for the computed value
97
+ * @param fn - Callback function that returns the computed value
98
+ * @param options - Configuration options including required OpenAPI schema and optional flattening
99
+ * @returns The serializer builder for method chaining
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * // Simple computed value
104
+ * .customAttribute('fullName', () =>
105
+ * `${user.firstName} ${user.lastName}`,
106
+ * { openapi: { type: 'string' } }
107
+ * )
108
+ *
109
+ * // Flattened object properties
110
+ * .customAttribute('coordinates', () => ({ lat: 40.7, lng: -74.0 }), {
111
+ * flatten: true,
112
+ * openapi: {
113
+ * lat: { type: 'number' },
114
+ * lng: { type: 'number' }
115
+ * }
116
+ * })
117
+ * ```
118
+ *
119
+ * See: {@link https://your-docs-url.com/docs/serializers/attributes | Serializer Attributes Documentation}
120
+ */
30
121
  customAttribute(name, fn, options) {
31
122
  this.attributes.push({
32
123
  type: 'customAttribute',
@@ -36,22 +127,104 @@ export default class ObjectSerializerBuilder {
36
127
  });
37
128
  return this;
38
129
  }
130
+ /**
131
+ * Includes a single associated object in the serialized output.
132
+ *
133
+ * For ObjectSerializer, explicit serializer configuration is always required
134
+ * since association schemas cannot be inferred from plain objects.
135
+ *
136
+ * @param name - The association property name
137
+ * @param options - Configuration options including required serializer and OpenAPI schema
138
+ * @returns The serializer builder for method chaining
139
+ *
140
+ * @example
141
+ * ```typescript
142
+ * // With explicit serializer function
143
+ * .rendersOne('owner', UserSerializer, {
144
+ * openapi: { $ref: '#/components/schemas/User' }
145
+ * })
146
+ *
147
+ * // With Dream class reference
148
+ * .rendersOne('creator', {
149
+ * dreamClass: User,
150
+ * serializerKey: 'summary',
151
+ * openapi: { $ref: '#/components/schemas/UserSummary' }
152
+ * })
153
+ * ```
154
+ *
155
+ * See: {@link https://your-docs-url.com/docs/serializers/associations | Serializer Associations Documentation}
156
+ */
39
157
  rendersOne(name, options) {
40
158
  this.attributes.push({
41
159
  type: 'rendersOne',
42
- name,
160
+ name: name,
43
161
  options: options ?? {},
44
162
  });
45
163
  return this;
46
164
  }
165
+ /**
166
+ * Includes an array of associated objects in the serialized output.
167
+ *
168
+ * For ObjectSerializer, explicit serializer configuration is always required
169
+ * since association schemas cannot be inferred from plain objects.
170
+ *
171
+ * @param name - The association property name (should be an array)
172
+ * @param options - Configuration options including required serializer and OpenAPI schema
173
+ * @returns The serializer builder for method chaining
174
+ *
175
+ * @example
176
+ * ```typescript
177
+ * // With explicit serializer function
178
+ * .rendersMany('articles', ArticleSerializer, {
179
+ * openapi: {
180
+ * type: 'array',
181
+ * items: { $ref: '#/components/schemas/Article' }
182
+ * }
183
+ * })
184
+ *
185
+ * // With ViewModel class reference
186
+ * .rendersMany('comments', {
187
+ * viewModelClass: CommentViewModel,
188
+ * serializer: CommentViewModelSerializer,
189
+ * openapi: {
190
+ * type: 'array',
191
+ * items: { $ref: '#/components/schemas/Comment' }
192
+ * }
193
+ * })
194
+ * ```
195
+ *
196
+ * See: {@link https://your-docs-url.com/docs/serializers/associations | Serializer Associations Documentation}
197
+ */
47
198
  rendersMany(name, options) {
48
199
  this.attributes.push({
49
200
  type: 'rendersMany',
50
- name,
201
+ name: name,
51
202
  options: options ?? {},
52
203
  });
53
204
  return this;
54
205
  }
206
+ /**
207
+ * Executes the serializer and returns the serialized output.
208
+ *
209
+ * This method processes all defined attributes, custom attributes, delegated attributes,
210
+ * and associations to produce the final serialized object. The result is suitable for
211
+ * JSON.stringify() and API responses.
212
+ *
213
+ * @param passthrough - Additional data to pass through to nested serializers
214
+ * @param opts - Rendering options for customizing the serialization process
215
+ * @returns The serialized object
216
+ *
217
+ * @example
218
+ * ```typescript
219
+ * const result = UserViewModelSerializer(userVm).render()
220
+ * // Returns: { id: '123', email: 'user@example.com', ... }
221
+ *
222
+ * // With passthrough data for nested serializers
223
+ * const result = UserViewModelSerializer(userVm).render({ currentUserId: '456' })
224
+ * ```
225
+ *
226
+ * See: {@link https://your-docs-url.com/docs/serializers/render | Serializer Rendering Documentation}
227
+ */
55
228
  render(passthrough = {}, opts = {}) {
56
229
  return new SerializerRenderer(this, passthrough, opts).render();
57
230
  }
@@ -0,0 +1,17 @@
1
+ import { inferSerializersFromDreamClassOrViewModelClass } from './inferSerializerFromDreamOrViewModel.js';
2
+ /**
3
+ * Only used when flatten: true, and the associated model is null, in which case,
4
+ * we need something to determine the keys that will be flattened into the
5
+ * rendering serializer
6
+ */
7
+ export function serializerForAssociatedClass(object, associationName, options) {
8
+ if (options.serializer)
9
+ return options.serializer;
10
+ if (!object.isDreamInstance)
11
+ return null;
12
+ const dream = object;
13
+ const association = dream['getAssociationMetadata'](associationName);
14
+ const associatedClasses = association.modelCB();
15
+ const associatedClass = Array.isArray(associatedClasses) ? associatedClasses[0] : associatedClasses;
16
+ return inferSerializersFromDreamClassOrViewModelClass(associatedClass, options.serializerKey)[0] ?? null;
17
+ }