@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.
Files changed (302) hide show
  1. package/README.md +2 -2
  2. package/dist/cjs/src/Dream.js +260 -55
  3. package/dist/cjs/src/bin/index.js +13 -0
  4. package/dist/cjs/src/cli/index.js +28 -17
  5. package/dist/cjs/src/db/migration-helpers/DreamMigrationHelpers.js +23 -21
  6. package/dist/cjs/src/decorators/Decorators.js +26 -4
  7. package/dist/cjs/src/decorators/field/Encrypted.js +35 -6
  8. package/dist/cjs/src/dream/DreamClassTransactionBuilder.js +6 -6
  9. package/dist/cjs/src/dream/DreamInstanceTransactionBuilder.js +63 -27
  10. package/dist/cjs/src/dream/LeftJoinLoadBuilder.js +3 -3
  11. package/dist/cjs/src/dream/LoadBuilder.js +1 -1
  12. package/dist/cjs/src/dream/Query.js +542 -167
  13. package/dist/cjs/src/dream/QueryDriver/Base.js +72 -0
  14. package/dist/cjs/src/dream/QueryDriver/Kysely.js +216 -50
  15. package/dist/cjs/src/dream/internal/associations/assertRecognizedAssociationConditionKeys.js +48 -0
  16. package/dist/cjs/src/dream/internal/associations/associationQuery.js +4 -0
  17. package/dist/cjs/src/dream/internal/reload.js +6 -1
  18. package/dist/cjs/src/dream/internal/saveDream.js +8 -2
  19. package/dist/cjs/src/dream/internal/sqlResultToDreamInstance.js +2 -0
  20. package/dist/cjs/src/dream/internal/undestroyDream.js +1 -1
  21. package/dist/cjs/src/dream-app/index.js +38 -0
  22. package/dist/cjs/src/encrypt/InternalEncrypt.js +77 -4
  23. package/dist/cjs/src/encrypt/defaultEncryptedColumnName.js +10 -0
  24. package/dist/cjs/src/encrypt/index.js +76 -9
  25. package/dist/cjs/src/errors/DoNotSetEncryptedFieldsDirectly.js +4 -0
  26. package/dist/cjs/src/errors/associations/UnrecognizedAssociationConditionKeys.js +25 -0
  27. package/dist/cjs/src/helpers/Env.js +28 -0
  28. package/dist/cjs/src/helpers/cli/generateDreamContent.js +2 -1
  29. package/dist/cjs/src/helpers/cli/generateFactoryContent.js +1 -1
  30. package/dist/cjs/src/helpers/cli/generateMigrationContent.js +9 -9
  31. package/dist/cjs/src/helpers/cli/generateSerializerContent.js +21 -8
  32. package/dist/cjs/src/serializer/SerializerRenderer.js +65 -13
  33. package/dist/cjs/src/serializer/builders/DreamSerializerBuilder.js +54 -38
  34. package/dist/cjs/src/serializer/builders/ObjectSerializerBuilder.js +34 -14
  35. package/dist/cjs/src/serializer/helpers/serializersForAssociatedClass.js +43 -0
  36. package/dist/esm/src/Dream.js +260 -55
  37. package/dist/esm/src/bin/index.js +13 -0
  38. package/dist/esm/src/cli/index.js +28 -17
  39. package/dist/esm/src/db/migration-helpers/DreamMigrationHelpers.js +23 -21
  40. package/dist/esm/src/decorators/Decorators.js +26 -4
  41. package/dist/esm/src/decorators/field/Encrypted.js +35 -6
  42. package/dist/esm/src/dream/DreamClassTransactionBuilder.js +6 -6
  43. package/dist/esm/src/dream/DreamInstanceTransactionBuilder.js +63 -27
  44. package/dist/esm/src/dream/LeftJoinLoadBuilder.js +3 -3
  45. package/dist/esm/src/dream/LoadBuilder.js +1 -1
  46. package/dist/esm/src/dream/Query.js +542 -167
  47. package/dist/esm/src/dream/QueryDriver/Base.js +72 -0
  48. package/dist/esm/src/dream/QueryDriver/Kysely.js +216 -50
  49. package/dist/esm/src/dream/internal/associations/assertRecognizedAssociationConditionKeys.js +48 -0
  50. package/dist/esm/src/dream/internal/associations/associationQuery.js +4 -0
  51. package/dist/esm/src/dream/internal/reload.js +6 -1
  52. package/dist/esm/src/dream/internal/saveDream.js +8 -2
  53. package/dist/esm/src/dream/internal/sqlResultToDreamInstance.js +2 -0
  54. package/dist/esm/src/dream/internal/undestroyDream.js +1 -1
  55. package/dist/esm/src/dream-app/index.js +38 -0
  56. package/dist/esm/src/encrypt/InternalEncrypt.js +77 -4
  57. package/dist/esm/src/encrypt/defaultEncryptedColumnName.js +10 -0
  58. package/dist/esm/src/encrypt/index.js +76 -9
  59. package/dist/esm/src/errors/DoNotSetEncryptedFieldsDirectly.js +4 -0
  60. package/dist/esm/src/errors/associations/UnrecognizedAssociationConditionKeys.js +25 -0
  61. package/dist/esm/src/helpers/Env.js +28 -0
  62. package/dist/esm/src/helpers/cli/generateDreamContent.js +2 -1
  63. package/dist/esm/src/helpers/cli/generateFactoryContent.js +1 -1
  64. package/dist/esm/src/helpers/cli/generateMigrationContent.js +9 -9
  65. package/dist/esm/src/helpers/cli/generateSerializerContent.js +21 -8
  66. package/dist/esm/src/serializer/SerializerRenderer.js +65 -13
  67. package/dist/esm/src/serializer/builders/DreamSerializerBuilder.js +54 -38
  68. package/dist/esm/src/serializer/builders/ObjectSerializerBuilder.js +34 -14
  69. package/dist/esm/src/serializer/helpers/serializersForAssociatedClass.js +43 -0
  70. package/dist/types/src/Dream.d.ts +208 -42
  71. package/dist/types/src/bin/index.d.ts +7 -1
  72. package/dist/types/src/cli/index.d.ts +13 -0
  73. package/dist/types/src/db/migration-helpers/DreamMigrationHelpers.d.ts +2 -2
  74. package/dist/types/src/decorators/Decorators.d.ts +26 -3
  75. package/dist/types/src/decorators/field/Encrypted.d.ts +6 -1
  76. package/dist/types/src/dream/DreamClassTransactionBuilder.d.ts +9 -9
  77. package/dist/types/src/dream/DreamInstanceTransactionBuilder.d.ts +52 -25
  78. package/dist/types/src/dream/LeftJoinLoadBuilder.d.ts +4 -4
  79. package/dist/types/src/dream/LoadBuilder.d.ts +1 -1
  80. package/dist/types/src/dream/Query.d.ts +272 -33
  81. package/dist/types/src/dream/QueryDriver/Base.d.ts +63 -1
  82. package/dist/types/src/dream/QueryDriver/Kysely.d.ts +85 -1
  83. package/dist/types/src/dream/internal/associations/assertRecognizedAssociationConditionKeys.d.ts +29 -0
  84. package/dist/types/src/dream-app/index.d.ts +56 -2
  85. package/dist/types/src/encrypt/InternalEncrypt.d.ts +29 -1
  86. package/dist/types/src/encrypt/defaultEncryptedColumnName.d.ts +7 -0
  87. package/dist/types/src/encrypt/index.d.ts +75 -6
  88. package/dist/types/src/errors/associations/UnrecognizedAssociationConditionKeys.d.ts +8 -0
  89. package/dist/types/src/helpers/Env.d.ts +28 -0
  90. package/dist/types/src/package-exports/openapi.d.ts +1 -1
  91. package/dist/types/src/package-exports/types.d.ts +2 -2
  92. package/dist/types/src/serializer/SerializerRenderer.d.ts +13 -0
  93. package/dist/types/src/serializer/builders/DreamSerializerBuilder.d.ts +59 -55
  94. package/dist/types/src/serializer/builders/ObjectSerializerBuilder.d.ts +40 -19
  95. package/dist/types/src/serializer/helpers/serializersForAssociatedClass.d.ts +17 -0
  96. package/dist/types/src/types/lifecycle.d.ts +6 -0
  97. package/dist/types/src/types/openapi.d.ts +52 -29
  98. package/dist/types/src/types/serializer.d.ts +43 -2
  99. package/dist/types/src/types/types/lifecycle.ts +6 -0
  100. package/dist/types/src/types/types/openapi.ts +51 -37
  101. package/dist/types/src/types/types/serializer.ts +62 -2
  102. package/dist/types/src/types/types/variadic.ts +99 -43
  103. package/dist/types/src/types/variadic.d.ts +29 -3
  104. package/docs/assets/hierarchy.js +1 -1
  105. package/docs/assets/highlight.css +4 -11
  106. package/docs/assets/navigation.js +1 -1
  107. package/docs/assets/search.js +1 -1
  108. package/docs/classes/db.DreamMigrationHelpers.html +13 -13
  109. package/docs/classes/db.KyselyQueryDriver.html +85 -46
  110. package/docs/classes/db.PostgresQueryDriver.html +86 -47
  111. package/docs/classes/db.QueryDriverBase.html +84 -45
  112. package/docs/classes/errors.CannotSaveMissingDream.html +2 -2
  113. package/docs/classes/errors.CheckConstraintViolation.html +3 -3
  114. package/docs/classes/errors.ColumnOverflow.html +3 -3
  115. package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
  116. package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +3 -3
  117. package/docs/classes/errors.DataTypeColumnTypeMismatch.html +3 -3
  118. package/docs/classes/errors.DecryptionError.html +2 -2
  119. package/docs/classes/errors.DecryptionParseError.html +2 -2
  120. package/docs/classes/errors.DecryptionRotationError.html +3 -3
  121. package/docs/classes/errors.GlobalNameNotSet.html +3 -3
  122. package/docs/classes/errors.InvalidCalendarDate.html +2 -2
  123. package/docs/classes/errors.InvalidClockTime.html +2 -2
  124. package/docs/classes/errors.InvalidClockTimeTz.html +2 -2
  125. package/docs/classes/errors.InvalidDateTime.html +2 -2
  126. package/docs/classes/errors.MissingSerializersDefinition.html +3 -3
  127. package/docs/classes/errors.NonLoadedAssociation.html +3 -3
  128. package/docs/classes/errors.NotNullViolation.html +3 -3
  129. package/docs/classes/errors.RecordNotFound.html +3 -3
  130. package/docs/classes/errors.SortableScopeDidNotStabilize.html +3 -3
  131. package/docs/classes/errors.SortableScopeLockWaitTimedOut.html +3 -3
  132. package/docs/classes/errors.ValidationError.html +3 -3
  133. package/docs/classes/index.CalendarDate.html +33 -33
  134. package/docs/classes/index.ClockTime.html +32 -32
  135. package/docs/classes/index.ClockTimeTz.html +35 -35
  136. package/docs/classes/index.DateTime.html +86 -86
  137. package/docs/classes/index.Decorators.html +37 -23
  138. package/docs/classes/index.Dream.html +270 -142
  139. package/docs/classes/index.DreamApp.html +40 -10
  140. package/docs/classes/index.DreamTransaction.html +3 -3
  141. package/docs/classes/index.Env.html +16 -2
  142. package/docs/classes/index.Query.html +331 -129
  143. package/docs/classes/system.CliFileWriter.html +4 -4
  144. package/docs/classes/system.DreamBin.html +6 -2
  145. package/docs/classes/system.DreamCLI.html +7 -7
  146. package/docs/classes/system.DreamImporter.html +2 -2
  147. package/docs/classes/system.DreamLogos.html +2 -2
  148. package/docs/classes/system.DreamSerializerBuilder.html +52 -34
  149. package/docs/classes/system.ObjectSerializerBuilder.html +41 -22
  150. package/docs/classes/system.PathHelpers.html +4 -4
  151. package/docs/classes/utils.Encrypt.html +54 -10
  152. package/docs/classes/utils.Range.html +2 -2
  153. package/docs/functions/db.closeAllDbConnections.html +1 -1
  154. package/docs/functions/db.dreamDbConnections.html +1 -1
  155. package/docs/functions/db.untypedDb.html +1 -1
  156. package/docs/functions/db.validateColumn.html +1 -1
  157. package/docs/functions/db.validateTable.html +1 -1
  158. package/docs/functions/errors.pgErrorType.html +1 -1
  159. package/docs/functions/index.DreamSerializer.html +1 -1
  160. package/docs/functions/index.ObjectSerializer.html +1 -1
  161. package/docs/functions/index.ReplicaSafe.html +1 -1
  162. package/docs/functions/index.STI.html +1 -1
  163. package/docs/functions/index.SoftDelete.html +1 -1
  164. package/docs/functions/utils.camelize.html +1 -1
  165. package/docs/functions/utils.capitalize.html +1 -1
  166. package/docs/functions/utils.cloneDeepSafe.html +1 -1
  167. package/docs/functions/utils.compact.html +1 -1
  168. package/docs/functions/utils.groupBy.html +1 -1
  169. package/docs/functions/utils.hyphenize.html +1 -1
  170. package/docs/functions/utils.intersection.html +1 -1
  171. package/docs/functions/utils.isEmpty.html +1 -1
  172. package/docs/functions/utils.normalizeUnicode.html +1 -1
  173. package/docs/functions/utils.pascalize.html +1 -1
  174. package/docs/functions/utils.percent.html +1 -1
  175. package/docs/functions/utils.range.html +1 -1
  176. package/docs/functions/utils.round.html +1 -1
  177. package/docs/functions/utils.sanitizeString.html +1 -1
  178. package/docs/functions/utils.snakeify.html +1 -1
  179. package/docs/functions/utils.sort.html +1 -1
  180. package/docs/functions/utils.sortBy.html +1 -1
  181. package/docs/functions/utils.sortObjectByKey.html +1 -1
  182. package/docs/functions/utils.sortObjectByValue.html +1 -1
  183. package/docs/functions/utils.uncapitalize.html +1 -1
  184. package/docs/functions/utils.uniq.html +1 -1
  185. package/docs/hierarchy.html +1 -1
  186. package/docs/index.html +1 -1
  187. package/docs/interfaces/openapi.OpenapiDescription.html +2 -2
  188. package/docs/interfaces/openapi.OpenapiSchemaProperties.html +1 -1
  189. package/docs/interfaces/openapi.OpenapiSchemaPropertiesShorthand.html +1 -1
  190. package/docs/interfaces/openapi.OpenapiTypeFieldObject.html +1 -1
  191. package/docs/interfaces/types.BelongsToStatement.html +2 -2
  192. package/docs/interfaces/types.DecoratorContext.html +2 -2
  193. package/docs/interfaces/types.DecryptCallbacks.html +6 -0
  194. package/docs/interfaces/types.DreamAppInitOptions.html +2 -2
  195. package/docs/interfaces/types.DreamAppOpts.html +2 -2
  196. package/docs/interfaces/types.DreamDbConfig.html +6 -6
  197. package/docs/interfaces/types.DurationObject.html +2 -2
  198. package/docs/interfaces/types.EncryptOptions.html +2 -2
  199. package/docs/interfaces/types.EncryptionLegacyKeyUsedEvent.html +10 -0
  200. package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
  201. package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
  202. package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
  203. package/docs/modules/openapi.html +1 -1
  204. package/docs/modules/types.html +1 -1
  205. package/docs/types/openapi.CommonOpenapiSchemaObjectFields.html +1 -1
  206. package/docs/types/openapi.OpenapiAllTypes.html +1 -1
  207. package/docs/types/openapi.OpenapiFormats.html +1 -1
  208. package/docs/types/openapi.OpenapiNumberFormats.html +1 -1
  209. package/docs/types/openapi.OpenapiPrimitiveBaseTypes.html +1 -1
  210. package/docs/types/openapi.OpenapiPrimitiveTypes.html +1 -1
  211. package/docs/types/openapi.OpenapiSchemaArray.html +1 -1
  212. package/docs/types/openapi.OpenapiSchemaArrayShorthand.html +1 -1
  213. package/docs/types/openapi.OpenapiSchemaBase.html +1 -1
  214. package/docs/types/openapi.OpenapiSchemaBody.html +1 -1
  215. package/docs/types/openapi.OpenapiSchemaBodyShorthand.html +1 -1
  216. package/docs/types/openapi.OpenapiSchemaCombinatorFields.html +4 -0
  217. package/docs/types/openapi.OpenapiSchemaCommonFields.html +5 -1
  218. package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +1 -2
  219. package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +1 -2
  220. package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +1 -2
  221. package/docs/types/openapi.OpenapiSchemaExpressionRef.html +2 -2
  222. package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +2 -2
  223. package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
  224. package/docs/types/openapi.OpenapiSchemaNull.html +4 -2
  225. package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
  226. package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
  227. package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +5 -1
  228. package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +2 -1
  229. package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
  230. package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
  231. package/docs/types/openapi.OpenapiSchemaObjectShorthand.html +1 -1
  232. package/docs/types/openapi.OpenapiSchemaPrimitiveGeneric.html +1 -1
  233. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAllOf.html +1 -2
  234. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +1 -2
  235. package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +1 -2
  236. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +2 -2
  237. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +2 -2
  238. package/docs/types/openapi.OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
  239. package/docs/types/openapi.OpenapiSchemaString.html +1 -1
  240. package/docs/types/openapi.OpenapiShorthandAllTypes.html +1 -1
  241. package/docs/types/openapi.OpenapiShorthandPrimitiveBaseTypes.html +1 -1
  242. package/docs/types/openapi.OpenapiShorthandPrimitiveTypes.html +1 -1
  243. package/docs/types/openapi.OpenapiTypeField.html +1 -1
  244. package/docs/types/system.DreamAppAllowedPackageManagersEnum.html +1 -1
  245. package/docs/types/types.CalendarDateDurationUnit.html +1 -1
  246. package/docs/types/types.CalendarDateObject.html +1 -1
  247. package/docs/types/types.Camelized.html +1 -1
  248. package/docs/types/types.ClockTimeObject.html +1 -1
  249. package/docs/types/types.DbConnectionType.html +1 -1
  250. package/docs/types/types.DbTypes.html +1 -1
  251. package/docs/types/types.DreamAssociationMetadata.html +1 -1
  252. package/docs/types/types.DreamAttributes.html +1 -1
  253. package/docs/types/types.DreamClassAssociationAndStatement.html +1 -1
  254. package/docs/types/types.DreamClassColumn.html +1 -1
  255. package/docs/types/types.DreamColumn.html +1 -1
  256. package/docs/types/types.DreamColumnNames.html +1 -1
  257. package/docs/types/types.DreamLogLevel.html +1 -1
  258. package/docs/types/types.DreamLogger.html +2 -2
  259. package/docs/types/types.DreamModelSerializerType.html +1 -1
  260. package/docs/types/types.DreamOrViewModelClassSerializerKey.html +1 -1
  261. package/docs/types/types.DreamOrViewModelSerializerKey.html +1 -1
  262. package/docs/types/types.DreamParamSafeAttributes.html +1 -1
  263. package/docs/types/types.DreamParamSafeColumnNames.html +1 -1
  264. package/docs/types/types.DreamSerializable.html +1 -1
  265. package/docs/types/types.DreamSerializableArray.html +1 -1
  266. package/docs/types/types.DreamSerializerKey.html +1 -1
  267. package/docs/types/types.DreamSerializers.html +1 -1
  268. package/docs/types/types.DreamVirtualColumns.html +1 -1
  269. package/docs/types/types.DurationUnit.html +1 -1
  270. package/docs/types/types.EncryptAlgorithm.html +1 -1
  271. package/docs/types/types.HasManyStatement.html +1 -1
  272. package/docs/types/types.HasOneStatement.html +1 -1
  273. package/docs/types/types.Hyphenized.html +1 -1
  274. package/docs/types/types.Pascalized.html +1 -1
  275. package/docs/types/types.PrimaryKeyType.html +1 -1
  276. package/docs/types/types.RoundingPrecision.html +1 -1
  277. package/docs/types/types.SerializerCasing.html +1 -1
  278. package/docs/types/types.SimpleObjectSerializerType.html +1 -1
  279. package/docs/types/types.Snakeified.html +1 -1
  280. package/docs/types/types.StrictInterface.html +1 -1
  281. package/docs/types/types.UpdateableAssociationProperties.html +1 -1
  282. package/docs/types/types.UpdateableProperties.html +1 -1
  283. package/docs/types/types.ValidationType.html +1 -1
  284. package/docs/types/types.ViewModel.html +2 -2
  285. package/docs/types/types.ViewModelClass.html +1 -1
  286. package/docs/types/types.WeekdayName.html +1 -1
  287. package/docs/types/types.WhereStatementForDream.html +1 -1
  288. package/docs/types/types.WhereStatementForDreamClass.html +1 -1
  289. package/docs/variables/index.DreamConst.html +1 -1
  290. package/docs/variables/index.ops.html +1 -1
  291. package/docs/variables/openapi.openapiPrimitiveTypes.html +1 -1
  292. package/docs/variables/openapi.openapiShorthandPrimitiveTypes.html +1 -1
  293. package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
  294. package/docs/variables/system.primaryKeyTypes.html +1 -1
  295. package/package.json +1 -1
  296. package/dist/cjs/src/serializer/helpers/serializerForAssociatedClass.js +0 -37
  297. package/dist/esm/src/serializer/helpers/serializerForAssociatedClass.js +0 -37
  298. package/dist/types/src/serializer/helpers/serializerForAssociatedClass.d.ts +0 -9
  299. package/docs/types/openapi.OpenapiSchemaObjectAnyOf.html +0 -1
  300. package/docs/types/openapi.OpenapiSchemaObjectAnyOfShorthand.html +0 -1
  301. package/docs/types/openapi.OpenapiSchemaObjectOneOf.html +0 -1
  302. package/docs/types/openapi.OpenapiSchemaObjectOneOfShorthand.html +0 -1
