@rvoh/dream 2.18.1 → 2.20.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 (265) hide show
  1. package/dist/cjs/src/Dream.js +186 -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 +148 -0
  6. package/dist/cjs/src/dream/QueryDriver/Base.js +84 -0
  7. package/dist/cjs/src/dream/QueryDriver/Kysely.js +420 -81
  8. package/dist/cjs/src/dream/internal/filterRowToKnownColumns.js +41 -0
  9. package/dist/cjs/src/dream/internal/saveDream.js +6 -1
  10. package/dist/cjs/src/dream/internal/sqlResultToDreamInstance.js +9 -2
  11. package/dist/cjs/src/errors/CannotNamespaceAssociationFilterToAnotherTable.js +27 -0
  12. package/dist/cjs/src/errors/schema-builder/CannotIgnoreAssociationColumn.js +38 -0
  13. package/dist/cjs/src/errors/schema-builder/CannotIgnoreEncryptedColumn.js +20 -0
  14. package/dist/cjs/src/errors/schema-builder/CannotIgnorePrimaryKey.js +18 -0
  15. package/dist/cjs/src/errors/schema-builder/CannotIgnoreSoftDeleteColumn.js +21 -0
  16. package/dist/cjs/src/errors/schema-builder/CannotIgnoreSortablePositionColumn.js +20 -0
  17. package/dist/cjs/src/errors/schema-builder/CannotIgnoreSortableScopeColumn.js +24 -0
  18. package/dist/cjs/src/errors/schema-builder/CannotIgnoreStiTypeColumn.js +17 -0
  19. package/dist/cjs/src/errors/schema-builder/ConflictingIgnoredColumns.js +27 -0
  20. package/dist/cjs/src/errors/schema-builder/IgnoredColumnMustBeCamelCase.js +21 -0
  21. package/dist/cjs/src/helpers/cli/ASTConnectionBuilder.js +38 -1
  22. package/dist/cjs/src/helpers/cli/ASTKyselyCodegenEnhancer.js +60 -0
  23. package/dist/cjs/src/helpers/cli/generateMigrationContent.js +21 -13
  24. package/dist/cjs/src/helpers/cli/resolveIgnoredColumns.js +198 -0
  25. package/dist/esm/src/Dream.js +186 -0
  26. package/dist/esm/src/db/DreamDbConnection.js +6 -0
  27. package/dist/esm/src/decorators/class/SoftDelete.js +12 -0
  28. package/dist/esm/src/dream/DreamClassTransactionBuilder.js +113 -0
  29. package/dist/esm/src/dream/Query.js +148 -0
  30. package/dist/esm/src/dream/QueryDriver/Base.js +84 -0
  31. package/dist/esm/src/dream/QueryDriver/Kysely.js +420 -81
  32. package/dist/esm/src/dream/internal/filterRowToKnownColumns.js +41 -0
  33. package/dist/esm/src/dream/internal/saveDream.js +6 -1
  34. package/dist/esm/src/dream/internal/sqlResultToDreamInstance.js +9 -2
  35. package/dist/esm/src/errors/CannotNamespaceAssociationFilterToAnotherTable.js +27 -0
  36. package/dist/esm/src/errors/schema-builder/CannotIgnoreAssociationColumn.js +38 -0
  37. package/dist/esm/src/errors/schema-builder/CannotIgnoreEncryptedColumn.js +20 -0
  38. package/dist/esm/src/errors/schema-builder/CannotIgnorePrimaryKey.js +18 -0
  39. package/dist/esm/src/errors/schema-builder/CannotIgnoreSoftDeleteColumn.js +21 -0
  40. package/dist/esm/src/errors/schema-builder/CannotIgnoreSortablePositionColumn.js +20 -0
  41. package/dist/esm/src/errors/schema-builder/CannotIgnoreSortableScopeColumn.js +24 -0
  42. package/dist/esm/src/errors/schema-builder/CannotIgnoreStiTypeColumn.js +17 -0
  43. package/dist/esm/src/errors/schema-builder/ConflictingIgnoredColumns.js +27 -0
  44. package/dist/esm/src/errors/schema-builder/IgnoredColumnMustBeCamelCase.js +21 -0
  45. package/dist/esm/src/helpers/cli/ASTConnectionBuilder.js +38 -1
  46. package/dist/esm/src/helpers/cli/ASTKyselyCodegenEnhancer.js +60 -0
  47. package/dist/esm/src/helpers/cli/generateMigrationContent.js +21 -13
  48. package/dist/esm/src/helpers/cli/resolveIgnoredColumns.js +198 -0
  49. package/dist/types/src/Dream.d.ts +178 -4
  50. package/dist/types/src/decorators/class/SoftDelete.d.ts +12 -0
  51. package/dist/types/src/dream/DreamClassTransactionBuilder.d.ts +103 -0
  52. package/dist/types/src/dream/Query.d.ts +138 -0
  53. package/dist/types/src/dream/QueryDriver/Base.d.ts +69 -0
  54. package/dist/types/src/dream/QueryDriver/Kysely.d.ts +187 -8
  55. package/dist/types/src/dream/internal/filterRowToKnownColumns.d.ts +30 -0
  56. package/dist/types/src/errors/CannotNamespaceAssociationFilterToAnotherTable.d.ts +8 -0
  57. package/dist/types/src/errors/schema-builder/CannotIgnoreAssociationColumn.d.ts +12 -0
  58. package/dist/types/src/errors/schema-builder/CannotIgnoreEncryptedColumn.d.ts +7 -0
  59. package/dist/types/src/errors/schema-builder/CannotIgnorePrimaryKey.d.ts +6 -0
  60. package/dist/types/src/errors/schema-builder/CannotIgnoreSoftDeleteColumn.d.ts +7 -0
  61. package/dist/types/src/errors/schema-builder/CannotIgnoreSortablePositionColumn.d.ts +7 -0
  62. package/dist/types/src/errors/schema-builder/CannotIgnoreSortableScopeColumn.d.ts +8 -0
  63. package/dist/types/src/errors/schema-builder/CannotIgnoreStiTypeColumn.d.ts +6 -0
  64. package/dist/types/src/errors/schema-builder/ConflictingIgnoredColumns.d.ts +7 -0
  65. package/dist/types/src/errors/schema-builder/IgnoredColumnMustBeCamelCase.d.ts +7 -0
  66. package/dist/types/src/helpers/cli/ASTConnectionBuilder.d.ts +20 -0
  67. package/dist/types/src/helpers/cli/ASTKyselyCodegenEnhancer.d.ts +13 -0
  68. package/dist/types/src/helpers/cli/resolveIgnoredColumns.d.ts +41 -0
  69. package/dist/types/src/types/associations/shared.d.ts +4 -1
  70. package/dist/types/src/types/dream.d.ts +17 -0
  71. package/dist/types/src/types/types/associations/shared.ts +10 -1
  72. package/dist/types/src/types/types/dream.ts +53 -0
  73. package/dist/types/src/types/types/variadic.ts +179 -140
  74. package/dist/types/src/types/variadic.d.ts +15 -10
  75. package/docs/assets/hierarchy.js +1 -1
  76. package/docs/assets/search.js +1 -1
  77. package/docs/classes/db.DreamMigrationHelpers.html +11 -11
  78. package/docs/classes/db.KyselyQueryDriver.html +96 -34
  79. package/docs/classes/db.PostgresQueryDriver.html +97 -35
  80. package/docs/classes/db.QueryDriverBase.html +77 -33
  81. package/docs/classes/errors.CheckConstraintViolation.html +3 -3
  82. package/docs/classes/errors.ColumnOverflow.html +3 -3
  83. package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
  84. package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +3 -3
  85. package/docs/classes/errors.DataTypeColumnTypeMismatch.html +3 -3
  86. package/docs/classes/errors.DecryptionError.html +2 -2
  87. package/docs/classes/errors.DecryptionParseError.html +2 -2
  88. package/docs/classes/errors.DecryptionRotationError.html +3 -3
  89. package/docs/classes/errors.GlobalNameNotSet.html +3 -3
  90. package/docs/classes/errors.InvalidCalendarDate.html +2 -2
  91. package/docs/classes/errors.InvalidClockTime.html +2 -2
  92. package/docs/classes/errors.InvalidClockTimeTz.html +2 -2
  93. package/docs/classes/errors.InvalidDateTime.html +2 -2
  94. package/docs/classes/errors.MissingSerializersDefinition.html +3 -3
  95. package/docs/classes/errors.NonLoadedAssociation.html +3 -3
  96. package/docs/classes/errors.NotNullViolation.html +3 -3
  97. package/docs/classes/errors.RecordNotFound.html +3 -3
  98. package/docs/classes/errors.ValidationError.html +3 -3
  99. package/docs/classes/index.CalendarDate.html +33 -33
  100. package/docs/classes/index.ClockTime.html +32 -32
  101. package/docs/classes/index.ClockTimeTz.html +35 -35
  102. package/docs/classes/index.DateTime.html +86 -86
  103. package/docs/classes/index.Decorators.html +19 -19
  104. package/docs/classes/index.Dream.html +247 -119
  105. package/docs/classes/index.DreamApp.html +10 -10
  106. package/docs/classes/index.DreamTransaction.html +2 -2
  107. package/docs/classes/index.Env.html +2 -2
  108. package/docs/classes/index.Query.html +155 -57
  109. package/docs/classes/system.CliFileWriter.html +4 -4
  110. package/docs/classes/system.DreamBin.html +2 -2
  111. package/docs/classes/system.DreamCLI.html +7 -7
  112. package/docs/classes/system.DreamImporter.html +2 -2
  113. package/docs/classes/system.DreamLogos.html +2 -2
  114. package/docs/classes/system.DreamSerializerBuilder.html +11 -11
  115. package/docs/classes/system.ObjectSerializerBuilder.html +8 -8
  116. package/docs/classes/system.PathHelpers.html +3 -3
  117. package/docs/classes/utils.Encrypt.html +3 -3
  118. package/docs/classes/utils.Range.html +2 -2
  119. package/docs/functions/db.closeAllDbConnections.html +1 -1
  120. package/docs/functions/db.dreamDbConnections.html +1 -1
  121. package/docs/functions/db.untypedDb.html +1 -1
  122. package/docs/functions/db.validateColumn.html +1 -1
  123. package/docs/functions/db.validateTable.html +1 -1
  124. package/docs/functions/errors.pgErrorType.html +1 -1
  125. package/docs/functions/index.DreamSerializer.html +1 -1
  126. package/docs/functions/index.ObjectSerializer.html +1 -1
  127. package/docs/functions/index.ReplicaSafe.html +1 -1
  128. package/docs/functions/index.STI.html +1 -1
  129. package/docs/functions/index.SoftDelete.html +12 -1
  130. package/docs/functions/utils.camelize.html +1 -1
  131. package/docs/functions/utils.capitalize.html +1 -1
  132. package/docs/functions/utils.cloneDeepSafe.html +1 -1
  133. package/docs/functions/utils.compact.html +1 -1
  134. package/docs/functions/utils.groupBy.html +1 -1
  135. package/docs/functions/utils.hyphenize.html +1 -1
  136. package/docs/functions/utils.intersection.html +1 -1
  137. package/docs/functions/utils.isEmpty.html +1 -1
  138. package/docs/functions/utils.normalizeUnicode.html +1 -1
  139. package/docs/functions/utils.pascalize.html +1 -1
  140. package/docs/functions/utils.percent.html +1 -1
  141. package/docs/functions/utils.range.html +1 -1
  142. package/docs/functions/utils.round.html +1 -1
  143. package/docs/functions/utils.sanitizeString.html +1 -1
  144. package/docs/functions/utils.snakeify.html +1 -1
  145. package/docs/functions/utils.sort.html +1 -1
  146. package/docs/functions/utils.sortBy.html +1 -1
  147. package/docs/functions/utils.sortObjectByKey.html +1 -1
  148. package/docs/functions/utils.sortObjectByValue.html +1 -1
  149. package/docs/functions/utils.uncapitalize.html +1 -1
  150. package/docs/functions/utils.uniq.html +1 -1
  151. package/docs/hierarchy.html +1 -1
  152. package/docs/interfaces/openapi.OpenapiDescription.html +2 -2
  153. package/docs/interfaces/openapi.OpenapiSchemaProperties.html +1 -1
  154. package/docs/interfaces/openapi.OpenapiSchemaPropertiesShorthand.html +1 -1
  155. package/docs/interfaces/openapi.OpenapiTypeFieldObject.html +1 -1
  156. package/docs/interfaces/types.BelongsToStatement.html +2 -2
  157. package/docs/interfaces/types.DecoratorContext.html +2 -2
  158. package/docs/interfaces/types.DreamAppInitOptions.html +2 -2
  159. package/docs/interfaces/types.DreamAppOpts.html +2 -2
  160. package/docs/interfaces/types.DreamDbConfig.html +5 -5
  161. package/docs/interfaces/types.DurationObject.html +2 -2
  162. package/docs/interfaces/types.EncryptOptions.html +2 -2
  163. package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
  164. package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
  165. package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
  166. package/docs/types/openapi.CommonOpenapiSchemaObjectFields.html +1 -1
  167. package/docs/types/openapi.OpenapiAllTypes.html +1 -1
  168. package/docs/types/openapi.OpenapiFormats.html +1 -1
  169. package/docs/types/openapi.OpenapiNumberFormats.html +1 -1
  170. package/docs/types/openapi.OpenapiPrimitiveBaseTypes.html +1 -1
  171. package/docs/types/openapi.OpenapiPrimitiveTypes.html +1 -1
  172. package/docs/types/openapi.OpenapiSchemaArray.html +1 -1
  173. package/docs/types/openapi.OpenapiSchemaArrayShorthand.html +1 -1
  174. package/docs/types/openapi.OpenapiSchemaBase.html +1 -1
  175. package/docs/types/openapi.OpenapiSchemaBody.html +1 -1
  176. package/docs/types/openapi.OpenapiSchemaBodyShorthand.html +1 -1
  177. package/docs/types/openapi.OpenapiSchemaCommonFields.html +1 -1
  178. package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +2 -2
  179. package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +2 -2
  180. package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +2 -2
  181. package/docs/types/openapi.OpenapiSchemaExpressionRef.html +2 -2
  182. package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +2 -2
  183. package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
  184. package/docs/types/openapi.OpenapiSchemaNull.html +2 -2
  185. package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
  186. package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
  187. package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +1 -1
  188. package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +1 -1
  189. package/docs/types/openapi.OpenapiSchemaObjectAnyOf.html +1 -1
  190. package/docs/types/openapi.OpenapiSchemaObjectAnyOfShorthand.html +1 -1
  191. package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
  192. package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
  193. package/docs/types/openapi.OpenapiSchemaObjectOneOf.html +1 -1
  194. package/docs/types/openapi.OpenapiSchemaObjectOneOfShorthand.html +1 -1
  195. package/docs/types/openapi.OpenapiSchemaObjectShorthand.html +1 -1
  196. package/docs/types/openapi.OpenapiSchemaPrimitiveGeneric.html +1 -1
  197. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAllOf.html +2 -2
  198. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +2 -2
  199. package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +2 -2
  200. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +2 -2
  201. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +2 -2
  202. package/docs/types/openapi.OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
  203. package/docs/types/openapi.OpenapiSchemaString.html +1 -1
  204. package/docs/types/openapi.OpenapiShorthandAllTypes.html +1 -1
  205. package/docs/types/openapi.OpenapiShorthandPrimitiveBaseTypes.html +1 -1
  206. package/docs/types/openapi.OpenapiShorthandPrimitiveTypes.html +1 -1
  207. package/docs/types/openapi.OpenapiTypeField.html +1 -1
  208. package/docs/types/system.DreamAppAllowedPackageManagersEnum.html +1 -1
  209. package/docs/types/types.CalendarDateDurationUnit.html +1 -1
  210. package/docs/types/types.CalendarDateObject.html +1 -1
  211. package/docs/types/types.Camelized.html +1 -1
  212. package/docs/types/types.ClockTimeObject.html +1 -1
  213. package/docs/types/types.DbConnectionType.html +1 -1
  214. package/docs/types/types.DbTypes.html +1 -1
  215. package/docs/types/types.DreamAssociationMetadata.html +1 -1
  216. package/docs/types/types.DreamAttributes.html +1 -1
  217. package/docs/types/types.DreamClassAssociationAndStatement.html +1 -1
  218. package/docs/types/types.DreamClassColumn.html +1 -1
  219. package/docs/types/types.DreamColumn.html +1 -1
  220. package/docs/types/types.DreamColumnNames.html +1 -1
  221. package/docs/types/types.DreamLogLevel.html +1 -1
  222. package/docs/types/types.DreamLogger.html +2 -2
  223. package/docs/types/types.DreamModelSerializerType.html +1 -1
  224. package/docs/types/types.DreamOrViewModelClassSerializerKey.html +1 -1
  225. package/docs/types/types.DreamOrViewModelSerializerKey.html +1 -1
  226. package/docs/types/types.DreamParamSafeAttributes.html +1 -1
  227. package/docs/types/types.DreamParamSafeColumnNames.html +1 -1
  228. package/docs/types/types.DreamSerializable.html +1 -1
  229. package/docs/types/types.DreamSerializableArray.html +1 -1
  230. package/docs/types/types.DreamSerializerKey.html +1 -1
  231. package/docs/types/types.DreamSerializers.html +1 -1
  232. package/docs/types/types.DreamVirtualColumns.html +1 -1
  233. package/docs/types/types.DurationUnit.html +1 -1
  234. package/docs/types/types.EncryptAlgorithm.html +1 -1
  235. package/docs/types/types.HasManyStatement.html +1 -1
  236. package/docs/types/types.HasOneStatement.html +1 -1
  237. package/docs/types/types.Hyphenized.html +1 -1
  238. package/docs/types/types.Pascalized.html +1 -1
  239. package/docs/types/types.PrimaryKeyType.html +1 -1
  240. package/docs/types/types.RoundingPrecision.html +1 -1
  241. package/docs/types/types.SerializerCasing.html +1 -1
  242. package/docs/types/types.SimpleObjectSerializerType.html +1 -1
  243. package/docs/types/types.Snakeified.html +1 -1
  244. package/docs/types/types.StrictInterface.html +1 -1
  245. package/docs/types/types.UpdateableAssociationProperties.html +1 -1
  246. package/docs/types/types.UpdateableProperties.html +1 -1
  247. package/docs/types/types.ValidationType.html +1 -1
  248. package/docs/types/types.ViewModel.html +2 -2
  249. package/docs/types/types.ViewModelClass.html +1 -1
  250. package/docs/types/types.WeekdayName.html +1 -1
  251. package/docs/types/types.WhereStatementForDream.html +1 -1
  252. package/docs/types/types.WhereStatementForDreamClass.html +1 -1
  253. package/docs/variables/index.DreamConst.html +1 -1
  254. package/docs/variables/index.ops.html +1 -1
  255. package/docs/variables/openapi.openapiPrimitiveTypes.html +1 -1
  256. package/docs/variables/openapi.openapiShorthandPrimitiveTypes.html +1 -1
  257. package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
  258. package/docs/variables/system.primaryKeyTypes.html +1 -1
  259. package/package.json +3 -3
  260. package/dist/cjs/src/dream/internal/associations/throughAssociationHasOptionsBesidesThroughAndSource.js +0 -11
  261. package/dist/cjs/src/errors/associations/ThroughAssociationConditionsIncompatibleWithThroughAssociationSource.js +0 -17
  262. package/dist/esm/src/dream/internal/associations/throughAssociationHasOptionsBesidesThroughAndSource.js +0 -11
  263. package/dist/esm/src/errors/associations/ThroughAssociationConditionsIncompatibleWithThroughAssociationSource.js +0 -17
  264. package/dist/types/src/dream/internal/associations/throughAssociationHasOptionsBesidesThroughAndSource.d.ts +0 -13
  265. package/dist/types/src/errors/associations/ThroughAssociationConditionsIncompatibleWithThroughAssociationSource.d.ts +0 -12
