@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
@@ -442,6 +442,17 @@ export default class Query {
442
442
  * 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.
443
443
  * 4. the individual query becomes more complex the more associations are included
444
444
  * 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
445
+ * 6. unlike base-model reads, `preload`/`load`, and saves — which tolerate
446
+ * schema/image skew (e.g. a rolling deploy dropping a column while
447
+ * containers compiled against the previous schema are still draining) —
448
+ * leftJoinPreload must enumerate every compiled column of every joined
449
+ * model under per-alias names (per-alias `*` is not expressible in a
450
+ * single flat row), so an **unplanned** column drop breaks
451
+ * leftJoinPreload queries for the duration of the rollout window. A
452
+ * **planned** drop is safe when performed via the two-deploy process
453
+ * documented on the `ignoredColumns` getter of Dream: declaring the
454
+ * column ignored removes it from the generated schema, so leftJoinPreload
455
+ * stops naming it a full deploy before the column is actually dropped.
445
456
  *
446
457
  *
447
458
  * ```ts
@@ -980,6 +991,39 @@ export default class Query {
980
991
  async count() {
981
992
  return await this.dbDriverInstance().count();
982
993
  }
994
+ /**
995
+ * Retrieves the number of records in each group, keyed by the
996
+ * value of the provided group column (a SQL `GROUP BY`).
997
+ *
998
+ * ```ts
999
+ * await User.query().countBy('name')
1000
+ * // Map(2) { 'fred' => 2, 'zed' => 1 }
1001
+ *
1002
+ * await User.where({ email: ops.ilike('%gmail.com') }).countBy('name')
1003
+ * // Map(1) { 'fred' => 3 }
1004
+ * ```
1005
+ *
1006
+ * Any `where` clauses, base scopes (soft-delete / STI), and joined-association
1007
+ * `and` clauses on the Query carry through automatically. A joined-association
1008
+ * column may be grouped on by passing its namespaced name (e.g.
1009
+ * `'compositionAssets.name'`).
1010
+ *
1011
+ * Only groups with at least one matching row appear in the Map (inherent to
1012
+ * `GROUP BY`); seed absent groups yourself with `map.get(key) ?? 0`. When the
1013
+ * group column is nullable, records with a `null` value are grouped under a real
1014
+ * `null` key.
1015
+ *
1016
+ * ```ts
1017
+ * await Composition.query().innerJoin('compositionAssets').countBy('compositionAssets.name')
1018
+ * // Map(2) { 'primary' => 3, null => 1 }
1019
+ * ```
1020
+ *
1021
+ * @param groupColumn - the column to group by (base or joined-association-namespaced)
1022
+ * @returns A Map from each present group value to the number of records in that group
1023
+ */
1024
+ async countBy(groupColumn) {
1025
+ return await this.dbDriverInstance().countBy(groupColumn);
1026
+ }
983
1027
  /**
984
1028
  * Returns new Query with distinct clause applied.
985
1029
  * If no column is specified, applies distinct to the primary key.
@@ -1038,6 +1082,32 @@ export default class Query {
1038
1082
  async max(columnName) {
1039
1083
  return await this.dbDriverInstance().max(columnName);
1040
1084
  }
1085
+ /**
1086
+ * Retrieves the max value of the specified column within each group, keyed by
1087
+ * the value of the provided group column (a SQL `GROUP BY`).
1088
+ *
1089
+ * ```ts
1090
+ * await CompositionAsset.query().maxBy('name', 'score')
1091
+ * // Map(2) { 'primary' => 9, 'secondary' => 4 }
1092
+ * ```
1093
+ *
1094
+ * Any `where` clauses, base scopes (soft-delete / STI), and joined-association
1095
+ * `and` clauses on the Query carry through automatically. A joined-association
1096
+ * column may be grouped on or aggregated by passing its namespaced name (e.g.
1097
+ * `'compositionAssets.name'`).
1098
+ *
1099
+ * Only groups with at least one matching row appear in the Map (inherent to
1100
+ * `GROUP BY`). When the group column is nullable, records with a `null` value
1101
+ * are grouped under a real `null` key; a group whose aggregated values are all
1102
+ * `null` yields a `null` value.
1103
+ *
1104
+ * @param groupColumn - the column to group by (base or joined-association-namespaced)
1105
+ * @param aggregatedColumn - the column to take the max of within each group
1106
+ * @returns A Map from each present group value to the max of the aggregated column in that group
1107
+ */
1108
+ async maxBy(groupColumn, aggregatedColumn) {
1109
+ return await this.dbDriverInstance().maxBy(groupColumn, aggregatedColumn);
1110
+ }
1041
1111
  /**
1042
1112
  * Retrieves the min value of the specified column
1043
1113
  * for this Query
@@ -1053,6 +1123,32 @@ export default class Query {
1053
1123
  async min(columnName) {
1054
1124
  return await this.dbDriverInstance().min(columnName);
1055
1125
  }
1126
+ /**
1127
+ * Retrieves the min value of the specified column within each group, keyed by
1128
+ * the value of the provided group column (a SQL `GROUP BY`).
1129
+ *
1130
+ * ```ts
1131
+ * await CompositionAsset.query().minBy('name', 'score')
1132
+ * // Map(2) { 'primary' => 1, 'secondary' => 4 }
1133
+ * ```
1134
+ *
1135
+ * Any `where` clauses, base scopes (soft-delete / STI), and joined-association
1136
+ * `and` clauses on the Query carry through automatically. A joined-association
1137
+ * column may be grouped on or aggregated by passing its namespaced name (e.g.
1138
+ * `'compositionAssets.name'`).
1139
+ *
1140
+ * Only groups with at least one matching row appear in the Map (inherent to
1141
+ * `GROUP BY`). When the group column is nullable, records with a `null` value
1142
+ * are grouped under a real `null` key; a group whose aggregated values are all
1143
+ * `null` yields a `null` value.
1144
+ *
1145
+ * @param groupColumn - the column to group by (base or joined-association-namespaced)
1146
+ * @param aggregatedColumn - the column to take the min of within each group
1147
+ * @returns A Map from each present group value to the min of the aggregated column in that group
1148
+ */
1149
+ async minBy(groupColumn, aggregatedColumn) {
1150
+ return await this.dbDriverInstance().minBy(groupColumn, aggregatedColumn);
1151
+ }
1056
1152
  /**
1057
1153
  * Retrieves the sum value of the specified column
1058
1154
  * for this Query
@@ -1068,6 +1164,32 @@ export default class Query {
1068
1164
  async sum(columnName) {
1069
1165
  return await this.dbDriverInstance().sum(columnName);
1070
1166
  }
1167
+ /**
1168
+ * Retrieves the sum of the specified column within each group, keyed by
1169
+ * the value of the provided group column (a SQL `GROUP BY`).
1170
+ *
1171
+ * ```ts
1172
+ * await CompositionAsset.query().sumBy('name', 'score')
1173
+ * // Map(2) { 'primary' => 10, 'secondary' => 4 }
1174
+ * ```
1175
+ *
1176
+ * Any `where` clauses, base scopes (soft-delete / STI), and joined-association
1177
+ * `and` clauses on the Query carry through automatically. A joined-association
1178
+ * column may be grouped on or aggregated by passing its namespaced name (e.g.
1179
+ * `'compositionAssets.name'`).
1180
+ *
1181
+ * Only groups with at least one matching row appear in the Map (inherent to
1182
+ * `GROUP BY`). When the group column is nullable, records with a `null` value
1183
+ * are grouped under a real `null` key; a group whose aggregated values are all
1184
+ * `null` yields a `null` value.
1185
+ *
1186
+ * @param groupColumn - the column to group by (base or joined-association-namespaced)
1187
+ * @param aggregatedColumn - the column to sum within each group
1188
+ * @returns A Map from each present group value to the sum of the aggregated column in that group
1189
+ */
1190
+ async sumBy(groupColumn, aggregatedColumn) {
1191
+ return await this.dbDriverInstance().sumBy(groupColumn, aggregatedColumn);
1192
+ }
1071
1193
  /**
1072
1194
  * Retrieves the average value of the specified column
1073
1195
  * for this Query
@@ -1083,6 +1205,32 @@ export default class Query {
1083
1205
  async avg(columnName) {
1084
1206
  return await this.dbDriverInstance().avg(columnName);
1085
1207
  }
1208
+ /**
1209
+ * Retrieves the average of the specified column within each group, keyed by
1210
+ * the value of the provided group column (a SQL `GROUP BY`).
1211
+ *
1212
+ * ```ts
1213
+ * await CompositionAsset.query().avgBy('name', 'score')
1214
+ * // Map(2) { 'primary' => 5, 'secondary' => 4 }
1215
+ * ```
1216
+ *
1217
+ * Any `where` clauses, base scopes (soft-delete / STI), and joined-association
1218
+ * `and` clauses on the Query carry through automatically. A joined-association
1219
+ * column may be grouped on or aggregated by passing its namespaced name (e.g.
1220
+ * `'compositionAssets.name'`).
1221
+ *
1222
+ * Only groups with at least one matching row appear in the Map (inherent to
1223
+ * `GROUP BY`). When the group column is nullable, records with a `null` value
1224
+ * are grouped under a real `null` key; a group whose aggregated values are all
1225
+ * `null` yields a `null` value.
1226
+ *
1227
+ * @param groupColumn - the column to group by (base or joined-association-namespaced)
1228
+ * @param aggregatedColumn - the column to average within each group
1229
+ * @returns A Map from each present group value to the average of the aggregated column in that group
1230
+ */
1231
+ async avgBy(groupColumn, aggregatedColumn) {
1232
+ return await this.dbDriverInstance().avgBy(groupColumn, aggregatedColumn);
1233
+ }
1086
1234
  /**
1087
1235
  * Plucks the provided fields from the given dream class table
1088
1236
  *
@@ -273,6 +273,23 @@ export default class QueryDriverBase {
273
273
  async max(columnName) {
274
274
  throw new Error('implement max in child class');
275
275
  }
276
+ /**
277
+ * Retrieves the max value of the specified column within each group,
278
+ * keyed by the value of the provided group column.
279
+ *
280
+ * ```ts
281
+ * await CompositionAsset.query().maxBy('name', 'score')
282
+ * // Map(2) { 'primary' => 9, 'secondary' => 4 }
283
+ * ```
284
+ *
285
+ * @param groupColumn - the column to group by
286
+ * @param aggregatedColumn - the column to take the max of within each group
287
+ * @returns A Map from each present group value to the max of the aggregated column in that group
288
+ */
289
+ // eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-unused-vars
290
+ async maxBy(groupColumn, aggregatedColumn) {
291
+ throw new Error('implement maxBy in child class');
292
+ }
276
293
  /**
277
294
  * Retrieves the min value of the specified column
278
295
  * for this Query
@@ -289,6 +306,23 @@ export default class QueryDriverBase {
289
306
  async min(columnName) {
290
307
  throw new Error('implement min in child class');
291
308
  }
309
+ /**
310
+ * Retrieves the min value of the specified column within each group,
311
+ * keyed by the value of the provided group column.
312
+ *
313
+ * ```ts
314
+ * await CompositionAsset.query().minBy('name', 'score')
315
+ * // Map(2) { 'primary' => 1, 'secondary' => 4 }
316
+ * ```
317
+ *
318
+ * @param groupColumn - the column to group by
319
+ * @param aggregatedColumn - the column to take the min of within each group
320
+ * @returns A Map from each present group value to the min of the aggregated column in that group
321
+ */
322
+ // eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-unused-vars
323
+ async minBy(groupColumn, aggregatedColumn) {
324
+ throw new Error('implement minBy in child class');
325
+ }
292
326
  /**
293
327
  * Retrieves the sum value of the specified column
294
328
  * for this Query
@@ -305,6 +339,23 @@ export default class QueryDriverBase {
305
339
  async sum(columnName) {
306
340
  throw new Error('implement sum in child class');
307
341
  }
342
+ /**
343
+ * Retrieves the sum of the specified column within each group,
344
+ * keyed by the value of the provided group column.
345
+ *
346
+ * ```ts
347
+ * await CompositionAsset.query().sumBy('name', 'score')
348
+ * // Map(2) { 'primary' => 10, 'secondary' => 4 }
349
+ * ```
350
+ *
351
+ * @param groupColumn - the column to group by
352
+ * @param aggregatedColumn - the column to sum within each group
353
+ * @returns A Map from each present group value to the sum of the aggregated column in that group
354
+ */
355
+ // eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-unused-vars
356
+ async sumBy(groupColumn, aggregatedColumn) {
357
+ throw new Error('implement sumBy in child class');
358
+ }
308
359
  /**
309
360
  * Retrieves the average value of the specified column
310
361
  * for this Query
@@ -321,6 +372,23 @@ export default class QueryDriverBase {
321
372
  async avg(columnName) {
322
373
  throw new Error('implement avg in child class');
323
374
  }
375
+ /**
376
+ * Retrieves the average of the specified column within each group,
377
+ * keyed by the value of the provided group column.
378
+ *
379
+ * ```ts
380
+ * await CompositionAsset.query().avgBy('name', 'score')
381
+ * // Map(2) { 'primary' => 5, 'secondary' => 4 }
382
+ * ```
383
+ *
384
+ * @param groupColumn - the column to group by
385
+ * @param aggregatedColumn - the column to average within each group
386
+ * @returns A Map from each present group value to the average of the aggregated column in that group
387
+ */
388
+ // eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-unused-vars
389
+ async avgBy(groupColumn, aggregatedColumn) {
390
+ throw new Error('implement avgBy in child class');
391
+ }
324
392
  /**
325
393
  * Retrieves the number of records in the database
326
394
  *
@@ -334,6 +402,22 @@ export default class QueryDriverBase {
334
402
  async count() {
335
403
  throw new Error('implement count in child class');
336
404
  }
405
+ /**
406
+ * Retrieves the number of records in each group, keyed by the
407
+ * value of the provided group column.
408
+ *
409
+ * ```ts
410
+ * await User.query().countBy('name')
411
+ * // Map(2) { 'fred' => 2, 'zed' => 1 }
412
+ * ```
413
+ *
414
+ * @param groupColumn - the column to group by
415
+ * @returns A Map from each present group value to the number of records in that group
416
+ */
417
+ // eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-unused-vars
418
+ async countBy(groupColumn) {
419
+ throw new Error('implement countBy in child class');
420
+ }
337
421
  /**
338
422
  * @internal
339
423
  *