@rvoh/dream 2.38.0 → 2.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -34
- package/dist/cjs/src/dream-app/index.js +31 -1
- package/dist/cjs/src/helpers/areEqual.js +2 -2
- package/dist/cjs/src/helpers/path/absoluteDreamPath.js +5 -3
- package/dist/cjs/src/serializer/DreamSerializer.js +5 -5
- package/dist/cjs/src/serializer/ObjectSerializer.js +5 -5
- package/dist/cjs/src/serializer/SerializerRenderer.js +21 -28
- package/dist/cjs/src/serializer/builders/DreamSerializerBuilder.js +40 -33
- package/dist/cjs/src/serializer/builders/ObjectSerializerBuilder.js +38 -33
- package/dist/cjs/src/serializer/helpers/nullFlattenedSerializerKeys.js +44 -68
- package/dist/cjs/src/serializer/helpers/serializersForAssociatedClass.js +4 -3
- package/dist/esm/src/dream-app/index.js +31 -1
- package/dist/esm/src/helpers/areEqual.js +2 -2
- package/dist/esm/src/helpers/path/absoluteDreamPath.js +5 -3
- package/dist/esm/src/serializer/DreamSerializer.js +5 -5
- package/dist/esm/src/serializer/ObjectSerializer.js +5 -5
- package/dist/esm/src/serializer/SerializerRenderer.js +21 -28
- package/dist/esm/src/serializer/builders/DreamSerializerBuilder.js +40 -33
- package/dist/esm/src/serializer/builders/ObjectSerializerBuilder.js +38 -33
- package/dist/esm/src/serializer/helpers/nullFlattenedSerializerKeys.js +44 -68
- package/dist/esm/src/serializer/helpers/serializersForAssociatedClass.js +4 -3
- package/dist/types/src/dream-app/index.d.ts +26 -3
- package/dist/types/src/serializer/DreamSerializer.d.ts +5 -5
- package/dist/types/src/serializer/ObjectSerializer.d.ts +5 -5
- package/dist/types/src/serializer/SerializerRenderer.d.ts +1 -1
- package/dist/types/src/serializer/builders/DreamSerializerBuilder.d.ts +43 -35
- package/dist/types/src/serializer/builders/ObjectSerializerBuilder.d.ts +41 -35
- package/dist/types/src/serializer/helpers/nullFlattenedSerializerKeys.d.ts +43 -33
- package/dist/types/src/serializer/helpers/serializersForAssociatedClass.d.ts +4 -3
- package/docs/assets/search.js +1 -1
- package/docs/classes/db.DreamMigrationHelpers.html +11 -11
- package/docs/classes/db.KyselyQueryDriver.html +49 -49
- package/docs/classes/db.PostgresQueryDriver.html +49 -49
- package/docs/classes/db.QueryDriverBase.html +49 -49
- package/docs/classes/errors.CannotSaveMissingDream.html +2 -2
- package/docs/classes/errors.CheckConstraintViolation.html +3 -3
- package/docs/classes/errors.ColumnOverflow.html +3 -3
- package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
- package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +3 -3
- package/docs/classes/errors.DataTypeColumnTypeMismatch.html +3 -3
- package/docs/classes/errors.DecryptionError.html +2 -2
- package/docs/classes/errors.DecryptionParseError.html +2 -2
- package/docs/classes/errors.DecryptionRotationError.html +3 -3
- package/docs/classes/errors.GlobalNameNotSet.html +3 -3
- package/docs/classes/errors.InvalidCalendarDate.html +2 -2
- package/docs/classes/errors.InvalidClockTime.html +2 -2
- package/docs/classes/errors.InvalidClockTimeTz.html +2 -2
- package/docs/classes/errors.InvalidDateTime.html +2 -2
- package/docs/classes/errors.MissingSerializersDefinition.html +3 -3
- package/docs/classes/errors.NonLoadedAssociation.html +3 -3
- package/docs/classes/errors.NotNullViolation.html +3 -3
- package/docs/classes/errors.RecordNotFound.html +3 -3
- package/docs/classes/errors.SortableScopeDidNotStabilize.html +3 -3
- package/docs/classes/errors.SortableScopeLockWaitTimedOut.html +3 -3
- package/docs/classes/errors.ValidationError.html +3 -3
- package/docs/classes/index.CalendarDate.html +33 -33
- package/docs/classes/index.ClockTime.html +32 -32
- package/docs/classes/index.ClockTimeTz.html +35 -35
- package/docs/classes/index.DateTime.html +86 -86
- package/docs/classes/index.Decorators.html +19 -19
- package/docs/classes/index.Dream.html +125 -125
- package/docs/classes/index.DreamApp.html +26 -11
- package/docs/classes/index.DreamTransaction.html +3 -3
- package/docs/classes/index.Env.html +5 -5
- package/docs/classes/index.Query.html +65 -65
- package/docs/classes/system.CliFileWriter.html +4 -4
- package/docs/classes/system.DreamBin.html +3 -3
- package/docs/classes/system.DreamCLI.html +7 -7
- package/docs/classes/system.DreamImporter.html +2 -2
- package/docs/classes/system.DreamLogos.html +2 -2
- package/docs/classes/system.DreamSerializerBuilder.html +51 -44
- package/docs/classes/system.ObjectSerializerBuilder.html +49 -43
- package/docs/classes/system.PathHelpers.html +3 -3
- package/docs/classes/utils.Encrypt.html +4 -4
- package/docs/classes/utils.Range.html +2 -2
- package/docs/functions/db.closeAllDbConnections.html +1 -1
- package/docs/functions/db.dreamDbConnections.html +1 -1
- package/docs/functions/db.untypedDb.html +1 -1
- package/docs/functions/db.validateColumn.html +1 -1
- package/docs/functions/db.validateTable.html +1 -1
- package/docs/functions/errors.pgErrorType.html +1 -1
- package/docs/functions/index.DreamSerializer.html +6 -6
- package/docs/functions/index.ObjectSerializer.html +6 -6
- package/docs/functions/index.ReplicaSafe.html +1 -1
- package/docs/functions/index.STI.html +1 -1
- package/docs/functions/index.SoftDelete.html +1 -1
- package/docs/functions/utils.camelize.html +1 -1
- package/docs/functions/utils.capitalize.html +1 -1
- package/docs/functions/utils.cloneDeepSafe.html +1 -1
- package/docs/functions/utils.compact.html +1 -1
- package/docs/functions/utils.groupBy.html +1 -1
- package/docs/functions/utils.hyphenize.html +1 -1
- package/docs/functions/utils.intersection.html +1 -1
- package/docs/functions/utils.isEmpty.html +1 -1
- package/docs/functions/utils.normalizeUnicode.html +1 -1
- package/docs/functions/utils.pascalize.html +1 -1
- package/docs/functions/utils.percent.html +1 -1
- package/docs/functions/utils.range.html +1 -1
- package/docs/functions/utils.round.html +1 -1
- package/docs/functions/utils.sanitizeString.html +1 -1
- package/docs/functions/utils.snakeify.html +1 -1
- package/docs/functions/utils.sort.html +1 -1
- package/docs/functions/utils.sortBy.html +1 -1
- package/docs/functions/utils.sortObjectByKey.html +1 -1
- package/docs/functions/utils.sortObjectByValue.html +1 -1
- package/docs/functions/utils.uncapitalize.html +1 -1
- package/docs/functions/utils.uniq.html +1 -1
- package/docs/index.html +2 -9
- package/docs/interfaces/openapi.OpenapiDescription.html +2 -2
- package/docs/interfaces/openapi.OpenapiSchemaProperties.html +1 -1
- package/docs/interfaces/openapi.OpenapiSchemaPropertiesShorthand.html +1 -1
- package/docs/interfaces/openapi.OpenapiTypeFieldObject.html +1 -1
- package/docs/interfaces/types.BelongsToStatement.html +2 -2
- package/docs/interfaces/types.DecoratorContext.html +2 -2
- package/docs/interfaces/types.DecryptCallbacks.html +2 -2
- package/docs/interfaces/types.DreamAppInitOptions.html +2 -2
- package/docs/interfaces/types.DreamAppOpts.html +2 -2
- package/docs/interfaces/types.DreamDbConfig.html +6 -6
- package/docs/interfaces/types.DurationObject.html +2 -2
- package/docs/interfaces/types.EncryptOptions.html +2 -2
- package/docs/interfaces/types.EncryptionLegacyKeyUsedEvent.html +4 -4
- package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
- package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
- package/docs/interfaces/types.IntrospectedColumn.html +7 -7
- package/docs/interfaces/types.IntrospectedDatabase.html +2 -2
- package/docs/interfaces/types.IntrospectedEnum.html +2 -2
- package/docs/interfaces/types.IntrospectedTable.html +5 -5
- package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
- package/docs/media/CONTRIBUTING.md +128 -0
- package/docs/types/openapi.CommonOpenapiSchemaObjectFields.html +1 -1
- package/docs/types/openapi.OpenapiAllTypes.html +1 -1
- package/docs/types/openapi.OpenapiFormats.html +1 -1
- package/docs/types/openapi.OpenapiNumberFormats.html +1 -1
- package/docs/types/openapi.OpenapiPrimitiveBaseTypes.html +1 -1
- package/docs/types/openapi.OpenapiPrimitiveTypes.html +1 -1
- package/docs/types/openapi.OpenapiSchemaArray.html +1 -1
- package/docs/types/openapi.OpenapiSchemaArrayShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaBase.html +1 -1
- package/docs/types/openapi.OpenapiSchemaBody.html +1 -1
- package/docs/types/openapi.OpenapiSchemaBodyShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaCombinatorFields.html +1 -1
- package/docs/types/openapi.OpenapiSchemaCommonFields.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionRef.html +2 -2
- package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +2 -2
- package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
- package/docs/types/openapi.OpenapiSchemaNull.html +2 -2
- package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaPrimitiveGeneric.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionAllOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
- package/docs/types/openapi.OpenapiSchemaString.html +1 -1
- package/docs/types/openapi.OpenapiShorthandAllTypes.html +1 -1
- package/docs/types/openapi.OpenapiShorthandPrimitiveBaseTypes.html +1 -1
- package/docs/types/openapi.OpenapiShorthandPrimitiveTypes.html +1 -1
- package/docs/types/openapi.OpenapiTypeField.html +1 -1
- package/docs/types/system.DreamAppAllowedPackageManagersEnum.html +1 -1
- package/docs/types/types.CalendarDateDurationUnit.html +1 -1
- package/docs/types/types.CalendarDateObject.html +1 -1
- package/docs/types/types.Camelized.html +1 -1
- package/docs/types/types.ClockTimeObject.html +1 -1
- package/docs/types/types.DbConnectionType.html +1 -1
- package/docs/types/types.DbTypes.html +1 -1
- package/docs/types/types.DreamAssociationMetadata.html +1 -1
- package/docs/types/types.DreamAttributes.html +1 -1
- package/docs/types/types.DreamClassAssociationAndStatement.html +1 -1
- package/docs/types/types.DreamClassColumn.html +1 -1
- package/docs/types/types.DreamColumn.html +1 -1
- package/docs/types/types.DreamColumnNames.html +1 -1
- package/docs/types/types.DreamLogLevel.html +1 -1
- package/docs/types/types.DreamLogger.html +2 -2
- package/docs/types/types.DreamModelSerializerType.html +1 -1
- package/docs/types/types.DreamOrViewModelClassSerializerKey.html +1 -1
- package/docs/types/types.DreamOrViewModelSerializerKey.html +1 -1
- package/docs/types/types.DreamParamSafeAttributes.html +1 -1
- package/docs/types/types.DreamParamSafeColumnNames.html +1 -1
- package/docs/types/types.DreamSerializable.html +1 -1
- package/docs/types/types.DreamSerializableArray.html +1 -1
- package/docs/types/types.DreamSerializerKey.html +1 -1
- package/docs/types/types.DreamSerializers.html +1 -1
- package/docs/types/types.DreamVirtualColumns.html +1 -1
- package/docs/types/types.DurationUnit.html +1 -1
- package/docs/types/types.EncryptAlgorithm.html +1 -1
- package/docs/types/types.HasManyStatement.html +1 -1
- package/docs/types/types.HasOneStatement.html +1 -1
- package/docs/types/types.Hyphenized.html +1 -1
- package/docs/types/types.IntrospectedValueType.html +1 -1
- package/docs/types/types.Pascalized.html +1 -1
- package/docs/types/types.PrimaryKeyType.html +1 -1
- package/docs/types/types.RoundingPrecision.html +1 -1
- package/docs/types/types.SerializerCasing.html +1 -1
- package/docs/types/types.SimpleObjectSerializerType.html +1 -1
- package/docs/types/types.Snakeified.html +1 -1
- package/docs/types/types.StrictInterface.html +1 -1
- package/docs/types/types.UpdateableAssociationProperties.html +1 -1
- package/docs/types/types.UpdateableProperties.html +1 -1
- package/docs/types/types.ValidationType.html +1 -1
- package/docs/types/types.ViewModel.html +2 -2
- package/docs/types/types.ViewModelClass.html +1 -1
- package/docs/types/types.WeekdayName.html +1 -1
- package/docs/types/types.WhereStatementForDream.html +1 -1
- package/docs/types/types.WhereStatementForDreamClass.html +1 -1
- package/docs/variables/index.DreamConst.html +1 -1
- package/docs/variables/index.ops.html +1 -1
- package/docs/variables/openapi.openapiPrimitiveTypes.html +1 -1
- package/docs/variables/openapi.openapiShorthandPrimitiveTypes.html +1 -1
- package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
- package/docs/variables/system.primaryKeyTypes.html +1 -1
- package/package.json +9 -5
|
@@ -146,28 +146,29 @@ export default class ObjectSerializerBuilder {
|
|
|
146
146
|
* - `openapi` - (required) OpenAPI schema definition for the computed value
|
|
147
147
|
* - `flatten` - When `true`, spreads the returned object's properties directly into the
|
|
148
148
|
* parent serialized output instead of nesting them under `name`. The `openapi` option
|
|
149
|
-
* then describes the whole returned object, not each property
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
149
|
+
* then describes the whole returned object, not each property: either an object schema
|
|
150
|
+
* with full property bodies (`type: 'object'`, `properties`, and `required` listing the
|
|
151
|
+
* keys that are always present), or `{ $serializer: SomeSerializer }` when the callback
|
|
152
|
+
* returns what that serializer renders. A serializer ref with `many: true` does not
|
|
153
|
+
* type-check here, since a list has no properties to spread. Whatever the callback
|
|
154
|
+
* returns, each key any shape of the `openapi` requires renders, as `null` wherever the
|
|
155
|
+
* value does not supply it (a returned plain object's key set to `undefined` does not
|
|
156
|
+
* supply it): a key an object shape lists in its `required` array, a key a `$serializer` or
|
|
157
|
+
* `$serializable` ref's serializer declares without `required: false` (for an STI base,
|
|
158
|
+
* any child's serializer), and each such key of any `allOf`, `anyOf` or `oneOf` member. So
|
|
159
|
+
* a `null` return, a serializer built over `null` or `undefined` data, or an `undefined`
|
|
160
|
+
* return without `required: false` renders each of them as `null`, and a present value
|
|
161
|
+
* renders its own keys over them, so a key another shape requires renders as `null` even
|
|
162
|
+
* when the value's own shape leaves it optional; the payload always includes the same
|
|
163
|
+
* keys whichever shape the value takes and whether it is null. An optional key no shape
|
|
164
|
+
* requires stays absent unless the value supplies it, and an `undefined` return with
|
|
165
|
+
* `required: false` adds no keys.
|
|
165
166
|
* Every key it adds follows the render's casing like the parent's own keys: a returned
|
|
166
167
|
* plain object's top-level keys and the `openapi`'s `properties` keys are cased (so
|
|
167
168
|
* `casing: 'snake'` renders `phoneNumber` as `phone_number`, present or `null`), while
|
|
168
|
-
* nested values render as returned. Attributes render in declaration order, so a key the
|
|
169
|
-
* another attribute takes the value of whichever is declared
|
|
170
|
-
* that value must match both
|
|
169
|
+
* nested values render as returned. Attributes render in declaration order, so a key the
|
|
170
|
+
* returned object shares with another attribute takes the value of whichever is declared
|
|
171
|
+
* later, and that value must match both the attribute's declaration and the `openapi`'s
|
|
171
172
|
* - `required` - Set to `false` to mark the attribute as optional in the OpenAPI schema;
|
|
172
173
|
* when omitted, attributes are required by default
|
|
173
174
|
* @returns The serializer builder for method chaining
|
|
@@ -217,23 +218,27 @@ export default class ObjectSerializerBuilder {
|
|
|
217
218
|
* declaration order, so when the parent and the association share a key (e.g., `id`),
|
|
218
219
|
* whichever is declared later wins: the association's value replaces an attribute declared
|
|
219
220
|
* before the `rendersOne`, and an attribute declared after it replaces the association's.
|
|
220
|
-
*
|
|
221
|
-
* attribute, delegatedAttribute or customAttribute declared without
|
|
222
|
-
* every non-flattened `rendersOne` and `rendersMany` (for a
|
|
223
|
-
* key the serializer of any of its target classes requires,
|
|
224
|
-
* STI base, each key the serializer of any of its STI children
|
|
225
|
-
* (so an `id` declared before the `rendersOne` becomes `null`
|
|
226
|
-
*
|
|
221
|
+
* Each key its serializer requires always renders, as `null` wherever the association
|
|
222
|
+
* does not supply it: an attribute, delegatedAttribute or customAttribute declared without
|
|
223
|
+
* `required: false`, and every non-flattened `rendersOne` and `rendersMany` (for a
|
|
224
|
+
* polymorphic `BelongsTo`, each key the serializer of any of its target classes requires,
|
|
225
|
+
* and for an association to an STI base, each key the serializer of any of its STI children
|
|
226
|
+
* requires), in the same order (so an `id` declared before the `rendersOne` becomes `null`
|
|
227
|
+
* when the association is `null`). A flattened `customAttribute` in that serializer adds the
|
|
227
228
|
* keys its `openapi` requires: a key an object shape lists in its `required` array, a key a
|
|
228
229
|
* `$serializer` or `$serializable` ref's serializer declares without `required: false`, and
|
|
229
230
|
* each such key of an `allOf`, `anyOf` or `oneOf` member; a ref with `many: true` adds none,
|
|
230
|
-
* and a flattened `customAttribute` declared with `required: false` adds none.
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
231
|
+
* and a flattened `customAttribute` declared with `required: false` adds none. When the
|
|
232
|
+
* association is `null`, each of these keys renders as `null` and nothing in its serializer
|
|
233
|
+
* is rendered, so its custom attribute callbacks do not run. When it is present, the held
|
|
234
|
+
* object's serializer renders its own keys over them, so a key another STI child's or
|
|
235
|
+
* target's serializer requires renders as `null` where the held one's serializer does not
|
|
236
|
+
* render it, including a key that serializer declares with `required: false`; the payload
|
|
237
|
+
* always includes the same keys whichever is held and whether the association is `null`. A
|
|
238
|
+
* key declared with `required: false` that no serializer requires stays absent unless it
|
|
239
|
+
* renders. The association's OpenAPI schema describes the parent's payload too, so a shared
|
|
240
|
+
* key's value must match both the parent's declaration and the association's, whichever
|
|
241
|
+
* declaration wins
|
|
237
242
|
* - `optional` - When `true`, allows the association to be null/missing without causing
|
|
238
243
|
* an `OpenapiResponseValidationFailure` during Psychic controller unit specs. By default,
|
|
239
244
|
* `rendersOne` expects the association to be present (mirroring the `optional` option on
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import snakeify from '../../helpers/snakeify.js';
|
|
2
2
|
import DreamSerializerBuilder from '../builders/DreamSerializerBuilder.js';
|
|
3
|
-
import ObjectSerializerBuilder from '../builders/ObjectSerializerBuilder.js';
|
|
4
3
|
import { inferSerializersFromDreamClassOrViewModelClass } from './inferSerializerFromDreamOrViewModel.js';
|
|
5
4
|
import { serializersForAssociatedClass } from './serializersForAssociatedClass.js';
|
|
6
5
|
/**
|
|
7
|
-
* The keys a flattened `rendersOne` adds to the parent's payload
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
6
|
+
* The keys a flattened `rendersOne` always adds to the parent's payload, returned as an object
|
|
7
|
+
* with each key set to `null`, ready to spread into the parent's payload (`Object.keys` of it for
|
|
8
|
+
* the key names alone): each key one of `serializers` requires. When the associated object is
|
|
9
|
+
* null, these are the keys it renders; when it is present, the rendered serializer's own keys
|
|
10
|
+
* render over them, so each of these it leaves out stays `null` and the payload always includes
|
|
11
|
+
* these keys, whichever serializer renders and whether the object is null. As a property read on
|
|
12
|
+
* an empty object is `undefined`, a null value carries no key it may omit: an attribute,
|
|
13
|
+
* delegatedAttribute or customAttribute declared with `required: false` adds no key unless another
|
|
14
|
+
* of `serializers` requires it. Every key is cased per `casing`, as the renderer cases it. There
|
|
15
|
+
* are several serializers when the association is a polymorphic BelongsTo, one for each target
|
|
16
|
+
* class, or when the associated class is an STI base, one for each child, and their required keys
|
|
17
|
+
* are unioned.
|
|
15
18
|
*
|
|
16
19
|
* Each serializer is built with `undefined` data to read its declarations, as Psychic's OpenAPI
|
|
17
20
|
* generation and `preloadFor` build it, and nothing is rendered: no attribute callback runs and
|
|
@@ -34,85 +37,58 @@ export function nullFlattenedSerializerKeys(serializers, options = {}) {
|
|
|
34
37
|
return nullRequiredKeys(walkSerializers(serializers, newWalk(options)));
|
|
35
38
|
}
|
|
36
39
|
/**
|
|
37
|
-
* The keys a flattened `customAttribute` with this `openapi` adds to the parent's payload
|
|
40
|
+
* The keys a flattened `customAttribute` with this `openapi` always adds to the parent's payload,
|
|
41
|
+
* each set to `null`: each key any shape of `openapi` requires, walked as
|
|
42
|
+
* `nullFlattenedSerializerKeys` walks a flattened `customAttribute` and cased per `casing`. When
|
|
38
43
|
* its callback returns null (or `undefined` without `required: false`), or a serializer built over
|
|
39
|
-
* null data,
|
|
40
|
-
*
|
|
44
|
+
* null data, these are the keys it renders; when it returns any other value, that value's own keys
|
|
45
|
+
* render over them, so each of these the value leaves out, or a returned plain object sets to
|
|
46
|
+
* `undefined`, stays `null`. With `required: false`, a callback that returns `undefined` adds none
|
|
47
|
+
* of them.
|
|
41
48
|
*/
|
|
42
49
|
export function nullFlattenedOpenapiKeys(openapi, options = {}) {
|
|
43
50
|
return nullRequiredKeys(walkOpenapi(openapi, newWalk(options)));
|
|
44
51
|
}
|
|
45
52
|
/**
|
|
46
|
-
* The keys a
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
53
|
+
* The keys only the other variants of a flattened `rendersOne` contribute to its payload, each set
|
|
54
|
+
* to `null`: each key one of `serializers` (every serializer the association may render with)
|
|
55
|
+
* requires that `renderedSerializer` does not declare at all. A key `renderedSerializer` declares
|
|
56
|
+
* is left out even when it declares it with `required: false` and another serializer requires it;
|
|
57
|
+
* the renderer fills that key with `null` too, since it renders every key
|
|
58
|
+
* `nullFlattenedSerializerKeys` returns beneath the rendered serializer's own keys.
|
|
50
59
|
*/
|
|
51
60
|
export function nullFlattenedSerializerKeysOfOtherVariants(serializers, renderedSerializer, options = {}) {
|
|
52
61
|
return nullKeysRequiredByOthers(walkSerializers(serializers, newWalk(options)), Object.keys(walkSerializers([renderedSerializer], newWalk(options))));
|
|
53
62
|
}
|
|
54
63
|
/**
|
|
55
|
-
* The keys a flattened `customAttribute` with this `openapi`
|
|
56
|
-
*
|
|
64
|
+
* The keys only the other variants of a flattened `customAttribute` with this `openapi` contribute
|
|
65
|
+
* to its payload, each set to `null`: each key a variant of `openapi` requires that
|
|
57
66
|
* `renderedVariant` does not declare. `renderedVariant` is any `openapi` shorthand: one member of
|
|
58
67
|
* an `anyOf` or `oneOf`, or `{ $serializer: childSerializer }` for one child of a `$serializable`
|
|
59
68
|
* ref to an STI base. A key requires its value when an object shape's `required` array lists it,
|
|
60
69
|
* whether the shape's own `properties` declare it or a member of its `allOf`, `anyOf` or `oneOf`
|
|
61
|
-
* does, or when a serializer declares it without `required: false`.
|
|
70
|
+
* does, or when a serializer declares it without `required: false`. A key `renderedVariant`
|
|
71
|
+
* declares is left out even when it is optional there and another variant requires it; the
|
|
72
|
+
* renderer fills that key with `null` too, since it renders every key `nullFlattenedOpenapiKeys`
|
|
73
|
+
* returns beneath the value's own keys.
|
|
62
74
|
*/
|
|
63
75
|
export function nullFlattenedOpenapiKeysOfOtherVariants(openapi, renderedVariant, options = {}) {
|
|
64
76
|
return nullKeysRequiredByOthers(walkOpenapi(openapi, newWalk(options)), Object.keys(walkOpenapi(renderedVariant, newWalk(options))));
|
|
65
77
|
}
|
|
66
78
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* several do, the first of them whose required keys the object all has, and when none is found,
|
|
79
|
-
* the object adds each key any variant requires. The object's top-level keys render cased per
|
|
80
|
-
* `casing`, so they are compared cased, and a key it has is never added.
|
|
79
|
+
* Lists the single shapes a value of a flattened `customAttribute` with this `openapi` may take,
|
|
80
|
+
* which a consumer can union into one description of the flattened payload: a `$serializer` ref to
|
|
81
|
+
* each serializer a `$serializable` ref resolves to (one per child for an STI base), or the members
|
|
82
|
+
* of an `anyOf` or `oneOf` (an `anyOf`'s members listed before a sibling `oneOf`'s, not paired with
|
|
83
|
+
* them), each member that itself has several shapes (a nested `anyOf` or `oneOf`, or a
|
|
84
|
+
* `$serializable` ref to an STI base) contributing those shapes in its place. An `allOf` beside
|
|
85
|
+
* the `anyOf` or `oneOf` describes every value, so each shape is that `allOf` with the shape added
|
|
86
|
+
* to its members. Anything else (a single shape, a ref with `many: true`, or a primitive) has no
|
|
87
|
+
* variants and returns an empty list. Each shape may be passed back as the `renderedVariant` of
|
|
88
|
+
* `nullFlattenedOpenapiKeysOfOtherVariants`. The renderer does not read a value's shape from this
|
|
89
|
+
* list: whatever shape the value takes, it renders every key `nullFlattenedOpenapiKeys` returns.
|
|
81
90
|
*/
|
|
82
|
-
export function
|
|
83
|
-
if (value instanceof DreamSerializerBuilder || value instanceof ObjectSerializerBuilder)
|
|
84
|
-
return nullKeysRequiredByOthers(walkOpenapi(openapi, newWalk(options)), Object.keys(walkSerializerBuilder(value, newWalk(options))));
|
|
85
|
-
if (typeof value !== 'object' || value === null)
|
|
86
|
-
return {};
|
|
87
|
-
const { casing } = newWalk(options);
|
|
88
|
-
const valueKeys = Object.keys(value).map(key => setCase(key, casing));
|
|
89
|
-
const variants = openapiVariants(openapi);
|
|
90
|
-
const candidates = variants
|
|
91
|
-
.map(variant => ({ variant, requirements: walkOpenapi(variant, newWalk(options)) }))
|
|
92
|
-
.filter(({ requirements }) => valueKeys.every(key => Object.prototype.hasOwnProperty.call(requirements, key)));
|
|
93
|
-
const renderedVariant = variants.length < 2
|
|
94
|
-
? openapi
|
|
95
|
-
: candidates.length === 1
|
|
96
|
-
? candidates[0].variant
|
|
97
|
-
: candidates.find(({ requirements }) => Object.keys(requirements).every(key => !requirements[key] || valueKeys.includes(key)))?.variant;
|
|
98
|
-
const requiredKeys = renderedVariant
|
|
99
|
-
? {
|
|
100
|
-
...nullFlattenedOpenapiKeysOfOtherVariants(openapi, renderedVariant, options),
|
|
101
|
-
...nullFlattenedOpenapiKeys(renderedVariant, options),
|
|
102
|
-
}
|
|
103
|
-
: nullFlattenedOpenapiKeys(openapi, options);
|
|
104
|
-
valueKeys.forEach(key => delete requiredKeys[key]);
|
|
105
|
-
return requiredKeys;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* The shapes a value of `openapi` may take, each one a variant a plain object may render: a
|
|
109
|
-
* `$serializer` ref to each serializer a `$serializable` ref resolves to, or the members of an
|
|
110
|
-
* `anyOf` or `oneOf`, each member that itself has several variants (a nested `anyOf` or `oneOf`,
|
|
111
|
-
* or a `$serializable` ref to an STI base) contributing those variants in its place. An `allOf`
|
|
112
|
-
* beside the `anyOf` or `oneOf` describes every value, so each variant is that `allOf` with the
|
|
113
|
-
* variant added to its members.
|
|
114
|
-
*/
|
|
115
|
-
function openapiVariants(openapi) {
|
|
91
|
+
export function flattenedOpenapiVariants(openapi) {
|
|
116
92
|
if (typeof openapi !== 'object' || Array.isArray(openapi))
|
|
117
93
|
return [];
|
|
118
94
|
if ('$serializable' in openapi)
|
|
@@ -123,7 +99,7 @@ function openapiVariants(openapi) {
|
|
|
123
99
|
...(('anyOf' in openapi && openapi.anyOf) || []),
|
|
124
100
|
...(('oneOf' in openapi && openapi.oneOf) || []),
|
|
125
101
|
].flatMap(member => {
|
|
126
|
-
const memberVariants =
|
|
102
|
+
const memberVariants = flattenedOpenapiVariants(member);
|
|
127
103
|
return memberVariants.length > 1 ? memberVariants : [member];
|
|
128
104
|
});
|
|
129
105
|
const sharedMembers = ('allOf' in openapi && openapi.allOf) || [];
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import uniq from '../../helpers/uniq.js';
|
|
2
2
|
import { inferSerializersFromDreamClassOrViewModelClass } from './inferSerializerFromDreamOrViewModel.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Used by every flattened rendersOne render, whether the associated object is present or null: it
|
|
5
|
+
* lists every serializer the association may render with, whose required keys the renderer renders
|
|
6
|
+
* as null in the parent's payload, beneath the present object's own keys or alone when the object
|
|
7
|
+
* is null, where there is no object to resolve a serializer from.
|
|
7
8
|
*
|
|
8
9
|
* Resolves, in order, to the `serializer` option, the serializers of the `dreamClass` or
|
|
9
10
|
* `viewModelClass` option, or the serializers of each class `parentClass` declares the association
|
|
@@ -14,7 +14,7 @@ import standardizeFullyQualifiedModelName from '../helpers/standardizeFullyQuali
|
|
|
14
14
|
import expandStiClasses from '../helpers/sti/expandStiClasses.js';
|
|
15
15
|
import inferSerializerFromDreamOrViewModel, { inferSerializersFromDreamClassOrViewModelClass } from '../serializer/helpers/inferSerializerFromDreamOrViewModel.js';
|
|
16
16
|
import isDreamSerializer from '../serializer/helpers/isDreamSerializer.js';
|
|
17
|
-
import { nullFlattenedOpenapiKeys, nullFlattenedOpenapiKeysOfOtherVariants, nullFlattenedSerializerKeys, nullFlattenedSerializerKeysOfOtherVariants } from '../serializer/helpers/nullFlattenedSerializerKeys.js';
|
|
17
|
+
import { flattenedOpenapiVariants, nullFlattenedOpenapiKeys, nullFlattenedOpenapiKeysOfOtherVariants, nullFlattenedSerializerKeys, nullFlattenedSerializerKeysOfOtherVariants } from '../serializer/helpers/nullFlattenedSerializerKeys.js';
|
|
18
18
|
import serializerNameFromFullyQualifiedModelName from '../serializer/helpers/serializerNameFromFullyQualifiedModelName.js';
|
|
19
19
|
import { DbConnectionType, LegacyCompatiblePrimaryKeyType } from '../types/db.js';
|
|
20
20
|
import { DreamModelSerializerType, SimpleObjectSerializerType } from '../types/serializer.js';
|
|
@@ -72,6 +72,7 @@ export default class DreamApp {
|
|
|
72
72
|
nullFlattenedSerializerKeysOfOtherVariants: typeof nullFlattenedSerializerKeysOfOtherVariants;
|
|
73
73
|
nullFlattenedOpenapiKeys: typeof nullFlattenedOpenapiKeys;
|
|
74
74
|
nullFlattenedOpenapiKeysOfOtherVariants: typeof nullFlattenedOpenapiKeysOfOtherVariants;
|
|
75
|
+
flattenedOpenapiVariants: typeof flattenedOpenapiVariants;
|
|
75
76
|
serializerNameFromFullyQualifiedModelName: typeof serializerNameFromFullyQualifiedModelName;
|
|
76
77
|
autogeneratedFileDisclaimer: typeof autogeneratedFileDisclaimer;
|
|
77
78
|
};
|
|
@@ -159,6 +160,26 @@ export default class DreamApp {
|
|
|
159
160
|
get packageManager(): "pnpm" | "yarn" | "npm" | "bun" | "deno";
|
|
160
161
|
private _importExtension;
|
|
161
162
|
get importExtension(): ".js" | ".ts" | "none";
|
|
163
|
+
private _importAliasPrefix;
|
|
164
|
+
/**
|
|
165
|
+
* The prefix of the import aliases the CLI generators write: the `@` in
|
|
166
|
+
* `@models/User.js`, `@serializers/UserSerializer.js` and
|
|
167
|
+
* `@spec/factories/UserFactory.js`. Set with
|
|
168
|
+
* `dreamApp.set('importAliasPrefix', '#')` to have them write
|
|
169
|
+
* `#models/User.js` and so on, which Node resolves as subpath imports
|
|
170
|
+
* declared under `imports` in the app's package.json.
|
|
171
|
+
*
|
|
172
|
+
* Defaults to `@`. The default becomes `#` in Dream 3; an app that wants
|
|
173
|
+
* to keep `@` should set it explicitly with
|
|
174
|
+
* `dreamApp.set('importAliasPrefix', '@')`.
|
|
175
|
+
*
|
|
176
|
+
* Psychic's resource controller-spec generator still writes its
|
|
177
|
+
* `@spec/unit/helpers/authentication.js` import with a literal `@` until
|
|
178
|
+
* Psychic reads this setting (planned for 3.17.0), so a Psychic app should
|
|
179
|
+
* keep its `@spec` alias, or wait for that release, before switching to
|
|
180
|
+
* `#` only.
|
|
181
|
+
*/
|
|
182
|
+
get importAliasPrefix(): "@" | "#";
|
|
162
183
|
/**
|
|
163
184
|
* if set to true, it will bypass deprecation checks that run
|
|
164
185
|
* during the sync hook. Defaults to false, we only recommend
|
|
@@ -242,7 +263,7 @@ export default class DreamApp {
|
|
|
242
263
|
private requireTestDatabaseClaimSupport;
|
|
243
264
|
load<RT extends 'models' | 'serializers'>(resourceType: RT, resourcePath: string, importCb: (path: string) => Promise<any>): Promise<void>;
|
|
244
265
|
plugin(cb: (app: DreamApp) => void | Promise<void>): void;
|
|
245
|
-
set<ApplyOpt extends DreamAppSetOption>(applyOption: ApplyOpt, options: ApplyOpt extends 'bypassDeprecationChecks' ? boolean : ApplyOpt extends 'db' ? DreamDbCredentialOptions | string : ApplyOpt extends 'encryption' ? DreamAppEncryptionOptions : ApplyOpt extends 'primaryKeyType' ? LegacyCompatiblePrimaryKeyType : ApplyOpt extends 'importExtension' ? GeneratorImportStyle : ApplyOpt extends 'logger' ? DreamLogger : ApplyOpt extends 'projectRoot' ? string : ApplyOpt extends 'inflections' ? () => void | Promise<void> : ApplyOpt extends 'packageManager' ? DreamAppAllowedPackageManagersEnum : ApplyOpt extends 'paths' ? DreamDirectoryPaths : ApplyOpt extends 'parallelTests' ? number : ApplyOpt extends 'unicodeNormalization' ? UnicodeNormalizationForm : ApplyOpt extends 'paginationPageSize' ? number : ApplyOpt extends 'paginationMaxPageSize' ? number : ApplyOpt extends 'sortableScopeLockTimeout' ? number : never, secondaryOptions?: ApplyOpt extends 'db' ? DreamDbCredentialOptions : never): void;
|
|
266
|
+
set<ApplyOpt extends DreamAppSetOption>(applyOption: ApplyOpt, options: ApplyOpt extends 'bypassDeprecationChecks' ? boolean : ApplyOpt extends 'db' ? DreamDbCredentialOptions | string : ApplyOpt extends 'encryption' ? DreamAppEncryptionOptions : ApplyOpt extends 'primaryKeyType' ? LegacyCompatiblePrimaryKeyType : ApplyOpt extends 'importExtension' ? GeneratorImportStyle : ApplyOpt extends 'importAliasPrefix' ? GeneratorImportAliasPrefix : ApplyOpt extends 'logger' ? DreamLogger : ApplyOpt extends 'projectRoot' ? string : ApplyOpt extends 'inflections' ? () => void | Promise<void> : ApplyOpt extends 'packageManager' ? DreamAppAllowedPackageManagersEnum : ApplyOpt extends 'paths' ? DreamDirectoryPaths : ApplyOpt extends 'parallelTests' ? number : ApplyOpt extends 'unicodeNormalization' ? UnicodeNormalizationForm : ApplyOpt extends 'paginationPageSize' ? number : ApplyOpt extends 'paginationMaxPageSize' ? number : ApplyOpt extends 'sortableScopeLockTimeout' ? number : never, secondaryOptions?: ApplyOpt extends 'db' ? DreamDbCredentialOptions : never): void;
|
|
246
267
|
/**
|
|
247
268
|
* Registers a callback for an app-level event. Callbacks for the same
|
|
248
269
|
* event run in the order they were registered.
|
|
@@ -289,7 +310,7 @@ export interface DreamAppOpts {
|
|
|
289
310
|
serializerCasing?: DreamSerializerCasing;
|
|
290
311
|
parallelTests: number | undefined;
|
|
291
312
|
}
|
|
292
|
-
export type DreamAppSetOption = 'bypassDeprecationChecks' | 'db' | 'encryption' | 'inflections' | 'importExtension' | 'logger' | 'paths' | 'primaryKeyType' | 'projectRoot' | 'serializerCasing' | 'parallelTests' | 'unicodeNormalization' | 'paginationPageSize' | 'paginationMaxPageSize' | 'sortableScopeLockTimeout' | 'packageManager';
|
|
313
|
+
export type DreamAppSetOption = 'bypassDeprecationChecks' | 'db' | 'encryption' | 'inflections' | 'importExtension' | 'importAliasPrefix' | 'logger' | 'paths' | 'primaryKeyType' | 'projectRoot' | 'serializerCasing' | 'parallelTests' | 'unicodeNormalization' | 'paginationPageSize' | 'paginationMaxPageSize' | 'sortableScopeLockTimeout' | 'packageManager';
|
|
293
314
|
export interface DreamDirectoryPaths {
|
|
294
315
|
models?: string;
|
|
295
316
|
serializers?: string;
|
|
@@ -447,4 +468,6 @@ export declare const DreamAppAllowedPackageManagersEnumValues: readonly ["pnpm",
|
|
|
447
468
|
export type DreamAppAllowedPackageManagersEnum = (typeof DreamAppAllowedPackageManagersEnumValues)[number];
|
|
448
469
|
export declare const GeneratorImportStyles: readonly [".js", ".ts", "none"];
|
|
449
470
|
export type GeneratorImportStyle = (typeof GeneratorImportStyles)[number];
|
|
471
|
+
export declare const GeneratorImportAliasPrefixes: readonly ["@", "#"];
|
|
472
|
+
export type GeneratorImportAliasPrefix = (typeof GeneratorImportAliasPrefixes)[number];
|
|
450
473
|
export {};
|
|
@@ -11,11 +11,11 @@ import DreamSerializerBuilder from './builders/DreamSerializerBuilder.js';
|
|
|
11
11
|
*
|
|
12
12
|
* A serializer must not read its data while being built: what it declares may not
|
|
13
13
|
* depend on its data. Dream and Psychic build it without data to read its shape (the
|
|
14
|
-
* OpenAPI schema, and the
|
|
15
|
-
* `
|
|
16
|
-
* built throws when a flattened association or
|
|
17
|
-
* rendered. Read the data inside a `customAttribute`
|
|
18
|
-
* the serializer renders, not while it is built.
|
|
14
|
+
* OpenAPI schema, and the keys a flattened association or `customAttribute` that uses
|
|
15
|
+
* it renders as `null` where its value does not supply them), so a serializer that
|
|
16
|
+
* reads its data while being built throws when a flattened association or
|
|
17
|
+
* `customAttribute` that uses it is rendered. Read the data inside a `customAttribute`
|
|
18
|
+
* callback, which runs only when the serializer renders, not while it is built.
|
|
19
19
|
*
|
|
20
20
|
* @param dreamClass - The Dream model class the serializer renders
|
|
21
21
|
* @param data - The Dream instance to render
|
|
@@ -10,11 +10,11 @@ import ObjectSerializerBuilder from './builders/ObjectSerializerBuilder.js';
|
|
|
10
10
|
*
|
|
11
11
|
* A serializer must not read its data while being built: what it declares may not
|
|
12
12
|
* depend on its data. Dream and Psychic build it without data to read its shape (the
|
|
13
|
-
* OpenAPI schema, and the
|
|
14
|
-
* `
|
|
15
|
-
* built throws when a flattened association or
|
|
16
|
-
* rendered. Read the data inside a `customAttribute`
|
|
17
|
-
* the serializer renders, not while it is built.
|
|
13
|
+
* OpenAPI schema, and the keys a flattened association or `customAttribute` that uses
|
|
14
|
+
* it renders as `null` where its value does not supply them), so a serializer that
|
|
15
|
+
* reads its data while being built throws when a flattened association or
|
|
16
|
+
* `customAttribute` that uses it is rendered. Read the data inside a `customAttribute`
|
|
17
|
+
* callback, which runs only when the serializer renders, not while it is built.
|
|
18
18
|
*
|
|
19
19
|
* @param data - The object to render
|
|
20
20
|
* @param passthroughData - Data available to this serializer and passed down to the serializers
|
|
@@ -10,6 +10,6 @@ export default class SerializerRenderer {
|
|
|
10
10
|
private renderOpts;
|
|
11
11
|
constructor(serializerBuilder: DreamSerializerBuilder<any, any> | ObjectSerializerBuilder<any, any> | null | undefined, passthroughData?: object, { casing }?: SerializerRendererOpts);
|
|
12
12
|
render(): Record<string, any> | null;
|
|
13
|
-
private
|
|
13
|
+
private setCaseOfDefinedKeys;
|
|
14
14
|
private setCase;
|
|
15
15
|
}
|
|
@@ -141,28 +141,29 @@ export default class DreamSerializerBuilder<DataTypeForOpenapi extends typeof Dr
|
|
|
141
141
|
* - `openapi` - (required) OpenAPI schema definition for the computed value
|
|
142
142
|
* - `flatten` - When `true`, spreads the returned object's properties directly into the
|
|
143
143
|
* parent serialized output instead of nesting them under `name`. The `openapi` option
|
|
144
|
-
* then describes the whole returned object, not each property
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
144
|
+
* then describes the whole returned object, not each property: either an object schema
|
|
145
|
+
* with full property bodies (`type: 'object'`, `properties`, and `required` listing the
|
|
146
|
+
* keys that are always present), or `{ $serializer: SomeSerializer }` when the callback
|
|
147
|
+
* returns what that serializer renders. A serializer ref with `many: true` does not
|
|
148
|
+
* type-check here, since a list has no properties to spread. Whatever the callback
|
|
149
|
+
* returns, each key any shape of the `openapi` requires renders, as `null` wherever the
|
|
150
|
+
* value does not supply it (a returned plain object's key set to `undefined` does not
|
|
151
|
+
* supply it): a key an object shape lists in its `required` array, a key a `$serializer` or
|
|
152
|
+
* `$serializable` ref's serializer declares without `required: false` (for an STI base,
|
|
153
|
+
* any child's serializer), and each such key of any `allOf`, `anyOf` or `oneOf` member. So
|
|
154
|
+
* a `null` return, a serializer built over `null` or `undefined` data, or an `undefined`
|
|
155
|
+
* return without `required: false` renders each of them as `null`, and a present value
|
|
156
|
+
* renders its own keys over them, so a key another shape requires renders as `null` even
|
|
157
|
+
* when the value's own shape leaves it optional; the payload always includes the same
|
|
158
|
+
* keys whichever shape the value takes and whether it is null. An optional key no shape
|
|
159
|
+
* requires stays absent unless the value supplies it, and an `undefined` return with
|
|
160
|
+
* `required: false` adds no keys.
|
|
160
161
|
* Every key it adds follows the render's casing like the parent's own keys: a returned
|
|
161
162
|
* plain object's top-level keys and the `openapi`'s `properties` keys are cased (so
|
|
162
163
|
* `casing: 'snake'` renders `phoneNumber` as `phone_number`, present or `null`), while
|
|
163
|
-
* nested values render as returned. Attributes render in declaration order, so a key the
|
|
164
|
-
* another attribute takes the value of whichever is declared
|
|
165
|
-
* that value must match both
|
|
164
|
+
* nested values render as returned. Attributes render in declaration order, so a key the
|
|
165
|
+
* returned object shares with another attribute takes the value of whichever is declared
|
|
166
|
+
* later, and that value must match both the attribute's declaration and the `openapi`'s
|
|
166
167
|
* - `required` - Set to `false` to mark the attribute as optional in the OpenAPI schema;
|
|
167
168
|
* when omitted, attributes are required by default
|
|
168
169
|
* @returns The serializer builder for method chaining
|
|
@@ -204,23 +205,29 @@ export default class DreamSerializerBuilder<DataTypeForOpenapi extends typeof Dr
|
|
|
204
205
|
* declaration order, so when the parent and the association share a key (e.g., `id`),
|
|
205
206
|
* whichever is declared later wins: the association's value replaces an attribute declared
|
|
206
207
|
* before the `rendersOne`, and an attribute declared after it replaces the association's.
|
|
207
|
-
*
|
|
208
|
-
* attribute, delegatedAttribute or customAttribute declared without
|
|
209
|
-
* every non-flattened `rendersOne` and `rendersMany` (for a
|
|
210
|
-
* key the serializer of any of its target classes requires,
|
|
211
|
-
* STI base, each key the serializer of any of its STI children
|
|
212
|
-
* (so an `id` declared before the `rendersOne` becomes `null`
|
|
213
|
-
*
|
|
208
|
+
* Each key its serializer requires always renders, as `null` wherever the association
|
|
209
|
+
* does not supply it: an attribute, delegatedAttribute or customAttribute declared without
|
|
210
|
+
* `required: false`, and every non-flattened `rendersOne` and `rendersMany` (for a
|
|
211
|
+
* polymorphic `BelongsTo`, each key the serializer of any of its target classes requires,
|
|
212
|
+
* and for an association to an STI base, each key the serializer of any of its STI children
|
|
213
|
+
* requires), in the same order (so an `id` declared before the `rendersOne` becomes `null`
|
|
214
|
+
* when the association is `null`). A flattened `customAttribute` in that serializer adds the
|
|
214
215
|
* keys its `openapi` requires: a key an object shape lists in its `required` array, a key a
|
|
215
216
|
* `$serializer` or `$serializable` ref's serializer declares without `required: false`, and
|
|
216
217
|
* each such key of an `allOf`, `anyOf` or `oneOf` member; a ref with `many: true` adds none,
|
|
217
|
-
* and a flattened `customAttribute` declared with `required: false` adds none.
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
*
|
|
218
|
+
* and a flattened `customAttribute` declared with `required: false` adds none. When the
|
|
219
|
+
* association is `null`, each of these keys renders as `null` and nothing in its serializer
|
|
220
|
+
* is rendered, so its custom attribute callbacks do not run. When it is present, the held
|
|
221
|
+
* object's serializer renders its own keys over them, so a key another STI child's or
|
|
222
|
+
* target's serializer requires renders as `null` where the held one's serializer does not
|
|
223
|
+
* render it, including a key that serializer declares with `required: false`; the payload
|
|
224
|
+
* always includes the same keys whichever is held and, for an association or a property
|
|
225
|
+
* given a `serializer` or `viewModelClass` option, whether it is `null` (a `null` property
|
|
226
|
+
* that is not an association and has neither option renders none of these keys, since no
|
|
227
|
+
* serializer is known for it). A key declared with `required: false` that no serializer
|
|
228
|
+
* requires stays absent unless it renders. The association's OpenAPI schema describes the
|
|
229
|
+
* parent's payload too, so a shared key's value must match both the parent's declaration
|
|
230
|
+
* and the association's, whichever declaration wins
|
|
224
231
|
* - `optional` - When `true`, allows the association to be null/missing without causing
|
|
225
232
|
* an `OpenapiResponseValidationFailure` during Psychic controller unit specs. By default,
|
|
226
233
|
* `rendersOne` expects the association to be present (mirroring the `optional` option on
|
|
@@ -276,8 +283,9 @@ export default class DreamSerializerBuilder<DataTypeForOpenapi extends typeof Dr
|
|
|
276
283
|
* If `true`, the rendered association's attributes are merged directly into
|
|
277
284
|
* the parent object instead of being nested under the association key. A key
|
|
278
285
|
* the parent shares with the association takes the value of whichever is
|
|
279
|
-
* declared later, and
|
|
280
|
-
*
|
|
286
|
+
* declared later, and each key its serializer requires renders, as `null`
|
|
287
|
+
* wherever the association does not supply it. See the `flatten` option of
|
|
288
|
+
* `rendersOne`.
|
|
281
289
|
*/
|
|
282
290
|
flatten?: boolean;
|
|
283
291
|
/**
|