@@ -56,6 +56,25 @@ export default class DreamClassTransactionBuilder<DreamClass extends typeof Drea
56
56
  * @returns The number of records corresponding to this model
57
57
  */
58
58
  count<I extends DreamClassTransactionBuilder<DreamClass, DreamInstance>>(this: I): Promise<number>;
59
+ /**
60
+ * Retrieves the number of records in each group, keyed by the
61
+ * value of the provided group column (a SQL `GROUP BY`).
62
+ *
63
+ * ```ts
64
+ * await ApplicationModel.transaction(async txn => {
65
+ * await User.txn(txn).countBy('name')
66
+ * // Map(2) { 'fred' => 2, 'zed' => 1 }
67
+ * })
68
+ * ```
69
+ *
70
+ * Only groups with at least one matching row appear in the Map; seed absent
71
+ * groups yourself with `map.get(key) ?? 0`. When the group column is nullable,
72
+ * records with a `null` value are grouped under a real `null` key.
73
+ *
74
+ * @param groupColumn - the column to group by
75
+ * @returns A Map from each present group value to the number of records in that group
76
+ */
77
+ countBy<I extends DreamClassTransactionBuilder<DreamClass, DreamInstance>, T extends DreamColumnNames<DreamInstance>>(this: I, groupColumn: T): Promise<Map<DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][T & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]["coercedType" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][T & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]], number>>;
59
78
  /**
60
79
  * Returns a new Query instance, specifying a limit
61
80
  *
@@ -99,6 +118,27 @@ export default class DreamClassTransactionBuilder<DreamClass extends typeof Drea
99
118
  * @returns The max value of the specified column for this model's records
100
119
  */
