@rvoh/dream 2.35.0 → 2.36.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/cjs/src/Dream.js +260 -55
- 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 +35 -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 +77 -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 +260 -55
- 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 +35 -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 +77 -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 +208 -42
- 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 +29 -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 +270 -142
- 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
|
@@ -2,7 +2,7 @@ import { CompiledQuery, DeleteQueryBuilder, SelectQueryBuilder, UpdateQueryBuild
|
|
|
2
2
|
import type { DreamDbConfig } from '../../dream-app/index.js';
|
|
3
3
|
import Dream from '../../Dream.js';
|
|
4
4
|
import { SchemaBuilderAssociationData, SchemaBuilderColumnData } from '../../helpers/cli/ASTBuilder.js';
|
|
5
|
-
import { AssociationStatement } from '../../types/associations/shared.js';
|
|
5
|
+
import { AssociationStatement, OrderQueryStatement } from '../../types/associations/shared.js';
|
|
6
6
|
import { DbConnectionType, LegacyCompatiblePrimaryKeyType } from '../../types/db.js';
|
|
7
7
|
import { DreamColumnNames, DreamConstructorType, DreamTableSchema } from '../../types/dream.js';
|
|
8
8
|
import { PreloadedDreamsAndWhatTheyPointTo, QueryToKyselyDBType, QueryToKyselyTableNamesType } from '../../types/query.js';
|
|
@@ -435,6 +435,68 @@ export default class QueryDriverBase<DreamInstance extends Dream> {
|
|
|
435
435
|
* @returns An array of plucked values
|
|
436
436
|
*/
|
|
437
437
|
pluck(...fields: DreamColumnNames<DreamInstance>[]): Promise<any[]>;
|
|
438
|
+
/**
|
|
439
|
+
* @internal
|
|
440
|
+
*
|
|
441
|
+
* The order statements that the declared `order` of the associations the
|
|
442
|
+
* Query is built on or joins contributes to its ORDER BY, in the order they
|
|
443
|
+
* sort, each column namespaced by the alias it is read from. Cursor
|
|
444
|
+
* pagination folds these into its cursor.
|
|
445
|
+
*
|
|
446
|
+
* @returns An array of namespaced order statements
|
|
447
|
+
*/
|
|
448
|
+
associationOrderStatements(): OrderQueryStatement<string>[];
|
|
449
|
+
/**
|
|
450
|
+
* @internal
|
|
451
|
+
*
|
|
452
|
+
* The primary key of each table the Query reaches through a HasOne or
|
|
453
|
+
* HasMany association (one it joins, one an association it joins goes
|
|
454
|
+
* through, or one its association query is built on), namespaced by the
|
|
455
|
+
* alias it is read from, in join order. Such a join can return a row of the
|
|
456
|
+
* Query's table once for each row it matches, and these keys, with the
|
|
457
|
+
* Query's own primary key, tell those rows apart. Cursor pagination pages by
|
|
458
|
+
* them after the Query's own primary key.
|
|
459
|
+
*
|
|
460
|
+
* @returns An array of namespaced primary key columns
|
|
461
|
+
*/
|
|
462
|
+
joinedRowKeyColumns(): string[];
|
|
463
|
+
/**
|
|
464
|
+
* @internal
|
|
465
|
+
*
|
|
466
|
+
* A page of a select that keeps one row of each group (DISTINCT ON, as a
|
|
467
|
+
* Query that calls `distinct`, or an association that declares `distinct`,
|
|
468
|
+
* produces), or null for any other select, whose pages cursor pagination
|
|
469
|
+
* reads as it reads any select's.
|
|
470
|
+
*
|
|
471
|
+
* The page is the values of the Query's order statement columns for each
|
|
472
|
+
* row the select returns that matches any of `rowsAfter` (every row when it
|
|
473
|
+
* is null), sorted by the Query's order statements and limited by its
|
|
474
|
+
* limit. The select chooses each group's row before `rowsAfter` narrows the
|
|
475
|
+
* rows, so that the page holds only rows the select returns.
|
|
476
|
+
*
|
|
477
|
+
* A driver whose selects never keep one row of each group returns null.
|
|
478
|
+
*
|
|
479
|
+
* @param rowsAfter - where statements, any of which a row of the page matches
|
|
480
|
+
* @returns The page's rows, each an array of its order statement columns' values, or null
|
|
481
|
+
*/
|
|
482
|
+
pluckDistinctOnPage(rowsAfter: Record<string, unknown>[] | null): Promise<unknown[][] | null>;
|
|
483
|
+
/**
|
|
484
|
+
* @internal
|
|
485
|
+
*
|
|
486
|
+
* For a select that keeps one row of each group (DISTINCT ON, as a Query
|
|
487
|
+
* that calls `distinct`, or an association that declares `distinct`,
|
|
488
|
+
* produces), the values of `rowKeyColumns` for every row it returns, sorted
|
|
489
|
+
* by those columns, ascending; null for any other select. `findEach` and
|
|
490
|
+
* `pluckEach` read a select that keeps one row of each group from these
|
|
491
|
+
* keys rather than by a cursor, which would narrow the select before it
|
|
492
|
+
* chooses each group's row.
|
|
493
|
+
*
|
|
494
|
+
* A driver whose selects never keep one row of each group returns null.
|
|
495
|
+
*
|
|
496
|
+
* @param rowKeyColumns - the namespaced columns that tell the select's rows apart
|
|
497
|
+
* @returns The rows' values of `rowKeyColumns`, or null
|
|
498
|
+
*/
|
|
499
|
+
pluckDistinctOnRowKeys(rowKeyColumns: string[]): Promise<unknown[][] | null>;
|
|
438
500
|
/**
|
|
439
501
|
* Returns a new Kysely SelectQueryBuilder instance to be used
|
|
440
502
|
* in a sub Query
|
|
@@ -4,7 +4,7 @@ import { DialectProviderCb } from '../../db/DreamDbConnection.js';
|
|
|
4
4
|
import { DreamDbConfig } from '../../dream-app/index.js';
|
|
5
5
|
import Dream from '../../Dream.js';
|
|
6
6
|
import { SchemaBuilderInformationSchemaRow } from '../../helpers/cli/ASTBuilder.js';
|
|
7
|
-
import { AssociationStatement } from '../../types/associations/shared.js';
|
|
7
|
+
import { AssociationStatement, OrderQueryStatement } from '../../types/associations/shared.js';
|
|
8
8
|
import { DbConnectionType, LegacyCompatiblePrimaryKeyType } from '../../types/db.js';
|
|
9
9
|
import { DreamColumnNames, DreamTableSchema, OrderDir, SqlCommandType } from '../../types/dream.js';
|
|
10
10
|
import { PreloadedDreamsAndWhatTheyPointTo, QueryToKyselyDBType, QueryToKyselyTableNamesType } from '../../types/query.js';
|
|
@@ -12,6 +12,21 @@ import DreamTransaction from '../DreamTransaction.js';
|
|
|
12
12
|
import Query from '../Query.js';
|
|
13
13
|
import QueryDriverBase from './Base.js';
|
|
14
14
|
export default class KyselyQueryDriver<DreamInstance extends Dream> extends QueryDriverBase<DreamInstance> {
|
|
15
|
+
/**
|
|
16
|
+
* @internal
|
|
17
|
+
*
|
|
18
|
+
* While `associationOrderStatements` builds a select, the order statements
|
|
19
|
+
* that association joins add to it, in the order they are added.
|
|
20
|
+
*/
|
|
21
|
+
private associationOrderCollector;
|
|
22
|
+
/**
|
|
23
|
+
* @internal
|
|
24
|
+
*
|
|
25
|
+
* While `joinedRowKeyColumns` builds a select, the namespaced primary keys of
|
|
26
|
+
* the tables that HasOne and HasMany joins add to it, in the order they are
|
|
27
|
+
* added.
|
|
28
|
+
*/
|
|
29
|
+
private joinedRowKeyCollector;
|
|
15
30
|
dbFor(sqlCommandType: SqlCommandType): Kysely<DreamInstance['DB']> | KyselyTransaction<DreamInstance['DB']>;
|
|
16
31
|
static dbFor<I extends Dream>(connectionName: string, dbConnectionType: DbConnectionType, dreamTransaction?: DreamTransaction<I> | null): Kysely<I['DB']> | KyselyTransaction<I['DB']>;
|
|
17
32
|
static dialectProvider(connectionName: string, dbConnectionType: DbConnectionType): DialectProviderCb;
|
|
@@ -400,6 +415,75 @@ export default class KyselyQueryDriver<DreamInstance extends Dream> extends Quer
|
|
|
400
415
|
}>;
|
|
401
416
|
private buildDelete;
|
|
402
417
|
private buildSelect;
|
|
418
|
+
/**
|
|
419
|
+
* @internal
|
|
420
|
+
*
|
|
421
|
+
* The select's source, joins, conditions, DISTINCT ON and similarity
|
|
422
|
+
* ranking, before the Query's own order statements, limit, offset and
|
|
423
|
+
* selection are applied, together with the connection the select runs on.
|
|
424
|
+
*/
|
|
425
|
+
private buildSelectCore;
|
|
426
|
+
/**
|
|
427
|
+
* @internal
|
|
428
|
+
*
|
|
429
|
+
* The order statements that the declared `order` of the associations the
|
|
430
|
+
* Query is built on or joins contributes to its ORDER BY, in the order they
|
|
431
|
+
* sort, each column namespaced by the alias it is read from. They are read
|
|
432
|
+
* off the same join code that emits them, by building the select.
|
|
433
|
+
*
|
|
434
|
+
* @returns An array of namespaced order statements
|
|
435
|
+
*/
|
|
436
|
+
associationOrderStatements(): OrderQueryStatement<string>[];
|
|
437
|
+
/**
|
|
438
|
+
* @internal
|
|
439
|
+
*
|
|
440
|
+
* The primary key of each table the Query reaches through a HasOne or
|
|
441
|
+
* HasMany association (one it joins, one an association it joins goes
|
|
442
|
+
* through, or one its association query is built on), namespaced by the
|
|
443
|
+
* alias it is read from, in join order. They are read off the same join code
|
|
444
|
+
* that emits the joins, by building the select.
|
|
445
|
+
*
|
|
446
|
+
* @returns An array of namespaced primary key columns
|
|
447
|
+
*/
|
|
448
|
+
joinedRowKeyColumns(): string[];
|
|
449
|
+
/**
|
|
450
|
+
* @internal
|
|
451
|
+
*
|
|
452
|
+
* A page of a select that carries DISTINCT ON (as a Query that calls
|
|
453
|
+
* `distinct`, or an association that declares `distinct`, produces), or null
|
|
454
|
+
* for any other select.
|
|
455
|
+
*
|
|
456
|
+
* Such a select keeps the row of each group that sorts first in its ORDER
|
|
457
|
+
* BY, so narrowing it to the rows after a cursor would let it keep a row it
|
|
458
|
+
* does not return (a group's later row, once the cursor has passed the
|
|
459
|
+
* group's first). It is read as a derived table instead, and narrowed to
|
|
460
|
+
* `rowsAfter`, sorted and limited outside it. The Query's order statements
|
|
461
|
+
* follow the select's own ORDER BY, if it has one, so that the select keeps
|
|
462
|
+
* the same row of each group every time it runs, and each of their columns
|
|
463
|
+
* is read out of it under a short alias (as `pluck` reads them), since a
|
|
464
|
+
* joined table's column cannot be named outside it.
|
|
465
|
+
*
|
|
466
|
+
* @param rowsAfter - where statements, any of which a row of the page matches
|
|
467
|
+
* @returns The page's rows, each an array of its order statement columns' values, or null
|
|
468
|
+
*/
|
|
469
|
+
pluckDistinctOnPage(rowsAfter: Record<string, unknown>[] | null): Promise<unknown[][] | null>;
|
|
470
|
+
/**
|
|
471
|
+
* @internal
|
|
472
|
+
*
|
|
473
|
+
* For a select that carries DISTINCT ON (as a Query that calls `distinct`,
|
|
474
|
+
* or an association that declares `distinct`, produces), the values of
|
|
475
|
+
* `rowKeyColumns` for every row it returns, sorted by those columns,
|
|
476
|
+
* ascending; null for any other select.
|
|
477
|
+
*
|
|
478
|
+
* The select runs as `all()` runs it, with its own ORDER BY choosing each
|
|
479
|
+
* group's row, and is read as a derived table, sorted outside it. Each of
|
|
480
|
+
* `rowKeyColumns` is read out of it under a short alias (as `pluck` reads
|
|
481
|
+
* them), since a joined table's column cannot be named outside it.
|
|
482
|
+
*
|
|
483
|
+
* @param rowKeyColumns - the namespaced columns that tell the select's rows apart
|
|
484
|
+
* @returns The rows' values of `rowKeyColumns`, or null
|
|
485
|
+
*/
|
|
486
|
+
pluckDistinctOnRowKeys(rowKeyColumns: string[]): Promise<unknown[][] | null>;
|
|
403
487
|
orderByDirection(direction: OrderDir | null): (obj: OrderByItemBuilder) => OrderByItemBuilder;
|
|
404
488
|
private buildUpdate;
|
|
405
489
|
/**
|
package/dist/types/src/dream/internal/associations/assertRecognizedAssociationConditionKeys.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The keys a condition object on an association accepts, whether it is
|
|
3
|
+
* passed in a chain (`preload('posts', { and: { ... } })`), returned from a
|
|
4
|
+
* `preloadFor`/`loadFor` modifier, or passed to `associationQuery`.
|
|
5
|
+
*/
|
|
6
|
+
export declare const ASSOCIATION_CONDITION_KEYS: readonly ["and", "andNot", "andAny"];
|
|
7
|
+
/**
|
|
8
|
+
* The keys accepted by `destroyAssociation`, `reallyDestroyAssociation`
|
|
9
|
+
* and `undestroyAssociation`.
|
|
10
|
+
*/
|
|
11
|
+
export declare const DESTROY_ASSOCIATION_OPTION_KEYS: readonly ["and", "andNot", "andAny", "bypassAllDefaultScopes", "defaultScopesToBypass", "cascade", "skipHooks"];
|
|
12
|
+
/**
|
|
13
|
+
* The keys accepted by `updateAssociation`.
|
|
14
|
+
*/
|
|
15
|
+
export declare const UPDATE_ASSOCIATION_OPTION_KEYS: readonly ["and", "andNot", "andAny", "bypassAllDefaultScopes", "defaultScopesToBypass", "skipHooks"];
|
|
16
|
+
/**
|
|
17
|
+
* Throws UnrecognizedAssociationConditionKeys when `value` is an object
|
|
18
|
+
* carrying any own key outside `acceptedKeys`, including a key whose value
|
|
19
|
+
* is `undefined`. Dream reads only the accepted keys, so an unrecognized key
|
|
20
|
+
* would otherwise be silently ignored (and, for the destroy family, act on
|
|
21
|
+
* every associated row instead of the ones the caller meant to select).
|
|
22
|
+
* Non-object values (`undefined`, `null`) pass through untouched.
|
|
23
|
+
*
|
|
24
|
+
* @param value - The condition object or options object to check
|
|
25
|
+
* @param acceptedKeys - The keys `value` may carry
|
|
26
|
+
* @param associationName - The association the object applies to, for the error message
|
|
27
|
+
* @param methodName - The public method the options were passed to, or null for a chain condition
|
|
28
|
+
*/
|
|
29
|
+
export default function assertRecognizedAssociationConditionKeys(value: unknown, acceptedKeys: readonly string[], associationName: string | number | symbol, methodName?: string | null): void;
|
|
@@ -238,9 +238,43 @@ export default class DreamApp {
|
|
|
238
238
|
load<RT extends 'models' | 'serializers'>(resourceType: RT, resourcePath: string, importCb: (path: string) => Promise<any>): Promise<void>;
|
|
239
239
|
plugin(cb: (app: DreamApp) => void | Promise<void>): void;
|
|
240
240
|
set<ApplyOpt extends DreamAppSetOption>(applyOption: ApplyOpt, options: ApplyOpt extends 'bypassDeprecationChecks' ? boolean : ApplyOpt extends 'db' ? DreamDbCredentialOptions | string : ApplyOpt extends 'encryption' ? DreamAppEncryptionOptions : ApplyOpt extends 'primaryKeyType' ? LegacyCompatiblePrimaryKeyType : ApplyOpt extends 'importExtension' ? GeneratorImportStyle : ApplyOpt extends 'logger' ? DreamLogger : ApplyOpt extends 'projectRoot' ? string : ApplyOpt extends 'inflections' ? () => void | Promise<void> : ApplyOpt extends 'packageManager' ? DreamAppAllowedPackageManagersEnum : ApplyOpt extends 'paths' ? DreamDirectoryPaths : ApplyOpt extends 'parallelTests' ? number : ApplyOpt extends 'unicodeNormalization' ? UnicodeNormalizationForm : ApplyOpt extends 'paginationPageSize' ? number : ApplyOpt extends 'paginationMaxPageSize' ? number : ApplyOpt extends 'sortableScopeLockTimeout' ? number : never, secondaryOptions?: ApplyOpt extends 'db' ? DreamDbCredentialOptions : never): void;
|
|
241
|
-
|
|
241
|
+
/**
|
|
242
|
+
* Registers a callback for an app-level event. Callbacks for the same
|
|
243
|
+
* event run in the order they were registered.
|
|
244
|
+
*
|
|
245
|
+
* - `'db:log'`: called with a {@link KyselyLogEvent} each time a query on a
|
|
246
|
+
* Dream database connection completes or fails.
|
|
247
|
+
* - `'repl:start'`: called, and awaited, with the console's REPL context
|
|
248
|
+
* when the Dream console starts.
|
|
249
|
+
* - `'encryption:legacy-key-used'`: called with an
|
|
250
|
+
* {@link EncryptionLegacyKeyUsedEvent} when reading an `@deco.Encrypted`
|
|
251
|
+
* property needed the `legacy` column encryption key, not `current`, to
|
|
252
|
+
* open the stored value. Use it during a key rotation to find rows still
|
|
253
|
+
* encrypted with the old key. The property decrypts on every read, so a
|
|
254
|
+
* record whose value is still under the old key fires the event each time
|
|
255
|
+
* the property is read. A row nobody reads never fires it, so a quiet
|
|
256
|
+
* event does not prove that `legacy` is safe to drop;
|
|
257
|
+
* `Model.reencryptEncryptedColumns()` rewrites every row instead. Neither
|
|
258
|
+
* it nor the migration helpers fire the event. The callback runs
|
|
259
|
+
* synchronously inside the property read, and an error it throws
|
|
260
|
+
* propagates from that read. Reading the same property of the same
|
|
261
|
+
* record inside the callback returns its value without firing the event
|
|
262
|
+
* again, so a callback can read the property and assign the value back,
|
|
263
|
+
* which re-encrypts it under `current` for the record's next save. That
|
|
264
|
+
* holds only while the callback runs synchronously: a callback that
|
|
265
|
+
* reads the property after an `await` fires the event again from that
|
|
266
|
+
* read, so an `async` callback should read the property before its
|
|
267
|
+
* first `await`.
|
|
268
|
+
*
|
|
269
|
+
* ```ts
|
|
270
|
+
* dreamApp.on('encryption:legacy-key-used', ({ dream, property }) => {
|
|
271
|
+
* console.warn(`${dream.constructor.name} ${dream.primaryKeyValue()} ${property} still uses the legacy key`)
|
|
272
|
+
* })
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
on<T extends DreamHookEventType>(hookEventType: T, cb: T extends 'db:log' ? (event: KyselyLogEvent) => void : T extends 'repl:start' ? (context: Context) => void | Promise<void> : T extends 'encryption:legacy-key-used' ? (event: EncryptionLegacyKeyUsedEvent) => void : never): void;
|
|
242
276
|
}
|
|
243
|
-
export type DreamHookEventType = 'db:log' | 'repl:start';
|
|
277
|
+
export type DreamHookEventType = 'db:log' | 'repl:start' | 'encryption:legacy-key-used';
|
|
244
278
|
export interface DreamAppOpts {
|
|
245
279
|
projectRoot: string;
|
|
246
280
|
primaryKeyType: LegacyCompatiblePrimaryKeyType;
|
|
@@ -373,6 +407,26 @@ interface SegmentedEncryptionOptions {
|
|
|
373
407
|
export interface DreamAppSpecialHooks {
|
|
374
408
|
dbLog: ((event: KyselyLogEvent) => void)[];
|
|
375
409
|
replStart: ((context: Context) => void | Promise<void>)[];
|
|
410
|
+
encryptionLegacyKeyUsed: ((event: EncryptionLegacyKeyUsedEvent) => void)[];
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Passed to `dreamApp.on('encryption:legacy-key-used', ...)` callbacks.
|
|
414
|
+
*/
|
|
415
|
+
export interface EncryptionLegacyKeyUsedEvent {
|
|
416
|
+
/**
|
|
417
|
+
* The record whose `@deco.Encrypted` property was read. Its class and
|
|
418
|
+
* `primaryKeyValue()` identify the row; a record not yet saved has no
|
|
419
|
+
* primary key.
|
|
420
|
+
*/
|
|
421
|
+
dream: Dream;
|
|
422
|
+
/**
|
|
423
|
+
* The `@deco.Encrypted` property that was read, e.g. `'phone'`.
|
|
424
|
+
*/
|
|
425
|
+
property: string;
|
|
426
|
+
/**
|
|
427
|
+
* The column holding the property's ciphertext, e.g. `'encryptedPhone'`.
|
|
428
|
+
*/
|
|
429
|
+
encryptedColumnName: string;
|
|
376
430
|
}
|
|
377
431
|
export interface DreamAppInitOptions {
|
|
378
432
|
bypassDreamIntegrityChecks?: boolean;
|
|
@@ -1,6 +1,34 @@
|
|
|
1
|
+
import { DecryptCallbacks } from './index.js';
|
|
1
2
|
export default class InternalEncrypt {
|
|
2
3
|
static encryptColumn(data: any): string | null;
|
|
3
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Returns `existingCiphertext` when the current column key opens it to a
|
|
6
|
+
* value whose JSON serialization equals `data`'s, the plaintext
|
|
7
|
+
* `encryptColumn(data)` would encrypt, and otherwise `encryptColumn(data)`.
|
|
8
|
+
* A value only the legacy key opens, ciphertext no key opens, and a
|
|
9
|
+
* missing `existingCiphertext` all get fresh ciphertext. It never calls
|
|
10
|
+
* `onLegacyKeyUsed`.
|
|
11
|
+
*/
|
|
12
|
+
static reuseOrEncryptColumn(data: any, existingCiphertext: unknown): string | null;
|
|
13
|
+
/**
|
|
14
|
+
* Decrypts `data` with the column keys, current then legacy.
|
|
15
|
+
* `onLegacyKeyUsed` is passed to `Encrypt.decrypt`, so it is called only
|
|
16
|
+
* when the legacy key opened the value.
|
|
17
|
+
*/
|
|
18
|
+
static decryptColumn(data: any, callbacks?: DecryptCallbacks): unknown;
|
|
19
|
+
/**
|
|
20
|
+
* Encrypts `data`, a column's ciphertext, again with the current column key
|
|
21
|
+
* (see `Encrypt.reencrypt`), opening it with the current key or, failing
|
|
22
|
+
* that, the legacy one. It does not call `onLegacyKeyUsed`.
|
|
23
|
+
*/
|
|
24
|
+
static reencryptColumn(data: any): string | null;
|
|
25
|
+
/**
|
|
26
|
+
* Whether `data` is ciphertext that the column keys (current, then legacy)
|
|
27
|
+
* open to a value `decryptColumn` returns. A missing column encryption
|
|
28
|
+
* config or key still throws, since that is a configuration error rather
|
|
29
|
+
* than a property of `data`.
|
|
30
|
+
*/
|
|
31
|
+
static isDecryptableColumnCiphertext(data: string): boolean;
|
|
4
32
|
private static doEncryption;
|
|
5
33
|
private static doDecryption;
|
|
6
34
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The column that holds an `@deco.Encrypted` property's ciphertext when the
|
|
3
|
+
* decorator is not given one: the property's name, pascalized and prefixed
|
|
4
|
+
* with `encrypted`. `secretPhone`, or `secret_phone`, gives
|
|
5
|
+
* `encryptedSecretPhone`, which is the `encrypted_secret_phone` column.
|
|
6
|
+
*/
|
|
7
|
+
export default function defaultEncryptedColumnName(propertyName: string): string;
|
|
@@ -19,12 +19,50 @@ export default class Encrypt {
|
|
|
19
19
|
*
|
|
20
20
|
* `MissingEncryptionKey` propagates from either form when a key is missing.
|
|
21
21
|
*
|
|
22
|
+
* **`onLegacyKeyUsed`** (optional fourth argument): during a key rotation,
|
|
23
|
+
* tells you which values still need the legacy key. It is called with no
|
|
24
|
+
* arguments, synchronously, before a three-arg call returns a value that
|
|
25
|
+
* the legacy key opened. It is not called when the current key opens the
|
|
26
|
+
* value, when decryption throws, or in the two-arg form. An error it
|
|
27
|
+
* throws propagates from `decrypt` as is.
|
|
28
|
+
*
|
|
29
|
+
* ```ts
|
|
30
|
+
* const value = Encrypt.decrypt<string>(
|
|
31
|
+
* encrypted,
|
|
32
|
+
* { algorithm: 'aes-256-gcm', key: newKey },
|
|
33
|
+
* { algorithm: 'aes-256-gcm', key: oldKey },
|
|
34
|
+
* { onLegacyKeyUsed: () => console.warn('this value is still encrypted with the old key') }
|
|
35
|
+
* )
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @throws MissingEncryptionKey
|
|
39
|
+
* @throws DecryptionError
|
|
40
|
+
* @throws DecryptionParseError
|
|
41
|
+
* @throws DecryptionRotationError
|
|
42
|
+
*/
|
|
43
|
+
static decrypt<RetType>(encrypted: string, { algorithm, key }: DecryptOptions, legacyOpts?: DecryptOptions, { onLegacyKeyUsed }?: DecryptCallbacks): RetType | null;
|
|
44
|
+
/**
|
|
45
|
+
* Opens `encrypted` as {@link Encrypt.decrypt} does, with `currentOpts` and,
|
|
46
|
+
* when they do not open it, `legacyOpts`, and encrypts the value again with
|
|
47
|
+
* `currentOpts`, so that reading it no longer needs the legacy key. Use it
|
|
48
|
+
* during a key rotation for a value stored outside an `@deco.Encrypted`
|
|
49
|
+
* column, such as a cookie; `Model.reencryptEncryptedColumns()` does this
|
|
50
|
+
* for every value of a model's encrypted properties.
|
|
51
|
+
*
|
|
52
|
+
* ```ts
|
|
53
|
+
* const rewritten = Encrypt.reencrypt(
|
|
54
|
+
* storedValue,
|
|
55
|
+
* { algorithm: 'aes-256-gcm', key: newKey },
|
|
56
|
+
* { algorithm: 'aes-256-gcm', key: oldKey }
|
|
57
|
+
* )
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
22
60
|
* @throws MissingEncryptionKey
|
|
23
61
|
* @throws DecryptionError
|
|
24
62
|
* @throws DecryptionParseError
|
|
25
63
|
* @throws DecryptionRotationError
|
|
26
64
|
*/
|
|
27
|
-
static
|
|
65
|
+
static reencrypt(encrypted: string, currentOpts: EncryptOptions, legacyOpts?: DecryptOptions): string;
|
|
28
66
|
private static attemptDecryptionWithLegacyKeys;
|
|
29
67
|
/**
|
|
30
68
|
* Generates a base64-encoded random key suitable for the given algorithm.
|
|
@@ -42,11 +80,26 @@ export default class Encrypt {
|
|
|
42
80
|
* to decrypt via `legacy` fallback.
|
|
43
81
|
* 4. For cookies, wait at least the cookie `maxAge` so all in-flight
|
|
44
82
|
* 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
|
-
*
|
|
47
|
-
* `
|
|
83
|
+
* `@Encrypted` columns, re-encrypt every existing row under the new key
|
|
84
|
+
* by calling `reencryptEncryptedColumns()` on each model that has
|
|
85
|
+
* encrypted properties (`await User.reencryptEncryptedColumns()`), in
|
|
86
|
+
* each environment, from a console or a script rather than a migration.
|
|
87
|
+
* Run it only once every server in that environment runs with the new
|
|
88
|
+
* `current`: a server still on the old `current` keeps writing old-key
|
|
89
|
+
* values that its single pass over the table can miss. Writing old-key
|
|
90
|
+
* ciphertext straight into a backing column (`setAttribute`,
|
|
91
|
+
* `setAttributes` or `updateAttributes` given the backing column) after
|
|
92
|
+
* it has run also puts an old-key value back. For any other value
|
|
93
|
+
* encrypted with these keys, {@link Encrypt.reencrypt} rewrites it.
|
|
48
94
|
* 5. Drop `legacy` from config and deploy again.
|
|
49
95
|
*
|
|
96
|
+
* To see which values still need the old key while `legacy` is
|
|
97
|
+
* configured, register `dreamApp.on('encryption:legacy-key-used', ...)`,
|
|
98
|
+
* which fires each time reading an `@Encrypted` property needed `legacy`
|
|
99
|
+
* to open the value, or pass `onLegacyKeyUsed` to {@link Encrypt.decrypt}
|
|
100
|
+
* for values you decrypt yourself. A value nobody reads never fires
|
|
101
|
+
* either, so silence alone does not show that `legacy` is safe to drop.
|
|
102
|
+
*
|
|
50
103
|
* ## When to rotate
|
|
51
104
|
*
|
|
52
105
|
* - On a scheduled cadence (90–180 days is a reasonable policy default).
|
|
@@ -58,8 +111,15 @@ export default class Encrypt {
|
|
|
58
111
|
* - For cookies: at least the cookie `maxAge`, so in-flight sessions are
|
|
59
112
|
* not forced to re-authenticate.
|
|
60
113
|
* - For `@Encrypted` columns: until every existing row has been
|
|
61
|
-
* re-encrypted under the new key.
|
|
62
|
-
* `
|
|
114
|
+
* re-encrypted under the new key. Once `legacy` is dropped, reading the
|
|
115
|
+
* `@Encrypted` property of a row that is still under the old key throws
|
|
116
|
+
* `DecryptionError`, the same error a tampered or corrupted value
|
|
117
|
+
* throws, so the error class alone cannot show that `legacy` was
|
|
118
|
+
* dropped too early. `DecryptionRotationError` is thrown only while
|
|
119
|
+
* `legacy` is configured and neither key opens the value. Neither class
|
|
120
|
+
* extends the other, so code that catches `DecryptionRotationError`
|
|
121
|
+
* during a rotation must also catch `DecryptionError` to handle such a
|
|
122
|
+
* read once `legacy` is dropped.
|
|
63
123
|
*/
|
|
64
124
|
static generateKey(algorithm: EncryptAlgorithm): string;
|
|
65
125
|
static validateKey(base64EncodedKey: string, algorithm: EncryptAlgorithm): boolean;
|
|
@@ -68,6 +128,15 @@ export interface EncryptOptions extends BaseOptions {
|
|
|
68
128
|
}
|
|
69
129
|
export interface DecryptOptions extends BaseOptions {
|
|
70
130
|
}
|
|
131
|
+
export interface DecryptCallbacks {
|
|
132
|
+
/**
|
|
133
|
+
* Called with no arguments, synchronously, before a three-arg
|
|
134
|
+
* {@link Encrypt.decrypt} returns a value that the legacy key opened.
|
|
135
|
+
* Never called when the current key opens the value, when decryption
|
|
136
|
+
* throws, or in the two-arg form.
|
|
137
|
+
*/
|
|
138
|
+
onLegacyKeyUsed?: () => void;
|
|
139
|
+
}
|
|
71
140
|
interface BaseOptions {
|
|
72
141
|
algorithm: EncryptAlgorithm;
|
|
73
142
|
key: string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export default class UnrecognizedAssociationConditionKeys extends Error {
|
|
2
|
+
private associationName;
|
|
3
|
+
private unrecognizedKeys;
|
|
4
|
+
private acceptedKeys;
|
|
5
|
+
private methodName;
|
|
6
|
+
constructor(associationName: string, unrecognizedKeys: string[], acceptedKeys: readonly string[], methodName: string | null);
|
|
7
|
+
get message(): string;
|
|
8
|
+
}
|
|
@@ -18,12 +18,40 @@ export default class Env<T extends {
|
|
|
18
18
|
} | undefined, ReturnType extends OptionalConfig extends undefined ? number : OptionalConfig extends {
|
|
19
19
|
optional: boolean;
|
|
20
20
|
} ? OptionalConfig['optional'] extends true ? number | undefined : number : number>(env: IntegerEnvs, opts?: OptionalConfig): ReturnType;
|
|
21
|
+
/**
|
|
22
|
+
* Reads a boolean environment variable. Only the exact string `"1"` is
|
|
23
|
+
* true. Every other value is false, including `"true"`, `"TRUE"`, `"yes"`
|
|
24
|
+
* and `""`, and so is an unset variable.
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* // FEATURE_FLAG=1
|
|
28
|
+
* AppEnv.boolean('FEATURE_FLAG') // true
|
|
29
|
+
*
|
|
30
|
+
* // FEATURE_FLAG=true
|
|
31
|
+
* AppEnv.boolean('FEATURE_FLAG') // false
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @param env - the name of the environment variable
|
|
35
|
+
* @returns `true` when the variable is exactly `"1"`, otherwise `false`
|
|
36
|
+
*/
|
|
21
37
|
boolean(env: BooleanEnvs): boolean;
|
|
22
38
|
setString(env: StringEnvs, val: string | undefined): void;
|
|
23
39
|
unsetString(env: StringEnvs): void;
|
|
24
40
|
setInteger(env: IntegerEnvs, val: number | undefined): void;
|
|
25
41
|
unsetInteger(env: IntegerEnvs): void;
|
|
42
|
+
/**
|
|
43
|
+
* Sets a boolean environment variable to `"1"`, the only value
|
|
44
|
+
* {@link Env.boolean} reads as true.
|
|
45
|
+
*
|
|
46
|
+
* @param env - the name of the environment variable
|
|
47
|
+
*/
|
|
26
48
|
setBoolean(env: BooleanEnvs): void;
|
|
49
|
+
/**
|
|
50
|
+
* Deletes a boolean environment variable. {@link Env.boolean} reads an
|
|
51
|
+
* unset variable as false, since only the exact string `"1"` is true.
|
|
52
|
+
*
|
|
53
|
+
* @param env - the name of the environment variable
|
|
54
|
+
*/
|
|
27
55
|
unsetBoolean(env: BooleanEnvs): void;
|
|
28
56
|
protected required(variable: string): string;
|
|
29
57
|
protected optional(variable: string): string | undefined;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { openapiPrimitiveTypes, openapiShorthandPrimitiveTypes } from '../dream/constants.js';
|
|
2
|
-
export { type CommonOpenapiSchemaObjectFields, type OpenapiAllTypes, type OpenapiDescription, type OpenapiFormats, type OpenapiNumberFormats, type OpenapiPrimitiveBaseTypes, type OpenapiPrimitiveTypes, type OpenapiSchemaArray, type OpenapiSchemaArrayShorthand, type OpenapiSchemaBase, type OpenapiSchemaBody, type OpenapiSchemaBodyShorthand, type OpenapiSchemaCommonFields, type OpenapiSchemaExpressionAllOf, type OpenapiSchemaExpressionAnyOf, type OpenapiSchemaExpressionOneOf, type OpenapiSchemaExpressionRef, type OpenapiSchemaExpressionRefSchemaShorthand, type OpenapiSchemaInteger, type OpenapiSchemaNull, type OpenapiSchemaNumber, type OpenapiSchemaObject, type OpenapiSchemaObjectAllOf, type OpenapiSchemaObjectAllOfShorthand, type
|
|
2
|
+
export { type CommonOpenapiSchemaObjectFields, type OpenapiAllTypes, type OpenapiDescription, type OpenapiFormats, type OpenapiNumberFormats, type OpenapiPrimitiveBaseTypes, type OpenapiPrimitiveTypes, type OpenapiSchemaArray, type OpenapiSchemaArrayShorthand, type OpenapiSchemaBase, type OpenapiSchemaBody, type OpenapiSchemaBodyShorthand, type OpenapiSchemaCombinatorFields, type OpenapiSchemaCommonFields, type OpenapiSchemaExpressionAllOf, type OpenapiSchemaExpressionAnyOf, type OpenapiSchemaExpressionOneOf, type OpenapiSchemaExpressionRef, type OpenapiSchemaExpressionRefSchemaShorthand, type OpenapiSchemaInteger, type OpenapiSchemaNull, type OpenapiSchemaNumber, type OpenapiSchemaObject, type OpenapiSchemaObjectAllOf, type OpenapiSchemaObjectAllOfShorthand, type OpenapiSchemaObjectBase, type OpenapiSchemaObjectBaseShorthand, type OpenapiSchemaObjectShorthand, type OpenapiSchemaPrimitiveGeneric, type OpenapiSchemaProperties, type OpenapiSchemaPropertiesShorthand, type OpenapiSchemaShorthandExpressionAllOf, type OpenapiSchemaShorthandExpressionAnyOf, type OpenapiSchemaShorthandExpressionOneOf, type OpenapiSchemaShorthandExpressionSerializableRef, type OpenapiSchemaShorthandExpressionSerializerRef, type OpenapiSchemaShorthandPrimitiveGeneric, type OpenapiSchemaString, type OpenapiShorthandAllTypes, type OpenapiShorthandPrimitiveBaseTypes, type OpenapiShorthandPrimitiveTypes, type OpenapiTypeField, type OpenapiTypeFieldObject, } from '../types/openapi.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { type DecoratorContext } from '../decorators/DecoratorContextType.js';
|
|
2
|
-
export { type EncryptAlgorithm, type EncryptOptions } from '../encrypt/index.js';
|
|
2
|
+
export { type DecryptCallbacks, type EncryptAlgorithm, type EncryptOptions } from '../encrypt/index.js';
|
|
3
3
|
export { type RoundingPrecision } from '../helpers/round.js';
|
|
4
4
|
export { type Camelized, type Hyphenized, type Pascalized, type Snakeified } from '../helpers/stringCasing.js';
|
|
5
5
|
export { type SerializerRendererOpts } from '../serializer/SerializerRenderer.js';
|
|
@@ -14,5 +14,5 @@ export { type DurationObject, type DurationUnit, type WeekdayName } from '../typ
|
|
|
14
14
|
export { type DreamAssociationMetadata, type DreamAttributes, type DreamClassAssociationAndStatement, type DreamClassColumn, type DreamColumn, type DreamColumnNames, type DreamOrViewModelClassSerializerKey, type DreamOrViewModelSerializerKey, type DreamParamSafeAttributes, type DreamParamSafeColumnNames, type DreamSerializable, type DreamSerializableArray, type DreamSerializerKey, type DreamSerializers, type DreamVirtualColumns, type UpdateableAssociationProperties, type UpdateableProperties, type ViewModel, type ViewModelClass, } from '../types/dream.js';
|
|
15
15
|
export { type DreamModelSerializerType, type InternalAnyTypedSerializerRendersMany, type InternalAnyTypedSerializerRendersOne, type SerializerCasing, type SimpleObjectSerializerType, } from '../types/serializer.js';
|
|
16
16
|
export { type ValidationType } from '../types/validation.js';
|
|
17
|
-
export { type DreamAppInitOptions, type DreamAppOpts, type DreamLogger, type DreamLogLevel, type DreamDbConfig, } from '../dream-app/index.js';
|
|
17
|
+
export { type DreamAppInitOptions, type DreamAppOpts, type DreamLogger, type DreamLogLevel, type DreamDbConfig, type EncryptionLegacyKeyUsedEvent, } from '../dream-app/index.js';
|
|
18
18
|
export { type WhereStatementForDream, type WhereStatementForDreamClass, } from '../types/associations/shared.js';
|
|
@@ -10,5 +10,18 @@ export default class SerializerRenderer {
|
|
|
10
10
|
private renderOpts;
|
|
11
11
|
constructor(serializerBuilder: DreamSerializerBuilder<any, any> | ObjectSerializerBuilder<any, any> | null | undefined, passthroughData?: object, { casing }?: SerializerRendererOpts);
|
|
12
12
|
render(): Record<string, any> | null;
|
|
13
|
+
/**
|
|
14
|
+
* The keys a flattened `rendersOne` adds to the parent's payload when its associated object is
|
|
15
|
+
* null: each key any of `serializers` declares, set to `null`. There are several serializers when
|
|
16
|
+
* the association is a polymorphic BelongsTo, one for each target class, or when the associated
|
|
17
|
+
* class is an STI base, one for each child, and their keys are unioned.
|
|
18
|
+
*
|
|
19
|
+
* Each serializer is built with `undefined` data to read its declarations, as Psychic's OpenAPI
|
|
20
|
+
* generation and `preloadFor` build it, and nothing is rendered: no attribute callback runs and
|
|
21
|
+
* no association of the missing object is read. A flattened `rendersOne` it declares adds its
|
|
22
|
+
* own serializers' keys the same way. A flattened `customAttribute` adds none, since only its
|
|
23
|
+
* callback knows its keys.
|
|
24
|
+
*/
|
|
25
|
+
private nullFlattenedAttributes;
|
|
13
26
|
private setCase;
|
|
14
27
|
}
|