@@ -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', { visibilty: 'public' }, 'replies').first()
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 where clauses
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', { visibilty: 'public' }, 'replies').first()
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 where clauses
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 where clauses
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 where clauses
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 where clauses
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 where clauses
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;
@@ -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,41 @@ 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
+ * writes (freshly encrypted, or the ciphertext as loaded or last saved,
2361
+ * which it keeps when that already holds the assigned plaintext). Every
2362
+ * caller-supplied value goes through setAttribute.
2363
+ */
2364
+ private setAttributeUnchecked;
2285
2365
  /**
2286
2366
  * Returns the value for a columnName provided,
2287
2367
  * bypassing the getters.
@@ -2336,43 +2416,55 @@ export default class Dream {
2336
2416
  * changed since last persisting, along with their current
2337
2417
  * and previously persisted values.
2338
2418
  *
2419
+ * For a column with an unsaved change, `was` is its value
2420
+ * as of the most recent save. For every other column, `was`
2421
+ * is its value from before that save, so the changes the
2422
+ * save made keep appearing, beside any later unsaved change,
2423
+ * until the next save.
2424
+ *
2425
+ * On a create, that earlier value is `undefined` for every
2426
+ * column of an instance from `new` or `create`, assigned or
2427
+ * not, and the copied value for an instance from
2428
+ * {@link Dream.dup | dup}. So after a create from `new` or
2429
+ * `create`, every column the insert returned counts as
2430
+ * changed: the primary key, timestamps, database defaults,
2431
+ * and `null` for each nullable column nobody assigned. After
2432
+ * a create from `dup`, the columns `dup` cleared (the primary
2433
+ * key, timestamps and sortable positions) count, and a copied
2434
+ * column counts only if the insert returned a different value.
2435
+ *
2339
2436
  * ```ts
2340
2437
  * const pet = Pet.new({ species: 'dog' })
2341
2438
  * pet.changes()
2342
2439
  * // {
2343
- * // species: {
2344
- * // was: undefined,
2345
- * // now: 'dog',
2346
- * // }
2440
+ * // species: { was: undefined, now: 'dog' },
2347
2441
  * // }
2348
2442
  *
2349
2443
  * await pet.save()
2350
2444
  * pet.changes()
2351
2445
  * // {
2352
- * // species: {
2353
- * // was: undefined,
2354
- * // now: 'dog',
2355
- * // }
2446
+ * // id: { was: undefined, now: 1 },
2447
+ * // species: { was: undefined, now: 'dog' },
2448
+ * // name: { was: undefined, now: null },
2449
+ * // ...every other column the insert returned
2356
2450
  * // }
2357
2451
  *
2358
2452
  * pet.species = 'cat'
2359
2453
  * pet.species = 'frog'
2360
2454
  * pet.changes()
2361
2455
  * // {
2362
- * // species: {
2363
- * // was: 'dog',
2364
- * // now: 'frog',
2365
- * // }
2456
+ * // id: { was: undefined, now: 1 },
2457
+ * // species: { was: 'dog', now: 'frog' },
2458
+ * // name: { was: undefined, now: null },
2459
+ * // ...every other change the create made
2366
2460
  * // }
2367
2461
  *
2368
2462
  * await pet.save()
2369
2463
  * pet.changes()
2370
2464
  * // {
2371
- * // species: {
2372
- * // was: 'dog',
2373
- * // now: 'frog',
2374
- * // }
2465
+ * // species: { was: 'dog', now: 'frog' },
2375
2466
  * // }
2467
+ * // (and `updatedAt`, on a model with that column)
2376
2468
  * ```
2377
2469
  *
2378
2470
  * @returns An object containing changed attributes
@@ -2382,8 +2474,22 @@ export default class Dream {
2382
2474
  now: Selectable<Table>[DreamColumnNames<I>];
2383
2475
  }>>>(this: I): RetType;
2384
2476
  /**
2385
- * Returns the value most recently persisted
2386
- * to the database.
2477
+ * Returns the value the column held before the most
2478
+ * recent save. For a column with an unsaved change, it
2479
+ * returns the column's value as of that save instead.
2480
+ *
2481
+ * On a create, the value before the save is `undefined`
2482
+ * for every column of an instance from `new` or `create`,
2483
+ * assigned or not, and the copied value for an instance
2484
+ * from {@link Dream.dup | dup} (`undefined` for the
2485
+ * columns `dup` cleared). So after a create from `new` or
2486
+ * `create`, this returns `undefined` for every column
2487
+ * without an unsaved change, not the value the insert
2488
+ * wrote. After an update, it returns the column's value
2489
+ * from before that update, which for a column the update
2490
+ * did not change is its current value. On a record loaded
2491
+ * from the database and not saved since, it returns the
2492
+ * loaded value.
2387
2493
  *
2388
2494
  * ```ts
2389
2495
  * const pet = Pet.new({ species: 'cat' })
@@ -2414,7 +2520,38 @@ export default class Dream {
2414
2520
  /**
2415
2521
  * Returns true if the columnName provided has
2416
2522
  * changes that were persisted during the most
2417
- * recent save.
2523
+ * recent save. An unsaved change does not count,
2524
+ * and an unsaved edit made after that save does
2525
+ * not undo a change the save made. On a record
2526
+ * that has not been persisted, this returns false.
2527
+ *
2528
+ * A create compares the value the insert returned
2529
+ * with `undefined` for every column of an instance
2530
+ * from `new` or `create`, assigned or not, and with
2531
+ * the copied value for an instance from
2532
+ * {@link Dream.dup | dup}. So after a create from
2533
+ * `new` or `create`, this returns true for every
2534
+ * column the insert returned: the primary key,
2535
+ * timestamps, database defaults, and a nullable
2536
+ * column nobody assigned, which comes back `null`.
2537
+ * To react only to the columns a create assigned,
2538
+ * use the `ifChanged` option of an after hook.
2539
+ *
2540
+ * ```ts
2541
+ * const pet = await Pet.create({ species: 'cat' })
2542
+ * pet.savedChangeToAttribute('species')
2543
+ * // true
2544
+ * pet.savedChangeToAttribute('name')
2545
+ * // true (unassigned, so the insert returned null)
2546
+ *
2547
+ * await pet.update({ name: 'Snoopy' })
2548
+ * pet.savedChangeToAttribute('species')
2549
+ * // false
2550
+ *
2551
+ * pet.species = 'dog'
2552
+ * pet.savedChangeToAttribute('species')
2553
+ * // false (not saved yet)
2554
+ * ```
2418
2555
  *
2419
2556
  * @param columnName - the column name to check
2420
2557
  * @returns A boolean
@@ -2642,19 +2779,19 @@ export default class Dream {
2642
2779
  * if the association is not already loaded.
2643
2780
  *
2644
2781
  * ```ts
2645
- * const user = await user
2646
- * .load('posts', { body: ops.ilike('%hello world%') }, 'comments', 'replies')
2782
+ * const loadedUser = await user
2783
+ * .load('posts', { and: { body: ops.ilike('%hello world%') } }, 'comments', 'replies')
2647
2784
  * .load('images')
2648
2785
  * .execute()
2649
2786
  *
2650
- * user.posts[0].comments[0].replies[0]
2787
+ * loadedUser.posts[0].comments[0].replies[0]
2651
2788
  * // Reply{}
2652
2789
  *
2653
- * user.images[0]
2790
+ * loadedUser.images[0]
2654
2791
  * // Image{}
2655
2792
  * ```
2656
2793
  *
2657
- * @param args - A list of associations (and optional where clauses) to load
2794
+ * @param args - A chain of association names and and/andNot/andAny clauses
2658
2795
  * @returns A chainable LoadBuilder instance. Call `.execute()` to get the cloned model with associations loaded.
2659
2796
  */
