@rvoh/dream 2.8.0 → 2.9.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/dist/cjs/src/bin/index.js +17 -2
- package/dist/cjs/src/cli/index.js +88 -12
- package/dist/cjs/src/db/helpers/syncDbTypesFiles.js +17 -12
- package/dist/cjs/src/decorators/class/ReplicaSafe.js +3 -4
- package/dist/cjs/src/decorators/class/STI.js +1 -2
- package/dist/cjs/src/decorators/class/SoftDelete.js +4 -5
- package/dist/cjs/src/dream/QueryDriver/Kysely.js +21 -10
- package/dist/cjs/src/encrypt/algorithms/aes-gcm/decryptAESGCM.js +19 -6
- package/dist/cjs/src/encrypt/index.js +80 -11
- package/dist/cjs/src/errors/SspawnRequiresDevelopmentOrTest.js +26 -0
- package/dist/cjs/src/errors/encrypt/DecryptionError.js +5 -0
- package/dist/cjs/src/errors/encrypt/DecryptionParseError.js +5 -0
- package/dist/cjs/src/errors/encrypt/DecryptionWithRotationError.js +12 -0
- package/dist/cjs/src/ops/index.js +28 -1
- package/dist/cjs/src/serializer/builders/DreamSerializerBuilder.js +29 -10
- package/dist/cjs/src/serializer/builders/ObjectSerializerBuilder.js +20 -4
- package/dist/esm/src/bin/index.js +17 -2
- package/dist/esm/src/cli/index.js +88 -12
- package/dist/esm/src/db/helpers/syncDbTypesFiles.js +17 -12
- package/dist/esm/src/decorators/class/ReplicaSafe.js +3 -4
- package/dist/esm/src/decorators/class/STI.js +1 -2
- package/dist/esm/src/decorators/class/SoftDelete.js +4 -5
- package/dist/esm/src/dream/QueryDriver/Kysely.js +21 -10
- package/dist/esm/src/encrypt/algorithms/aes-gcm/decryptAESGCM.js +19 -6
- package/dist/esm/src/encrypt/index.js +80 -11
- package/dist/esm/src/errors/SspawnRequiresDevelopmentOrTest.js +26 -0
- package/dist/esm/src/errors/encrypt/DecryptionError.js +5 -0
- package/dist/esm/src/errors/encrypt/DecryptionParseError.js +5 -0
- package/dist/esm/src/errors/encrypt/DecryptionWithRotationError.js +12 -0
- package/dist/esm/src/ops/index.js +28 -1
- package/dist/esm/src/serializer/builders/DreamSerializerBuilder.js +29 -10
- package/dist/esm/src/serializer/builders/ObjectSerializerBuilder.js +20 -4
- package/dist/types/src/cli/index.d.ts +57 -4
- package/dist/types/src/decorators/class/ReplicaSafe.d.ts +2 -1
- package/dist/types/src/decorators/class/STI.d.ts +1 -1
- package/dist/types/src/decorators/class/SoftDelete.d.ts +2 -1
- package/dist/types/src/dream/QueryDriver/Kysely.d.ts +17 -0
- package/dist/types/src/dream-app/index.d.ts +25 -1
- package/dist/types/src/encrypt/algorithms/aes-gcm/decryptAESGCM.d.ts +1 -1
- package/dist/types/src/encrypt/index.d.ts +59 -0
- package/dist/types/src/errors/SspawnRequiresDevelopmentOrTest.d.ts +5 -0
- package/dist/types/src/errors/encrypt/DecryptionError.d.ts +3 -0
- package/dist/types/src/errors/encrypt/DecryptionParseError.d.ts +3 -0
- package/dist/types/src/errors/encrypt/DecryptionWithRotationError.d.ts +7 -0
- package/dist/types/src/ops/index.d.ts +28 -1
- package/dist/types/src/serializer/builders/DreamSerializerBuilder.d.ts +40 -12
- package/dist/types/src/serializer/builders/ObjectSerializerBuilder.d.ts +23 -5
- package/docs/classes/db.DreamMigrationHelpers.html +9 -9
- package/docs/classes/db.KyselyQueryDriver.html +32 -32
- package/docs/classes/db.PostgresQueryDriver.html +33 -33
- package/docs/classes/db.QueryDriverBase.html +31 -31
- 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.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.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 +118 -118
- package/docs/classes/index.DreamApp.html +5 -5
- package/docs/classes/index.DreamTransaction.html +2 -2
- package/docs/classes/index.Env.html +2 -2
- package/docs/classes/index.Query.html +56 -56
- package/docs/classes/system.CliFileWriter.html +4 -4
- package/docs/classes/system.DreamBin.html +2 -2
- package/docs/classes/system.DreamCLI.html +41 -6
- package/docs/classes/system.DreamImporter.html +2 -2
- package/docs/classes/system.DreamLogos.html +2 -2
- package/docs/classes/system.DreamSerializerBuilder.html +45 -23
- package/docs/classes/system.ObjectSerializerBuilder.html +32 -13
- package/docs/classes/system.PathHelpers.html +3 -3
- package/docs/classes/utils.Encrypt.html +51 -2
- 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 +1 -1
- package/docs/functions/index.ObjectSerializer.html +1 -1
- package/docs/functions/index.ReplicaSafe.html +1 -1
- package/docs/functions/index.STI.html +1 -1
- package/docs/functions/index.SoftDelete.html +2 -2
- 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/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.DreamAppInitOptions.html +2 -2
- package/docs/interfaces/types.DreamAppOpts.html +2 -2
- package/docs/interfaces/types.DurationObject.html +2 -2
- package/docs/interfaces/types.EncryptOptions.html +2 -2
- package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
- package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
- package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
- 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.OpenapiSchemaCommonFields.html +1 -1
- package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +2 -2
- 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.OpenapiSchemaObjectAnyOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAnyOfShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectOneOf.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectOneOfShorthand.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 +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +2 -2
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +2 -2
- 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.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 +26 -4
- 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 +1 -1
- package/dist/cjs/src/helpers/sspawn.js +0 -44
- package/dist/esm/src/helpers/sspawn.js +0 -44
- package/dist/types/src/helpers/sspawn.d.ts +0 -7
|
@@ -63,17 +63,38 @@ const ops = {
|
|
|
63
63
|
* Creates an `OpsStatement` using the SQL `LIKE` operator for case-sensitive pattern matching.
|
|
64
64
|
* Use `%` as a wildcard in the pattern string.
|
|
65
65
|
*
|
|
66
|
+
* **User-supplied patterns:** the value is bound as a parameter (no SQL
|
|
67
|
+
* injection), but `%`, `_`, and `\` in the bound value are still interpreted
|
|
68
|
+
* as wildcards by the SQL engine. Wrap user input with `ops.like.escape`
|
|
69
|
+
* if you need literal matching:
|
|
70
|
+
*
|
|
71
|
+
* User.where({ name: ops.like(`%${ops.like.escape(query)}%`) })
|
|
72
|
+
*
|
|
73
|
+
* `ops.like.escape` escapes the three metacharacters that PostgreSQL's
|
|
74
|
+
* `LIKE` / `ILIKE` operators treat as wildcards (`\`, `%`, `_`) so the
|
|
75
|
+
* returned string matches literally. The same helper applies to all four
|
|
76
|
+
* LIKE-family ops (`like`, `ilike`, `not.like`, `not.ilike`); it is exposed
|
|
77
|
+
* here as the canonical entry point. If a caller uses `ESCAPE '...'` with
|
|
78
|
+
* a non-default character this helper will not be appropriate.
|
|
79
|
+
*
|
|
66
80
|
* @param like - The pattern string (e.g. `'%hello%'`).
|
|
67
81
|
* @returns An `OpsStatement` using the `like` operator.
|
|
68
82
|
*
|
|
69
83
|
* @example
|
|
70
84
|
* User.where({ name: ops.like('%alice%') })
|
|
71
85
|
*/
|
|
72
|
-
like: (like) => new OpsStatement('like', like),
|
|
86
|
+
like: Object.assign((like) => new OpsStatement('like', like), {
|
|
87
|
+
escape: (input) => input.replace(/\\/g, '\\\\').replace(/%/g, '\\%').replace(/_/g, '\\_'),
|
|
88
|
+
}),
|
|
73
89
|
/**
|
|
74
90
|
* Creates an `OpsStatement` using the SQL `ILIKE` operator for case-insensitive pattern matching.
|
|
75
91
|
* Use `%` as a wildcard in the pattern string.
|
|
76
92
|
*
|
|
93
|
+
* **User-supplied patterns:** the value is bound as a parameter (no SQL
|
|
94
|
+
* injection), but `%`, `_`, and `\` in the bound value are still interpreted
|
|
95
|
+
* as wildcards by the SQL engine. Wrap user input with `ops.like.escape`
|
|
96
|
+
* if you need literal matching.
|
|
97
|
+
*
|
|
77
98
|
* @param ilike - The pattern string (e.g. `'%hello%'`).
|
|
78
99
|
* @returns An `OpsStatement` using the `ilike` operator.
|
|
79
100
|
*
|
|
@@ -201,6 +222,9 @@ const ops = {
|
|
|
201
222
|
/**
|
|
202
223
|
* Creates an `OpsStatement` using the `NOT LIKE` operator for case-sensitive pattern exclusion.
|
|
203
224
|
*
|
|
225
|
+
* **User-supplied patterns:** see the note on `ops.like`. Wrap user input
|
|
226
|
+
* with `ops.like.escape` for literal matching.
|
|
227
|
+
*
|
|
204
228
|
* @param like - The pattern string (e.g. `'%spam%'`).
|
|
205
229
|
* @returns An `OpsStatement` using the `not like` operator.
|
|
206
230
|
*
|
|
@@ -211,6 +235,9 @@ const ops = {
|
|
|
211
235
|
/**
|
|
212
236
|
* Creates an `OpsStatement` using the `NOT ILIKE` operator for case-insensitive pattern exclusion.
|
|
213
237
|
*
|
|
238
|
+
* **User-supplied patterns:** see the note on `ops.ilike`. Wrap user input
|
|
239
|
+
* with `ops.like.escape` for literal matching.
|
|
240
|
+
*
|
|
214
241
|
* @param ilike - The pattern string (e.g. `'%spam%'`).
|
|
215
242
|
* @returns An `OpsStatement` using the `not ilike` operator.
|
|
216
243
|
*
|
|
@@ -20,14 +20,27 @@ export default class DreamSerializerBuilder {
|
|
|
20
20
|
/**
|
|
21
21
|
* Includes an attribute from a nested object in the serialized output.
|
|
22
22
|
*
|
|
23
|
-
* Accesses `targetName.name` on the data object.
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* Accesses `targetName.name` on the data object. When the target object or the
|
|
24
|
+
* delegated attribute is null/undefined, the resolution order is:
|
|
25
|
+
* 1. `default` if provided → renders the default value
|
|
26
|
+
* 2. `required: false` → omits the key entirely from the rendered output
|
|
27
|
+
* 3. otherwise → renders `null`
|
|
26
28
|
*
|
|
27
29
|
* When the target is a Dream model, OpenAPI types may be automatically inferred
|
|
28
30
|
* for standard database columns. For json/jsonb columns or non-Dream targets,
|
|
29
31
|
* the `openapi` option is required.
|
|
30
32
|
*
|
|
33
|
+
* `optional` and `required` are not aliases — they encode different things and can
|
|
34
|
+
* be used together:
|
|
35
|
+
* - `optional: true` is an OpenAPI-only marker (no runtime effect). It declares
|
|
36
|
+
* that the rendered value may be `null` (e.g. when delegating through a HasOne
|
|
37
|
+
* that may be missing). Use this when you want the key to always be present
|
|
38
|
+
* but the value to be nullable in the schema.
|
|
39
|
+
* - `required: false` affects both runtime and OpenAPI. At runtime, when the
|
|
40
|
+
* resolved value is `undefined` (which includes the case of a missing delegated
|
|
41
|
+
* association with no `default`), the key is omitted from the rendered output.
|
|
42
|
+
* In OpenAPI, the field is marked as not required.
|
|
43
|
+
*
|
|
31
44
|
* @param targetName - The property name containing the target object (e.g., an association name)
|
|
32
45
|
* @param name - The attribute name within the target object
|
|
33
46
|
* @param options - Configuration options:
|
|
@@ -35,16 +48,22 @@ export default class DreamSerializerBuilder {
|
|
|
35
48
|
* (e.g., delegating `'user', 'email'` with `as: 'userEmail'` outputs the value
|
|
36
49
|
* under `userEmail`)
|
|
37
50
|
* - `default` - Value to use when the target object or its attribute is null/undefined
|
|
51
|
+
* (not available when delegating to a `'type'` STI discriminator column: substituting
|
|
52
|
+
* a discriminator string when the association is actually missing produces a response
|
|
53
|
+
* indistinguishable from "association present with that type," which is misleading)
|
|
38
54
|
* - `openapi` - OpenAPI schema definition; required for non-Dream targets and json/jsonb
|
|
39
55
|
* columns, optional for standard Dream columns (where types are inferred)
|
|
40
|
-
* - `optional` - Set to `true` to
|
|
41
|
-
* (wraps the type in `anyOf: [schema, { type: 'null' }]`).
|
|
42
|
-
*
|
|
43
|
-
*
|
|
56
|
+
* - `optional` - Set to `true` to mark the value as nullable in the OpenAPI schema
|
|
57
|
+
* (wraps the type in `anyOf: [schema, { type: 'null' }]`). OpenAPI-only — the
|
|
58
|
+
* key is still rendered (as `null`). For Dream models, this is auto-inferred
|
|
59
|
+
* from optional BelongsTo associations. Use this when delegating through a
|
|
60
|
+
* HasOne or other nullable association.
|
|
44
61
|
* - `precision` - Round decimal values to the specified number of decimal places (0–9)
|
|
45
|
-
* during rendering; does not affect the OpenAPI shape
|
|
46
|
-
*
|
|
47
|
-
*
|
|
62
|
+
* during rendering; does not affect the OpenAPI shape (not available when delegating
|
|
63
|
+
* to a `'type'` STI discriminator column, which is always a string enum)
|
|
64
|
+
* - `required` - Set to `false` to omit the key from the rendered output when the
|
|
65
|
+
* resolved value is `undefined` (including a missing delegated association with
|
|
66
|
+
* no `default`), and to mark the field as not required in the OpenAPI schema
|
|
48
67
|
* @returns The serializer builder for method chaining
|
|
49
68
|
*
|
|
50
69
|
* @example
|
|
@@ -69,8 +69,20 @@ export default class ObjectSerializerBuilder {
|
|
|
69
69
|
* Includes an attribute from a nested object in the serialized output.
|
|
70
70
|
*
|
|
71
71
|
* Accesses `targetName.name` on the data object. The `openapi` option is always
|
|
72
|
-
* required.
|
|
73
|
-
* the
|
|
72
|
+
* required. When the target object or the delegated attribute is null/undefined,
|
|
73
|
+
* the resolution order is:
|
|
74
|
+
* 1. `default` if provided → renders the default value
|
|
75
|
+
* 2. `required: false` → omits the key entirely from the rendered output
|
|
76
|
+
* 3. otherwise → renders `null`
|
|
77
|
+
*
|
|
78
|
+
* `optional` and `required` are not aliases — they encode different things and can
|
|
79
|
+
* be used together:
|
|
80
|
+
* - `optional: true` is an OpenAPI-only marker (no runtime effect). It declares
|
|
81
|
+
* that the rendered value may be `null`. Use this when you want the key to always
|
|
82
|
+
* be present but the value to be nullable in the schema.
|
|
83
|
+
* - `required: false` affects both runtime and OpenAPI. At runtime, when the
|
|
84
|
+
* resolved value is `undefined`, the key is omitted from the rendered output.
|
|
85
|
+
* In OpenAPI, the field is marked as not required.
|
|
74
86
|
*
|
|
75
87
|
* @param targetName - The property name containing the target object
|
|
76
88
|
* @param name - The attribute name within the target object
|
|
@@ -80,10 +92,14 @@ export default class ObjectSerializerBuilder {
|
|
|
80
92
|
* (e.g., delegating `'profile', 'avatarUrl'` with `as: 'avatar'` outputs the value
|
|
81
93
|
* under `avatar`)
|
|
82
94
|
* - `default` - Value to use when the target object or its attribute is null/undefined
|
|
95
|
+
* - `optional` - Set to `true` to mark the value as nullable in the OpenAPI schema
|
|
96
|
+
* (wraps the type in `anyOf: [schema, { type: 'null' }]`). OpenAPI-only — the
|
|
97
|
+
* key is still rendered (as `null`)
|
|
83
98
|
* - `precision` - Round decimal values to the specified number of decimal places (0–9)
|
|
84
99
|
* during rendering; does not affect the OpenAPI shape
|
|
85
|
-
* - `required` - Set to `false` to
|
|
86
|
-
*
|
|
100
|
+
* - `required` - Set to `false` to omit the key from the rendered output when the
|
|
101
|
+
* resolved value is `undefined`, and to mark the field as not required in the
|
|
102
|
+
* OpenAPI schema
|
|
87
103
|
* @returns The serializer builder for method chaining
|
|
88
104
|
*
|
|
89
105
|
* @example
|
|
@@ -1,7 +1,18 @@
|
|
|
1
|
-
import { SpawnOptions } from 'child_process';
|
|
1
|
+
import { SpawnOptions as NodeSpawnOptions } from 'child_process';
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import DreamApp, { DreamAppInitOptions } from '../dream-app/index.js';
|
|
4
4
|
import DreamCliLogger from './logger/DreamCliLogger.js';
|
|
5
|
+
export type SpawnOptions = Omit<NodeSpawnOptions, 'shell'> & {
|
|
6
|
+
onStdout?: (str: string) => void;
|
|
7
|
+
/**
|
|
8
|
+
* Argv elements passed to the child as separate arguments. Defaults to `[]`.
|
|
9
|
+
* Each entry is passed literally — shell meta-characters (`$`, backticks,
|
|
10
|
+
* `&&`, spaces, etc.) inside any element are not interpreted by a shell.
|
|
11
|
+
* This is the right shape for any caller that interpolates a path or
|
|
12
|
+
* credential.
|
|
13
|
+
*/
|
|
14
|
+
args?: string[];
|
|
15
|
+
};
|
|
5
16
|
export declare const CLI_INDENT = " ";
|
|
6
17
|
export declare const baseColumnsWithTypesDescription = "space separated snake-case (except for belongs_to model name) properties like this:\n title:citext subtitle:string body_markdown:text style:enum:post_styles:formal,informal User:belongs_to\n \n all properties default to not nullable; null can be allowed by appending ':optional':\n subtitle:string:optional\n \n supported types:\n - uuid:\n - uuid[]:\n a column optimized for storing UUIDs\n \n - citext:\n - citext[]:\n case insensitive text (indexes and queries are automatically case insensitive)\n \n - encrypted:\n encrypted text (used in conjunction with the @deco.Encrypted decorator)\n \n - string:\n - string[]:\n varchar; allowed length defaults to 255, but may be customized, e.g.: subtitle:string:128 or subtitle:string:128:optional\n \n - text\n - text[]\n - date\n - date[]\n - datetime\n - datetime[]\n - time\n - time[]\n - timetz\n - timetz[]\n - integer\n - integer[]\n \n - decimal:\n - decimal[]:\n precision,scale is required, e.g.: volume:decimal:3,2 or volume:decimal:3,2:optional\n \n leveraging arrays, add the \"[]\" suffix, e.g.: volume:decimal[]:3,2\n \n - enum:\n - enum[]:\n include the enum name to automatically create the enum:\n type:enum:room_types:bathroom,kitchen,bedroom or type:enum:room_types:bathroom,kitchen,bedroom:optional\n \n omit the enum values to leverage an existing enum (omits the enum type creation):\n type:enum:room_types or type:enum:room_types:optional\n \n leveraging arrays, add the \"[]\" suffix, e.g.: type:enum[]:room_types:bathroom,kitchen,bedroom";
|
|
7
18
|
export default class DreamCLI {
|
|
@@ -56,9 +67,51 @@ export default class DreamCLI {
|
|
|
56
67
|
seedDb: () => Promise<void> | void;
|
|
57
68
|
onSync: () => Promise<void> | void;
|
|
58
69
|
}): void;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Run a developer-authored CLI command. Always runs in argv form (the
|
|
72
|
+
* underlying child_process `spawn` is called with `shell: false`):
|
|
73
|
+
* `command` is exec'd literally and `opts.args` are passed as separate
|
|
74
|
+
* argv elements. Shell-form invocation is intentionally not supported —
|
|
75
|
+
* there is no caller that needs `&&`-chaining, globs, or other shell
|
|
76
|
+
* features that can't be expressed as argv.
|
|
77
|
+
*
|
|
78
|
+
* For backward compatibility, `command` may contain implicit args
|
|
79
|
+
* separated by whitespace (e.g. `'pnpm psy sync'`); the leading token
|
|
80
|
+
* becomes the program and the rest are split out and prepended to any
|
|
81
|
+
* `opts.args` so the original argument order is preserved:
|
|
82
|
+
*
|
|
83
|
+
* DreamCLI.spawn('pnpm psy sync')
|
|
84
|
+
* → spawn('pnpm', ['psy', 'sync'])
|
|
85
|
+
*
|
|
86
|
+
* DreamCLI.spawn('pnpm psy', { args: ['sync', '--flag'] })
|
|
87
|
+
* → spawn('pnpm', ['psy', 'sync', '--flag'])
|
|
88
|
+
*
|
|
89
|
+
* ## Threat model (R-015)
|
|
90
|
+
*
|
|
91
|
+
* For dev-time CLI glue only (scaffolding, doc generation, type sync).
|
|
92
|
+
* **No runtime HTTP request input ever reaches this function.** Inputs
|
|
93
|
+
* are constant literals or composed from developer-supplied config
|
|
94
|
+
* (package.json scripts, CLI argv, scaffold templates) — never from
|
|
95
|
+
* runtime request input or any other untrusted external source.
|
|
96
|
+
*
|
|
97
|
+
* Argv-form is the safe choice for any caller that interpolates a
|
|
98
|
+
* config value, path, or credential: a database password containing
|
|
99
|
+
* `$` or backticks is passed literally to the child rather than
|
|
100
|
+
* interpreted by a shell.
|
|
101
|
+
*
|
|
102
|
+
* ## Layered defense
|
|
103
|
+
*
|
|
104
|
+
* Primary gate: every caller restricts spawn use to dev/test code paths
|
|
105
|
+
* (CLI commands, the dev watcher, scaffold-time code generators,
|
|
106
|
+
* generated `cli:sync` initializers wrapped in
|
|
107
|
+
* `if (AppEnv.isDevelopmentOrTest)`).
|
|
108
|
+
*
|
|
109
|
+
* Backstop: throws `SspawnRequiresDevelopmentOrTest` when `NODE_ENV` is
|
|
110
|
+
* anything other than `development` or `test`. Checking
|
|
111
|
+
* `!isDevelopmentOrTest` (rather than `isProduction`) means staging-style
|
|
112
|
+
* envs and any unforeseen NODE_ENV value also fail closed.
|
|
113
|
+
*/
|
|
114
|
+
static spawn(command: string, opts?: SpawnOptions): Promise<void>;
|
|
62
115
|
static get logger(): DreamCliLogger;
|
|
63
116
|
private static _logger;
|
|
64
117
|
}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import Dream from '../../Dream.js';
|
|
2
|
+
export default function ReplicaSafe(): (target: typeof Dream) => void;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import Dream from '../../Dream.js';
|
|
1
2
|
export declare const SOFT_DELETE_SCOPE_NAME = "dream:SoftDelete";
|
|
2
3
|
/**
|
|
3
4
|
* Instructs the model to set a timestamp when deleting,
|
|
@@ -34,4 +35,4 @@ export declare const SOFT_DELETE_SCOPE_NAME = "dream:SoftDelete";
|
|
|
34
35
|
* }
|
|
35
36
|
* }
|
|
36
37
|
*/
|
|
37
|
-
export default function SoftDelete():
|
|
38
|
+
export default function SoftDelete(): (target: typeof Dream) => void;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import type { ConnectionOptions as TlsConnectionOptions } from 'node:tls';
|
|
1
2
|
import { DeleteQueryBuilder, Kysely, Transaction as KyselyTransaction, OrderByItemBuilder, SelectQueryBuilder, UpdateQueryBuilder } from 'kysely';
|
|
2
3
|
import { DialectProviderCb } from '../../db/DreamDbConnection.js';
|
|
4
|
+
import { SingleDbCredential } from '../../dream-app/index.js';
|
|
3
5
|
import Dream from '../../Dream.js';
|
|
4
6
|
import { SchemaBuilderInformationSchemaRow } from '../../helpers/cli/ASTBuilder.js';
|
|
5
7
|
import { AssociationStatement } from '../../types/associations/shared.js';
|
|
@@ -467,3 +469,18 @@ export default class KyselyQueryDriver<DreamInstance extends Dream> extends Quer
|
|
|
467
469
|
private applyOnePreload;
|
|
468
470
|
private _applyOnePreload;
|
|
469
471
|
}
|
|
472
|
+
/**
|
|
473
|
+
* Resolve the value passed to `pg.Pool`'s `ssl` field for a given credential.
|
|
474
|
+
*
|
|
475
|
+
* Precedence:
|
|
476
|
+
* 1. If `connectionConf.ssl` is set (boolean or `tls.ConnectionOptions`),
|
|
477
|
+
* pass it straight through to `pg`. This is the verified-TLS path —
|
|
478
|
+
* apps configure `{ rejectUnauthorized: true, ca: <bundle> }` for
|
|
479
|
+
* authenticated TLS against a private PKI, or `true` to use Node's
|
|
480
|
+
* default verification against the system CA store.
|
|
481
|
+
* 2. Else if `connectionConf.useSsl` is `true`, fall back to
|
|
482
|
+
* `{ rejectUnauthorized: false }` — encrypted but **not** authenticated.
|
|
483
|
+
* Preserved for back-compat; new code should set `ssl` explicitly.
|
|
484
|
+
* 3. Else disable TLS.
|
|
485
|
+
*/
|
|
486
|
+
export declare function resolvePostgresSsl(connectionConf: SingleDbCredential): boolean | TlsConnectionOptions;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CompiledQuery } from 'kysely';
|
|
2
|
+
import type { ConnectionOptions as TlsConnectionOptions } from 'node:tls';
|
|
2
3
|
import { Context } from 'node:vm';
|
|
3
4
|
import Dream from '../Dream.js';
|
|
4
5
|
import QueryDriverBase from '../dream/QueryDriver/Base.js';
|
|
@@ -209,7 +210,30 @@ export interface SingleDbCredential {
|
|
|
209
210
|
host: string;
|
|
210
211
|
name: string;
|
|
211
212
|
port: number;
|
|
212
|
-
|
|
213
|
+
/**
|
|
214
|
+
* @deprecated Use `ssl` instead.
|
|
215
|
+
*
|
|
216
|
+
* The legacy boolean opt-in for Postgres TLS. When `true` (and `ssl` is not
|
|
217
|
+
* set), Dream connects with `{ rejectUnauthorized: false }` — TLS is on but
|
|
218
|
+
* the server certificate is not verified. The new `ssl` field accepts a
|
|
219
|
+
* full `tls.ConnectionOptions` object so callers can opt into verified TLS
|
|
220
|
+
* (`ssl: { rejectUnauthorized: true, ca: readFileSync('ca.pem') }`) or use
|
|
221
|
+
* Node's defaults (`ssl: true`). This field is preserved for back-compat
|
|
222
|
+
* and will be removed in a future major version.
|
|
223
|
+
*/
|
|
224
|
+
useSsl?: boolean;
|
|
225
|
+
/**
|
|
226
|
+
* Optional explicit TLS configuration passed straight through to `pg.Pool`'s
|
|
227
|
+
* `ssl` field. Takes precedence over the deprecated `useSsl` when provided.
|
|
228
|
+
*
|
|
229
|
+
* - `true` lets `pg` use Node's defaults (verified TLS against the system CA).
|
|
230
|
+
* - `false` disables TLS.
|
|
231
|
+
* - An object is `tls.ConnectionOptions` — set `rejectUnauthorized: true` plus
|
|
232
|
+
* a `ca` bundle for verified TLS against a private PKI; set
|
|
233
|
+
* `rejectUnauthorized: false` only if you accept opportunistic-TLS-without-
|
|
234
|
+
* authentication (the historical default produced by `useSsl: true` alone).
|
|
235
|
+
*/
|
|
236
|
+
ssl?: boolean | TlsConnectionOptions;
|
|
213
237
|
}
|
|
214
238
|
export type DreamLogger = {
|
|
215
239
|
info: (...args: any[]) => void;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { EncryptAESAlgorithm } from '../../index.js';
|
|
2
|
-
export default function decryptAESGCM<RetType>(algorithm: EncryptAESAlgorithm, encrypted: string, key: string): RetType
|
|
2
|
+
export default function decryptAESGCM<RetType>(algorithm: EncryptAESAlgorithm, encrypted: string, key: string): RetType;
|
|
@@ -1,7 +1,66 @@
|
|
|
1
1
|
export default class Encrypt {
|
|
2
2
|
static encrypt(data: any, { algorithm, key }: EncryptOptions): string;
|
|
3
|
+
/**
|
|
4
|
+
* Decrypts a value previously produced by {@link Encrypt.encrypt}.
|
|
5
|
+
*
|
|
6
|
+
* Behavior depends on whether `legacyOpts` is provided:
|
|
7
|
+
*
|
|
8
|
+
* **Two-arg form** (no rotation):
|
|
9
|
+
* - `null`/`undefined` input returns `null`.
|
|
10
|
+
* - Cipher op / auth tag / payload-shape failure throws `DecryptionError`.
|
|
11
|
+
* - Successful decrypt with non-JSON plaintext throws `DecryptionParseError`.
|
|
12
|
+
*
|
|
13
|
+
* **Three-arg form** (rotation): tries the current key first; on
|
|
14
|
+
* `DecryptionError` falls back to the legacy key. If both fail, throws
|
|
15
|
+
* `DecryptionWithRotationError` carrying both per-key errors. A
|
|
16
|
+
* `DecryptionParseError` from the current key is **not** retried — the
|
|
17
|
+
* cipher already matched, so a parse failure means the encrypted format
|
|
18
|
+
* is wrong (an app bug), not a wrong key.
|
|
19
|
+
*
|
|
20
|
+
* `MissingEncryptionKey` propagates from either form when a key is missing.
|
|
21
|
+
*
|
|
22
|
+
* @throws MissingEncryptionKey
|
|
23
|
+
* @throws DecryptionError
|
|
24
|
+
* @throws DecryptionParseError
|
|
25
|
+
* @throws DecryptionWithRotationError
|
|
26
|
+
*/
|
|
3
27
|
static decrypt<RetType>(encrypted: string, { algorithm, key }: DecryptOptions, legacyOpts?: DecryptOptions): RetType | null;
|
|
4
28
|
private static attemptDecryptionWithLegacyKeys;
|
|
29
|
+
/**
|
|
30
|
+
* Generates a base64-encoded random key suitable for the given algorithm.
|
|
31
|
+
*
|
|
32
|
+
* ## Rotation workflow
|
|
33
|
+
*
|
|
34
|
+
* 1. Generate a new key: `const newKey = Encrypt.generateKey('aes-256-gcm')`.
|
|
35
|
+
* 2. Configure rotation by setting both `current` and `legacy`. For
|
|
36
|
+
* encrypted columns: `dreamApp.set('encryption', { columns: { current:
|
|
37
|
+
* { algorithm: 'aes-256-gcm', key: newKey }, legacy: { algorithm:
|
|
38
|
+
* 'aes-256-gcm', key: oldKey } } })`. For cookies, use the equivalent
|
|
39
|
+
* shape under `psychicApp.set('encryption', { cookies: { current,
|
|
40
|
+
* legacy } })`.
|
|
41
|
+
* 3. Deploy. New encryptions use `current`; existing ciphertext continues
|
|
42
|
+
* to decrypt via `legacy` fallback.
|
|
43
|
+
* 4. For cookies, wait at least the cookie `maxAge` so all in-flight
|
|
44
|
+
* cookies have either expired or been re-issued under the new key. For
|
|
45
|
+
* `@Encrypted` columns, re-encrypt every existing row under the new
|
|
46
|
+
* key (read each row and write it back; the setter re-encrypts with
|
|
47
|
+
* `current`).
|
|
48
|
+
* 5. Drop `legacy` from config and deploy again.
|
|
49
|
+
*
|
|
50
|
+
* ## When to rotate
|
|
51
|
+
*
|
|
52
|
+
* - On a scheduled cadence (90–180 days is a reasonable policy default).
|
|
53
|
+
* - Incident response: leaked env file, departing employee with key
|
|
54
|
+
* access, or any suspected key compromise.
|
|
55
|
+
*
|
|
56
|
+
* ## How long to keep `legacy`
|
|
57
|
+
*
|
|
58
|
+
* - For cookies: at least the cookie `maxAge`, so in-flight sessions are
|
|
59
|
+
* not forced to re-authenticate.
|
|
60
|
+
* - For `@Encrypted` columns: until every existing row has been
|
|
61
|
+
* re-encrypted under the new key. Dropping `legacy` early will cause
|
|
62
|
+
* `DecryptionWithRotationError` on any not-yet-rewritten row.
|
|
63
|
+
*/
|
|
5
64
|
static generateKey(algorithm: EncryptAlgorithm): string;
|
|
6
65
|
static validateKey(base64EncodedKey: string, algorithm: EncryptAlgorithm): boolean;
|
|
7
66
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import DecryptionError from './DecryptionError.js';
|
|
2
|
+
export default class DecryptionWithRotationError extends Error {
|
|
3
|
+
readonly currentKeyError: DecryptionError;
|
|
4
|
+
readonly legacyKeyError: DecryptionError;
|
|
5
|
+
constructor(currentKeyError: DecryptionError, legacyKeyError: DecryptionError);
|
|
6
|
+
get message(): string;
|
|
7
|
+
}
|
|
@@ -56,17 +56,38 @@ declare const ops: {
|
|
|
56
56
|
* Creates an `OpsStatement` using the SQL `LIKE` operator for case-sensitive pattern matching.
|
|
57
57
|
* Use `%` as a wildcard in the pattern string.
|
|
58
58
|
*
|
|
59
|
+
* **User-supplied patterns:** the value is bound as a parameter (no SQL
|
|
60
|
+
* injection), but `%`, `_`, and `\` in the bound value are still interpreted
|
|
61
|
+
* as wildcards by the SQL engine. Wrap user input with `ops.like.escape`
|
|
62
|
+
* if you need literal matching:
|
|
63
|
+
*
|
|
64
|
+
* User.where({ name: ops.like(`%${ops.like.escape(query)}%`) })
|
|
65
|
+
*
|
|
66
|
+
* `ops.like.escape` escapes the three metacharacters that PostgreSQL's
|
|
67
|
+
* `LIKE` / `ILIKE` operators treat as wildcards (`\`, `%`, `_`) so the
|
|
68
|
+
* returned string matches literally. The same helper applies to all four
|
|
69
|
+
* LIKE-family ops (`like`, `ilike`, `not.like`, `not.ilike`); it is exposed
|
|
70
|
+
* here as the canonical entry point. If a caller uses `ESCAPE '...'` with
|
|
71
|
+
* a non-default character this helper will not be appropriate.
|
|
72
|
+
*
|
|
59
73
|
* @param like - The pattern string (e.g. `'%hello%'`).
|
|
60
74
|
* @returns An `OpsStatement` using the `like` operator.
|
|
61
75
|
*
|
|
62
76
|
* @example
|
|
63
77
|
* User.where({ name: ops.like('%alice%') })
|
|
64
78
|
*/
|
|
65
|
-
like: (like: string) => OpsStatement<"like", string, undefined
|
|
79
|
+
like: ((like: string) => OpsStatement<"like", string, undefined>) & {
|
|
80
|
+
escape: (input: string) => string;
|
|
81
|
+
};
|
|
66
82
|
/**
|
|
67
83
|
* Creates an `OpsStatement` using the SQL `ILIKE` operator for case-insensitive pattern matching.
|
|
68
84
|
* Use `%` as a wildcard in the pattern string.
|
|
69
85
|
*
|
|
86
|
+
* **User-supplied patterns:** the value is bound as a parameter (no SQL
|
|
87
|
+
* injection), but `%`, `_`, and `\` in the bound value are still interpreted
|
|
88
|
+
* as wildcards by the SQL engine. Wrap user input with `ops.like.escape`
|
|
89
|
+
* if you need literal matching.
|
|
90
|
+
*
|
|
70
91
|
* @param ilike - The pattern string (e.g. `'%hello%'`).
|
|
71
92
|
* @returns An `OpsStatement` using the `ilike` operator.
|
|
72
93
|
*
|
|
@@ -208,6 +229,9 @@ declare const ops: {
|
|
|
208
229
|
/**
|
|
209
230
|
* Creates an `OpsStatement` using the `NOT LIKE` operator for case-sensitive pattern exclusion.
|
|
210
231
|
*
|
|
232
|
+
* **User-supplied patterns:** see the note on `ops.like`. Wrap user input
|
|
233
|
+
* with `ops.like.escape` for literal matching.
|
|
234
|
+
*
|
|
211
235
|
* @param like - The pattern string (e.g. `'%spam%'`).
|
|
212
236
|
* @returns An `OpsStatement` using the `not like` operator.
|
|
213
237
|
*
|
|
@@ -218,6 +242,9 @@ declare const ops: {
|
|
|
218
242
|
/**
|
|
219
243
|
* Creates an `OpsStatement` using the `NOT ILIKE` operator for case-insensitive pattern exclusion.
|
|
220
244
|
*
|
|
245
|
+
* **User-supplied patterns:** see the note on `ops.ilike`. Wrap user input
|
|
246
|
+
* with `ops.like.escape` for literal matching.
|
|
247
|
+
*
|
|
221
248
|
* @param ilike - The pattern string (e.g. `'%spam%'`).
|
|
222
249
|
* @returns An `OpsStatement` using the `not ilike` operator.
|
|
223
250
|
*
|
|
@@ -59,14 +59,27 @@ export default class DreamSerializerBuilder<DataTypeForOpenapi extends typeof Dr
|
|
|
59
59
|
/**
|
|
60
60
|
* Includes an attribute from a nested object in the serialized output.
|
|
61
61
|
*
|
|
62
|
-
* Accesses `targetName.name` on the data object.
|
|
63
|
-
*
|
|
64
|
-
*
|
|
62
|
+
* Accesses `targetName.name` on the data object. When the target object or the
|
|
63
|
+
* delegated attribute is null/undefined, the resolution order is:
|
|
64
|
+
* 1. `default` if provided → renders the default value
|
|
65
|
+
* 2. `required: false` → omits the key entirely from the rendered output
|
|
66
|
+
* 3. otherwise → renders `null`
|
|
65
67
|
*
|
|
66
68
|
* When the target is a Dream model, OpenAPI types may be automatically inferred
|
|
67
69
|
* for standard database columns. For json/jsonb columns or non-Dream targets,
|
|
68
70
|
* the `openapi` option is required.
|
|
69
71
|
*
|
|
72
|
+
* `optional` and `required` are not aliases — they encode different things and can
|
|
73
|
+
* be used together:
|
|
74
|
+
* - `optional: true` is an OpenAPI-only marker (no runtime effect). It declares
|
|
75
|
+
* that the rendered value may be `null` (e.g. when delegating through a HasOne
|
|
76
|
+
* that may be missing). Use this when you want the key to always be present
|
|
77
|
+
* but the value to be nullable in the schema.
|
|
78
|
+
* - `required: false` affects both runtime and OpenAPI. At runtime, when the
|
|
79
|
+
* resolved value is `undefined` (which includes the case of a missing delegated
|
|
80
|
+
* association with no `default`), the key is omitted from the rendered output.
|
|
81
|
+
* In OpenAPI, the field is marked as not required.
|
|
82
|
+
*
|
|
70
83
|
* @param targetName - The property name containing the target object (e.g., an association name)
|
|
71
84
|
* @param name - The attribute name within the target object
|
|
72
85
|
* @param options - Configuration options:
|
|
@@ -74,16 +87,22 @@ export default class DreamSerializerBuilder<DataTypeForOpenapi extends typeof Dr
|
|
|
74
87
|
* (e.g., delegating `'user', 'email'` with `as: 'userEmail'` outputs the value
|
|
75
88
|
* under `userEmail`)
|
|
76
89
|
* - `default` - Value to use when the target object or its attribute is null/undefined
|
|
90
|
+
* (not available when delegating to a `'type'` STI discriminator column: substituting
|
|
91
|
+
* a discriminator string when the association is actually missing produces a response
|
|
92
|
+
* indistinguishable from "association present with that type," which is misleading)
|
|
77
93
|
* - `openapi` - OpenAPI schema definition; required for non-Dream targets and json/jsonb
|
|
78
94
|
* columns, optional for standard Dream columns (where types are inferred)
|
|
79
|
-
* - `optional` - Set to `true` to
|
|
80
|
-
* (wraps the type in `anyOf: [schema, { type: 'null' }]`).
|
|
81
|
-
*
|
|
82
|
-
*
|
|
95
|
+
* - `optional` - Set to `true` to mark the value as nullable in the OpenAPI schema
|
|
96
|
+
* (wraps the type in `anyOf: [schema, { type: 'null' }]`). OpenAPI-only — the
|
|
97
|
+
* key is still rendered (as `null`). For Dream models, this is auto-inferred
|
|
98
|
+
* from optional BelongsTo associations. Use this when delegating through a
|
|
99
|
+
* HasOne or other nullable association.
|
|
83
100
|
* - `precision` - Round decimal values to the specified number of decimal places (0–9)
|
|
84
|
-
* during rendering; does not affect the OpenAPI shape
|
|
85
|
-
*
|
|
86
|
-
*
|
|
101
|
+
* during rendering; does not affect the OpenAPI shape (not available when delegating
|
|
102
|
+
* to a `'type'` STI discriminator column, which is always a string enum)
|
|
103
|
+
* - `required` - Set to `false` to omit the key from the rendered output when the
|
|
104
|
+
* resolved value is `undefined` (including a missing delegated association with
|
|
105
|
+
* no `default`), and to mark the field as not required in the OpenAPI schema
|
|
87
106
|
* @returns The serializer builder for method chaining
|
|
88
107
|
*
|
|
89
108
|
* @example
|
|
@@ -106,9 +125,18 @@ export default class DreamSerializerBuilder<DataTypeForOpenapi extends typeof Dr
|
|
|
106
125
|
*/
|
|
107
126
|
delegatedAttribute<ProvidedModelType = undefined, ProvidedTargetName extends ProvidedModelType extends undefined ? undefined : Exclude<keyof ProvidedModelType, DreamPropertiesToExclude> = ProvidedModelType extends undefined ? undefined : Exclude<keyof ProvidedModelType, DreamPropertiesToExclude>, ActualDataType extends ProvidedModelType extends undefined ? InstanceType<DataTypeForOpenapi> : ProvidedModelType = ProvidedModelType extends undefined ? InstanceType<DataTypeForOpenapi> : ProvidedModelType, TargetName extends ProvidedTargetName extends undefined ? Exclude<keyof ActualDataType, DreamPropertiesToExclude> : ProvidedTargetName & keyof ActualDataType = ProvidedTargetName extends undefined ? Exclude<keyof ActualDataType, DreamPropertiesToExclude> : ProvidedTargetName & keyof ActualDataType, AssociatedModelType = Exclude<ActualDataType[TargetName], null>, TargetAttributeName extends AssociatedModelType extends object ? Exclude<keyof AssociatedModelType, DreamPropertiesToExclude> & string : never = AssociatedModelType extends object ? Exclude<keyof AssociatedModelType, DreamPropertiesToExclude> & string : never>(targetName: TargetName, name: TargetAttributeName, options?: AssociatedModelType extends Dream ? TargetAttributeName extends NonJsonDreamColumnNames<AssociatedModelType> & keyof AssociatedModelType & 'type' ? AutomaticSerializerAttributeOptionsForType & {
|
|
108
127
|
optional?: boolean;
|
|
109
|
-
|
|
128
|
+
required?: false;
|
|
129
|
+
} : TargetAttributeName extends DreamVirtualColumns<AssociatedModelType>[number] ? SerializerAttributeOptionsForVirtualColumn & {
|
|
130
|
+
optional?: boolean;
|
|
131
|
+
} : TargetAttributeName extends NonJsonDreamColumnNames<AssociatedModelType> & keyof AssociatedModelType & string ? (AutomaticSerializerAttributeOptions & {
|
|
110
132
|
optional?: boolean;
|
|
111
|
-
}) | NonAutomaticSerializerAttributeOptionsWithPossibleDecimalRenderOption
|
|
133
|
+
}) | (NonAutomaticSerializerAttributeOptionsWithPossibleDecimalRenderOption & {
|
|
134
|
+
optional?: boolean;
|
|
135
|
+
}) : NonAutomaticSerializerAttributeOptionsWithPossibleDecimalRenderOption & {
|
|
136
|
+
optional?: boolean;
|
|
137
|
+
} : NonAutomaticSerializerAttributeOptionsWithPossibleDecimalRenderOption & {
|
|
138
|
+
optional?: boolean;
|
|
139
|
+
}): this;
|
|
112
140
|
/**
|
|
113
141
|
* Includes a computed value in the serialized output.
|
|
114
142
|
*
|
|
@@ -63,8 +63,20 @@ export default class ObjectSerializerBuilder<MaybeNullDataType extends object |
|
|
|
63
63
|
* Includes an attribute from a nested object in the serialized output.
|
|
64
64
|
*
|
|
65
65
|
* Accesses `targetName.name` on the data object. The `openapi` option is always
|
|
66
|
-
* required.
|
|
67
|
-
* the
|
|
66
|
+
* required. When the target object or the delegated attribute is null/undefined,
|
|
67
|
+
* the resolution order is:
|
|
68
|
+
* 1. `default` if provided → renders the default value
|
|
69
|
+
* 2. `required: false` → omits the key entirely from the rendered output
|
|
70
|
+
* 3. otherwise → renders `null`
|
|
71
|
+
*
|
|
72
|
+
* `optional` and `required` are not aliases — they encode different things and can
|
|
73
|
+
* be used together:
|
|
74
|
+
* - `optional: true` is an OpenAPI-only marker (no runtime effect). It declares
|
|
75
|
+
* that the rendered value may be `null`. Use this when you want the key to always
|
|
76
|
+
* be present but the value to be nullable in the schema.
|
|
77
|
+
* - `required: false` affects both runtime and OpenAPI. At runtime, when the
|
|
78
|
+
* resolved value is `undefined`, the key is omitted from the rendered output.
|
|
79
|
+
* In OpenAPI, the field is marked as not required.
|
|
68
80
|
*
|
|
69
81
|
* @param targetName - The property name containing the target object
|
|
70
82
|
* @param name - The attribute name within the target object
|
|
@@ -74,10 +86,14 @@ export default class ObjectSerializerBuilder<MaybeNullDataType extends object |
|
|
|
74
86
|
* (e.g., delegating `'profile', 'avatarUrl'` with `as: 'avatar'` outputs the value
|
|
75
87
|
* under `avatar`)
|
|
76
88
|
* - `default` - Value to use when the target object or its attribute is null/undefined
|
|
89
|
+
* - `optional` - Set to `true` to mark the value as nullable in the OpenAPI schema
|
|
90
|
+
* (wraps the type in `anyOf: [schema, { type: 'null' }]`). OpenAPI-only — the
|
|
91
|
+
* key is still rendered (as `null`)
|
|
77
92
|
* - `precision` - Round decimal values to the specified number of decimal places (0–9)
|
|
78
93
|
* during rendering; does not affect the OpenAPI shape
|
|
79
|
-
* - `required` - Set to `false` to
|
|
80
|
-
*
|
|
94
|
+
* - `required` - Set to `false` to omit the key from the rendered output when the
|
|
95
|
+
* resolved value is `undefined`, and to mark the field as not required in the
|
|
96
|
+
* OpenAPI schema
|
|
81
97
|
* @returns The serializer builder for method chaining
|
|
82
98
|
*
|
|
83
99
|
* @example
|
|
@@ -100,7 +116,9 @@ export default class ObjectSerializerBuilder<MaybeNullDataType extends object |
|
|
|
100
116
|
* })
|
|
101
117
|
* ```
|
|
102
118
|
*/
|
|
103
|
-
delegatedAttribute<ProvidedModelType = undefined, ProvidedAttributeName extends ProvidedModelType extends undefined ? undefined : Exclude<keyof ProvidedModelType, DreamPropertiesToExclude> = ProvidedModelType extends undefined ? undefined : Exclude<keyof ProvidedModelType, DreamPropertiesToExclude>, ActualDataType extends ProvidedModelType extends undefined ? DataType : ProvidedModelType = ProvidedModelType extends undefined ? DataType : ProvidedModelType, TargetName extends ProvidedAttributeName extends undefined ? Exclude<keyof ActualDataType, DreamPropertiesToExclude> : ProvidedAttributeName & keyof ActualDataType = ProvidedAttributeName extends undefined ? Exclude<keyof ActualDataType, DreamPropertiesToExclude> : ProvidedAttributeName & keyof ActualDataType, TargetObject extends ActualDataType[TargetName] = ActualDataType[TargetName], AttributeName extends TargetObject extends object ? Exclude<keyof TargetObject, DreamPropertiesToExclude> & string : never = TargetObject extends object ? Exclude<keyof TargetObject, DreamPropertiesToExclude> & string : never>(targetName: TargetName, name: AttributeName, options: NonAutomaticSerializerAttributeOptionsWithPossibleDecimalRenderOption
|
|
119
|
+
delegatedAttribute<ProvidedModelType = undefined, ProvidedAttributeName extends ProvidedModelType extends undefined ? undefined : Exclude<keyof ProvidedModelType, DreamPropertiesToExclude> = ProvidedModelType extends undefined ? undefined : Exclude<keyof ProvidedModelType, DreamPropertiesToExclude>, ActualDataType extends ProvidedModelType extends undefined ? DataType : ProvidedModelType = ProvidedModelType extends undefined ? DataType : ProvidedModelType, TargetName extends ProvidedAttributeName extends undefined ? Exclude<keyof ActualDataType, DreamPropertiesToExclude> : ProvidedAttributeName & keyof ActualDataType = ProvidedAttributeName extends undefined ? Exclude<keyof ActualDataType, DreamPropertiesToExclude> : ProvidedAttributeName & keyof ActualDataType, TargetObject extends ActualDataType[TargetName] = ActualDataType[TargetName], AttributeName extends TargetObject extends object ? Exclude<keyof TargetObject, DreamPropertiesToExclude> & string : never = TargetObject extends object ? Exclude<keyof TargetObject, DreamPropertiesToExclude> & string : never>(targetName: TargetName, name: AttributeName, options: NonAutomaticSerializerAttributeOptionsWithPossibleDecimalRenderOption & {
|
|
120
|
+
optional?: boolean;
|
|
121
|
+
}): this;
|
|
104
122
|
/**
|
|
105
123
|
* Includes a computed value in the serialized output.
|
|
106
124
|
*
|