@rvoh/dream 2.18.0 → 2.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/dist/cjs/src/Dream.js +103 -0
  2. package/dist/cjs/src/db/DreamDbConnection.js +6 -0
  3. package/dist/cjs/src/decorators/class/SoftDelete.js +12 -0
  4. package/dist/cjs/src/dream/DreamClassTransactionBuilder.js +113 -0
  5. package/dist/cjs/src/dream/Query.js +137 -0
  6. package/dist/cjs/src/dream/QueryDriver/Base.js +84 -0
  7. package/dist/cjs/src/dream/QueryDriver/Kysely.js +358 -67
  8. package/dist/cjs/src/errors/CannotNamespaceAssociationFilterToAnotherTable.js +27 -0
  9. package/dist/cjs/src/helpers/cli/generateMigrationContent.js +21 -13
  10. package/dist/esm/src/Dream.js +103 -0
  11. package/dist/esm/src/db/DreamDbConnection.js +6 -0
  12. package/dist/esm/src/decorators/class/SoftDelete.js +12 -0
  13. package/dist/esm/src/dream/DreamClassTransactionBuilder.js +113 -0
  14. package/dist/esm/src/dream/Query.js +137 -0
  15. package/dist/esm/src/dream/QueryDriver/Base.js +84 -0
  16. package/dist/esm/src/dream/QueryDriver/Kysely.js +358 -67
  17. package/dist/esm/src/errors/CannotNamespaceAssociationFilterToAnotherTable.js +27 -0
  18. package/dist/esm/src/helpers/cli/generateMigrationContent.js +21 -13
  19. package/dist/types/src/Dream.d.ts +97 -4
  20. package/dist/types/src/decorators/class/SoftDelete.d.ts +12 -0
  21. package/dist/types/src/dream/DreamClassTransactionBuilder.d.ts +103 -0
  22. package/dist/types/src/dream/Query.d.ts +127 -0
  23. package/dist/types/src/dream/QueryDriver/Base.d.ts +69 -0
  24. package/dist/types/src/dream/QueryDriver/Kysely.d.ts +166 -8
  25. package/dist/types/src/errors/CannotNamespaceAssociationFilterToAnotherTable.d.ts +8 -0
  26. package/dist/types/src/types/associations/shared.d.ts +4 -1
  27. package/dist/types/src/types/dream.d.ts +17 -0
  28. package/dist/types/src/types/{associations → types/associations}/shared.ts +10 -1
  29. package/dist/types/src/types/{dream.ts → types/dream.ts} +53 -0
  30. package/dist/types/src/types/{variadic.ts → types/variadic.ts} +179 -140
  31. package/dist/types/src/types/variadic.d.ts +15 -10
  32. package/docs/assets/hierarchy.js +1 -1
  33. package/docs/assets/search.js +1 -1
  34. package/docs/classes/db.DreamMigrationHelpers.html +11 -11
  35. package/docs/classes/db.KyselyQueryDriver.html +78 -34
  36. package/docs/classes/db.PostgresQueryDriver.html +79 -35
  37. package/docs/classes/db.QueryDriverBase.html +77 -33
  38. package/docs/classes/errors.CheckConstraintViolation.html +3 -3
  39. package/docs/classes/errors.ColumnOverflow.html +3 -3
  40. package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
  41. package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +3 -3
  42. package/docs/classes/errors.DataTypeColumnTypeMismatch.html +3 -3
  43. package/docs/classes/errors.DecryptionError.html +2 -2
  44. package/docs/classes/errors.DecryptionParseError.html +2 -2
  45. package/docs/classes/errors.DecryptionRotationError.html +3 -3
  46. package/docs/classes/errors.GlobalNameNotSet.html +3 -3
  47. package/docs/classes/errors.InvalidCalendarDate.html +2 -2
  48. package/docs/classes/errors.InvalidClockTime.html +2 -2
  49. package/docs/classes/errors.InvalidClockTimeTz.html +2 -2
  50. package/docs/classes/errors.InvalidDateTime.html +2 -2
  51. package/docs/classes/errors.MissingSerializersDefinition.html +3 -3
  52. package/docs/classes/errors.NonLoadedAssociation.html +3 -3
  53. package/docs/classes/errors.NotNullViolation.html +3 -3
  54. package/docs/classes/errors.RecordNotFound.html +3 -3
  55. package/docs/classes/errors.ValidationError.html +3 -3
  56. package/docs/classes/index.CalendarDate.html +33 -33
  57. package/docs/classes/index.ClockTime.html +32 -32
  58. package/docs/classes/index.ClockTimeTz.html +35 -35
  59. package/docs/classes/index.DateTime.html +86 -86
  60. package/docs/classes/index.Decorators.html +19 -19
  61. package/docs/classes/index.Dream.html +182 -119
  62. package/docs/classes/index.DreamApp.html +10 -10
  63. package/docs/classes/index.DreamTransaction.html +2 -2
  64. package/docs/classes/index.Env.html +2 -2
  65. package/docs/classes/index.Query.html +144 -57
  66. package/docs/classes/system.CliFileWriter.html +4 -4
  67. package/docs/classes/system.DreamBin.html +2 -2
  68. package/docs/classes/system.DreamCLI.html +7 -7
  69. package/docs/classes/system.DreamImporter.html +2 -2
  70. package/docs/classes/system.DreamLogos.html +2 -2
  71. package/docs/classes/system.DreamSerializerBuilder.html +11 -11
  72. package/docs/classes/system.ObjectSerializerBuilder.html +8 -8
  73. package/docs/classes/system.PathHelpers.html +3 -3
  74. package/docs/classes/utils.Encrypt.html +3 -3
  75. package/docs/classes/utils.Range.html +2 -2
  76. package/docs/functions/db.closeAllDbConnections.html +1 -1
  77. package/docs/functions/db.dreamDbConnections.html +1 -1
  78. package/docs/functions/db.untypedDb.html +1 -1
  79. package/docs/functions/db.validateColumn.html +1 -1
  80. package/docs/functions/db.validateTable.html +1 -1
  81. package/docs/functions/errors.pgErrorType.html +1 -1
  82. package/docs/functions/index.DreamSerializer.html +1 -1
  83. package/docs/functions/index.ObjectSerializer.html +1 -1
  84. package/docs/functions/index.ReplicaSafe.html +1 -1
  85. package/docs/functions/index.STI.html +1 -1
  86. package/docs/functions/index.SoftDelete.html +12 -1
  87. package/docs/functions/utils.camelize.html +1 -1
  88. package/docs/functions/utils.capitalize.html +1 -1
  89. package/docs/functions/utils.cloneDeepSafe.html +1 -1
  90. package/docs/functions/utils.compact.html +1 -1
  91. package/docs/functions/utils.groupBy.html +1 -1
  92. package/docs/functions/utils.hyphenize.html +1 -1
  93. package/docs/functions/utils.intersection.html +1 -1
  94. package/docs/functions/utils.isEmpty.html +1 -1
  95. package/docs/functions/utils.normalizeUnicode.html +1 -1
  96. package/docs/functions/utils.pascalize.html +1 -1
  97. package/docs/functions/utils.percent.html +1 -1
  98. package/docs/functions/utils.range.html +1 -1
  99. package/docs/functions/utils.round.html +1 -1
  100. package/docs/functions/utils.sanitizeString.html +1 -1
  101. package/docs/functions/utils.snakeify.html +1 -1
  102. package/docs/functions/utils.sort.html +1 -1
  103. package/docs/functions/utils.sortBy.html +1 -1
  104. package/docs/functions/utils.sortObjectByKey.html +1 -1
  105. package/docs/functions/utils.sortObjectByValue.html +1 -1
  106. package/docs/functions/utils.uncapitalize.html +1 -1
  107. package/docs/functions/utils.uniq.html +1 -1
  108. package/docs/hierarchy.html +1 -1
  109. package/docs/interfaces/openapi.OpenapiDescription.html +2 -2
  110. package/docs/interfaces/openapi.OpenapiSchemaProperties.html +1 -1
  111. package/docs/interfaces/openapi.OpenapiSchemaPropertiesShorthand.html +1 -1
  112. package/docs/interfaces/openapi.OpenapiTypeFieldObject.html +1 -1
  113. package/docs/interfaces/types.BelongsToStatement.html +2 -2
  114. package/docs/interfaces/types.DecoratorContext.html +2 -2
  115. package/docs/interfaces/types.DreamAppInitOptions.html +2 -2
  116. package/docs/interfaces/types.DreamAppOpts.html +2 -2
  117. package/docs/interfaces/types.DreamDbConfig.html +5 -5
  118. package/docs/interfaces/types.DurationObject.html +2 -2
  119. package/docs/interfaces/types.EncryptOptions.html +2 -2
  120. package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
  121. package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
  122. package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
  123. package/docs/types/openapi.CommonOpenapiSchemaObjectFields.html +1 -1
  124. package/docs/types/openapi.OpenapiAllTypes.html +1 -1
  125. package/docs/types/openapi.OpenapiFormats.html +1 -1
  126. package/docs/types/openapi.OpenapiNumberFormats.html +1 -1
  127. package/docs/types/openapi.OpenapiPrimitiveBaseTypes.html +1 -1
  128. package/docs/types/openapi.OpenapiPrimitiveTypes.html +1 -1
  129. package/docs/types/openapi.OpenapiSchemaArray.html +1 -1
  130. package/docs/types/openapi.OpenapiSchemaArrayShorthand.html +1 -1
  131. package/docs/types/openapi.OpenapiSchemaBase.html +1 -1
  132. package/docs/types/openapi.OpenapiSchemaBody.html +1 -1
  133. package/docs/types/openapi.OpenapiSchemaBodyShorthand.html +1 -1
  134. package/docs/types/openapi.OpenapiSchemaCommonFields.html +1 -1
  135. package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +2 -2
  136. package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +2 -2
  137. package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +2 -2
  138. package/docs/types/openapi.OpenapiSchemaExpressionRef.html +2 -2
  139. package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +2 -2
  140. package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
  141. package/docs/types/openapi.OpenapiSchemaNull.html +2 -2
  142. package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
  143. package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
  144. package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +1 -1
  145. package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +1 -1
  146. package/docs/types/openapi.OpenapiSchemaObjectAnyOf.html +1 -1
  147. package/docs/types/openapi.OpenapiSchemaObjectAnyOfShorthand.html +1 -1
  148. package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
  149. package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
  150. package/docs/types/openapi.OpenapiSchemaObjectOneOf.html +1 -1
  151. package/docs/types/openapi.OpenapiSchemaObjectOneOfShorthand.html +1 -1
  152. package/docs/types/openapi.OpenapiSchemaObjectShorthand.html +1 -1
  153. package/docs/types/openapi.OpenapiSchemaPrimitiveGeneric.html +1 -1
  154. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAllOf.html +2 -2
  155. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +2 -2
  156. package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +2 -2
  157. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +2 -2
  158. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +2 -2
  159. package/docs/types/openapi.OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
  160. package/docs/types/openapi.OpenapiSchemaString.html +1 -1
  161. package/docs/types/openapi.OpenapiShorthandAllTypes.html +1 -1
  162. package/docs/types/openapi.OpenapiShorthandPrimitiveBaseTypes.html +1 -1
  163. package/docs/types/openapi.OpenapiShorthandPrimitiveTypes.html +1 -1
  164. package/docs/types/openapi.OpenapiTypeField.html +1 -1
  165. package/docs/types/system.DreamAppAllowedPackageManagersEnum.html +1 -1
  166. package/docs/types/types.CalendarDateDurationUnit.html +1 -1
  167. package/docs/types/types.CalendarDateObject.html +1 -1
  168. package/docs/types/types.Camelized.html +1 -1
  169. package/docs/types/types.ClockTimeObject.html +1 -1
  170. package/docs/types/types.DbConnectionType.html +1 -1
  171. package/docs/types/types.DbTypes.html +1 -1
  172. package/docs/types/types.DreamAssociationMetadata.html +1 -1
  173. package/docs/types/types.DreamAttributes.html +1 -1
  174. package/docs/types/types.DreamClassAssociationAndStatement.html +1 -1
  175. package/docs/types/types.DreamClassColumn.html +1 -1
  176. package/docs/types/types.DreamColumn.html +1 -1
  177. package/docs/types/types.DreamColumnNames.html +1 -1
  178. package/docs/types/types.DreamLogLevel.html +1 -1
  179. package/docs/types/types.DreamLogger.html +2 -2
  180. package/docs/types/types.DreamModelSerializerType.html +1 -1
  181. package/docs/types/types.DreamOrViewModelClassSerializerKey.html +1 -1
  182. package/docs/types/types.DreamOrViewModelSerializerKey.html +1 -1
  183. package/docs/types/types.DreamParamSafeAttributes.html +1 -1
  184. package/docs/types/types.DreamParamSafeColumnNames.html +1 -1
  185. package/docs/types/types.DreamSerializable.html +1 -1
  186. package/docs/types/types.DreamSerializableArray.html +1 -1
  187. package/docs/types/types.DreamSerializerKey.html +1 -1
  188. package/docs/types/types.DreamSerializers.html +1 -1
  189. package/docs/types/types.DreamVirtualColumns.html +1 -1
  190. package/docs/types/types.DurationUnit.html +1 -1
  191. package/docs/types/types.EncryptAlgorithm.html +1 -1
  192. package/docs/types/types.HasManyStatement.html +1 -1
  193. package/docs/types/types.HasOneStatement.html +1 -1
  194. package/docs/types/types.Hyphenized.html +1 -1
  195. package/docs/types/types.Pascalized.html +1 -1
  196. package/docs/types/types.PrimaryKeyType.html +1 -1
  197. package/docs/types/types.RoundingPrecision.html +1 -1
  198. package/docs/types/types.SerializerCasing.html +1 -1
  199. package/docs/types/types.SimpleObjectSerializerType.html +1 -1
  200. package/docs/types/types.Snakeified.html +1 -1
  201. package/docs/types/types.StrictInterface.html +1 -1
  202. package/docs/types/types.UpdateableAssociationProperties.html +1 -1
  203. package/docs/types/types.UpdateableProperties.html +1 -1
  204. package/docs/types/types.ValidationType.html +1 -1
  205. package/docs/types/types.ViewModel.html +2 -2
  206. package/docs/types/types.ViewModelClass.html +1 -1
  207. package/docs/types/types.WeekdayName.html +1 -1
  208. package/docs/types/types.WhereStatementForDream.html +1 -1
  209. package/docs/types/types.WhereStatementForDreamClass.html +1 -1
  210. package/docs/variables/index.DreamConst.html +1 -1
  211. package/docs/variables/index.ops.html +1 -1
  212. package/docs/variables/openapi.openapiPrimitiveTypes.html +1 -1
  213. package/docs/variables/openapi.openapiShorthandPrimitiveTypes.html +1 -1
  214. package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
  215. package/docs/variables/system.primaryKeyTypes.html +1 -1
  216. package/package.json +3 -3
  217. package/dist/cjs/src/dream/internal/associations/throughAssociationHasOptionsBesidesThroughAndSource.js +0 -11
  218. package/dist/cjs/src/errors/associations/ThroughAssociationConditionsIncompatibleWithThroughAssociationSource.js +0 -17
  219. package/dist/esm/src/dream/internal/associations/throughAssociationHasOptionsBesidesThroughAndSource.js +0 -11
  220. package/dist/esm/src/errors/associations/ThroughAssociationConditionsIncompatibleWithThroughAssociationSource.js +0 -17
  221. package/dist/types/src/dream/internal/associations/throughAssociationHasOptionsBesidesThroughAndSource.d.ts +0 -13
  222. package/dist/types/src/errors/associations/ThroughAssociationConditionsIncompatibleWithThroughAssociationSource.d.ts +0 -12
  223. /package/dist/types/src/types/{associations → types/associations}/belongsTo.ts +0 -0
  224. /package/dist/types/src/types/{associations → types/associations}/hasMany.ts +0 -0
  225. /package/dist/types/src/types/{associations → types/associations}/hasOne.ts +0 -0
  226. /package/dist/types/src/types/{calendardate.ts → types/calendardate.ts} +0 -0
  227. /package/dist/types/src/types/{clocktime.ts → types/clocktime.ts} +0 -0
  228. /package/dist/types/src/types/{datetime.ts → types/datetime.ts} +0 -0
  229. /package/dist/types/src/types/{db.ts → types/db.ts} +0 -0
  230. /package/dist/types/src/types/{lifecycle.ts → types/lifecycle.ts} +0 -0
  231. /package/dist/types/src/types/{logger.ts → types/logger.ts} +0 -0
  232. /package/dist/types/src/types/{moduleDeclarations → types/moduleDeclarations}/luxon.d.ts +0 -0
  233. /package/dist/types/src/types/{openapi.ts → types/openapi.ts} +0 -0
  234. /package/dist/types/src/types/{query.ts → types/query.ts} +0 -0
  235. /package/dist/types/src/types/{recursiveSerialization.ts → types/recursiveSerialization.ts} +0 -0
  236. /package/dist/types/src/types/{serializer.ts → types/serializer.ts} +0 -0
  237. /package/dist/types/src/types/{utils.ts → types/utils.ts} +0 -0
  238. /package/dist/types/src/types/{validation.ts → types/validation.ts} +0 -0