2660
2797
  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>;
@@ -2855,19 +2992,19 @@ export default class Dream {
2855
2992
  * 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
2856
2993
  *
2857
2994
  * ```ts
2858
- * const user = await user
2859
- * .leftJoinLoad('posts', { body: ops.ilike('%hello world%') }, 'comments', 'replies')
2995
+ * const loadedUser = await user
2996
+ * .leftJoinLoad('posts', { and: { body: ops.ilike('%hello world%') } }, 'comments', 'replies')
2860
2997
  * .leftJoinLoad('images')
2861
2998
  * .execute()
2862
2999
  *
2863
- * user.posts[0].comments[0].replies[0]
3000
+ * loadedUser.posts[0].comments[0].replies[0]
2864
3001
  * // Reply{}
2865
3002
  *
2866
- * user.images[0]
3003
+ * loadedUser.images[0]
2867
3004
  * // Image{}
2868
3005
  * ```
2869
3006
  *
2870
- * @param args - A list of associations (and optional where clauses) to load
3007
+ * @param args - A chain of association names and and/andNot/andAny clauses
2871
3008
  * @returns A chainable LeftJoinLoadBuilder instance. Call `.execute()` to get the cloned model with associations loaded.
2872
3009
  */
2873
3010
  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>;
@@ -2929,6 +3066,13 @@ export default class Dream {
2929
3066
  * Takes the attributes passed in and sets their values internally,
2930
3067
  * bypassing any custom setters defined for these attributes.
2931
3068
  *
3069
+ * An encrypted property (e.g. `secret`) is still encrypted. Its
3070
+ * `@Encrypted` backing column (e.g. `encryptedSecret`) accepts only
3071
+ * ciphertext that decrypts with this app's column encryption keys, or
3072
+ * `null`; anything else throws (see {@link Dream.setAttribute | setAttribute}).
3073
+ * Attributes are set in order, so those before the rejected one have
3074
+ * already been set when it throws.
3075
+ *
2932
3076
  * NOTE:
2933
3077
  * To leverage custom-defined setters, use `#assignAttributes` instead.
2934
3078
  *
@@ -2959,6 +3103,10 @@ export default class Dream {
2959
3103
  * Upon updating an instance, the update timestamp (if defined)
2960
3104
  * will be updated on the model.
2961
3105
  *
3106
+ * A column whose value is `undefined` is skipped, not written: a new
3107
+ * record gets the column's database default, and a persisted record
3108
+ * keeps the value stored for it. Set a column to `null` to clear it.
3109
+ *
2962
3110
  * ```ts
2963
3111
  * const user = User.new({ email: 'how@yadoin' })
2964
3112
  * user.name = 'fred'
@@ -3004,6 +3152,12 @@ export default class Dream {
3004
3152
  * See {@link Dream.save | save} for details on
3005
3153
  * the side effects of saving.
3006
3154
  *
3155
+ * A column whose value is still `undefined` after setters run is
3156
+ * skipped, not written (see {@link Dream.save | save}), with two
3157
+ * `@Encrypted` exceptions: `undefined` for an encrypted property (e.g.
3158
+ * `secret`) is encrypted to `null`, so it clears the column, and
3159
+ * `undefined` for its backing column (e.g. `encryptedSecret`) throws.
3160
+ *
3007
3161
  * NOTE:
3008
3162
  * To bypass custom-defined setters, use {@link Dream.updateAttributes | updateAttributes} instead.
3009
3163
  *
@@ -3027,6 +3181,18 @@ export default class Dream {
3027
3181
  * See {@link Dream.save | save} for details on
3028
3182
  * the side effects of saving.
3029
3183
  *
3184
+ * An encrypted property (e.g. `secret`) is still encrypted. Its
3185
+ * `@Encrypted` backing column (e.g. `encryptedSecret`) accepts only
3186
+ * ciphertext that decrypts with this app's column encryption keys, or
3187
+ * `null`; anything else throws before anything is saved (see
3188
+ * {@link Dream.setAttribute | setAttribute}).
3189
+ *
3190
+ * A column whose value is still `undefined` after setters run is
3191
+ * skipped, not written (see {@link Dream.save | save}), with two
3192
+ * `@Encrypted` exceptions: `undefined` for an encrypted property (e.g.
3193
+ * `secret`) is encrypted to `null`, so it clears the column, and
3194
+ * `undefined` for its backing column (e.g. `encryptedSecret`) throws.
3195
+ *
3030
3196
  * NOTE:
3031
3197
  * To update the values without bypassing any custom-defined
3032
3198
  * 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
- connectionName: string;
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;
@@ -16,7 +16,20 @@ export type SpawnOptions = Omit<NodeSpawnOptions, 'shell'> & {
16
16
  };
17
17
  export declare const CLI_INDENT = " ";
18
18
  export declare const baseColumnsWithTypesDescription = "space separated snake-case properties like this:\n title:citext subtitle:string body_markdown:text style:enum:post_styles:formal,informal\n \n all properties default to not nullable; null can be allowed by appending ':optional':\n subtitle:string:optional\n \n supported types:\n - uuid:\n - uuid[]:\n a column optimized for storing UUIDs\n \n - citext:\n - citext[]:\n case insensitive text (indexes and queries are automatically case insensitive)\n \n - encrypted:\n encrypted text (used in conjunction with the @deco.Encrypted decorator)\n \n - string:\n - string[]:\n varchar; allowed length defaults to 255, but may be customized, e.g.: subtitle:string:128 or subtitle:string:128:optional\n \n - text\n - text[]\n - date\n - date[]\n - datetime\n - datetime[]\n - time\n - time[]\n - timetz\n - timetz[]\n - integer\n - integer[]\n - boolean\n - boolean[]\n \n - decimal:\n - decimal[]:\n precision,scale is required, e.g.: volume:decimal:3,2 or volume:decimal:3,2:optional\n \n leveraging arrays, add the \"[]\" suffix, e.g.: volume:decimal[]:3,2\n \n - enum:\n - enum[]:\n include the enum name to automatically create the enum:\n type:enum:room_types:bathroom,kitchen,bedroom or type:enum:room_types:bathroom,kitchen,bedroom:optional\n \n omit the enum values to leverage an existing enum (omits the enum type creation):\n type:enum:room_types or type:enum:room_types:optional\n \n leveraging arrays, add the \"[]\" suffix, e.g.: type:enum[]:room_types:bathroom,kitchen,bedroom";
19
+ /**
20
+ * The `[columnsWithTypes...]` argument description for `g:model`. Exported so
21
+ * that spec/unit/cli/generateMigrationContent.spec.ts can run each
22
+ * `:belongs_to` example in this text through the migration generator and check
23
+ * the FK column the example's comment names: an example that drifts from what
24
+ * the generator actually produces then fails the suite instead of shipping.
25
+ */
26
+ export declare const columnsWithTypesDescription: string;
19
27
  export declare const columnsWithTypesDescriptionForStiChild: string;
28
+ /**
29
+ * The `[columnsWithTypes...]` argument description for `g:migration`. Exported
30
+ * for the same `:belongs_to` example check as `columnsWithTypesDescription`.
31
+ */
32
+ export declare const columnsWithTypesDescriptionForMigration: string;
20
33
  /**
21
34
  * The `<migrationName>` argument description for `g:migration`. Exported so
22
35
  * that spec/unit/helpers/cli/generateMigration.spec.ts can read the example
@@ -183,7 +183,7 @@ export default class DreamMigrationHelpers {
183
183
  * @param options - Configuration options
184
184
  * @param options.table - The name of the table
185
185
  * @param options.column - The current (plaintext) column name
186
- * @param options.encryptedColumnName - The target encrypted column name. Defaults to `encrypted_<column>`, matching the `@Encrypted` decorator's default; pass this when the decorator was given a custom encrypted column name.
186
+ * @param options.encryptedColumnName - The target encrypted column name. Defaults to the column the `@Encrypted` decorator reads for a property named after `column` (`encrypted_phone` for `phone`); pass this when the decorator was given a custom encrypted column name.
187
187
  * @param options.primaryKey - The primary key column used to keyset-paginate and target each row's update. Defaults to `id`.
188
188
  * @param options.batchSize - How many rows to read per batch. Defaults to `1000`.
189
189
  */
@@ -215,7 +215,7 @@ export default class DreamMigrationHelpers {
215
215
  * @param options - Configuration options
216
216
  * @param options.table - The name of the table
217
217
  * @param options.column - The target (plaintext) column name to rename back to
218
- * @param options.encryptedColumnName - The current encrypted column name. Defaults to `encrypted_<column>`.
218
+ * @param options.encryptedColumnName - The current encrypted column name. Defaults to the column the `@Encrypted` decorator reads for a property named after `column` (`encrypted_phone` for `phone`).
219
219
  * @param options.primaryKey - The primary key column used to keyset-paginate and target each row's update. Defaults to `id`.
220
220
  * @param options.batchSize - How many rows to read per batch. Defaults to `1000`.
221
221
  * @param options.columnType - When provided, the restored column is converted to this type. When omitted, the column is left as `text`.
@@ -6,6 +6,7 @@ import { DreamColumnNames, GlobalModelNameTableMap, SortableOptions } from '../t
6
6
  import { AfterHookOpts, BeforeHookOpts } from '../types/lifecycle.js';
7
7
  import { OpenapiSchemaBodyShorthand, OpenapiShorthandPrimitiveTypes } from '../types/openapi.js';
8
8
  import { ValidationType } from '../types/validation.js';
9
+ import { EncryptedOptions } from './field/Encrypted.js';
9
10
  export default class Decorators<TD extends typeof Dream, T extends Dream = InstanceType<TD>> {
10
11
  BelongsTo<const AssociationGlobalNameOrNames extends keyof GlobalModelNameTableMap<T> | (keyof GlobalModelNameTableMap<T>)[]>(this: Decorators<TD>, globalAssociationNameOrNames: AssociationGlobalNameOrNames, options?: NonPolymorphicBelongsToOptions<T, AssociationGlobalNameOrNames>): any;
11
12
  BelongsTo<const AssociationGlobalNameOrNames extends keyof GlobalModelNameTableMap<T> | (keyof GlobalModelNameTableMap<T>)[]>(this: Decorators<TD>, globalAssociationNameOrNames: AssociationGlobalNameOrNames, options?: PolymorphicBelongsToOptions<T, AssociationGlobalNameOrNames>): any;
@@ -29,15 +30,37 @@ export default class Decorators<TD extends typeof Dream, T extends Dream = Insta
29
30
  *
30
31
  * // automatically sets `myEncryptedPhone` to the encrypted value that
31
32
  * // `phone` is set to new/create/update, e.g., `await user.update({ phone })`
32
- * @deco.Encrypted('myEncryptedPhone)
33
+ * @deco.Encrypted('myEncryptedPhone')
33
34
  * public phone: string
35
+ *
36
+ * // automatically sets `myEncryptedMfaSettings` to the encrypted value that
37
+ * // `mfaSettings` is set to in new/create/update, and declares the
38
+ * // value's OpenAPI shape, since it is not a string
39
+ * @deco.Encrypted({
40
+ * column: 'myEncryptedMfaSettings',
41
+ * openapi: { type: ['object', 'null'], properties: { token: 'string' } },
42
+ * })
43
+ * public mfaSettings: { token: string } | null
34
44
  * }
35
45
  * ```
36
46
  *
37
- * @param column — if omitted, then 'encrypted' is prepended to the Pascal cased version of the decorated field
47
+ * The decorated property may hold any JSON-serializable value. Its OpenAPI
48
+ * shape is what Psychic uses to cast the property in params and to render
49
+ * it in request body and serializer OpenAPI. Without an `openapi` option,
50
+ * that shape is `'string'`, or `['string', 'null']` when the backing column
51
+ * allows null. Pass `openapi` when the property holds a non-string value,
52
+ * such as an object, a number, or an array; it accepts any shape
53
+ * `@deco.Virtual` accepts. The declared shape is used exactly as given and
54
+ * replaces the nullability inferred from the backing column, so when the
55
+ * backing column allows null, include `'null'` in the shape, e.g.
56
+ * `type: ['object', 'null']`.
57
+ *
58
+ * @param columnOrOptions - Either the backing column's name, or an options object:
59
+ * - `column` — the backing column's name; if omitted, then 'encrypted' is prepended to the Pascal cased version of the decorated field
60
+ * - `openapi` — the OpenAPI shape of the decorated property's value; if omitted, the property's shape is a string (see above)
38
61
  * @returns An Encrypted decorator
39
62
  */
40
- Encrypted(this: Decorators<TD>, column?: DreamColumnNames<T>): any;
63
+ Encrypted(this: Decorators<TD>, columnOrOptions?: DreamColumnNames<T> | EncryptedOptions<DreamColumnNames<T>>): any;
41
64
  /**
42
65
  * The Scope decorator decorates a static method that accepts
43
66
  * and returns a Dream Query.
@@ -1,4 +1,9 @@
1
- export default function Encrypted(encryptedColumnName?: string): any;
1
+ import { OpenapiSchemaBodyShorthand, OpenapiShorthandPrimitiveTypes } from '../../types/openapi.js';
2
+ export default function Encrypted(columnOrOptions?: string | EncryptedOptions): any;
3
+ export interface EncryptedOptions<ColumnName extends string = string> {
4
+ column?: ColumnName;
5
+ openapi?: OpenapiShorthandPrimitiveTypes | OpenapiSchemaBodyShorthand;
6
+ }
2
7
  export interface EncryptedAttributeStatement {
3
8
  property: string;
4
9
  encryptedColumnName: string;
@@ -453,15 +453,15 @@ export default class DreamClassTransactionBuilder<DreamClass extends typeof Drea
453
453
  * 5. associations loading associations loading associations could result in exponential amounts of data; in those cases, `.preload(...).findEach(...)` avoids instantiating massive amounts of data at once
454
454
  *
455
455
  * ```ts
456
- * const user = await User.txn(txn).leftJoinPreload('posts', 'comments', { visibilty: 'public' }, 'replies').first()
456
+ * const user = await User.txn(txn).leftJoinPreload('posts', 'comments', { and: { visibility: 'public' } }, 'replies').first()
457
457
  * console.log(user.posts[0].comments[0].replies)
458
458
  * // [Reply{id: 1}, Reply{id: 2}]
459
459
  * ```
460
460
  *
461
- * @param args - A chain of association names and where clauses
461
+ * @param args - A chain of association names and and/andNot/andAny clauses
462
462
  * @returns A query for this model with the include statement applied
463
463
  */
464
- leftJoinPreload<I extends DreamClassTransactionBuilder<DreamClass, DreamInstance>, DB extends DreamInstance['DB'], TableName extends DreamInstance['table'], Schema extends DreamInstance['schema'], const Arr extends readonly unknown[], const LastArg extends VariadicLeftJoinLoadArgs<DreamInstance, DB, Schema, TableName, Arr>, const JoinedAssociationsCandidate = JoinedAssociationsTypeFromAssociations<DB, Schema, TableName, [
464
+ leftJoinPreload<I extends DreamClassTransactionBuilder<DreamClass, DreamInstance>, DB extends DreamInstance['DB'], TableName extends DreamInstance['table'], Schema extends DreamInstance['schema'], const Arr extends readonly unknown[], const LastArg extends VariadicLeftJoinLoadArgs<DreamInstance, DB, Schema, TableName, Arr, LastArg>, const JoinedAssociationsCandidate = JoinedAssociationsTypeFromAssociations<DB, Schema, TableName, [
465
465
  ...Arr,
466
466
  LastArg
467
467
  ]>, const JoinedAssociations extends readonly JoinedAssociation[] = JoinedAssociationsCandidate extends readonly JoinedAssociation[] ? JoinedAssociationsCandidate : never, RetQuery = QueryWithJoinedAssociationsTypeAndNoPreload<Query<DreamInstance>, JoinedAssociations>>(this: I, ...args: [...Arr, LastArg]): RetQuery;
@@ -477,13 +477,13 @@ export default class DreamClassTransactionBuilder<DreamClass extends typeof Drea
477
477
  *
478
478
  * ```ts
479
479
  * await ApplicationModel.transaction(async txn => {
480
- * const user = await User.txn(txn).preload('posts', 'comments', { visibilty: 'public' }, 'replies').first()
480
+ * const user = await User.txn(txn).preload('posts', 'comments', { and: { visibility: 'public' } }, 'replies').first()
481
481
  * console.log(user.posts[0].comments[0].replies)
482
482
  * // [Reply{id: 1}, Reply{id: 2}]
483
483
  * })
484
484
  * ```
485
485
  *
486
- * @param args - A chain of association names and where clauses
486
+ * @param args - A chain of association names and and/andNot/andAny clauses
487
487
  * @returns A query for this model with the preload statement applied
488
488
  */
489
489
  preload<I extends DreamClassTransactionBuilder<DreamClass, DreamInstance>, DB extends DreamInstance['DB'], TableName extends DreamInstance['table'], Schema extends DreamInstance['schema'], const Arr extends readonly unknown[]>(this: I, ...args: [...Arr, VariadicLoadArgs<DreamInstance, DB, Schema, TableName, Arr>]): Query<DreamInstance, Readonly<{
@@ -561,10 +561,10 @@ export default class DreamClassTransactionBuilder<DreamClass extends typeof Drea
561
561
  * })
562
562
  * ```
563
563
  *
564
- * @param args - A chain of association names and where clauses
564
+ * @param args - A chain of association names and and/andNot/andAny clauses
565
565
  * @returns A Query for this model with the inner join clause applied
566
566
  */
567
- innerJoin<I extends DreamClassTransactionBuilder<DreamClass, DreamInstance>, DB extends DreamInstance['DB'], TableName extends DreamInstance['table'], Schema extends DreamInstance['schema'], const Arr extends readonly unknown[], const LastArg extends VariadicJoinsArgs<DreamInstance, DB, Schema, TableName, Arr>, const JoinedAssociationsCandidate = JoinedAssociationsTypeFromAssociations<DB, Schema, TableName, [
567
+ innerJoin<I extends DreamClassTransactionBuilder<DreamClass, DreamInstance>, DB extends DreamInstance['DB'], TableName extends DreamInstance['table'], Schema extends DreamInstance['schema'], const Arr extends readonly unknown[], const LastArg extends VariadicJoinsArgs<DreamInstance, DB, Schema, TableName, Arr, LastArg>, const JoinedAssociationsCandidate = JoinedAssociationsTypeFromAssociations<DB, Schema, TableName, [
568
568
  ...Arr,
569
569
  LastArg
570
570
  ]>, const JoinedAssociations extends readonly JoinedAssociation[] = JoinedAssociationsCandidate extends readonly JoinedAssociation[] ? JoinedAssociationsCandidate : never, RetQuery = QueryWithJoinedAssociationsType<Query<DreamInstance>, JoinedAssociations>>(this: I, ...args: [...Arr, LastArg]): RetQuery;
@@ -578,10 +578,10 @@ export default class DreamClassTransactionBuilder<DreamClass extends typeof Drea
578
578
  * })
579
579
  * ```
580
580
  *
581
- * @param args - A chain of association names and where clauses
581
+ * @param args - A chain of association names and and/andNot/andAny clauses
582
582
  * @returns A Query for this model with the left join clause applied
583
583
  */
584
- leftJoin<I extends DreamClassTransactionBuilder<DreamClass, DreamInstance>, DB extends DreamInstance['DB'], TableName extends DreamInstance['table'], Schema extends DreamInstance['schema'], const Arr extends readonly unknown[], const LastArg extends VariadicJoinsArgs<DreamInstance, DB, Schema, TableName, Arr>, const JoinedAssociationsCandidate = JoinedAssociationsTypeFromAssociations<DB, Schema, TableName, [
584
+ leftJoin<I extends DreamClassTransactionBuilder<DreamClass, DreamInstance>, DB extends DreamInstance['DB'], TableName extends DreamInstance['table'], Schema extends DreamInstance['schema'], const Arr extends readonly unknown[], const LastArg extends VariadicJoinsArgs<DreamInstance, DB, Schema, TableName, Arr, LastArg>, const JoinedAssociationsCandidate = JoinedAssociationsTypeFromAssociations<DB, Schema, TableName, [
585
585
  ...Arr,
586
586
  LastArg
587
587
  ]>, const JoinedAssociations extends readonly JoinedAssociation[] = JoinedAssociationsCandidate extends readonly JoinedAssociation[] ? JoinedAssociationsCandidate : never, RetQuery = QueryWithJoinedAssociationsType<Query<DreamInstance>, JoinedAssociations>>(this: I, ...args: [...Arr, LastArg]): RetQuery;