101
120
  max<I extends DreamClassTransactionBuilder<DreamClass, DreamInstance>, T extends DreamColumnNames<DreamInstance>>(this: I, columnName: T): Promise<DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][T & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]["coercedType" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][T & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]]>;
121
+ /**
122
+ * Retrieves the max value of the specified column within each group, keyed by
123
+ * the value of the provided group column (a SQL `GROUP BY`).
124
+ *
125
+ * ```ts
126
+ * await ApplicationModel.transaction(async txn => {
127
+ * await CompositionAsset.txn(txn).maxBy('name', 'score')
128
+ * // Map(2) { 'primary' => 9, 'secondary' => 4 }
129
+ * })
130
+ * ```
131
+ *
132
+ * Only groups with at least one matching row appear in the Map. When the group
133
+ * column is nullable, records with a `null` value are grouped under a real
134
+ * `null` key; a group whose aggregated values are all `null` yields a `null`
135
+ * value.
136
+ *
137
+ * @param groupColumn - the column to group by
138
+ * @param aggregatedColumn - the column to take the max of within each group
139
+ * @returns A Map from each present group value to the max of the aggregated column in that group
140
+ */
141
+ maxBy<I extends DreamClassTransactionBuilder<DreamClass, DreamInstance>, GroupColumnName extends DreamColumnNames<DreamInstance>, AggregatedColumnName extends DreamColumnNames<DreamInstance>>(this: I, groupColumn: GroupColumnName, aggregatedColumn: AggregatedColumnName): Promise<Map<DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][GroupColumnName & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]["coercedType" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][GroupColumnName & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]], DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][AggregatedColumnName & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]["coercedType" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][AggregatedColumnName & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]]>>;
102
142
  /**
103
143
  * Retrieves the min value of the specified column
104
144
  * for this model's records.
@@ -114,6 +154,27 @@ export default class DreamClassTransactionBuilder<DreamClass extends typeof Drea
114
154
  * @returns The min value of the specified column for this model's records
115
155
  */
