graphile-pg-aggregates 1.1.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 (63) hide show
  1. package/AddAggregateTypesPlugin.d.ts +38 -0
  2. package/AddAggregateTypesPlugin.js +268 -0
  3. package/AddConnectionAggregatesPlugin.d.ts +2 -0
  4. package/AddConnectionAggregatesPlugin.js +56 -0
  5. package/AddConnectionGroupedAggregatesPlugin.d.ts +10 -0
  6. package/AddConnectionGroupedAggregatesPlugin.js +118 -0
  7. package/AddGroupByAggregateEnumValuesForAttributesPlugin.d.ts +10 -0
  8. package/AddGroupByAggregateEnumValuesForAttributesPlugin.js +116 -0
  9. package/AddGroupByAggregateEnumsPlugin.d.ts +2 -0
  10. package/AddGroupByAggregateEnumsPlugin.js +51 -0
  11. package/AddHavingAggregateTypesPlugin.d.ts +22 -0
  12. package/AddHavingAggregateTypesPlugin.js +449 -0
  13. package/AggregateSpecsPlugin.d.ts +1 -0
  14. package/AggregateSpecsPlugin.js +206 -0
  15. package/AggregatesSmartTagsPlugin.d.ts +8 -0
  16. package/AggregatesSmartTagsPlugin.js +65 -0
  17. package/EXPORTABLE.d.ts +1 -0
  18. package/EXPORTABLE.js +15 -0
  19. package/FilterRelationalAggregatesPlugin.d.ts +74 -0
  20. package/FilterRelationalAggregatesPlugin.js +443 -0
  21. package/InflectionPlugin.d.ts +67 -0
  22. package/InflectionPlugin.js +71 -0
  23. package/LICENSE +23 -0
  24. package/OrderByAggregatesPlugin.d.ts +31 -0
  25. package/OrderByAggregatesPlugin.js +205 -0
  26. package/README.md +128 -0
  27. package/esm/AddAggregateTypesPlugin.d.ts +38 -0
  28. package/esm/AddAggregateTypesPlugin.js +265 -0
  29. package/esm/AddConnectionAggregatesPlugin.d.ts +2 -0
  30. package/esm/AddConnectionAggregatesPlugin.js +53 -0
  31. package/esm/AddConnectionGroupedAggregatesPlugin.d.ts +10 -0
  32. package/esm/AddConnectionGroupedAggregatesPlugin.js +115 -0
  33. package/esm/AddGroupByAggregateEnumValuesForAttributesPlugin.d.ts +10 -0
  34. package/esm/AddGroupByAggregateEnumValuesForAttributesPlugin.js +113 -0
  35. package/esm/AddGroupByAggregateEnumsPlugin.d.ts +2 -0
  36. package/esm/AddGroupByAggregateEnumsPlugin.js +48 -0
  37. package/esm/AddHavingAggregateTypesPlugin.d.ts +22 -0
  38. package/esm/AddHavingAggregateTypesPlugin.js +446 -0
  39. package/esm/AggregateSpecsPlugin.d.ts +1 -0
  40. package/esm/AggregateSpecsPlugin.js +203 -0
  41. package/esm/AggregatesSmartTagsPlugin.d.ts +8 -0
  42. package/esm/AggregatesSmartTagsPlugin.js +62 -0
  43. package/esm/EXPORTABLE.d.ts +1 -0
  44. package/esm/EXPORTABLE.js +12 -0
  45. package/esm/FilterRelationalAggregatesPlugin.d.ts +74 -0
  46. package/esm/FilterRelationalAggregatesPlugin.js +440 -0
  47. package/esm/InflectionPlugin.d.ts +67 -0
  48. package/esm/InflectionPlugin.js +68 -0
  49. package/esm/OrderByAggregatesPlugin.d.ts +31 -0
  50. package/esm/OrderByAggregatesPlugin.js +202 -0
  51. package/esm/index.d.ts +42 -0
  52. package/esm/index.js +37 -0
  53. package/esm/interfaces.d.ts +145 -0
  54. package/esm/interfaces.js +44 -0
  55. package/esm/utils.d.ts +23 -0
  56. package/esm/utils.js +22 -0
  57. package/index.d.ts +42 -0
  58. package/index.js +40 -0
  59. package/interfaces.d.ts +145 -0
  60. package/interfaces.js +47 -0
  61. package/package.json +61 -0
  62. package/utils.d.ts +23 -0
  63. package/utils.js +25 -0
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PgAggregatesAddGroupByAggregateEnumsPlugin = void 0;
4
+ const version = '1.0.0';
5
+ const Plugin = {
6
+ name: 'PgAggregatesAddGroupByAggregateEnumsPlugin',
7
+ description: 'Creates the enum types used for grouping in groupedAggregates.',
8
+ version,
9
+ provides: ['aggregates'],
10
+ schema: {
11
+ entityBehavior: {
12
+ pgResource: ['select', 'order', 'groupedAggregates']
13
+ },
14
+ hooks: {
15
+ // Create the group by enums for each table
16
+ init(_, build) {
17
+ const { inflection } = build;
18
+ for (const resource of Object.values(build.input.pgRegistry.pgResources)) {
19
+ if (resource.parameters ||
20
+ !resource.codec.attributes ||
21
+ resource.isUnique) {
22
+ continue;
23
+ }
24
+ if (!build.behavior.pgResourceMatches(resource, 'select')) {
25
+ continue;
26
+ }
27
+ if (!build.behavior.pgResourceMatches(resource, 'order')) {
28
+ continue;
29
+ }
30
+ if (!build.behavior.pgResourceMatches(resource, 'resource:groupedAggregates')) {
31
+ continue;
32
+ }
33
+ const tableTypeName = inflection.tableType(resource.codec);
34
+ /* const TableGroupByType = */
35
+ build.registerEnumType(inflection.aggregateGroupByType({ resource }), {
36
+ pgTypeResource: resource,
37
+ isPgAggregateGroupEnum: true
38
+ }, () => ({
39
+ name: inflection.aggregateGroupByType({ resource }),
40
+ description: build.wrapDescription(`Grouping methods for \`${tableTypeName}\` for usage during aggregation.`, 'type'),
41
+ values: {
42
+ /* no default values, these will be added via hooks */
43
+ }
44
+ }), `Adding connection "groupBy" enum type for ${resource.name}.`);
45
+ }
46
+ return _;
47
+ }
48
+ }
49
+ }
50
+ };
51
+ exports.PgAggregatesAddGroupByAggregateEnumsPlugin = Plugin;
@@ -0,0 +1,22 @@
1
+ declare global {
2
+ namespace GraphileBuild {
3
+ interface BehaviorStrings {
4
+ 'resource:groupedAggregates:having': true;
5
+ having: true;
6
+ 'resource:havingBy': true;
7
+ 'attribute:havingBy': true;
8
+ havingBy: true;
9
+ 'sum:resource:groupedAggregates:having': true;
10
+ 'distinctCount:resource:groupedAggregates:having': true;
11
+ 'min:resource:groupedAggregates:having': true;
12
+ 'max:resource:groupedAggregates:having': true;
13
+ 'average:resource:groupedAggregates:having': true;
14
+ 'stddevSample:resource:groupedAggregates:having': true;
15
+ 'stddevPopulation:resource:groupedAggregates:having': true;
16
+ 'varianceSample:resource:groupedAggregates:having': true;
17
+ 'variancePopulation:resource:groupedAggregates:having': true;
18
+ }
19
+ }
20
+ }
21
+ declare const Plugin: GraphileConfig.Plugin;
22
+ export { Plugin as PgAggregatesAddHavingAggregateTypesPlugin };
@@ -0,0 +1,449 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PgAggregatesAddHavingAggregateTypesPlugin = void 0;
4
+ const EXPORTABLE_1 = require("./EXPORTABLE");
5
+ const interfaces_1 = require("./interfaces");
6
+ const utils_1 = require("./utils");
7
+ const version = '1.0.0';
8
+ const pgAggregatesApplyAnd = (0, EXPORTABLE_1.EXPORTABLE)(() => function apply($where) {
9
+ return $where;
10
+ }, [], 'pgAggregatesApplyAnd');
11
+ const pgAggregatesApplyHaving = (0, EXPORTABLE_1.EXPORTABLE)(() => function apply($filter) {
12
+ return $filter;
13
+ }, [], 'pgAggregatesApplyHaving');
14
+ const pgAggregatesApplyAttributeFilter = (0, EXPORTABLE_1.EXPORTABLE)(() => (PgBooleanFilter, aggregateSpec, attribute, attributeName, sql, $having) => {
15
+ const attributeExpression = sql.fragment `${$having.alias}.${sql.identifier(attributeName)}`;
16
+ const aggregateExpression = aggregateSpec.sqlAggregateWrap(attributeExpression, attribute.codec);
17
+ return new PgBooleanFilter($having, aggregateExpression);
18
+ }, [], 'pgAggregatesApplyAttributeFilter');
19
+ const pgAggregatesApplyComputedColumnFilter = (0, EXPORTABLE_1.EXPORTABLE)(() => (PgBooleanFilter, aggregateSpec, computedAttributeResource, from, getNullableType, isInputObjectType, makeArgsRuntime, parameterAnalysis, parameters, pgFromExpressionRuntime, $having, input, { field, schema }) => {
20
+ if (input == null) {
21
+ return;
22
+ }
23
+ const fieldType = getNullableType(field.type);
24
+ if (!isInputObjectType(fieldType)) {
25
+ throw new Error(`Expected an input object type (${field.type})`);
26
+ }
27
+ const argsField = fieldType.getFields().args;
28
+ const firstArg = {
29
+ placeholder: $having.alias,
30
+ position: 0
31
+ };
32
+ let src;
33
+ if (argsField && input.args != null) {
34
+ const argsType = getNullableType(fieldType.getFields().args.type);
35
+ if (!isInputObjectType(argsType)) {
36
+ throw new Error(`Expected an input object type (${argsType})`);
37
+ }
38
+ const fields = argsType.getFields();
39
+ // Because we require that the computed attribute is
40
+ // evaluated inline, we have to convert it to an
41
+ // expression here; this is only needed because of the
42
+ // aggregation.
43
+ src = pgFromExpressionRuntime(from, parameters, [firstArg, ...makeArgsRuntime(schema, fields, input.args)], parameterAnalysis);
44
+ }
45
+ else {
46
+ src = pgFromExpressionRuntime(from, parameters, [firstArg], parameterAnalysis);
47
+ }
48
+ const aggregateExpression = aggregateSpec.sqlAggregateWrap(src, computedAttributeResource.codec);
49
+ const $filter = new PgBooleanFilter($having, aggregateExpression);
50
+ // fieldArgs.apply($filter, "filter");
51
+ return $filter;
52
+ }, [], 'pgAggregatesApplyComputedColumnFilter');
53
+ const pgAggregatesPlanAggregatesField = (0, EXPORTABLE_1.EXPORTABLE)(() => function apply($having) {
54
+ return $having;
55
+ }, [], 'pgAggregatesPlanAggregatesField');
56
+ const pgAggregatesApplyHavingBinaryOperation = (0, EXPORTABLE_1.EXPORTABLE)(() => (codec, infix, sql, sqlValueWithCodec, $booleanFilter, input) => {
57
+ if (input == null)
58
+ return;
59
+ $booleanFilter.having(sql `(${sql.parens($booleanFilter.expression)} ${infix()} ${sqlValueWithCodec(input, codec)})`);
60
+ }, [], 'pgAggregatesApplyHavingBinaryOperation');
61
+ const Plugin = {
62
+ name: 'PgAggregatesAddHavingAggregateTypesPlugin',
63
+ description: `\
64
+ Creates the types for the 'having' clause in groupedAggregates, the fields \
65
+ below that for each aggregate spec, and adds fields for attributes and computed \
66
+ columns.`,
67
+ version,
68
+ provides: ['aggregates'],
69
+ after: ['PgBasicsPlugin'],
70
+ schema: {
71
+ behaviorRegistry: {
72
+ add: {
73
+ having: {
74
+ description: "Should we add a 'having' option to aggregates on this resource?",
75
+ entities: ['pgResource']
76
+ },
77
+ havingBy: {
78
+ description: "Should this function-like resource, or attribute, be usable in the 'having' clause when aggregating?",
79
+ entities: ['pgResource', 'pgCodecAttribute']
80
+ }
81
+ }
82
+ },
83
+ entityBehavior: {
84
+ // having - for connections' groupedAggregates field
85
+ // havingBy - for computed column functions acting like attributes
86
+ pgResource: ['order', 'having', 'havingBy'],
87
+ pgCodecAttribute: ['havingBy']
88
+ },
89
+ hooks: {
90
+ build(build) {
91
+ if (!build.dataplanPg) {
92
+ throw new Error(`PgBasicsPlugin must be loaded first`);
93
+ }
94
+ const { dataplanPg: { TYPES } } = build;
95
+ return build.extend(build, {
96
+ pgHavingFilterTypeNameForCodec(codec) {
97
+ switch (codec) {
98
+ case TYPES.int2:
99
+ case TYPES.int: {
100
+ return build.inflection.aggregateHavingFilterInputType('int');
101
+ }
102
+ case TYPES.bigint: {
103
+ return build.inflection.aggregateHavingFilterInputType('bigint');
104
+ }
105
+ case TYPES.float4:
106
+ case TYPES.float: {
107
+ return build.inflection.aggregateHavingFilterInputType('float');
108
+ }
109
+ case TYPES.money:
110
+ case TYPES.numeric: {
111
+ return build.inflection.aggregateHavingFilterInputType('bigfloat');
112
+ }
113
+ case TYPES.date:
114
+ case TYPES.timestamp:
115
+ case TYPES.timestamptz: {
116
+ return build.inflection.aggregateHavingFilterInputType('datetime');
117
+ }
118
+ case TYPES.char:
119
+ case TYPES.text:
120
+ case TYPES.varchar: {
121
+ return build.inflection.aggregateHavingFilterInputType('string');
122
+ }
123
+ default: {
124
+ return null;
125
+ }
126
+ }
127
+ }
128
+ }, 'adding pgHavingFilterTypeForTypeAndModifier');
129
+ },
130
+ init(_, build, _context) {
131
+ const { graphql: { GraphQLList, GraphQLNonNull, getNullableType, isInputObjectType }, inflection, sql, dataplanPg: { PgOrFilter, PgBooleanFilter, pgFromExpressionRuntime, generatePgParameterAnalysis }, EXPORTABLE } = build;
132
+ for (const spec of interfaces_1.CORE_HAVING_FILTER_SPECS) {
133
+ const name = build.inflection.aggregateHavingFilterInputType(spec);
134
+ build.registerInputObjectType(name, {
135
+ isPgHavingFilterInputType: true,
136
+ pgHavingFilterSpec: spec
137
+ }, () => ({
138
+ name,
139
+ fields: Object.create(null)
140
+ }), '');
141
+ }
142
+ for (const resource of Object.values(build.input.pgRegistry.pgResources)) {
143
+ if (resource.parameters ||
144
+ !resource.codec.attributes ||
145
+ resource.isUnique) {
146
+ continue;
147
+ }
148
+ if (!build.behavior.pgResourceMatches(resource, 'order')) {
149
+ continue;
150
+ }
151
+ if (!build.behavior.pgResourceMatches(resource, 'resource:groupedAggregates:having')) {
152
+ continue;
153
+ }
154
+ const tableTypeName = inflection.tableType(resource.codec);
155
+ const tableHavingInputTypeName = inflection.aggregateHavingInputType({
156
+ resource: resource
157
+ });
158
+ build.registerInputObjectType(tableHavingInputTypeName, {
159
+ pgTypeResource: resource,
160
+ isPgAggregateHavingInputType: true
161
+ }, () => ({
162
+ description: build.wrapDescription(`Conditions for \`${tableTypeName}\` aggregates.`, 'type'),
163
+ fields: () => {
164
+ return {
165
+ AND: {
166
+ type: new GraphQLList(new GraphQLNonNull(build.getInputTypeByName(tableHavingInputTypeName))),
167
+ apply: pgAggregatesApplyAnd
168
+ // No need to auto-apply, the having field calls `fieldArgs.apply(...)`
169
+ },
170
+ OR: {
171
+ type: new GraphQLList(new GraphQLNonNull(build.getInputTypeByName(tableHavingInputTypeName))),
172
+ apply: EXPORTABLE((PgOrFilter) => ($where) => new PgOrFilter($where), [PgOrFilter])
173
+ // No need to auto-apply, the having field calls `fieldArgs.apply(...)`
174
+ }
175
+ };
176
+ }
177
+ }), `Adding connection "groupBy" having input type for ${resource.name}.`);
178
+ const computedAttributeResources = (0, utils_1.getComputedAttributeResources)(build, resource);
179
+ for (const aggregateSpec of build.pgAggregateSpecs) {
180
+ for (const computedAttributeResource of computedAttributeResources) {
181
+ const argsTypeName = inflection.aggregateHavingAggregateComputedAttributeArgsInputType({
182
+ resource: resource,
183
+ aggregateSpec,
184
+ computedAttributeResource: computedAttributeResource
185
+ });
186
+ build.registerInputObjectType(argsTypeName, {}, () => {
187
+ return {
188
+ fields: () => {
189
+ const { argDetails } = build.pgGetArgDetailsFromParameters(computedAttributeResource, computedAttributeResource.parameters, 1);
190
+ return argDetails.reduce((memo, { inputType, graphqlArgName }) => {
191
+ memo[graphqlArgName] = {
192
+ type: inputType
193
+ // NO PLAN NEEDED!
194
+ };
195
+ return memo;
196
+ }, Object.create(null));
197
+ }
198
+ };
199
+ }, '');
200
+ const computedHavingInputName = inflection.aggregateHavingAggregateComputedAttributeInputType({
201
+ resource: resource,
202
+ aggregateSpec,
203
+ computedAttributeResource: computedAttributeResource
204
+ });
205
+ /*const ComputedHavingInput =*/
206
+ build.registerInputObjectType(computedHavingInputName, {}, () => {
207
+ return {
208
+ fields: () => {
209
+ const havingFilterTypeName = build.pgHavingFilterTypeNameForCodec(computedAttributeResource.codec);
210
+ const HavingFilterType = havingFilterTypeName
211
+ ? build.getTypeByName(havingFilterTypeName)
212
+ : undefined;
213
+ const ArgsType = build.getTypeByName(argsTypeName);
214
+ if (!HavingFilterType || !ArgsType) {
215
+ return { fields: Object.create(null) };
216
+ }
217
+ const requiresAtLeastOneArg = computedAttributeResource.parameters
218
+ .slice(1)
219
+ .some((p) => !p.optional);
220
+ return {
221
+ ...(ArgsType
222
+ ? {
223
+ args: {
224
+ type: build.nullableIf(!requiresAtLeastOneArg, ArgsType)
225
+ // NO PLAN NEEDED
226
+ }
227
+ }
228
+ : null),
229
+ filter: {
230
+ type: new GraphQLNonNull(HavingFilterType),
231
+ apply: pgAggregatesApplyHaving
232
+ // No need to auto-apply, parent calls `fieldArgs.apply($filter, "filter")` below
233
+ }
234
+ };
235
+ }
236
+ };
237
+ }, '');
238
+ }
239
+ const typeName = inflection.aggregateHavingAggregateInputType({
240
+ resource: resource,
241
+ aggregateSpec
242
+ });
243
+ build.registerInputObjectType(typeName, {}, () => ({
244
+ name: typeName,
245
+ fields: ({ fieldWithHooks }) => {
246
+ let fields = Object.create(null);
247
+ fields = build.extend(fields, Object.entries(resource.codec.attributes).reduce((newFields, [attributeName, attribute]) => {
248
+ if (!build.behavior.pgCodecAttributeMatches([resource.codec, attributeName], 'attribute:havingBy')) {
249
+ return newFields;
250
+ }
251
+ const fieldName = inflection.attribute({
252
+ codec: resource.codec,
253
+ attributeName: attributeName
254
+ });
255
+ const havingFilterTypeName = build.pgHavingFilterTypeNameForCodec(attribute.codec);
256
+ const HavingFilterType = havingFilterTypeName
257
+ ? build.getTypeByName(havingFilterTypeName)
258
+ : undefined;
259
+ if (!HavingFilterType) {
260
+ return newFields;
261
+ }
262
+ const newField = fieldWithHooks({ fieldName }, () => ({
263
+ type: HavingFilterType,
264
+ apply: EXPORTABLE((PgBooleanFilter, aggregateSpec, attribute, attributeName, pgAggregatesApplyAttributeFilter, sql) => ($having) => {
265
+ return pgAggregatesApplyAttributeFilter(PgBooleanFilter, aggregateSpec, attribute, attributeName, sql, $having);
266
+ }, [
267
+ PgBooleanFilter,
268
+ aggregateSpec,
269
+ attribute,
270
+ attributeName,
271
+ pgAggregatesApplyAttributeFilter,
272
+ sql
273
+ ])
274
+ }));
275
+ return build.extend(newFields, { [fieldName]: newField }, `Adding attribute '${attributeName}' to having filter type for '${resource.name}'`);
276
+ }, Object.create(null)), '');
277
+ fields = build.extend(fields, computedAttributeResources.reduce((memo, computedAttributeResource) => {
278
+ if (!build.behavior.pgResourceMatches(computedAttributeResource, 'resource:havingBy')) {
279
+ return memo;
280
+ }
281
+ const codec = computedAttributeResource.codec;
282
+ if ((aggregateSpec.shouldApplyToEntity &&
283
+ !aggregateSpec.shouldApplyToEntity({
284
+ type: 'computedAttribute',
285
+ resource: computedAttributeResource
286
+ })) ||
287
+ !aggregateSpec.isSuitableType(codec)) {
288
+ return memo;
289
+ }
290
+ const argsTypeName = inflection.aggregateHavingAggregateComputedAttributeArgsInputType({
291
+ resource: resource,
292
+ aggregateSpec,
293
+ computedAttributeResource: computedAttributeResource
294
+ });
295
+ const havingFilterTypeName = build.pgHavingFilterTypeNameForCodec(computedAttributeResource.codec);
296
+ const HavingFilterType = havingFilterTypeName
297
+ ? build.getTypeByName(havingFilterTypeName)
298
+ : undefined;
299
+ const ArgsType = build.getTypeByName(argsTypeName);
300
+ const computedHavingInputName = inflection.aggregateHavingAggregateComputedAttributeInputType({
301
+ resource: resource,
302
+ aggregateSpec,
303
+ computedAttributeResource: computedAttributeResource
304
+ });
305
+ const ComputedHavingInput = build.getTypeByName(computedHavingInputName);
306
+ if (!HavingFilterType ||
307
+ !ArgsType ||
308
+ !ComputedHavingInput) {
309
+ return memo;
310
+ }
311
+ const fieldName = inflection.computedAttributeField({
312
+ resource: computedAttributeResource
313
+ });
314
+ const { from: rawFrom, parameters } = computedAttributeResource;
315
+ const { makeArgsRuntime } = build.pgGetArgDetailsFromParameters(computedAttributeResource, parameters, 1);
316
+ const parameterAnalysis = EXPORTABLE((generatePgParameterAnalysis, parameters) => generatePgParameterAnalysis(parameters), [generatePgParameterAnalysis, parameters], `${computedAttributeResource.name}ParameterAnalysis`);
317
+ const from = typeof rawFrom === 'function'
318
+ ? rawFrom
319
+ : () => rawFrom;
320
+ const newField = fieldWithHooks({ fieldName }, {
321
+ type: ComputedHavingInput,
322
+ apply: EXPORTABLE((PgBooleanFilter, aggregateSpec, computedAttributeResource, from, getNullableType, isInputObjectType, makeArgsRuntime, parameterAnalysis, parameters, pgAggregatesApplyComputedColumnFilter, pgFromExpressionRuntime) => ($having, input, info) => {
323
+ return pgAggregatesApplyComputedColumnFilter(PgBooleanFilter, aggregateSpec, computedAttributeResource, from, getNullableType, isInputObjectType, makeArgsRuntime, parameterAnalysis, parameters, pgFromExpressionRuntime, $having, input, info);
324
+ }, [
325
+ PgBooleanFilter,
326
+ aggregateSpec,
327
+ computedAttributeResource,
328
+ from,
329
+ getNullableType,
330
+ isInputObjectType,
331
+ makeArgsRuntime,
332
+ parameterAnalysis,
333
+ parameters,
334
+ pgAggregatesApplyComputedColumnFilter,
335
+ pgFromExpressionRuntime
336
+ ])
337
+ // No need to auto-apply, parent does `return $having;`
338
+ });
339
+ return build.extend(memo, { [fieldName]: newField }, `Adding computed attribute function '${computedAttributeResource.name}' to having filter type for '${resource.name}'`);
340
+ }, Object.create(null)), '');
341
+ return fields;
342
+ }
343
+ }), '');
344
+ }
345
+ }
346
+ return _;
347
+ },
348
+ GraphQLInputObjectType_fields(inFields, build, context) {
349
+ const { sql, inflection, dataplanPg: { TYPES, sqlValueWithCodec }, EXPORTABLE } = build;
350
+ const { scope: { isPgHavingFilterInputType, pgHavingFilterSpec, isPgAggregateHavingInputType, pgTypeResource: table }, fieldWithHooks } = context;
351
+ let fields = inFields;
352
+ fields = (() => {
353
+ if (!isPgAggregateHavingInputType ||
354
+ !table ||
355
+ table.parameters ||
356
+ !table.codec.attributes) {
357
+ return fields;
358
+ }
359
+ return build.extend(fields, build.pgAggregateSpecs.reduce((aggregateFields, aggregateSpec) => {
360
+ if (!build.behavior.pgResourceMatches(table, `${aggregateSpec.id}:resource:groupedAggregates:having`)) {
361
+ return aggregateFields;
362
+ }
363
+ const typeName = inflection.aggregateHavingAggregateInputType({
364
+ resource: table,
365
+ aggregateSpec
366
+ });
367
+ const SpecInput = build.getTypeByName(typeName);
368
+ if (!SpecInput) {
369
+ return aggregateFields;
370
+ }
371
+ const fieldName = inflection.aggregatesField({ aggregateSpec });
372
+ return build.extend(aggregateFields, {
373
+ [fieldName]: fieldWithHooks({ fieldName }, // e.g. 'average' or 'stddevPopulation'
374
+ {
375
+ type: SpecInput,
376
+ apply: pgAggregatesPlanAggregatesField
377
+ // No need to auto-apply, `filter` field does `return new PgBooleanFilter($having, aggregateExpression)`
378
+ })
379
+ }, '');
380
+ }, Object.create(null)), `Adding attributes to having filter for '${table.name}'`);
381
+ })();
382
+ fields = (() => {
383
+ if (!isPgHavingFilterInputType) {
384
+ return fields;
385
+ }
386
+ const rawCodec = (() => {
387
+ switch (pgHavingFilterSpec) {
388
+ case 'int':
389
+ return TYPES.int;
390
+ case 'bigint':
391
+ return TYPES.bigint;
392
+ case 'float':
393
+ return TYPES.float;
394
+ case 'bigfloat':
395
+ return TYPES.numeric;
396
+ case 'datetime':
397
+ return TYPES.timestamptz;
398
+ default: {
399
+ return null;
400
+ }
401
+ }
402
+ })();
403
+ if (rawCodec === null) {
404
+ return fields;
405
+ }
406
+ const codec = rawCodec;
407
+ const FieldType = build.getGraphQLTypeByPgCodec(codec, 'input');
408
+ if (FieldType == null) {
409
+ return fields;
410
+ }
411
+ function addBinaryOp(fieldName, infix) {
412
+ fields = build.extend(fields, {
413
+ [fieldName]: fieldWithHooks({ fieldName }, {
414
+ type: FieldType,
415
+ apply: EXPORTABLE((codec, infix, pgAggregatesApplyHavingBinaryOperation, sql, sqlValueWithCodec) => ($booleanFilter, input) => {
416
+ return pgAggregatesApplyHavingBinaryOperation(codec, infix, sql, sqlValueWithCodec, $booleanFilter, input);
417
+ }, [
418
+ codec,
419
+ infix,
420
+ pgAggregatesApplyHavingBinaryOperation,
421
+ sql,
422
+ sqlValueWithCodec
423
+ ])
424
+ // No need to auto-apply
425
+ })
426
+ }, '');
427
+ }
428
+ switch (pgHavingFilterSpec) {
429
+ case 'int':
430
+ case 'bigint':
431
+ case 'float':
432
+ case 'bigfloat':
433
+ case 'datetime': {
434
+ addBinaryOp('equalTo', EXPORTABLE((sql) => () => sql.fragment `=`, [sql]));
435
+ addBinaryOp('notEqualTo', EXPORTABLE((sql) => () => sql.fragment `<>`, [sql]));
436
+ addBinaryOp('greaterThan', EXPORTABLE((sql) => () => sql.fragment `>`, [sql]));
437
+ addBinaryOp('greaterThanOrEqualTo', EXPORTABLE((sql) => () => sql.fragment `>=`, [sql]));
438
+ addBinaryOp('lessThan', EXPORTABLE((sql) => () => sql.fragment `<`, [sql]));
439
+ addBinaryOp('lessThanOrEqualTo', EXPORTABLE((sql) => () => sql.fragment `<=`, [sql]));
440
+ }
441
+ }
442
+ return fields;
443
+ })();
444
+ return fields;
445
+ }
446
+ }
447
+ }
448
+ };
449
+ exports.PgAggregatesAddHavingAggregateTypesPlugin = Plugin;
@@ -0,0 +1 @@
1
+ export declare const PgAggregatesSpecsPlugin: GraphileConfig.Plugin;