@rvoh/dream 2.34.0 → 2.36.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 -2
- package/dist/cjs/src/Dream.js +270 -69
- package/dist/cjs/src/bin/index.js +13 -0
- package/dist/cjs/src/cli/index.js +28 -17
- package/dist/cjs/src/db/migration-helpers/DreamMigrationHelpers.js +23 -21
- package/dist/cjs/src/decorators/Decorators.js +26 -4
- package/dist/cjs/src/decorators/field/Encrypted.js +30 -6
- package/dist/cjs/src/dream/DreamClassTransactionBuilder.js +6 -6
- package/dist/cjs/src/dream/DreamInstanceTransactionBuilder.js +63 -27
- package/dist/cjs/src/dream/LeftJoinLoadBuilder.js +3 -3
- package/dist/cjs/src/dream/LoadBuilder.js +1 -1
- package/dist/cjs/src/dream/Query.js +542 -167
- package/dist/cjs/src/dream/QueryDriver/Base.js +72 -0
- package/dist/cjs/src/dream/QueryDriver/Kysely.js +216 -50
- package/dist/cjs/src/dream/internal/associations/assertRecognizedAssociationConditionKeys.js +48 -0
- package/dist/cjs/src/dream/internal/associations/associationQuery.js +4 -0
- package/dist/cjs/src/dream/internal/reload.js +6 -1
- package/dist/cjs/src/dream/internal/saveDream.js +8 -2
- package/dist/cjs/src/dream/internal/sqlResultToDreamInstance.js +2 -0
- package/dist/cjs/src/dream/internal/undestroyDream.js +1 -1
- package/dist/cjs/src/dream-app/index.js +38 -0
- package/dist/cjs/src/encrypt/InternalEncrypt.js +49 -4
- package/dist/cjs/src/encrypt/defaultEncryptedColumnName.js +10 -0
- package/dist/cjs/src/encrypt/index.js +76 -9
- package/dist/cjs/src/errors/DoNotSetEncryptedFieldsDirectly.js +4 -0
- package/dist/cjs/src/errors/associations/UnrecognizedAssociationConditionKeys.js +25 -0
- package/dist/cjs/src/helpers/Env.js +28 -0
- package/dist/cjs/src/helpers/cli/generateDreamContent.js +2 -1
- package/dist/cjs/src/helpers/cli/generateFactoryContent.js +1 -1
- package/dist/cjs/src/helpers/cli/generateMigrationContent.js +9 -9
- package/dist/cjs/src/helpers/cli/generateSerializerContent.js +21 -8
- package/dist/cjs/src/serializer/SerializerRenderer.js +65 -13
- package/dist/cjs/src/serializer/builders/DreamSerializerBuilder.js +54 -38
- package/dist/cjs/src/serializer/builders/ObjectSerializerBuilder.js +34 -14
- package/dist/cjs/src/serializer/helpers/serializersForAssociatedClass.js +43 -0
- package/dist/esm/src/Dream.js +270 -69
- package/dist/esm/src/bin/index.js +13 -0
- package/dist/esm/src/cli/index.js +28 -17
- package/dist/esm/src/db/migration-helpers/DreamMigrationHelpers.js +23 -21
- package/dist/esm/src/decorators/Decorators.js +26 -4
- package/dist/esm/src/decorators/field/Encrypted.js +30 -6
- package/dist/esm/src/dream/DreamClassTransactionBuilder.js +6 -6
- package/dist/esm/src/dream/DreamInstanceTransactionBuilder.js +63 -27
- package/dist/esm/src/dream/LeftJoinLoadBuilder.js +3 -3
- package/dist/esm/src/dream/LoadBuilder.js +1 -1
- package/dist/esm/src/dream/Query.js +542 -167
- package/dist/esm/src/dream/QueryDriver/Base.js +72 -0
- package/dist/esm/src/dream/QueryDriver/Kysely.js +216 -50
- package/dist/esm/src/dream/internal/associations/assertRecognizedAssociationConditionKeys.js +48 -0
- package/dist/esm/src/dream/internal/associations/associationQuery.js +4 -0
- package/dist/esm/src/dream/internal/reload.js +6 -1
- package/dist/esm/src/dream/internal/saveDream.js +8 -2
- package/dist/esm/src/dream/internal/sqlResultToDreamInstance.js +2 -0
- package/dist/esm/src/dream/internal/undestroyDream.js +1 -1
- package/dist/esm/src/dream-app/index.js +38 -0
- package/dist/esm/src/encrypt/InternalEncrypt.js +49 -4
- package/dist/esm/src/encrypt/defaultEncryptedColumnName.js +10 -0
- package/dist/esm/src/encrypt/index.js +76 -9
- package/dist/esm/src/errors/DoNotSetEncryptedFieldsDirectly.js +4 -0
- package/dist/esm/src/errors/associations/UnrecognizedAssociationConditionKeys.js +25 -0
- package/dist/esm/src/helpers/Env.js +28 -0
- package/dist/esm/src/helpers/cli/generateDreamContent.js +2 -1
- package/dist/esm/src/helpers/cli/generateFactoryContent.js +1 -1
- package/dist/esm/src/helpers/cli/generateMigrationContent.js +9 -9
- package/dist/esm/src/helpers/cli/generateSerializerContent.js +21 -8
- package/dist/esm/src/serializer/SerializerRenderer.js +65 -13
- package/dist/esm/src/serializer/builders/DreamSerializerBuilder.js +54 -38
- package/dist/esm/src/serializer/builders/ObjectSerializerBuilder.js +34 -14
- package/dist/esm/src/serializer/helpers/serializersForAssociatedClass.js +43 -0
- package/dist/types/src/Dream.d.ts +217 -55
- package/dist/types/src/bin/index.d.ts +7 -1
- package/dist/types/src/cli/index.d.ts +13 -0
- package/dist/types/src/db/migration-helpers/DreamMigrationHelpers.d.ts +2 -2
- package/dist/types/src/decorators/Decorators.d.ts +26 -3
- package/dist/types/src/decorators/field/Encrypted.d.ts +6 -1
- package/dist/types/src/dream/DreamClassTransactionBuilder.d.ts +9 -9
- package/dist/types/src/dream/DreamInstanceTransactionBuilder.d.ts +52 -25
- package/dist/types/src/dream/LeftJoinLoadBuilder.d.ts +4 -4
- package/dist/types/src/dream/LoadBuilder.d.ts +1 -1
- package/dist/types/src/dream/Query.d.ts +272 -33
- package/dist/types/src/dream/QueryDriver/Base.d.ts +63 -1
- package/dist/types/src/dream/QueryDriver/Kysely.d.ts +85 -1
- package/dist/types/src/dream/internal/associations/assertRecognizedAssociationConditionKeys.d.ts +29 -0
- package/dist/types/src/dream-app/index.d.ts +56 -2
- package/dist/types/src/encrypt/InternalEncrypt.d.ts +20 -1
- package/dist/types/src/encrypt/defaultEncryptedColumnName.d.ts +7 -0
- package/dist/types/src/encrypt/index.d.ts +75 -6
- package/dist/types/src/errors/associations/UnrecognizedAssociationConditionKeys.d.ts +8 -0
- package/dist/types/src/helpers/Env.d.ts +28 -0
- package/dist/types/src/package-exports/openapi.d.ts +1 -1
- package/dist/types/src/package-exports/types.d.ts +2 -2
- package/dist/types/src/serializer/SerializerRenderer.d.ts +13 -0
- package/dist/types/src/serializer/builders/DreamSerializerBuilder.d.ts +59 -55
- package/dist/types/src/serializer/builders/ObjectSerializerBuilder.d.ts +40 -19
- package/dist/types/src/serializer/helpers/serializersForAssociatedClass.d.ts +17 -0
- package/dist/types/src/types/lifecycle.d.ts +6 -0
- package/dist/types/src/types/openapi.d.ts +52 -29
- package/dist/types/src/types/serializer.d.ts +43 -2
- package/dist/types/src/types/types/lifecycle.ts +6 -0
- package/dist/types/src/types/types/openapi.ts +51 -37
- package/dist/types/src/types/types/serializer.ts +62 -2
- package/dist/types/src/types/types/variadic.ts +99 -43
- package/dist/types/src/types/variadic.d.ts +29 -3
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/highlight.css +4 -11
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/db.DreamMigrationHelpers.html +13 -13
- package/docs/classes/db.KyselyQueryDriver.html +85 -46
- package/docs/classes/db.PostgresQueryDriver.html +86 -47
- package/docs/classes/db.QueryDriverBase.html +84 -45
- 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 +37 -23
- package/docs/classes/index.Dream.html +281 -155
- package/docs/classes/index.DreamApp.html +40 -10
- package/docs/classes/index.DreamTransaction.html +3 -3
- package/docs/classes/index.Env.html +16 -2
- package/docs/classes/index.Query.html +331 -129
- package/docs/classes/system.CliFileWriter.html +4 -4
- package/docs/classes/system.DreamBin.html +6 -2
- 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 +52 -34
- package/docs/classes/system.ObjectSerializerBuilder.html +41 -22
- package/docs/classes/system.PathHelpers.html +4 -4
- package/docs/classes/utils.Encrypt.html +54 -10
- 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 +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/hierarchy.html +1 -1
- package/docs/index.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.DecryptCallbacks.html +6 -0
- 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 +10 -0
- 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/modules/openapi.html +1 -1
- package/docs/modules/types.html +1 -1
- 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 +4 -0
- package/docs/types/openapi.OpenapiSchemaCommonFields.html +5 -1
- package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +1 -2
- package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +1 -2
- package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +1 -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 +4 -2
- package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
- package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +5 -1
- package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +2 -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 -2
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +1 -2
- package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +1 -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 +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 +1 -1
- package/dist/cjs/src/serializer/helpers/serializerForAssociatedClass.js +0 -37
- package/dist/esm/src/serializer/helpers/serializerForAssociatedClass.js +0 -37
- package/dist/types/src/serializer/helpers/serializerForAssociatedClass.d.ts +0 -9
- package/docs/types/openapi.OpenapiSchemaObjectAnyOf.html +0 -1
- package/docs/types/openapi.OpenapiSchemaObjectAnyOfShorthand.html +0 -1
- package/docs/types/openapi.OpenapiSchemaObjectOneOf.html +0 -1
- package/docs/types/openapi.OpenapiSchemaObjectOneOfShorthand.html +0 -1
|
@@ -92,9 +92,10 @@ export default class ObjectSerializerBuilder {
|
|
|
92
92
|
* (e.g., delegating `'profile', 'avatarUrl'` with `as: 'avatar'` outputs the value
|
|
93
93
|
* under `avatar`)
|
|
94
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
|
-
*
|
|
97
|
-
*
|
|
95
|
+
* - `optional` - Set to `true` to mark the value as nullable in the OpenAPI schema:
|
|
96
|
+
* Psychic adds `null` to the rendered schema (e.g., `type: 'string'` becomes
|
|
97
|
+
* `type: ['string', 'null']`, and a `$ref` becomes `anyOf: [{ $ref }, { type: 'null' }]`).
|
|
98
|
+
* OpenAPI-only — the key is still rendered (as `null`)
|
|
98
99
|
* - `precision` - Round decimal values to the specified number of decimal places (0–9)
|
|
99
100
|
* during rendering; does not affect the OpenAPI shape
|
|
100
101
|
* - `required` - Set to `false` to omit the key from the rendered output when the
|
|
@@ -137,17 +138,23 @@ export default class ObjectSerializerBuilder {
|
|
|
137
138
|
* Executes a callback function to generate a custom attribute value.
|
|
138
139
|
* The `openapi` option is always required since the return type cannot be inferred.
|
|
139
140
|
*
|
|
140
|
-
*
|
|
141
|
-
* or `precision`.
|
|
141
|
+
* The callback's return value renders as is, so any fallback belongs in the callback.
|
|
142
142
|
*
|
|
143
143
|
* @param name - The attribute name for the computed value
|
|
144
144
|
* @param fn - Callback function that returns the computed value
|
|
145
145
|
* @param options - Configuration options:
|
|
146
146
|
* - `openapi` - (required) OpenAPI schema definition for the computed value
|
|
147
|
-
* - `default` - Value to use when the callback returns undefined
|
|
148
147
|
* - `flatten` - When `true`, spreads the returned object's properties directly into the
|
|
149
|
-
* parent serialized output instead of nesting them under `name
|
|
150
|
-
*
|
|
148
|
+
* parent serialized output instead of nesting them under `name`. The `openapi` option
|
|
149
|
+
* then describes the whole returned object, not each property, because Psychic adds it
|
|
150
|
+
* to the parent's schema as an `allOf` branch: either an object schema with full
|
|
151
|
+
* property bodies (`type: 'object'`, `properties`, and `required` listing the keys that
|
|
152
|
+
* are always present), or `{ $serializer: SomeSerializer }` when the callback returns
|
|
153
|
+
* what that serializer renders. A serializer ref with `many: true` does not type-check
|
|
154
|
+
* here, since a list has no properties to spread. A `null` or `undefined` return adds no
|
|
155
|
+
* keys. Attributes render in declaration order, so a key the returned object shares with
|
|
156
|
+
* another attribute takes the value of whichever is declared later; under the `allOf`,
|
|
157
|
+
* that value must match both schemas
|
|
151
158
|
* - `required` - Set to `false` to mark the attribute as optional in the OpenAPI schema;
|
|
152
159
|
* when omitted, attributes are required by default
|
|
153
160
|
* @returns The serializer builder for method chaining
|
|
@@ -160,12 +167,16 @@ export default class ObjectSerializerBuilder {
|
|
|
160
167
|
* { openapi: { type: 'string' } }
|
|
161
168
|
* )
|
|
162
169
|
*
|
|
163
|
-
* // Flattened object properties
|
|
170
|
+
* // Flattened object properties: `openapi` describes the whole returned object
|
|
164
171
|
* .customAttribute('coordinates', () => ({ lat: 40.7, lng: -74.0 }), {
|
|
165
172
|
* flatten: true,
|
|
166
173
|
* openapi: {
|
|
167
|
-
*
|
|
168
|
-
*
|
|
174
|
+
* type: 'object',
|
|
175
|
+
* required: ['lat', 'lng'],
|
|
176
|
+
* properties: {
|
|
177
|
+
* lat: { type: 'number' },
|
|
178
|
+
* lng: { type: 'number' }
|
|
179
|
+
* }
|
|
169
180
|
* }
|
|
170
181
|
* })
|
|
171
182
|
* ```
|
|
@@ -189,9 +200,18 @@ export default class ObjectSerializerBuilder {
|
|
|
189
200
|
* @param options - Configuration options:
|
|
190
201
|
* - `as` - Rename the association key in the serialized output
|
|
191
202
|
* - `flatten` - When `true`, spreads the rendered association's attributes directly into
|
|
192
|
-
* the parent serialized output instead of nesting them under `name`.
|
|
193
|
-
*
|
|
194
|
-
*
|
|
203
|
+
* the parent serialized output instead of nesting them under `name`. Attributes render in
|
|
204
|
+
* declaration order, so when the parent and the association share a key (e.g., `id`),
|
|
205
|
+
* whichever is declared later wins: the association's value replaces an attribute declared
|
|
206
|
+
* before the `rendersOne`, and an attribute declared after it replaces the association's.
|
|
207
|
+
* When the association is `null`, every key its serializer declares renders as `null`
|
|
208
|
+
* (for a polymorphic `BelongsTo`, every key the serializer of any of its target classes
|
|
209
|
+
* declares, and for an association to an STI base, every key the serializer of any of its
|
|
210
|
+
* STI children declares), in the same order (so an `id` declared before the `rendersOne` becomes
|
|
211
|
+
* `null`); nothing in that serializer is rendered, so its custom attribute callbacks do
|
|
212
|
+
* not run, and a flattened `customAttribute` in it adds no keys. Psychic adds the association's OpenAPI
|
|
213
|
+
* schema to the parent's as an `allOf` branch, so a shared key's value must match both
|
|
214
|
+
* schemas, whichever declaration wins
|
|
195
215
|
* - `optional` - When `true`, allows the association to be null/missing without causing
|
|
196
216
|
* an `OpenapiResponseValidationFailure` during Psychic controller unit specs. By default,
|
|
197
217
|
* `rendersOne` expects the association to be present (mirroring the `optional` option on
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import uniq from '../../helpers/uniq.js';
|
|
2
|
+
import { inferSerializersFromDreamClassOrViewModelClass } from './inferSerializerFromDreamOrViewModel.js';
|
|
3
|
+
/**
|
|
4
|
+
* Only used when flatten: true, and the associated object is null, in which case there is no
|
|
5
|
+
* object to resolve a serializer from, but the renderer still needs the serializers whose keys it
|
|
6
|
+
* renders as null in the parent's payload.
|
|
7
|
+
*
|
|
8
|
+
* Resolves, in order, to the `serializer` option, the serializers of the `dreamClass` or
|
|
9
|
+
* `viewModelClass` option, or the serializers of each class `parentClass` declares the association
|
|
10
|
+
* to: the one class of most associations, or every target class of a polymorphic BelongsTo. A
|
|
11
|
+
* class that is an STI base contributes the serializer of every one of its children, since the
|
|
12
|
+
* association renders with whichever child it holds when present. The renderer renders the union
|
|
13
|
+
* of all their keys, each key once. Returns no serializers when none applies, e.g. a
|
|
14
|
+
* non-association property without a `serializer` option, so the flattened association adds no
|
|
15
|
+
* keys.
|
|
16
|
+
*/
|
|
17
|
+
export function serializersForAssociatedClass(parentClass, associationName, options) {
|
|
18
|
+
if (options.serializer)
|
|
19
|
+
return [options.serializer];
|
|
20
|
+
const optionClass = options.dreamClass ?? options.viewModelClass;
|
|
21
|
+
let associatedClasses;
|
|
22
|
+
if (optionClass) {
|
|
23
|
+
associatedClasses = [optionClass];
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
const association = parentClass?.['getAssociationMetadata'](associationName);
|
|
27
|
+
if (!association)
|
|
28
|
+
return [];
|
|
29
|
+
const modelClassOrClasses = association.modelCB();
|
|
30
|
+
associatedClasses = Array.isArray(modelClassOrClasses) ? modelClassOrClasses : [modelClassOrClasses];
|
|
31
|
+
}
|
|
32
|
+
// Every serializer of every class: one for a plain class, and one per child (sorted by
|
|
33
|
+
// sanitizedName) for an STI base, so the parent JSON carries the flattened keys of every child
|
|
34
|
+
// as nulls, as it carries those of every target class of a polymorphic BelongsTo. Several classes
|
|
35
|
+
// may resolve to the same serializer; the renderer walks each serializer once either way.
|
|
36
|
+
// (rendersMany never reaches here and does not accept `flatten`.)
|
|
37
|
+
return uniq(associatedClasses.flatMap(associatedClass => inferSerializersFromDreamClassOrViewModelClass(associatedClass, options.serializerKey, {
|
|
38
|
+
// Reached only from SerializerRenderer's rendersOne branch, so the edge type is fixed. No
|
|
39
|
+
// declaring serializer: the renderer holds the rendered attribute, not the serializer that
|
|
40
|
+
// declared it.
|
|
41
|
+
edge: { type: 'rendersOne', associationName },
|
|
42
|
+
})));
|
|
43
|
+
}
|
|
@@ -1063,6 +1063,47 @@ export default class Dream {
|
|
|
1063
1063
|
* @returns void
|
|
1064
1064
|
*/
|
|
1065
1065
|
static findEach<T extends typeof Dream>(this: T, cb: (instance: InstanceType<T>) => void | Promise<void>, opts?: FindEachOpts): Promise<void>;
|
|
1066
|
+
/**
|
|
1067
|
+
* Encrypts every value of the model's `@deco.Encrypted` properties again
|
|
1068
|
+
* with the current column encryption key, so that reading them no longer
|
|
1069
|
+
* needs the `legacy` key. It is a step of a key rotation (see
|
|
1070
|
+
* `Encrypt.generateKey`): run it in each environment, once that
|
|
1071
|
+
* environment has deployed its rotated keys, from a console or a script,
|
|
1072
|
+
* not from a migration, whose result would then depend on the keys a given
|
|
1073
|
+
* environment has configured when the migration runs.
|
|
1074
|
+
*
|
|
1075
|
+
* ```ts
|
|
1076
|
+
* await User.reencryptEncryptedColumns()
|
|
1077
|
+
* ```
|
|
1078
|
+
*
|
|
1079
|
+
* It walks every row of the model's table, including rows its default
|
|
1080
|
+
* scopes (such as soft delete) hide and an STI model's siblings, in batches in primary key order, and opens
|
|
1081
|
+
* each non-null value with the current key or, failing that, the legacy
|
|
1082
|
+
* one (see `Encrypt.reencrypt`). Each row is written on its own, with
|
|
1083
|
+
* no model hooks and without changing `updatedAt`, and only while the
|
|
1084
|
+
* column still holds the value read, so a row an app saves in between
|
|
1085
|
+
* keeps the newer value. Reading values here does not fire
|
|
1086
|
+
* `dreamApp.on('encryption:legacy-key-used', ...)`.
|
|
1087
|
+
*
|
|
1088
|
+
* **Run it only once every server encrypts with the new key.** It walks
|
|
1089
|
+
* the table once, so a row a server still configured with the old
|
|
1090
|
+
* `current` writes behind it stays encrypted with the old key, and so does
|
|
1091
|
+
* old-key ciphertext later written straight into a backing column
|
|
1092
|
+
* (`setAttribute`, `setAttributes` and `updateAttributes` accept, for a
|
|
1093
|
+
* backing column, ciphertext that either key opens). Once no writer uses
|
|
1094
|
+
* the old key and this has run for every model with encrypted properties,
|
|
1095
|
+
* `legacy` is safe to drop.
|
|
1096
|
+
*
|
|
1097
|
+
* **A value neither key opens stops it**, throwing as reading the property
|
|
1098
|
+
* would (`DecryptionRotationError` while a `legacy` key is configured,
|
|
1099
|
+
* `DecryptionError` without one). The rows rewritten before it stay
|
|
1100
|
+
* rewritten; running it again once the value is fixed rewrites them again
|
|
1101
|
+
* harmlessly.
|
|
1102
|
+
*
|
|
1103
|
+
* @param opts - Optional parameters
|
|
1104
|
+
* @param opts.batchSize - how many rows to read per batch. Defaults to 1000
|
|
1105
|
+
*/
|
|
1106
|
+
static reencryptEncryptedColumns<T extends typeof Dream>(this: T, opts?: FindEachOpts): Promise<void>;
|
|
1066
1107
|
/**
|
|
1067
1108
|
* Returns a new instance of Query scoped to the given
|
|
1068
1109
|
* model class. Especially useful with {@link Query#toKysely}.
|
|
@@ -1174,15 +1215,15 @@ export default class Dream {
|
|
|
1174
1215
|
* planned drop safe.
|
|
1175
1216
|
*
|
|
1176
1217
|
* ```ts
|
|
1177
|
-
* const user = await User.leftJoinPreload('posts', 'comments', {
|
|
1218
|
+
* const user = await User.leftJoinPreload('posts', 'comments', { and: { visibility: 'public' } }, 'replies').first()
|
|
1178
1219
|
* console.log(user.posts[0].comments[0].replies)
|
|
1179
1220
|
* // [Reply{id: 1}, Reply{id: 2}]
|
|
1180
1221
|
* ```
|
|
1181
1222
|
*
|
|
1182
|
-
* @param args - A chain of association names and
|
|
1223
|
+
* @param args - A chain of association names and and/andNot/andAny clauses
|
|
1183
1224
|
* @returns A query for this model with the include statement applied
|
|
1184
1225
|
*/
|
|
1185
|
-
static leftJoinPreload<T extends typeof Dream, I extends InstanceType<T>, DB extends I['DB'], TableName extends InstanceType<T>['table'], Schema extends I['schema'], const Arr extends readonly unknown[], const LastArg extends VariadicLeftJoinLoadArgs<I, DB, Schema, TableName, Arr>, const JoinedAssociationsCandidate = JoinedAssociationsTypeFromAssociations<DB, Schema, TableName, [
|
|
1226
|
+
static leftJoinPreload<T extends typeof Dream, I extends InstanceType<T>, DB extends I['DB'], TableName extends InstanceType<T>['table'], Schema extends I['schema'], const Arr extends readonly unknown[], const LastArg extends VariadicLeftJoinLoadArgs<I, DB, Schema, TableName, Arr, LastArg>, const JoinedAssociationsCandidate = JoinedAssociationsTypeFromAssociations<DB, Schema, TableName, [
|
|
1186
1227
|
...Arr,
|
|
1187
1228
|
LastArg
|
|
1188
1229
|
]>, const JoinedAssociations extends readonly JoinedAssociation[] = JoinedAssociationsCandidate extends readonly JoinedAssociation[] ? JoinedAssociationsCandidate : never, RetQuery = QueryWithJoinedAssociationsTypeAndNoPreload<Query<I>, JoinedAssociations>>(this: T, ...args: [...Arr, LastArg]): RetQuery;
|
|
@@ -1197,12 +1238,12 @@ export default class Dream {
|
|
|
1197
1238
|
* Preload is useful for avoiding the N+1 query problem
|
|
1198
1239
|
*
|
|
1199
1240
|
* ```ts
|
|
1200
|
-
* const user = await User.preload('posts', 'comments', {
|
|
1241
|
+
* const user = await User.preload('posts', 'comments', { and: { visibility: 'public' } }, 'replies').first()
|
|
1201
1242
|
* console.log(user.posts[0].comments[0].replies)
|
|
1202
1243
|
* // [Reply{id: 1}, Reply{id: 2}]
|
|
1203
1244
|
* ```
|
|
1204
1245
|
*
|
|
1205
|
-
* @param args - A chain of association names and
|
|
1246
|
+
* @param args - A chain of association names and and/andNot/andAny clauses
|
|
1206
1247
|
* @returns A query for this model with the preload statement applied
|
|
1207
1248
|
*/
|
|
1208
1249
|
static preload<T extends typeof Dream, I extends InstanceType<T>, DB extends I['DB'], TableName extends InstanceType<T>['table'], Schema extends I['schema'], const Arr extends readonly unknown[]>(this: T, ...args: [...Arr, VariadicLoadArgs<I, DB, Schema, TableName, Arr>]): Query<InstanceType<T>, Readonly<{
|
|
@@ -1276,10 +1317,10 @@ export default class Dream {
|
|
|
1276
1317
|
* await User.innerJoin('posts').first()
|
|
1277
1318
|
* ```
|
|
1278
1319
|
*
|
|
1279
|
-
* @param args - A chain of association names and
|
|
1320
|
+
* @param args - A chain of association names and and/andNot/andAny clauses
|
|
1280
1321
|
* @returns A Query for this model with the inner join clause applied
|
|
1281
1322
|
*/
|
|
1282
|
-
static innerJoin<T extends typeof Dream, I extends InstanceType<T>, DB extends I['DB'], Schema extends I['schema'], TableName extends I['table'] & keyof Schema, const Arr extends readonly unknown[], const LastArg extends VariadicJoinsArgs<I, DB, Schema, TableName, Arr>, const JoinedAssociationsCandidate = JoinedAssociationsTypeFromAssociations<DB, Schema, TableName, [
|
|
1323
|
+
static innerJoin<T extends typeof Dream, I extends InstanceType<T>, DB extends I['DB'], Schema extends I['schema'], TableName extends I['table'] & keyof Schema, const Arr extends readonly unknown[], const LastArg extends VariadicJoinsArgs<I, DB, Schema, TableName, Arr, LastArg>, const JoinedAssociationsCandidate = JoinedAssociationsTypeFromAssociations<DB, Schema, TableName, [
|
|
1283
1324
|
...Arr,
|
|
1284
1325
|
LastArg
|
|
1285
1326
|
]>, const JoinedAssociations extends readonly JoinedAssociation[] = JoinedAssociationsCandidate extends readonly JoinedAssociation[] ? JoinedAssociationsCandidate : never, RetQuery = QueryWithJoinedAssociationsType<Query<I>, JoinedAssociations>>(this: T, ...args: [...Arr, LastArg]): RetQuery;
|
|
@@ -1291,10 +1332,10 @@ export default class Dream {
|
|
|
1291
1332
|
* await user.innerJoin('posts').first()
|
|
1292
1333
|
* ```
|
|
1293
1334
|
*
|
|
1294
|
-
* @param args - A chain of association names and
|
|
1335
|
+
* @param args - A chain of association names and and/andNot/andAny clauses
|
|
1295
1336
|
* @returns A Query for this model with the inner join clause applied
|
|
1296
1337
|
*/
|
|
1297
|
-
innerJoin<I extends Dream, DB extends I['DB'], Schema extends I['schema'], TableName extends I['table'] & keyof Schema, const Arr extends readonly unknown[], const LastArg extends VariadicJoinsArgs<I, DB, Schema, TableName, Arr>, const JoinedAssociationsCandidate = JoinedAssociationsTypeFromAssociations<DB, Schema, TableName, [
|
|
1338
|
+
innerJoin<I extends Dream, DB extends I['DB'], Schema extends I['schema'], TableName extends I['table'] & keyof Schema, const Arr extends readonly unknown[], const LastArg extends VariadicJoinsArgs<I, DB, Schema, TableName, Arr, LastArg>, const JoinedAssociationsCandidate = JoinedAssociationsTypeFromAssociations<DB, Schema, TableName, [
|
|
1298
1339
|
...Arr,
|
|
1299
1340
|
LastArg
|
|
1300
1341
|
]>, const JoinedAssociations extends readonly JoinedAssociation[] = JoinedAssociationsCandidate extends readonly JoinedAssociation[] ? JoinedAssociationsCandidate : never, RetQuery = QueryWithJoinedAssociationsType<Query<I>, JoinedAssociations>>(this: I, ...args: [...Arr, LastArg]): RetQuery;
|
|
@@ -1306,10 +1347,10 @@ export default class Dream {
|
|
|
1306
1347
|
* await User.leftJoin('posts').first()
|
|
1307
1348
|
* ```
|
|
1308
1349
|
*
|
|
1309
|
-
* @param args - A chain of association names and
|
|
1350
|
+
* @param args - A chain of association names and and/andNot/andAny clauses
|
|
1310
1351
|
* @returns A Query for this model with the left join clause applied
|
|
1311
1352
|
*/
|
|
1312
|
-
static leftJoin<T extends typeof Dream, I extends InstanceType<T>, DB extends I['DB'], Schema extends I['schema'], TableName extends I['table'] & keyof Schema, const Arr extends readonly unknown[], const LastArg extends VariadicJoinsArgs<I, DB, Schema, TableName, Arr>, const JoinedAssociationsCandidate = JoinedAssociationsTypeFromAssociations<DB, Schema, TableName, [
|
|
1353
|
+
static leftJoin<T extends typeof Dream, I extends InstanceType<T>, DB extends I['DB'], Schema extends I['schema'], TableName extends I['table'] & keyof Schema, const Arr extends readonly unknown[], const LastArg extends VariadicJoinsArgs<I, DB, Schema, TableName, Arr, LastArg>, const JoinedAssociationsCandidate = JoinedAssociationsTypeFromAssociations<DB, Schema, TableName, [
|
|
1313
1354
|
...Arr,
|
|
1314
1355
|
LastArg
|
|
1315
1356
|
]>, const JoinedAssociations extends readonly JoinedAssociation[] = JoinedAssociationsCandidate extends readonly JoinedAssociation[] ? JoinedAssociationsCandidate : never, RetQuery = QueryWithJoinedAssociationsType<Query<I>, JoinedAssociations>>(this: T, ...args: [...Arr, LastArg]): RetQuery;
|
|
@@ -1321,10 +1362,10 @@ export default class Dream {
|
|
|
1321
1362
|
* await user.leftJoin('posts').first()
|
|
1322
1363
|
* ```
|
|
1323
1364
|
*
|
|
1324
|
-
* @param args - A chain of association names and
|
|
1365
|
+
* @param args - A chain of association names and and/andNot/andAny clauses
|
|
1325
1366
|
* @returns A Query for this model with the left join clause applied
|
|
1326
1367
|
*/
|
|
1327
|
-
leftJoin<I extends Dream, DB extends I['DB'], Schema extends I['schema'], TableName extends I['table'] & keyof Schema, const Arr extends readonly unknown[], const LastArg extends VariadicJoinsArgs<I, DB, Schema, TableName, Arr>, const JoinedAssociationsCandidate = JoinedAssociationsTypeFromAssociations<DB, Schema, TableName, [
|
|
1368
|
+
leftJoin<I extends Dream, DB extends I['DB'], Schema extends I['schema'], TableName extends I['table'] & keyof Schema, const Arr extends readonly unknown[], const LastArg extends VariadicJoinsArgs<I, DB, Schema, TableName, Arr, LastArg>, const JoinedAssociationsCandidate = JoinedAssociationsTypeFromAssociations<DB, Schema, TableName, [
|
|
1328
1369
|
...Arr,
|
|
1329
1370
|
LastArg
|
|
1330
1371
|
]>, const JoinedAssociations extends readonly JoinedAssociation[] = JoinedAssociationsCandidate extends readonly JoinedAssociation[] ? JoinedAssociationsCandidate : never, RetQuery = QueryWithJoinedAssociationsType<Query<I>, JoinedAssociations>>(this: I, ...args: [...Arr, LastArg]): RetQuery;
|
|
@@ -1900,8 +1941,8 @@ export default class Dream {
|
|
|
1900
1941
|
/**
|
|
1901
1942
|
* Returns true if any of the attributes on the instance
|
|
1902
1943
|
* have changed since it was last pulled from the database.
|
|
1903
|
-
*
|
|
1904
|
-
*
|
|
1944
|
+
* On an unpersisted instance, it returns true when at least
|
|
1945
|
+
* one column has a value other than `undefined`.
|
|
1905
1946
|
*
|
|
1906
1947
|
* ```ts
|
|
1907
1948
|
* const post = Post.new({ body: 'howyadoin' })
|
|
@@ -2165,6 +2206,15 @@ export default class Dream {
|
|
|
2165
2206
|
* const user = User.new({ email: 'how@yadoin' })
|
|
2166
2207
|
* ```
|
|
2167
2208
|
*
|
|
2209
|
+
* @param opts - the attributes to set on the new instance
|
|
2210
|
+
* @param additionalOpts - optional parameters
|
|
2211
|
+
* @param additionalOpts.bypassUserDefinedSetters - if true, sets the attributes
|
|
2212
|
+
* as {@link Dream.setAttributes | setAttributes} does, bypassing any
|
|
2213
|
+
* custom-defined setters. An encrypted property (e.g. `secret`) is still
|
|
2214
|
+
* encrypted, and an `@Encrypted` backing column (e.g. `encryptedSecret`)
|
|
2215
|
+
* accepts only ciphertext that decrypts with this app's column encryption
|
|
2216
|
+
* keys, or `null`; anything else throws (see
|
|
2217
|
+
* {@link Dream.setAttribute | setAttribute}). Defaults to false
|
|
2168
2218
|
* @returns A new (unpersisted) instance of the provided dream class
|
|
2169
2219
|
*/
|
|
2170
2220
|
static new<T extends typeof Dream>(this: T, opts?: UpdateablePropertiesForClass<T>, additionalOpts?: {
|
|
@@ -2189,6 +2239,7 @@ export default class Dream {
|
|
|
2189
2239
|
*/
|
|
2190
2240
|
constructor(opts: any, additionalOpts: {
|
|
2191
2241
|
bypassUserDefinedSetters?: boolean;
|
|
2242
|
+
fromDatabase?: boolean;
|
|
2192
2243
|
isPersisted?: boolean;
|
|
2193
2244
|
_internalUseOnly: true;
|
|
2194
2245
|
});
|
|
@@ -2276,12 +2327,39 @@ export default class Dream {
|
|
|
2276
2327
|
* bypassing any custom-defined setters. If you would like to set attributes
|
|
2277
2328
|
* without bypassing custom-defined setters, use #assignAttribute instead
|
|
2278
2329
|
*
|
|
2330
|
+
* An `@Encrypted` backing column (e.g. `encryptedSecret`) accepts only
|
|
2331
|
+
* a string of ciphertext that decrypts with this app's column encryption
|
|
2332
|
+
* keys (current or legacy), or `null`, which clears it. Anything else,
|
|
2333
|
+
* including plaintext, `undefined`, a non-string value, and ciphertext
|
|
2334
|
+
* made with a key this app does not hold, throws and leaves the column
|
|
2335
|
+
* unchanged. The check covers the backing columns of this model's class,
|
|
2336
|
+
* including those it inherits from an STI parent; a backing column
|
|
2337
|
+
* declared only by another class in the same STI hierarchy is not
|
|
2338
|
+
* checked.
|
|
2339
|
+
*
|
|
2340
|
+
* Given the name of an encrypted property (e.g. `secret`), setAttribute
|
|
2341
|
+
* neither encrypts the value nor stores it: it keeps the value,
|
|
2342
|
+
* unencrypted, under that name in this instance's attributes, which a
|
|
2343
|
+
* save does not write, while the backing column and the property keep
|
|
2344
|
+
* the value they had. To store a new value, assign the property
|
|
2345
|
+
* (`user.secret = 'new secret'`) or pass it to
|
|
2346
|
+
* {@link Dream.setAttributes | setAttributes}, each of which encrypts it.
|
|
2347
|
+
*
|
|
2279
2348
|
* ```ts
|
|
2280
2349
|
* const user = new User()
|
|
2281
2350
|
* user.setAttribute('email', 'sally@gmail.com')
|
|
2282
2351
|
* ```
|
|
2283
2352
|
*/
|
|
2284
2353
|
setAttribute<I extends Dream, Key extends AttributeKeys<I>>(this: I, column: Key & string, val: any): void;
|
|
2354
|
+
/**
|
|
2355
|
+
* @internal
|
|
2356
|
+
*
|
|
2357
|
+
* Writes the value into the current attributes as given, with none of
|
|
2358
|
+
* setAttribute's checks. Only for values Dream already trusts: a row read
|
|
2359
|
+
* from the database, and the ciphertext the @Encrypted property setter
|
|
2360
|
+
* has just produced. Every caller-supplied value goes through setAttribute.
|
|
2361
|
+
*/
|
|
2362
|
+
private setAttributeUnchecked;
|
|
2285
2363
|
/**
|
|
2286
2364
|
* Returns the value for a columnName provided,
|
|
2287
2365
|
* bypassing the getters.
|
|
@@ -2312,9 +2390,8 @@ export default class Dream {
|
|
|
2312
2390
|
* being persisted to the database, with the values
|
|
2313
2391
|
* that were last persisted to the database.
|
|
2314
2392
|
*
|
|
2315
|
-
* On a record that has not been persisted,
|
|
2316
|
-
*
|
|
2317
|
-
* for every column.
|
|
2393
|
+
* On a record that has not been persisted, only columns
|
|
2394
|
+
* with values other than `undefined` count as changed.
|
|
2318
2395
|
*
|
|
2319
2396
|
* ```ts
|
|
2320
2397
|
* const user = User.new({ email: 'original@email', password: 'howyadoin' })
|
|
@@ -2337,43 +2414,55 @@ export default class Dream {
|
|
|
2337
2414
|
* changed since last persisting, along with their current
|
|
2338
2415
|
* and previously persisted values.
|
|
2339
2416
|
*
|
|
2417
|
+
* For a column with an unsaved change, `was` is its value
|
|
2418
|
+
* as of the most recent save. For every other column, `was`
|
|
2419
|
+
* is its value from before that save, so the changes the
|
|
2420
|
+
* save made keep appearing, beside any later unsaved change,
|
|
2421
|
+
* until the next save.
|
|
2422
|
+
*
|
|
2423
|
+
* On a create, that earlier value is `undefined` for every
|
|
2424
|
+
* column of an instance from `new` or `create`, assigned or
|
|
2425
|
+
* not, and the copied value for an instance from
|
|
2426
|
+
* {@link Dream.dup | dup}. So after a create from `new` or
|
|
2427
|
+
* `create`, every column the insert returned counts as
|
|
2428
|
+
* changed: the primary key, timestamps, database defaults,
|
|
2429
|
+
* and `null` for each nullable column nobody assigned. After
|
|
2430
|
+
* a create from `dup`, the columns `dup` cleared (the primary
|
|
2431
|
+
* key, timestamps and sortable positions) count, and a copied
|
|
2432
|
+
* column counts only if the insert returned a different value.
|
|
2433
|
+
*
|
|
2340
2434
|
* ```ts
|
|
2341
2435
|
* const pet = Pet.new({ species: 'dog' })
|
|
2342
2436
|
* pet.changes()
|
|
2343
2437
|
* // {
|
|
2344
|
-
* // species: {
|
|
2345
|
-
* // was: undefined,
|
|
2346
|
-
* // now: 'dog',
|
|
2347
|
-
* // }
|
|
2438
|
+
* // species: { was: undefined, now: 'dog' },
|
|
2348
2439
|
* // }
|
|
2349
2440
|
*
|
|
2350
2441
|
* await pet.save()
|
|
2351
2442
|
* pet.changes()
|
|
2352
2443
|
* // {
|
|
2353
|
-
* //
|
|
2354
|
-
* //
|
|
2355
|
-
* //
|
|
2356
|
-
* //
|
|
2444
|
+
* // id: { was: undefined, now: 1 },
|
|
2445
|
+
* // species: { was: undefined, now: 'dog' },
|
|
2446
|
+
* // name: { was: undefined, now: null },
|
|
2447
|
+
* // ...every other column the insert returned
|
|
2357
2448
|
* // }
|
|
2358
2449
|
*
|
|
2359
2450
|
* pet.species = 'cat'
|
|
2360
2451
|
* pet.species = 'frog'
|
|
2361
2452
|
* pet.changes()
|
|
2362
2453
|
* // {
|
|
2363
|
-
* //
|
|
2364
|
-
* //
|
|
2365
|
-
* //
|
|
2366
|
-
* //
|
|
2454
|
+
* // id: { was: undefined, now: 1 },
|
|
2455
|
+
* // species: { was: 'dog', now: 'frog' },
|
|
2456
|
+
* // name: { was: undefined, now: null },
|
|
2457
|
+
* // ...every other change the create made
|
|
2367
2458
|
* // }
|
|
2368
2459
|
*
|
|
2369
2460
|
* await pet.save()
|
|
2370
2461
|
* pet.changes()
|
|
2371
2462
|
* // {
|
|
2372
|
-
* // species: {
|
|
2373
|
-
* // was: 'dog',
|
|
2374
|
-
* // now: 'frog',
|
|
2375
|
-
* // }
|
|
2463
|
+
* // species: { was: 'dog', now: 'frog' },
|
|
2376
2464
|
* // }
|
|
2465
|
+
* // (and `updatedAt`, on a model with that column)
|
|
2377
2466
|
* ```
|
|
2378
2467
|
*
|
|
2379
2468
|
* @returns An object containing changed attributes
|
|
@@ -2383,8 +2472,22 @@ export default class Dream {
|
|
|
2383
2472
|
now: Selectable<Table>[DreamColumnNames<I>];
|
|
2384
2473
|
}>>>(this: I): RetType;
|
|
2385
2474
|
/**
|
|
2386
|
-
* Returns the value
|
|
2387
|
-
*
|
|
2475
|
+
* Returns the value the column held before the most
|
|
2476
|
+
* recent save. For a column with an unsaved change, it
|
|
2477
|
+
* returns the column's value as of that save instead.
|
|
2478
|
+
*
|
|
2479
|
+
* On a create, the value before the save is `undefined`
|
|
2480
|
+
* for every column of an instance from `new` or `create`,
|
|
2481
|
+
* assigned or not, and the copied value for an instance
|
|
2482
|
+
* from {@link Dream.dup | dup} (`undefined` for the
|
|
2483
|
+
* columns `dup` cleared). So after a create from `new` or
|
|
2484
|
+
* `create`, this returns `undefined` for every column
|
|
2485
|
+
* without an unsaved change, not the value the insert
|
|
2486
|
+
* wrote. After an update, it returns the column's value
|
|
2487
|
+
* from before that update, which for a column the update
|
|
2488
|
+
* did not change is its current value. On a record loaded
|
|
2489
|
+
* from the database and not saved since, it returns the
|
|
2490
|
+
* loaded value.
|
|
2388
2491
|
*
|
|
2389
2492
|
* ```ts
|
|
2390
2493
|
* const pet = Pet.new({ species: 'cat' })
|
|
@@ -2415,7 +2518,38 @@ export default class Dream {
|
|
|
2415
2518
|
/**
|
|
2416
2519
|
* Returns true if the columnName provided has
|
|
2417
2520
|
* changes that were persisted during the most
|
|
2418
|
-
* recent save.
|
|
2521
|
+
* recent save. An unsaved change does not count,
|
|
2522
|
+
* and an unsaved edit made after that save does
|
|
2523
|
+
* not undo a change the save made. On a record
|
|
2524
|
+
* that has not been persisted, this returns false.
|
|
2525
|
+
*
|
|
2526
|
+
* A create compares the value the insert returned
|
|
2527
|
+
* with `undefined` for every column of an instance
|
|
2528
|
+
* from `new` or `create`, assigned or not, and with
|
|
2529
|
+
* the copied value for an instance from
|
|
2530
|
+
* {@link Dream.dup | dup}. So after a create from
|
|
2531
|
+
* `new` or `create`, this returns true for every
|
|
2532
|
+
* column the insert returned: the primary key,
|
|
2533
|
+
* timestamps, database defaults, and a nullable
|
|
2534
|
+
* column nobody assigned, which comes back `null`.
|
|
2535
|
+
* To react only to the columns a create assigned,
|
|
2536
|
+
* use the `ifChanged` option of an after hook.
|
|
2537
|
+
*
|
|
2538
|
+
* ```ts
|
|
2539
|
+
* const pet = await Pet.create({ species: 'cat' })
|
|
2540
|
+
* pet.savedChangeToAttribute('species')
|
|
2541
|
+
* // true
|
|
2542
|
+
* pet.savedChangeToAttribute('name')
|
|
2543
|
+
* // true (unassigned, so the insert returned null)
|
|
2544
|
+
*
|
|
2545
|
+
* await pet.update({ name: 'Snoopy' })
|
|
2546
|
+
* pet.savedChangeToAttribute('species')
|
|
2547
|
+
* // false
|
|
2548
|
+
*
|
|
2549
|
+
* pet.species = 'dog'
|
|
2550
|
+
* pet.savedChangeToAttribute('species')
|
|
2551
|
+
* // false (not saved yet)
|
|
2552
|
+
* ```
|
|
2419
2553
|
*
|
|
2420
2554
|
* @param columnName - the column name to check
|
|
2421
2555
|
* @returns A boolean
|
|
@@ -2425,9 +2559,9 @@ export default class Dream {
|
|
|
2425
2559
|
* Returns true if the columnName provided has
|
|
2426
2560
|
* changes that have not yet been persisted.
|
|
2427
2561
|
*
|
|
2428
|
-
* On a record that has not been persisted,
|
|
2429
|
-
* column
|
|
2430
|
-
*
|
|
2562
|
+
* On a record that has not been persisted, this returns
|
|
2563
|
+
* true only for a column with a value other than `undefined`.
|
|
2564
|
+
* An explicit `null` counts as a change.
|
|
2431
2565
|
*
|
|
2432
2566
|
* @param attribute - the column name to check
|
|
2433
2567
|
* @returns A boolean
|
|
@@ -2444,15 +2578,14 @@ export default class Dream {
|
|
|
2444
2578
|
* of columns that have changed since last persist,
|
|
2445
2579
|
* and their current values.
|
|
2446
2580
|
*
|
|
2447
|
-
* On a record that has not been persisted,
|
|
2448
|
-
*
|
|
2449
|
-
*
|
|
2450
|
-
* whose value is `undefined`.
|
|
2581
|
+
* On a record that has not been persisted, the object
|
|
2582
|
+
* contains only columns with values other than `undefined`.
|
|
2583
|
+
* An explicit `null` is included.
|
|
2451
2584
|
*
|
|
2452
2585
|
* ```ts
|
|
2453
2586
|
* const user = User.new({ email: 'hello@world' })
|
|
2454
2587
|
* user.dirtyAttributes()
|
|
2455
|
-
* // {
|
|
2588
|
+
* // { email: 'hello@world' }
|
|
2456
2589
|
*
|
|
2457
2590
|
* await user.save()
|
|
2458
2591
|
*
|
|
@@ -2644,19 +2777,19 @@ export default class Dream {
|
|
|
2644
2777
|
* if the association is not already loaded.
|
|
2645
2778
|
*
|
|
2646
2779
|
* ```ts
|
|
2647
|
-
* const
|
|
2648
|
-
* .load('posts', { body: ops.ilike('%hello world%') }, 'comments', 'replies')
|
|
2780
|
+
* const loadedUser = await user
|
|
2781
|
+
* .load('posts', { and: { body: ops.ilike('%hello world%') } }, 'comments', 'replies')
|
|
2649
2782
|
* .load('images')
|
|
2650
2783
|
* .execute()
|
|
2651
2784
|
*
|
|
2652
|
-
*
|
|
2785
|
+
* loadedUser.posts[0].comments[0].replies[0]
|
|
2653
2786
|
* // Reply{}
|
|
2654
2787
|
*
|
|
2655
|
-
*
|
|
2788
|
+
* loadedUser.images[0]
|
|
2656
2789
|
* // Image{}
|
|
2657
2790
|
* ```
|
|
2658
2791
|
*
|
|
2659
|
-
* @param args - A
|
|
2792
|
+
* @param args - A chain of association names and and/andNot/andAny clauses
|
|
2660
2793
|
* @returns A chainable LoadBuilder instance. Call `.execute()` to get the cloned model with associations loaded.
|
|
2661
2794
|
*/
|
|
2662
2795
|
load<I extends Dream, DB extends I['DB'], TableName extends I['table'], Schema extends I['schema'], const Arr extends readonly unknown[]>(this: I, ...args: [...Arr, VariadicLoadArgs<I, DB, Schema, TableName, Arr>]): LoadBuilder<I>;
|
|
@@ -2857,19 +2990,19 @@ export default class Dream {
|
|
|
2857
2990
|
* 5. associations loading associations loading associations could result in exponential amounts of data; in those cases, `.load(...).findEach(...)` avoids instantiating massive amounts of data at once
|
|
2858
2991
|
*
|
|
2859
2992
|
* ```ts
|
|
2860
|
-
* const
|
|
2861
|
-
* .leftJoinLoad('posts', { body: ops.ilike('%hello world%') }, 'comments', 'replies')
|
|
2993
|
+
* const loadedUser = await user
|
|
2994
|
+
* .leftJoinLoad('posts', { and: { body: ops.ilike('%hello world%') } }, 'comments', 'replies')
|
|
2862
2995
|
* .leftJoinLoad('images')
|
|
2863
2996
|
* .execute()
|
|
2864
2997
|
*
|
|
2865
|
-
*
|
|
2998
|
+
* loadedUser.posts[0].comments[0].replies[0]
|
|
2866
2999
|
* // Reply{}
|
|
2867
3000
|
*
|
|
2868
|
-
*
|
|
3001
|
+
* loadedUser.images[0]
|
|
2869
3002
|
* // Image{}
|
|
2870
3003
|
* ```
|
|
2871
3004
|
*
|
|
2872
|
-
* @param args - A
|
|
3005
|
+
* @param args - A chain of association names and and/andNot/andAny clauses
|
|
2873
3006
|
* @returns A chainable LeftJoinLoadBuilder instance. Call `.execute()` to get the cloned model with associations loaded.
|
|
2874
3007
|
*/
|
|
2875
3008
|
leftJoinLoad<I extends Dream, DB extends I['DB'], TableName extends I['table'], Schema extends I['schema'], const Arr extends readonly unknown[]>(this: I, ...args: [...Arr, VariadicLeftJoinLoadArgs<I, DB, Schema, TableName, Arr>]): LeftJoinLoadBuilder<I>;
|
|
@@ -2931,6 +3064,13 @@ export default class Dream {
|
|
|
2931
3064
|
* Takes the attributes passed in and sets their values internally,
|
|
2932
3065
|
* bypassing any custom setters defined for these attributes.
|
|
2933
3066
|
*
|
|
3067
|
+
* An encrypted property (e.g. `secret`) is still encrypted. Its
|
|
3068
|
+
* `@Encrypted` backing column (e.g. `encryptedSecret`) accepts only
|
|
3069
|
+
* ciphertext that decrypts with this app's column encryption keys, or
|
|
3070
|
+
* `null`; anything else throws (see {@link Dream.setAttribute | setAttribute}).
|
|
3071
|
+
* Attributes are set in order, so those before the rejected one have
|
|
3072
|
+
* already been set when it throws.
|
|
3073
|
+
*
|
|
2934
3074
|
* NOTE:
|
|
2935
3075
|
* To leverage custom-defined setters, use `#assignAttributes` instead.
|
|
2936
3076
|
*
|
|
@@ -2961,6 +3101,10 @@ export default class Dream {
|
|
|
2961
3101
|
* Upon updating an instance, the update timestamp (if defined)
|
|
2962
3102
|
* will be updated on the model.
|
|
2963
3103
|
*
|
|
3104
|
+
* A column whose value is `undefined` is skipped, not written: a new
|
|
3105
|
+
* record gets the column's database default, and a persisted record
|
|
3106
|
+
* keeps the value stored for it. Set a column to `null` to clear it.
|
|
3107
|
+
*
|
|
2964
3108
|
* ```ts
|
|
2965
3109
|
* const user = User.new({ email: 'how@yadoin' })
|
|
2966
3110
|
* user.name = 'fred'
|
|
@@ -3006,6 +3150,12 @@ export default class Dream {
|
|
|
3006
3150
|
* See {@link Dream.save | save} for details on
|
|
3007
3151
|
* the side effects of saving.
|
|
3008
3152
|
*
|
|
3153
|
+
* A column whose value is still `undefined` after setters run is
|
|
3154
|
+
* skipped, not written (see {@link Dream.save | save}), with two
|
|
3155
|
+
* `@Encrypted` exceptions: `undefined` for an encrypted property (e.g.
|
|
3156
|
+
* `secret`) is encrypted to `null`, so it clears the column, and
|
|
3157
|
+
* `undefined` for its backing column (e.g. `encryptedSecret`) throws.
|
|
3158
|
+
*
|
|
3009
3159
|
* NOTE:
|
|
3010
3160
|
* To bypass custom-defined setters, use {@link Dream.updateAttributes | updateAttributes} instead.
|
|
3011
3161
|
*
|
|
@@ -3029,6 +3179,18 @@ export default class Dream {
|
|
|
3029
3179
|
* See {@link Dream.save | save} for details on
|
|
3030
3180
|
* the side effects of saving.
|
|
3031
3181
|
*
|
|
3182
|
+
* An encrypted property (e.g. `secret`) is still encrypted. Its
|
|
3183
|
+
* `@Encrypted` backing column (e.g. `encryptedSecret`) accepts only
|
|
3184
|
+
* ciphertext that decrypts with this app's column encryption keys, or
|
|
3185
|
+
* `null`; anything else throws before anything is saved (see
|
|
3186
|
+
* {@link Dream.setAttribute | setAttribute}).
|
|
3187
|
+
*
|
|
3188
|
+
* A column whose value is still `undefined` after setters run is
|
|
3189
|
+
* skipped, not written (see {@link Dream.save | save}), with two
|
|
3190
|
+
* `@Encrypted` exceptions: `undefined` for an encrypted property (e.g.
|
|
3191
|
+
* `secret`) is encrypted to `null`, so it clears the column, and
|
|
3192
|
+
* `undefined` for its backing column (e.g. `encryptedSecret`) throws.
|
|
3193
|
+
*
|
|
3032
3194
|
* NOTE:
|
|
3033
3195
|
* To update the values without bypassing any custom-defined
|
|
3034
3196
|
* setters, use {@link Dream.update | update} instead.
|
|
@@ -21,7 +21,13 @@ export default class DreamBin {
|
|
|
21
21
|
}): Promise<void>;
|
|
22
22
|
static generateStiChild(fullyQualifiedModelName: string, fullyQualifiedParentName: string, columnsWithTypes: string[], options: {
|
|
23
23
|
serializer: boolean;
|
|
24
|
-
|
|
24
|
+
/**
|
|
25
|
+
* The connection whose migrations folder receives the child's
|
|
26
|
+
* migration. Defaults to the parent model's connection, which is the
|
|
27
|
+
* connection the child uses; the parent must then be one of the app's
|
|
28
|
+
* models, or this throws before any file is written.
|
|
29
|
+
*/
|
|
30
|
+
connectionName?: string;
|
|
25
31
|
adminSerializers?: boolean;
|
|
26
32
|
internalSerializers?: boolean;
|
|
27
33
|
modelName?: string;
|