116
156
  min<I extends DreamClassTransactionBuilder<DreamClass, DreamInstance>, T extends DreamColumnNames<DreamInstance>>(this: I, columnName: T): Promise<DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][T & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]["coercedType" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][T & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]]>;
157
+ /**
158
+ * Retrieves the min value of the specified column within each group, keyed by
159
+ * the value of the provided group column (a SQL `GROUP BY`).
160
+ *
161
+ * ```ts
162
+ * await ApplicationModel.transaction(async txn => {
163
+ * await CompositionAsset.txn(txn).minBy('name', 'score')
164
+ * // Map(2) { 'primary' => 1, 'secondary' => 4 }
165
+ * })
166
+ * ```
167
+ *
168
+ * Only groups with at least one matching row appear in the Map. When the group
169
+ * column is nullable, records with a `null` value are grouped under a real
170
+ * `null` key; a group whose aggregated values are all `null` yields a `null`
171
+ * value.
172
+ *
173
+ * @param groupColumn - the column to group by
174
+ * @param aggregatedColumn - the column to take the min of within each group
175
+ * @returns A Map from each present group value to the min of the aggregated column in that group
176
+ */
177
+ minBy<I extends DreamClassTransactionBuilder<DreamClass, DreamInstance>, GroupColumnName extends DreamColumnNames<DreamInstance>, AggregatedColumnName extends DreamColumnNames<DreamInstance>>(this: I, groupColumn: GroupColumnName, aggregatedColumn: AggregatedColumnName): Promise<Map<DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][GroupColumnName & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]["coercedType" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][GroupColumnName & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]], DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][AggregatedColumnName & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]["coercedType" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][AggregatedColumnName & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]]>>;
117
178
  /**
118
179
  * Retrieves the sum value of the specified column
119
180
  * for this Query
@@ -127,6 +188,27 @@ export default class DreamClassTransactionBuilder<DreamClass extends typeof Drea
127
188
  * @returns the sum of the values of the specified column for this Query
128
189
  */