@@ -205,6 +205,20 @@ export default class QueryDriverBase<DreamInstance extends Dream> {
205
205
  *
206
206
  */
207
207
  max(columnName: string): Promise<any>;
208
+ /**
209
+ * Retrieves the max value of the specified column within each group,
210
+ * keyed by the value of the provided group column.
211
+ *
212
+ * ```ts
213
+ * await CompositionAsset.query().maxBy('name', 'score')
214
+ * // Map(2) { 'primary' => 9, 'secondary' => 4 }
215
+ * ```
216
+ *
217
+ * @param groupColumn - the column to group by
218
+ * @param aggregatedColumn - the column to take the max of within each group
219
+ * @returns A Map from each present group value to the max of the aggregated column in that group
220
+ */
221
+ maxBy(groupColumn: string, aggregatedColumn: string): Promise<Map<any, any>>;
208
222
  /**
209
223
  * Retrieves the min value of the specified column
210
224
  * for this Query
@@ -218,6 +232,20 @@ export default class QueryDriverBase<DreamInstance extends Dream> {
218
232
  * @returns the min value of the specified column for this Query
219
233
  */
220
234
  min(columnName: string): Promise<any>;
235
+ /**
236
+ * Retrieves the min value of the specified column within each group,
237
+ * keyed by the value of the provided group column.
238
+ *
239
+ * ```ts
240
+ * await CompositionAsset.query().minBy('name', 'score')
241
+ * // Map(2) { 'primary' => 1, 'secondary' => 4 }
242
+ * ```
243
+ *
244
+ * @param groupColumn - the column to group by
245
+ * @param aggregatedColumn - the column to take the min of within each group
246
+ * @returns A Map from each present group value to the min of the aggregated column in that group
247
+ */
248
+ minBy(groupColumn: string, aggregatedColumn: string): Promise<Map<any, any>>;
221
249
  /**
222
250
  * Retrieves the sum value of the specified column
223
251
  * for this Query
@@ -231,6 +259,20 @@ export default class QueryDriverBase<DreamInstance extends Dream> {
231
259
  * @returns the sum of the values of the specified column for this Query
232
260
  */
233
261
  sum(columnName: string): Promise<any>;
262
+ /**
263
+ * Retrieves the sum of the specified column within each group,
264
+ * keyed by the value of the provided group column.
265
+ *
266
+ * ```ts
267
+ * await CompositionAsset.query().sumBy('name', 'score')
268
+ * // Map(2) { 'primary' => 10, 'secondary' => 4 }
269
+ * ```
270
+ *
271
+ * @param groupColumn - the column to group by
272
+ * @param aggregatedColumn - the column to sum within each group
273
+ * @returns A Map from each present group value to the sum of the aggregated column in that group
274
+ */
275
+ sumBy(groupColumn: string, aggregatedColumn: string): Promise<Map<any, any>>;
234
276
  /**
235
277
  * Retrieves the average value of the specified column
236
278
  * for this Query
@@ -244,6 +286,20 @@ export default class QueryDriverBase<DreamInstance extends Dream> {
244
286
  * @returns the average of the values of the specified column for this Query
245
287
  */
246
288
  avg(columnName: string): Promise<any>;
289
+ /**
290
+ * Retrieves the average of the specified column within each group,
291
+ * keyed by the value of the provided group column.
292
+ *
293
+ * ```ts
294
+ * await CompositionAsset.query().avgBy('name', 'score')
295
+ * // Map(2) { 'primary' => 5, 'secondary' => 4 }
296
+ * ```
297
+ *
298
+ * @param groupColumn - the column to group by
299
+ * @param aggregatedColumn - the column to average within each group
300
+ * @returns A Map from each present group value to the average of the aggregated column in that group
301
+ */
302
+ avgBy(groupColumn: string, aggregatedColumn: string): Promise<Map<any, any>>;
247
303
  /**
248
304
  * Retrieves the number of records in the database
249
305
  *
@@ -254,6 +310,19 @@ export default class QueryDriverBase<DreamInstance extends Dream> {
254
310
  * @returns The number of records in the database
255
311
  */
256
312
  count(): Promise<number>;
313
+ /**
314
+ * Retrieves the number of records in each group, keyed by the
315
+ * value of the provided group column.
316
+ *
317
+ * ```ts
318
+ * await User.query().countBy('name')
319
+ * // Map(2) { 'fred' => 2, 'zed' => 1 }
320
+ * ```
321
+ *
322
+ * @param groupColumn - the column to group by
323
+ * @returns A Map from each present group value to the number of records in that group
324
+ */
325
+ countBy(groupColumn: string): Promise<Map<any, number>>;
257
326
  /**
258
327
  * @internal
259
328
  *
@@ -157,6 +157,20 @@ export default class KyselyQueryDriver<DreamInstance extends Dream> extends Quer
157
157
  *
158
158
  */
159
159
  max(columnName: string): Promise<any>;
160
+ /**
161
+ * Retrieves the max value of the specified column within each group,
162
+ * keyed by the value of the provided group column.
163
+ *
164
+ * ```ts
165
+ * await CompositionAsset.query().maxBy('name', 'score')
166
+ * // Map(2) { 'primary' => 9, 'secondary' => 4 }
167
+ * ```
168
+ *
169
+ * @param groupColumn - the column to group by (base or joined-association-namespaced)
170
+ * @param aggregatedColumn - the column to take the max of within each group
171
+ * @returns A Map from each present group value to the max of the aggregated column in that group
172
+ */
173
+ maxBy(groupColumn: string, aggregatedColumn: string): Promise<Map<any, any>>;
160
174
  /**
161
175
  * Retrieves the min value of the specified column
162
176
  * for this Query
@@ -170,6 +184,20 @@ export default class KyselyQueryDriver<DreamInstance extends Dream> extends Quer
170
184
  * @returns the min value of the specified column for this Query
171
185
  */
172
186
  min(columnName: string): Promise<any>;
187
+ /**
188
+ * Retrieves the min value of the specified column within each group,
189
+ * keyed by the value of the provided group column.
190
+ *
191
+ * ```ts
192
+ * await CompositionAsset.query().minBy('name', 'score')
193
+ * // Map(2) { 'primary' => 1, 'secondary' => 4 }
194
+ * ```
195
+ *
196
+ * @param groupColumn - the column to group by (base or joined-association-namespaced)
197
+ * @param aggregatedColumn - the column to take the min of within each group
198
+ * @returns A Map from each present group value to the min of the aggregated column in that group
199
+ */
200
+ minBy(groupColumn: string, aggregatedColumn: string): Promise<Map<any, any>>;
173
201
  /**
174
202
  * Retrieves the sum value of the specified column
175
203
  * for this Query
@@ -183,6 +211,20 @@ export default class KyselyQueryDriver<DreamInstance extends Dream> extends Quer
183
211
  * @returns the sum of the values of the specified column for this Query
184
212
  */
185
213
  sum(columnName: string): Promise<any>;
214
+ /**
215
+ * Retrieves the sum of the specified column within each group,
216
+ * keyed by the value of the provided group column.
217
+ *
218
+ * ```ts
219
+ * await CompositionAsset.query().sumBy('name', 'score')
220
+ * // Map(2) { 'primary' => 10, 'secondary' => 4 }
221
+ * ```
222
+ *
223
+ * @param groupColumn - the column to group by (base or joined-association-namespaced)
224
+ * @param aggregatedColumn - the column to sum within each group
225
+ * @returns A Map from each present group value to the sum of the aggregated column in that group
226
+ */
227
+ sumBy(groupColumn: string, aggregatedColumn: string): Promise<Map<any, any>>;
186
228
  /**
187
229
  * Retrieves the average value of the specified column
188
230
  * for this Query
@@ -196,6 +238,20 @@ export default class KyselyQueryDriver<DreamInstance extends Dream> extends Quer
196
238
  * @returns the average of the values of the specified column for this Query
197
239
  */
198
240
  avg(columnName: string): Promise<any>;
241
+ /**
242
+ * Retrieves the average of the specified column within each group,
243
+ * keyed by the value of the provided group column.
244
+ *
245
+ * ```ts
246
+ * await CompositionAsset.query().avgBy('name', 'score')
247
+ * // Map(2) { 'primary' => 5, 'secondary' => 4 }
248
+ * ```
249
+ *
250
+ * @param groupColumn - the column to group by (base or joined-association-namespaced)
251
+ * @param aggregatedColumn - the column to average within each group
252
+ * @returns A Map from each present group value to the average of the aggregated column in that group
253
+ */
254
+ avgBy(groupColumn: string, aggregatedColumn: string): Promise<Map<any, any>>;
199
255
  /**
200
256
  * Retrieves the number of records in the database
201
257
  *
@@ -206,6 +262,38 @@ export default class KyselyQueryDriver<DreamInstance extends Dream> extends Quer
206
262
  * @returns The number of records in the database
207
263
  */
208
264
  count(): Promise<number>;
265
+ /**
266
+ * Retrieves the number of records in each group, keyed by the
267
+ * value of the provided group column.
268
+ *
269
+ * ```ts
270
+ * await User.query().countBy('name')
271
+ * // Map(2) { 'fred' => 2, 'zed' => 1 }
272
+ * ```
273
+ *
274
+ * @param groupColumn - the column to group by (base or joined-association-namespaced)
275
+ * @returns A Map from each present group value to the number of records in that group
276
+ */
277
+ countBy(groupColumn: string): Promise<Map<any, number>>;
278
+ /**
279
+ * @internal
280
+ *
281
+ * Shared plumbing for grouped aggregates (`countBy` and the value-aggregate
282
+ * siblings `minBy` / `maxBy` / `sumBy` / `avgBy`). Selects the group column
283
+ * alongside a single aggregate expression, groups by the group column, executes,
284
+ * and folds the resulting rows into a Map keyed by the group value.
285
+ *
286
+ * The group column and the aggregate are selected under stable, underscore-free
287
+ * aliases so they can be read back off each row without being affected by
288
+ * Kysely's CamelCasePlugin (which would otherwise mangle a namespaced alias),
289
+ * mirroring the short-alias strategy used by `pluck`.
290
+ *
291
+ * @param groupColumn - the column to GROUP BY (base or joined-association-namespaced)
292
+ * @param aggregateExpression - the Kysely aggregate expression to select per group (e.g. `count(pk)`)
293
+ * @param coerceValue - maps each raw aggregate value to the value stored in the returned Map
294
+ * @returns A Map from each present group value to its coerced aggregate value
295
+ */
296
+ private groupedAggregate;
209
297
  /**
210
298
  * @internal
211
299
  *
@@ -319,6 +407,48 @@ export default class KyselyQueryDriver<DreamInstance extends Dream> extends Quer
319
407
  private inArrayWithNull_or_notInArrayWithoutNull_ExpressionBuilder;
320
408
  private inArrayWithoutNullExpressionBuilder;
321
409
  private notInArrayWithNullExpressionBuilder;
410
+ /**
411
+ * @internal
412
+ *
413
+ * A Dream instance (or array of Dream instances) as a where-clause value is
414
+ * resolved as an association of the dreamClass whose statement is being
415
+ * compiled, so a key namespaced to a different table (e.g.
416
+ * `where({ 'c.user': user })` after `innerJoin('composition as c')`) would
417
+ * silently resolve the association against the wrong class, emitting invalid
418
+ * SQL or SQL that filters the wrong table. Such keys are already rejected at
419
+ * the type level; this guard rejects them at runtime. Un-namespaced keys and
420
+ * keys namespaced to the alias the statement applies to are unaffected, as
421
+ * are callers that do not declare an expected alias.
422
+ */
423
+ private validateAssociationFilterAlias;
424
+ /**
425
+ * @internal
426
+ *
427
+ * An array under an association name can only be an array of Dream instances
428
+ * (association names are not columns). The every-element check simply avoids
429
+ * changing the handling of invalid runtime input (e.g. an array of ids under
430
+ * an association name), which the type system already rejects.
431
+ */
432
+ private isAssociationInstanceArray;
433
+ /**
434
+ * @internal
435
+ *
436
+ * Expands an array of Dream instances under a BelongsTo association name into
437
+ * foreign key filtering:
438
+ * - non-polymorphic: `foreignKey IN (...)`
439
+ * - polymorphic: instances are grouped by their reference type (STI children
440
+ * collapse into their base class), each group becoming
441
+ * `(foreignKey IN (...) AND foreignKeyTypeField = 'TheType')`, with multiple
442
+ * groups ORed together
443
+ * - empty array: matches nothing (FALSE); when the caller negates, NOT(FALSE)
444
+ * matches everything, mirroring empty `in`/`not in` array semantics
445
+ *
446
+ * When `negate` is set, IS NOT NULL conditions are included so that the
447
+ * caller's negation also matches records in which the foreign key (or type
448
+ * field) is null, consistent with negation of single Dream instances and of
449
+ * `in` arrays.
450
+ */
451
+ private associationInstanceArrayToExpressionWrapper;
322
452
  private dreamWhereStatementToExpressionBuilderParts;
323
453
  private normalizedWhereValue;
324
454
  private recursivelyJoin;
@@ -466,26 +596,54 @@ export default class KyselyQueryDriver<DreamInstance extends Dream> extends Quer
466
596
  * public b
467
597
  * ```
468
598
  *
599
+ * Options declared on a through association (`and`/`andAny`/`andNot`/`selfAnd`/
600
+ * `selfAndNot`/`order`/`distinct`) are applied at the join of the table where the
601
+ * through association's target model materializes. When a source is itself a
602
+ * through association, that join is only reached after bridging further through
603
+ * associations, so each through association is pushed onto the
604
+ * `previousThroughAssociations` stack (along with the alias `selfAnd`/`selfAndNot`
605
+ * clauses reference) before the terminal `applyOneJoin` call, and the stack is
606
+ * threaded through every recursion until `addAssociationJoinStatementToQuery`
607
+ * reaches a concrete (non-through) association, where every stacked entry is
608
+ * applied to that join.
609
+ *
469
610
  * Then `MyModel.leftJoinPreload('myB')` is processed as follows:
470
611
  * - `applyOneJoin` is called with the `myB` association
471
612
  * - `joinsBridgeThroughAssociations` is called with the `myB` association
472
613
  * - `joinsBridgeThroughAssociations` is called with the `myA` association
473
614
  * - `addAssociationJoinStatementToQuery` is called with the `otherModel` association
474
- * - `applyOneJoin` is called with the `a` association from OtherModel
475
- * - `joinsBridgeThroughAssociations` is called with the `a` association from OtherModel
476
- * // throw ThroughAssociationConditionsIncompatibleWithThroughAssociationSource if
477
- * // myA in MyModel defines conditions, distinct, or order
615
+ * - `applyOneJoin` is called with the `a` association from OtherModel, with `myA` pushed
616
+ * onto the previousThroughAssociations stack
617
+ * - `joinsBridgeThroughAssociations` is called with the `a` association from OtherModel,
618
+ * inheriting the stack
478
619
  * - `addAssociationJoinStatementToQuery` is called with the `aToOtherModelJoinModel` association
479
- * - `applyOneJoin` is called with the `a` association from AToOtherModelJoinModel with conditions (if present) on `a` defined on OtherModel
480
- * - `addAssociationJoinStatementToQuery` is called with the `myA` association
481
- * - `applyOneJoin` is called with the `b` association from A with conditions (if present) from `myB` defined on MyModel
482
- * - `addAssociationJoinStatementToQuery` is called with the `myB` association
620
+ * - `applyOneJoin` is called with the `a` association from AToOtherModelJoinModel, with the
621
+ * `a` association from OtherModel pushed onto the stack
622
+ * - `addAssociationJoinStatementToQuery` is called with the `a` association from
623
+ * AToOtherModelJoinModel, applying the options (if present) of every stacked through
624
+ * association (`myA` defined on MyModel, `a` defined on OtherModel) to the `through_as` join
625
+ * - `applyOneJoin` is called with the `b` association from A, with `myB` pushed onto the stack
626
+ * - `addAssociationJoinStatementToQuery` is called with the `b` association from A, applying
627
+ * the options (if present) of `myB` defined on MyModel to the `through_bs` join
483
628
  */
484
629
  private joinsBridgeThroughAssociations;
485
630
  private applyOneJoin;
486
631
  private addAssociationJoinStatementToQuery;
487
632
  private applyOrderStatementForAssociation;
488
633
  private distinctColumnNameForAssociation;
634
+ /**
635
+ * Applies the and-family clauses (`and`/`andAny`/`andNot`/`selfAnd`/`selfAndNot`)
636
+ * of every pending through association to the terminal concrete join of a
637
+ * through association chain.
638
+ *
639
+ * The first entry in the stack is the association the developer named in the
640
+ * join/preload/associationQuery statement, so it is the association the
641
+ * developer-supplied joinAndStatement corresponds to (used to satisfy
642
+ * `DreamConst.required` clauses); `DreamConst.required` on any other stacked
643
+ * through association cannot be satisfied and will throw
644
+ * `MissingRequiredAssociationAndClause`.
645
+ */
646
+ private applyPreviousThroughAssociationAndStatementsToJoinStatement;
489
647
  private applyAssociationAndStatementsToJoinStatement;
490
648
  private throwUnlessAllRequiredWhereClausesProvided;
491
649
  private conditionallyApplyDefaultScopesDependentOnAssociation;
@@ -0,0 +1,8 @@
1
+ import Dream from '../Dream.js';
2
+ export default class CannotNamespaceAssociationFilterToAnotherTable extends Error {
3
+ private dreamClass;
4
+ private key;
5
+ private expectedAlias;
6
+ constructor(dreamClass: typeof Dream, key: string, expectedAlias: string);
7
+ get message(): string;
8
+ }
@@ -34,8 +34,11 @@ type JoinedAssociationColumnNames<JoinedAssociations extends Readonly<JoinedAsso
34
34
  type Whereable<R> = {
35
35
  [K in keyof Selectable<R>]?: Selectable<R>[K] | Selectable<R>[K][];
36
36
  };
37
+ type WhereableAssociatedModelParam<I extends Dream> = {
38
+ [K in keyof AssociatedModelParam<I>]: AssociatedModelParam<I>[K] | NonNullable<AssociatedModelParam<I>[K]>[];
39
+ };
37
40
  export type WhereStatement<I extends Dream> = InternalWhereStatement<I, I['DB'], I['schema'], I['table']>;
38
- export type InternalWhereStatement<I extends Dream, DB, Schema, TableName extends AssociationTableNames<DB, Schema> & keyof DB> = Partial<MergeUnionOfRecordTypes<Whereable<DB[TableName]> | DreamSelectable<DB, Schema, TableName> | AssociatedModelParam<I>>>;
41
+ export type InternalWhereStatement<I extends Dream, DB, Schema, TableName extends AssociationTableNames<DB, Schema> & keyof DB> = Partial<MergeUnionOfRecordTypes<Whereable<DB[TableName]> | DreamSelectable<DB, Schema, TableName> | WhereableAssociatedModelParam<I>>>;
39
42
  export type OnStatementForAssociation<I extends Dream, DB, Schema, TableName extends AssociationTableNames<DB, Schema> & keyof DB, RequiredOnClauseKeysForThisAssociation, OnStatement extends InternalWhereStatement<I, DB, Schema, TableName> = InternalWhereStatement<I, DB, Schema, TableName>> = RequiredOnClauseKeysForThisAssociation extends null ? InternalWhereStatement<I, DB, Schema, TableName> : RequiredOnClauseKeysForThisAssociation extends string[] ? Required<Pick<OnStatement, RequiredOnClauseKeysForThisAssociation[number] & keyof OnStatement>> & Partial<Omit<OnStatement, RequiredOnClauseKeysForThisAssociation[number] & keyof OnStatement>> : never;
40
43
  export type OnStatementForSpecificColumns<I extends Dream, DB, Schema, TableName extends AssociationTableNames<DB, Schema> & keyof DB, Columns extends string[], OnStatement extends InternalWhereStatement<I, DB, Schema, TableName> = InternalWhereStatement<I, DB, Schema, TableName>> = Pick<OnStatement, Columns[number] & keyof OnStatement>;
41
44
  type OnStatementForAssociationDefinition<DB, Schema, TableName extends AssociationTableNames<DB, Schema> & keyof DB> = Partial<MergeUnionOfRecordTypes<Partial<Selectable<DB[TableName]>> | Partial<{
@@ -51,6 +51,23 @@ export type PassthroughOnClauseKeys<Schema, TableName, AssociationName, Associat
51
51
  * must be forbidden at compile time for the hydrating load variants.
52
52
  */
53
53
  export type IsNonOptionalBelongsToAssociation<Schema, TableName, AssociationName, Associations = TableName extends null ? null : TableName extends keyof Schema & string ? Schema[TableName]['associations' & keyof Schema[TableName]] : null, Association = Associations extends null ? null : AssociationName extends keyof Associations ? Associations[AssociationName] : null> = Association extends null ? false : Association['type' & keyof Association] extends 'BelongsTo' ? Association['optional' & keyof Association] extends false ? true : false : false;
54
+ /**
55
+ * Resolves to `true` when the named association on the given table is a
56
+ * polymorphic BelongsTo. Joining a polymorphic BelongsTo raises
57
+ * CannotJoinPolymorphicBelongsToError at runtime, so the variadic join types
58
+ * (innerJoin / leftJoin / leftJoinPreload / leftJoinLoad) reject these
59
+ * association names at compile time.
60
+ */
61
+ export type IsPolymorphicBelongsToAssociation<Schema, TableName, AssociationName, Associations = TableName extends null ? null : TableName extends keyof Schema & string ? Schema[TableName]['associations' & keyof Schema[TableName]] : null, Association = Associations extends null ? null : AssociationName extends keyof Associations ? Associations[AssociationName] : null> = Association extends null ? false : Association['type' & keyof Association] extends 'BelongsTo' ? Association['foreignKeyTypeColumn' & keyof Association] extends string ? true : false : false;
62
+ /**
63
+ * Union of the association names on the given table that are polymorphic
64
+ * BelongsTo associations. Used by the variadic join types to exclude these
65
+ * names from the allowed argument values, since joining a polymorphic
66
+ * BelongsTo raises CannotJoinPolymorphicBelongsToError at runtime.
67
+ */
68
+ export type PolymorphicBelongsToAssociationNames<Schema, TableName extends keyof Schema, AssociationMetadata = AssociationMetadataForTable<Schema, TableName>> = IsAny<AssociationMetadata> extends true ? never : {
69
+ [K in keyof AssociationMetadata]: AssociationMetadata[K]['type' & keyof AssociationMetadata[K]] extends 'BelongsTo' ? AssociationMetadata[K]['foreignKeyTypeColumn' & keyof AssociationMetadata[K]] extends string ? K : never : never;
70
+ }[keyof AssociationMetadata];
54
71
  export type DreamAssociationNames<DreamInstance extends Dream, SchemaAssociations = DreamAssociationMetadata<DreamInstance>> = keyof SchemaAssociations;
55
72
  export type DreamBelongsToAssociationNames<DreamInstance extends Dream> = keyof DreamBelongsToAssociationMetadata<DreamInstance>;
56
73
  export type DreamHasOneAssociationNames<DreamInstance extends Dream> = keyof DreamHasOneAssociationMetadata<DreamInstance>;
@@ -221,6 +221,15 @@ type Whereable<R> = {
221
221
  [K in keyof Selectable<R>]?: Selectable<R>[K] | Selectable<R>[K][]
222
222
  }
223
223
 
224
+ // For filtering by BelongsTo model instance(s) in a where/and statement, e.g.
225
+ // `await Room.where({ place: [place1, place2] }).all()`. Unlike
226
+ // `AssociatedModelParam` (the create/update param type, where an array of
227
+ // instances would be meaningless), each association also accepts an array
228
+ // of associated model instances.
229
+ type WhereableAssociatedModelParam<I extends Dream> = {
230
+ [K in keyof AssociatedModelParam<I>]: AssociatedModelParam<I>[K] | NonNullable<AssociatedModelParam<I>[K]>[]
231
+ }
232
+
224
233
  export type WhereStatement<I extends Dream> = InternalWhereStatement<I, I['DB'], I['schema'], I['table']>
225
234
 
226
235
  export type InternalWhereStatement<
@@ -230,7 +239,7 @@ export type InternalWhereStatement<
230
239
  TableName extends AssociationTableNames<DB, Schema> & keyof DB,
231
240
  > = Partial<
232
241
  MergeUnionOfRecordTypes<
233
- Whereable<DB[TableName]> | DreamSelectable<DB, Schema, TableName> | AssociatedModelParam<I>
242
+ Whereable<DB[TableName]> | DreamSelectable<DB, Schema, TableName> | WhereableAssociatedModelParam<I>
234
243
  >
235
244
  >
236
245
 
@@ -254,6 +254,59 @@ export type IsNonOptionalBelongsToAssociation<
254
254
  : false
255
255
  : false
256
256
 
257
+ /**
258
+ * Resolves to `true` when the named association on the given table is a
259
+ * polymorphic BelongsTo. Joining a polymorphic BelongsTo raises
260
+ * CannotJoinPolymorphicBelongsToError at runtime, so the variadic join types
261
+ * (innerJoin / leftJoin / leftJoinPreload / leftJoinLoad) reject these
262
+ * association names at compile time.
263
+ */
264
+ export type IsPolymorphicBelongsToAssociation<
265
+ Schema,
266
+ TableName,
267
+ AssociationName,
268
+ Associations = TableName extends null
269
+ ? null
270
+ : TableName extends keyof Schema & string
271
+ ? Schema[TableName]['associations' & keyof Schema[TableName]]
272
+ : null,
273
+ Association = Associations extends null
274
+ ? null
275
+ : AssociationName extends keyof Associations
276
+ ? Associations[AssociationName]
277
+ : null,
278
+ > = Association extends null
279
+ ? false
280
+ : Association['type' & keyof Association] extends 'BelongsTo'
281
+ ? Association['foreignKeyTypeColumn' & keyof Association] extends string
282
+ ? true
283
+ : false
284
+ : false
285
+
286
+ /**
287
+ * Union of the association names on the given table that are polymorphic
288
+ * BelongsTo associations. Used by the variadic join types to exclude these
289
+ * names from the allowed argument values, since joining a polymorphic
290
+ * BelongsTo raises CannotJoinPolymorphicBelongsToError at runtime.
291
+ */
292
+ export type PolymorphicBelongsToAssociationNames<
293
+ Schema,
294
+ TableName extends keyof Schema,
295
+ AssociationMetadata = AssociationMetadataForTable<Schema, TableName>,
296
+ > =
297
+ // when the schema is untyped (`any`), resolve to `never` so nothing is
298
+ // excluded from the allowed association names
299
+ IsAny<AssociationMetadata> extends true
300
+ ? never
301
+ : {
302
+ [K in keyof AssociationMetadata]: AssociationMetadata[K]['type' &
303
+ keyof AssociationMetadata[K]] extends 'BelongsTo'
304
+ ? AssociationMetadata[K]['foreignKeyTypeColumn' & keyof AssociationMetadata[K]] extends string
305
+ ? K
306
+ : never
307
+ : never
308
+ }[keyof AssociationMetadata]
309
+
257
310
  export type DreamAssociationNames<
258
311
  DreamInstance extends Dream,
259
312
  SchemaAssociations = DreamAssociationMetadata<DreamInstance>,