129
190
  sum<I extends DreamClassTransactionBuilder<DreamClass, DreamInstance>, T extends DreamColumnNames<DreamInstance>>(this: I, columnName: T): Promise<DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][T & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]["coercedType" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][T & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]]>;
191
+ /**
192
+ * Retrieves the sum of the specified column within each group, keyed by
193
+ * the value of the provided group column (a SQL `GROUP BY`).
194
+ *
195
+ * ```ts
196
+ * await ApplicationModel.transaction(async txn => {
197
+ * await CompositionAsset.txn(txn).sumBy('name', 'score')
198
+ * // Map(2) { 'primary' => 10, 'secondary' => 4 }
199
+ * })
200
+ * ```
201
+ *
202
+ * Only groups with at least one matching row appear in the Map. When the group
203
+ * column is nullable, records with a `null` value are grouped under a real
204
+ * `null` key; a group whose aggregated values are all `null` yields a `null`
205
+ * value.
206
+ *
207
+ * @param groupColumn - the column to group by
208
+ * @param aggregatedColumn - the column to sum within each group
209
+ * @returns A Map from each present group value to the sum of the aggregated column in that group
210
+ */
211
+ sumBy<I extends DreamClassTransactionBuilder<DreamClass, DreamInstance>, GroupColumnName extends DreamColumnNames<DreamInstance>, AggregatedColumnName extends DreamColumnNames<DreamInstance>>(this: I, groupColumn: GroupColumnName, aggregatedColumn: AggregatedColumnName): Promise<Map<DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][GroupColumnName & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]["coercedType" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][GroupColumnName & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]], DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][AggregatedColumnName & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]["coercedType" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][AggregatedColumnName & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]]>>;
130
212
  /**
131
213
  * Retrieves the average value of the specified column
132
214
  * for this Query
@@ -140,6 +222,27 @@ export default class DreamClassTransactionBuilder<DreamClass extends typeof Drea
140
222
  * @returns the average of the values of the specified column for this Query
141
223
  */
142
224
  avg<I extends DreamClassTransactionBuilder<DreamClass, DreamInstance>, T extends DreamColumnNames<DreamInstance>>(this: I, columnName: T): Promise<DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][T & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]["coercedType" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][T & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]]>;
225
+ /**
226
+ * Retrieves the average of the specified column within each group, keyed by
227
+ * the value of the provided group column (a SQL `GROUP BY`).
228
+ *
229
+ * ```ts
230
+ * await ApplicationModel.transaction(async txn => {
231
+ * await CompositionAsset.txn(txn).avgBy('name', 'score')
232
+ * // Map(2) { 'primary' => 5, 'secondary' => 4 }
233
+ * })
234
+ * ```
235
+ *
236
+ * Only groups with at least one matching row appear in the Map. When the group
237
+ * column is nullable, records with a `null` value are grouped under a real
238
+ * `null` key; a group whose aggregated values are all `null` yields a `null`
239
+ * value.
240
+ *
241
+ * @param groupColumn - the column to group by
242
+ * @param aggregatedColumn - the column to average within each group
243
+ * @returns A Map from each present group value to the average of the aggregated column in that group
244
+ */
245
+ avgBy<I extends DreamClassTransactionBuilder<DreamClass, DreamInstance>, GroupColumnName extends DreamColumnNames<DreamInstance>, AggregatedColumnName extends DreamColumnNames<DreamInstance>>(this: I, groupColumn: GroupColumnName, aggregatedColumn: AggregatedColumnName): Promise<Map<DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][GroupColumnName & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]["coercedType" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][GroupColumnName & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]], DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][AggregatedColumnName & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]["coercedType" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]][AggregatedColumnName & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]["columns" & keyof DreamInstance["schema"][DreamInstance["table"] & keyof DreamInstance["schema"]]]]]>>;
143
246
  /**
144
247
  * Persists a new record, setting the provided attributes.
145
248
  * Automatically sets createdAt and updatedAt timestamps.
@@ -308,6 +308,17 @@ export default class Query<DreamInstance extends Dream, QueryTypeOpts extends Re
308
308
  * 3. each nested association will result in an additional record which duplicates data from the outer record. E.g., given `.leftJoinPreload('a', 'b', 'c')`, if each `a` has 10 `b` and each `b` has 10 `c`, then for one `a`, 100 records will be returned, each of which has all of the columns of `a`. `.preload('a', 'b', 'c')` would perform three separate SQL queries, but the data for a single `a` would only be returned once.
309
309
  * 4. the individual query becomes more complex the more associations are included
310
310
  * 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
311
+ * 6. unlike base-model reads, `preload`/`load`, and saves — which tolerate
312
+ * schema/image skew (e.g. a rolling deploy dropping a column while
313
+ * containers compiled against the previous schema are still draining) —
314
+ * leftJoinPreload must enumerate every compiled column of every joined
315
+ * model under per-alias names (per-alias `*` is not expressible in a
316
+ * single flat row), so an **unplanned** column drop breaks
317
+ * leftJoinPreload queries for the duration of the rollout window. A
318
+ * **planned** drop is safe when performed via the two-deploy process
319
+ * documented on the `ignoredColumns` getter of Dream: declaring the
320
+ * column ignored removes it from the generated schema, so leftJoinPreload
321
+ * stops naming it a full deploy before the column is actually dropped.
311
322
  *
312
323
  *
313
324
  * ```ts
@@ -697,6 +708,37 @@ export default class Query<DreamInstance extends Dream, QueryTypeOpts extends Re
697
708
  * @returns The number of records matching the Query
698
709
  */
699
710
  count(): Promise<number>;
711
+ /**
712
+ * Retrieves the number of records in each group, keyed by the
713
+ * value of the provided group column (a SQL `GROUP BY`).
714
+ *
715
+ * ```ts
716
+ * await User.query().countBy('name')
717
+ * // Map(2) { 'fred' => 2, 'zed' => 1 }
718
+ *
719
+ * await User.where({ email: ops.ilike('%gmail.com') }).countBy('name')
720
+ * // Map(1) { 'fred' => 3 }
721
+ * ```
722
+ *
723
+ * Any `where` clauses, base scopes (soft-delete / STI), and joined-association
724
+ * `and` clauses on the Query carry through automatically. A joined-association
725
+ * column may be grouped on by passing its namespaced name (e.g.
726
+ * `'compositionAssets.name'`).
727
+ *
728
+ * Only groups with at least one matching row appear in the Map (inherent to
729
+ * `GROUP BY`); seed absent groups yourself with `map.get(key) ?? 0`. When the
730
+ * group column is nullable, records with a `null` value are grouped under a real
731
+ * `null` key.
732
+ *
733
+ * ```ts
734
+ * await Composition.query().innerJoin('compositionAssets').countBy('compositionAssets.name')
735
+ * // Map(2) { 'primary' => 3, null => 1 }
736
+ * ```
737
+ *
738
+ * @param groupColumn - the column to group by (base or joined-association-namespaced)
739
+ * @returns A Map from each present group value to the number of records in that group
740
+ */
741
+ countBy<Q extends Query<DreamInstance, QueryTypeOpts>, DB extends DreamInstance['DB'], GroupColumnName extends ColumnNamesAccountingForJoinedAssociations<Q['queryTypeOpts']['joinedAssociations'], DB, QueryTypeOpts['rootTableName'], QueryTypeOpts['rootTableAlias']>, GroupKey extends NamespacedOrBaseModelColumnTypes<[GroupColumnName], Q, DreamInstance>[0]>(groupColumn: GroupColumnName): Promise<Map<GroupKey, number>>;
700
742
  /**
701
743
  * Returns new Query with distinct clause applied.
702
744
  * If no column is specified, applies distinct to the primary key.
@@ -739,6 +781,30 @@ export default class Query<DreamInstance extends Dream, QueryTypeOpts extends Re
739
781
  *
740
782
  */
741
783
  max<Q extends Query<DreamInstance, QueryTypeOpts>, DB extends DreamInstance['DB'], ColumnName extends ColumnNamesAccountingForJoinedAssociations<Q['queryTypeOpts']['joinedAssociations'], DB, QueryTypeOpts['rootTableName'], QueryTypeOpts['rootTableAlias']>, ReturnType extends NamespacedOrBaseModelColumnTypes<[ColumnName], Q, DreamInstance>[0]>(columnName: ColumnName): Promise<ReturnType>;
784
+ /**
785
+ * Retrieves the max value of the specified column within each group, keyed by
786
+ * the value of the provided group column (a SQL `GROUP BY`).
787
+ *
788
+ * ```ts
789
+ * await CompositionAsset.query().maxBy('name', 'score')
790
+ * // Map(2) { 'primary' => 9, 'secondary' => 4 }
791
+ * ```
792
+ *
793
+ * Any `where` clauses, base scopes (soft-delete / STI), and joined-association
794
+ * `and` clauses on the Query carry through automatically. A joined-association
795
+ * column may be grouped on or aggregated by passing its namespaced name (e.g.
796
+ * `'compositionAssets.name'`).
797
+ *
798
+ * Only groups with at least one matching row appear in the Map (inherent to
799
+ * `GROUP BY`). When the group column is nullable, records with a `null` value
800
+ * are grouped under a real `null` key; a group whose aggregated values are all
801
+ * `null` yields a `null` value.
802
+ *
803
+ * @param groupColumn - the column to group by (base or joined-association-namespaced)
804
+ * @param aggregatedColumn - the column to take the max of within each group
805
+ * @returns A Map from each present group value to the max of the aggregated column in that group
806
+ */
807
+ maxBy<Q extends Query<DreamInstance, QueryTypeOpts>, DB extends DreamInstance['DB'], GroupColumnName extends ColumnNamesAccountingForJoinedAssociations<Q['queryTypeOpts']['joinedAssociations'], DB, QueryTypeOpts['rootTableName'], QueryTypeOpts['rootTableAlias']>, AggregatedColumnName extends ColumnNamesAccountingForJoinedAssociations<Q['queryTypeOpts']['joinedAssociations'], DB, QueryTypeOpts['rootTableName'], QueryTypeOpts['rootTableAlias']>, GroupKey extends NamespacedOrBaseModelColumnTypes<[GroupColumnName], Q, DreamInstance>[0], AggregatedType extends NamespacedOrBaseModelColumnTypes<[AggregatedColumnName], Q, DreamInstance>[0]>(groupColumn: GroupColumnName, aggregatedColumn: AggregatedColumnName): Promise<Map<GroupKey, AggregatedType>>;
742
808
  /**
743
809
  * Retrieves the min value of the specified column
744
810
  * for this Query
@@ -752,6 +818,30 @@ export default class Query<DreamInstance extends Dream, QueryTypeOpts extends Re
752
818
  * @returns the min value of the specified column for this Query
753
819
  */
754
820
  min<Q extends Query<DreamInstance, QueryTypeOpts>, DB extends DreamInstance['DB'], ColumnName extends ColumnNamesAccountingForJoinedAssociations<Q['queryTypeOpts']['joinedAssociations'], DB, QueryTypeOpts['rootTableName'], QueryTypeOpts['rootTableAlias']>, ReturnType extends NamespacedOrBaseModelColumnTypes<[ColumnName], Q, DreamInstance>[0]>(columnName: ColumnName): Promise<ReturnType>;
821
+ /**
822
+ * Retrieves the min value of the specified column within each group, keyed by
823
+ * the value of the provided group column (a SQL `GROUP BY`).
824
+ *
825
+ * ```ts
826
+ * await CompositionAsset.query().minBy('name', 'score')
827
+ * // Map(2) { 'primary' => 1, 'secondary' => 4 }
828
+ * ```
829
+ *
830
+ * Any `where` clauses, base scopes (soft-delete / STI), and joined-association
831
+ * `and` clauses on the Query carry through automatically. A joined-association
832
+ * column may be grouped on or aggregated by passing its namespaced name (e.g.
833
+ * `'compositionAssets.name'`).
834
+ *
835
+ * Only groups with at least one matching row appear in the Map (inherent to
836
+ * `GROUP BY`). When the group column is nullable, records with a `null` value
837
+ * are grouped under a real `null` key; a group whose aggregated values are all
838
+ * `null` yields a `null` value.
839
+ *
840
+ * @param groupColumn - the column to group by (base or joined-association-namespaced)
841
+ * @param aggregatedColumn - the column to take the min of within each group
842
+ * @returns A Map from each present group value to the min of the aggregated column in that group
843
+ */
844
+ minBy<Q extends Query<DreamInstance, QueryTypeOpts>, DB extends DreamInstance['DB'], GroupColumnName extends ColumnNamesAccountingForJoinedAssociations<Q['queryTypeOpts']['joinedAssociations'], DB, QueryTypeOpts['rootTableName'], QueryTypeOpts['rootTableAlias']>, AggregatedColumnName extends ColumnNamesAccountingForJoinedAssociations<Q['queryTypeOpts']['joinedAssociations'], DB, QueryTypeOpts['rootTableName'], QueryTypeOpts['rootTableAlias']>, GroupKey extends NamespacedOrBaseModelColumnTypes<[GroupColumnName], Q, DreamInstance>[0], AggregatedType extends NamespacedOrBaseModelColumnTypes<[AggregatedColumnName], Q, DreamInstance>[0]>(groupColumn: GroupColumnName, aggregatedColumn: AggregatedColumnName): Promise<Map<GroupKey, AggregatedType>>;
755
845
  /**
756
846
  * Retrieves the sum value of the specified column
757
847
  * for this Query
@@ -765,6 +855,30 @@ export default class Query<DreamInstance extends Dream, QueryTypeOpts extends Re
765
855
  * @returns the sum of the values of the specified column for this Query
766
856
  */
767
857
  sum<Q extends Query<DreamInstance, QueryTypeOpts>, DB extends DreamInstance['DB'], ColumnName extends ColumnNamesAccountingForJoinedAssociations<Q['queryTypeOpts']['joinedAssociations'], DB, QueryTypeOpts['rootTableName'], QueryTypeOpts['rootTableAlias']>, ReturnType extends NamespacedOrBaseModelColumnTypes<[ColumnName], Q, DreamInstance>[0]>(columnName: ColumnName): Promise<ReturnType>;
858
+ /**
859
+ * Retrieves the sum of the specified column within each group, keyed by
860
+ * the value of the provided group column (a SQL `GROUP BY`).
861
+ *
862
+ * ```ts
863
+ * await CompositionAsset.query().sumBy('name', 'score')
864
+ * // Map(2) { 'primary' => 10, 'secondary' => 4 }
865
+ * ```
866
+ *
867
+ * Any `where` clauses, base scopes (soft-delete / STI), and joined-association
868
+ * `and` clauses on the Query carry through automatically. A joined-association
869
+ * column may be grouped on or aggregated by passing its namespaced name (e.g.
870
+ * `'compositionAssets.name'`).
871
+ *
872
+ * Only groups with at least one matching row appear in the Map (inherent to
873
+ * `GROUP BY`). When the group column is nullable, records with a `null` value
874
+ * are grouped under a real `null` key; a group whose aggregated values are all
875
+ * `null` yields a `null` value.
876
+ *
877
+ * @param groupColumn - the column to group by (base or joined-association-namespaced)
878
+ * @param aggregatedColumn - the column to sum within each group
879
+ * @returns A Map from each present group value to the sum of the aggregated column in that group
880
+ */
881
+ sumBy<Q extends Query<DreamInstance, QueryTypeOpts>, DB extends DreamInstance['DB'], GroupColumnName extends ColumnNamesAccountingForJoinedAssociations<Q['queryTypeOpts']['joinedAssociations'], DB, QueryTypeOpts['rootTableName'], QueryTypeOpts['rootTableAlias']>, AggregatedColumnName extends ColumnNamesAccountingForJoinedAssociations<Q['queryTypeOpts']['joinedAssociations'], DB, QueryTypeOpts['rootTableName'], QueryTypeOpts['rootTableAlias']>, GroupKey extends NamespacedOrBaseModelColumnTypes<[GroupColumnName], Q, DreamInstance>[0], AggregatedType extends NamespacedOrBaseModelColumnTypes<[AggregatedColumnName], Q, DreamInstance>[0]>(groupColumn: GroupColumnName, aggregatedColumn: AggregatedColumnName): Promise<Map<GroupKey, AggregatedType>>;
768
882
  /**
769
883
  * Retrieves the average value of the specified column
770
884
  * for this Query
@@ -778,6 +892,30 @@ export default class Query<DreamInstance extends Dream, QueryTypeOpts extends Re
778
892
  * @returns the average of the values of the specified column for this Query
779
893
  */
780
894
  avg<Q extends Query<DreamInstance, QueryTypeOpts>, DB extends DreamInstance['DB'], ColumnName extends ColumnNamesAccountingForJoinedAssociations<Q['queryTypeOpts']['joinedAssociations'], DB, QueryTypeOpts['rootTableName'], QueryTypeOpts['rootTableAlias']>, ReturnType extends NamespacedOrBaseModelColumnTypes<[ColumnName], Q, DreamInstance>[0]>(columnName: ColumnName): Promise<ReturnType>;
895
+ /**
896
+ * Retrieves the average of the specified column within each group, keyed by
897
+ * the value of the provided group column (a SQL `GROUP BY`).
898
+ *
899
+ * ```ts
900
+ * await CompositionAsset.query().avgBy('name', 'score')
901
+ * // Map(2) { 'primary' => 5, 'secondary' => 4 }
902
+ * ```
903
+ *
904
+ * Any `where` clauses, base scopes (soft-delete / STI), and joined-association
905
+ * `and` clauses on the Query carry through automatically. A joined-association
906
+ * column may be grouped on or aggregated by passing its namespaced name (e.g.
907
+ * `'compositionAssets.name'`).
908
+ *
909
+ * Only groups with at least one matching row appear in the Map (inherent to
910
+ * `GROUP BY`). When the group column is nullable, records with a `null` value
911
+ * are grouped under a real `null` key; a group whose aggregated values are all
912
+ * `null` yields a `null` value.
913
+ *
914
+ * @param groupColumn - the column to group by (base or joined-association-namespaced)
915
+ * @param aggregatedColumn - the column to average within each group
916
+ * @returns A Map from each present group value to the average of the aggregated column in that group
917
+ */
918
+ avgBy<Q extends Query<DreamInstance, QueryTypeOpts>, DB extends DreamInstance['DB'], GroupColumnName extends ColumnNamesAccountingForJoinedAssociations<Q['queryTypeOpts']['joinedAssociations'], DB, QueryTypeOpts['rootTableName'], QueryTypeOpts['rootTableAlias']>, AggregatedColumnName extends ColumnNamesAccountingForJoinedAssociations<Q['queryTypeOpts']['joinedAssociations'], DB, QueryTypeOpts['rootTableName'], QueryTypeOpts['rootTableAlias']>, GroupKey extends NamespacedOrBaseModelColumnTypes<[GroupColumnName], Q, DreamInstance>[0], AggregatedType extends NamespacedOrBaseModelColumnTypes<[AggregatedColumnName], Q, DreamInstance>[0]>(groupColumn: GroupColumnName, aggregatedColumn: AggregatedColumnName): Promise<Map<GroupKey, AggregatedType>>;
781
919
  /**
782
920
  * Plucks the provided fields from the given dream class table
783
921
  *
@@ -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
  *