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.
- package/AddAggregateTypesPlugin.d.ts +38 -0
- package/AddAggregateTypesPlugin.js +268 -0
- package/AddConnectionAggregatesPlugin.d.ts +2 -0
- package/AddConnectionAggregatesPlugin.js +56 -0
- package/AddConnectionGroupedAggregatesPlugin.d.ts +10 -0
- package/AddConnectionGroupedAggregatesPlugin.js +118 -0
- package/AddGroupByAggregateEnumValuesForAttributesPlugin.d.ts +10 -0
- package/AddGroupByAggregateEnumValuesForAttributesPlugin.js +116 -0
- package/AddGroupByAggregateEnumsPlugin.d.ts +2 -0
- package/AddGroupByAggregateEnumsPlugin.js +51 -0
- package/AddHavingAggregateTypesPlugin.d.ts +22 -0
- package/AddHavingAggregateTypesPlugin.js +449 -0
- package/AggregateSpecsPlugin.d.ts +1 -0
- package/AggregateSpecsPlugin.js +206 -0
- package/AggregatesSmartTagsPlugin.d.ts +8 -0
- package/AggregatesSmartTagsPlugin.js +65 -0
- package/EXPORTABLE.d.ts +1 -0
- package/EXPORTABLE.js +15 -0
- package/FilterRelationalAggregatesPlugin.d.ts +74 -0
- package/FilterRelationalAggregatesPlugin.js +443 -0
- package/InflectionPlugin.d.ts +67 -0
- package/InflectionPlugin.js +71 -0
- package/LICENSE +23 -0
- package/OrderByAggregatesPlugin.d.ts +31 -0
- package/OrderByAggregatesPlugin.js +205 -0
- package/README.md +128 -0
- package/esm/AddAggregateTypesPlugin.d.ts +38 -0
- package/esm/AddAggregateTypesPlugin.js +265 -0
- package/esm/AddConnectionAggregatesPlugin.d.ts +2 -0
- package/esm/AddConnectionAggregatesPlugin.js +53 -0
- package/esm/AddConnectionGroupedAggregatesPlugin.d.ts +10 -0
- package/esm/AddConnectionGroupedAggregatesPlugin.js +115 -0
- package/esm/AddGroupByAggregateEnumValuesForAttributesPlugin.d.ts +10 -0
- package/esm/AddGroupByAggregateEnumValuesForAttributesPlugin.js +113 -0
- package/esm/AddGroupByAggregateEnumsPlugin.d.ts +2 -0
- package/esm/AddGroupByAggregateEnumsPlugin.js +48 -0
- package/esm/AddHavingAggregateTypesPlugin.d.ts +22 -0
- package/esm/AddHavingAggregateTypesPlugin.js +446 -0
- package/esm/AggregateSpecsPlugin.d.ts +1 -0
- package/esm/AggregateSpecsPlugin.js +203 -0
- package/esm/AggregatesSmartTagsPlugin.d.ts +8 -0
- package/esm/AggregatesSmartTagsPlugin.js +62 -0
- package/esm/EXPORTABLE.d.ts +1 -0
- package/esm/EXPORTABLE.js +12 -0
- package/esm/FilterRelationalAggregatesPlugin.d.ts +74 -0
- package/esm/FilterRelationalAggregatesPlugin.js +440 -0
- package/esm/InflectionPlugin.d.ts +67 -0
- package/esm/InflectionPlugin.js +68 -0
- package/esm/OrderByAggregatesPlugin.d.ts +31 -0
- package/esm/OrderByAggregatesPlugin.js +202 -0
- package/esm/index.d.ts +42 -0
- package/esm/index.js +37 -0
- package/esm/interfaces.d.ts +145 -0
- package/esm/interfaces.js +44 -0
- package/esm/utils.d.ts +23 -0
- package/esm/utils.js +22 -0
- package/index.d.ts +42 -0
- package/index.js +40 -0
- package/interfaces.d.ts +145 -0
- package/interfaces.js +47 -0
- package/package.json +61 -0
- package/utils.d.ts +23 -0
- package/utils.js +25 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const version = '1.0.0';
|
|
2
|
+
export const PgAggregatesInflectorsPlugin = {
|
|
3
|
+
name: 'PgAggregatesInflectorsPlugin',
|
|
4
|
+
description: 'Adds the inflectors used by the pg-aggregates preset.',
|
|
5
|
+
version,
|
|
6
|
+
provides: ['aggregates'],
|
|
7
|
+
inflection: {
|
|
8
|
+
add: {
|
|
9
|
+
aggregateContainerType(_preset, details) {
|
|
10
|
+
return this.upperCamelCase(`${this._singularizedCodecName(details.resource.codec)}-aggregates`);
|
|
11
|
+
},
|
|
12
|
+
aggregateType(_preset, details) {
|
|
13
|
+
return this.upperCamelCase(`${this._singularizedCodecName(details.resource.codec)}-${details.aggregateSpec.id}-aggregates`);
|
|
14
|
+
},
|
|
15
|
+
aggregatesContainerField(_preset, _details) {
|
|
16
|
+
return 'aggregates';
|
|
17
|
+
},
|
|
18
|
+
groupedAggregatesContainerField(_preset, _details) {
|
|
19
|
+
return 'groupedAggregates';
|
|
20
|
+
},
|
|
21
|
+
aggregatesField(_preset, details) {
|
|
22
|
+
return details.aggregateSpec.id;
|
|
23
|
+
},
|
|
24
|
+
aggregateGroupByType(_preset, details) {
|
|
25
|
+
return this.upperCamelCase(`${this._singularizedCodecName(details.resource.codec)}-group-by`);
|
|
26
|
+
},
|
|
27
|
+
aggregateGroupByAttributeEnum(_preset, details) {
|
|
28
|
+
return this.constantCase(`${this._attributeName({
|
|
29
|
+
attributeName: details.attributeName,
|
|
30
|
+
codec: details.resource.codec
|
|
31
|
+
})}`);
|
|
32
|
+
},
|
|
33
|
+
aggregateHavingInputType(_preset, details) {
|
|
34
|
+
return this.upperCamelCase(`${this._singularizedCodecName(details.resource.codec)}-having-input`);
|
|
35
|
+
},
|
|
36
|
+
aggregateHavingAggregateInputType(_preset, details) {
|
|
37
|
+
return this.upperCamelCase(`${this._singularizedCodecName(details.resource.codec)}-having-${details.aggregateSpec.id}-input`);
|
|
38
|
+
},
|
|
39
|
+
aggregateHavingAggregateComputedAttributeInputType(_preset, details) {
|
|
40
|
+
return this.upperCamelCase(`${this._singularizedCodecName(details.resource.codec)}-having-${details.aggregateSpec.id}-${this._resourceName(details.computedAttributeResource)}-input`);
|
|
41
|
+
},
|
|
42
|
+
aggregateHavingAggregateComputedAttributeArgsInputType(_preset, details) {
|
|
43
|
+
return this.upperCamelCase(`${this._singularizedCodecName(details.resource.codec)}-having-${details.aggregateSpec.id}-${this._resourceName(details.computedAttributeResource)}-args-input`);
|
|
44
|
+
},
|
|
45
|
+
aggregateGroupByAttributeDerivativeEnum(_preset, details) {
|
|
46
|
+
return this.constantCase(`${this._attributeName({
|
|
47
|
+
attributeName: details.attributeName,
|
|
48
|
+
codec: details.resource.codec
|
|
49
|
+
})}-${details.aggregateGroupBySpec.id}`);
|
|
50
|
+
},
|
|
51
|
+
orderByCountOfManyRelationByKeys(_preset, details) {
|
|
52
|
+
const relationName = this._manyRelation(details);
|
|
53
|
+
return this.constantCase(`${relationName}-count`);
|
|
54
|
+
},
|
|
55
|
+
orderByAttributeAggregateOfManyRelationByKeys(_preset, details) {
|
|
56
|
+
const relationName = this._manyRelation(details);
|
|
57
|
+
const relation = details.registry.pgRelations[details.codec.name][details.relationName];
|
|
58
|
+
return this.constantCase(`${relationName}-${details.aggregateSpec.id}-${this._attributeName({
|
|
59
|
+
codec: relation.remoteResource.codec,
|
|
60
|
+
attributeName: details.attributeName
|
|
61
|
+
})}`);
|
|
62
|
+
},
|
|
63
|
+
aggregateHavingFilterInputType(_preset, spec) {
|
|
64
|
+
return this.upperCamelCase(`having-${spec}-filter`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
namespace GraphileBuild {
|
|
3
|
+
interface BehaviorStrings {
|
|
4
|
+
'relatedAggregates:orderBy': true;
|
|
5
|
+
'resource:relatedAggregates:orderBy': true;
|
|
6
|
+
'aggregates:orderBy': true;
|
|
7
|
+
'manyRelation:aggregates:orderBy': true;
|
|
8
|
+
'aggregate:orderBy': true;
|
|
9
|
+
'attribute:aggregate:orderBy': true;
|
|
10
|
+
'sum:manyRelation:aggregates:orderBy': true;
|
|
11
|
+
'distinctCount:manyRelation:aggregates:orderBy': true;
|
|
12
|
+
'min:manyRelation:aggregates:orderBy': true;
|
|
13
|
+
'max:manyRelation:aggregates:orderBy': true;
|
|
14
|
+
'average:manyRelation:aggregates:orderBy': true;
|
|
15
|
+
'stddevSample:manyRelation:aggregates:orderBy': true;
|
|
16
|
+
'stddevPopulation:manyRelation:aggregates:orderBy': true;
|
|
17
|
+
'varianceSample:manyRelation:aggregates:orderBy': true;
|
|
18
|
+
'variancePopulation:manyRelation:aggregates:orderBy': true;
|
|
19
|
+
'sum:attribute:aggregate:orderBy': true;
|
|
20
|
+
'distinctCount:attribute:aggregate:orderBy': true;
|
|
21
|
+
'min:attribute:aggregate:orderBy': true;
|
|
22
|
+
'max:attribute:aggregate:orderBy': true;
|
|
23
|
+
'average:attribute:aggregate:orderBy': true;
|
|
24
|
+
'stddevSample:attribute:aggregate:orderBy': true;
|
|
25
|
+
'stddevPopulation:attribute:aggregate:orderBy': true;
|
|
26
|
+
'varianceSample:attribute:aggregate:orderBy': true;
|
|
27
|
+
'variancePopulation:attribute:aggregate:orderBy': true;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export declare const PgAggregatesOrderByAggregatesPlugin: GraphileConfig.Plugin;
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { EXPORTABLE } from './EXPORTABLE';
|
|
2
|
+
const version = '1.0.0';
|
|
3
|
+
const pgAggregatesApplyOrderByTotalCount = EXPORTABLE(() => (TYPES, direction, relation, sql, table, $select) => {
|
|
4
|
+
const foreignTableAlias = $select.alias;
|
|
5
|
+
const conditions = [];
|
|
6
|
+
const tableAlias = sql.identifier(Symbol(table.name));
|
|
7
|
+
relation.localAttributes.forEach((localAttribute, i) => {
|
|
8
|
+
const remoteAttribute = relation.remoteAttributes[i];
|
|
9
|
+
conditions.push(sql.fragment `${tableAlias}.${sql.identifier(remoteAttribute)} = ${foreignTableAlias}.${sql.identifier(localAttribute)}`);
|
|
10
|
+
});
|
|
11
|
+
if (typeof table.from === 'function') {
|
|
12
|
+
throw new Error(`Function source unsupported`);
|
|
13
|
+
}
|
|
14
|
+
// TODO: refactor this to use joins instead of subqueries
|
|
15
|
+
const fragment = sql `(${sql.indent `select count(*)
|
|
16
|
+
from ${table.from} ${tableAlias}
|
|
17
|
+
where ${sql.parens(sql.join(conditions.map((c) => sql.parens(c)), ' AND '))}`})`;
|
|
18
|
+
$select.orderBy({
|
|
19
|
+
fragment,
|
|
20
|
+
codec: TYPES.bigint,
|
|
21
|
+
direction
|
|
22
|
+
});
|
|
23
|
+
}, [], 'pgAggregatesApplyOrderByTotalCount');
|
|
24
|
+
const pgAggregatesApplyOrderByAttribute = EXPORTABLE(() => (aggregateSpec, attribute, attributeName, direction, relation, sql, table, $select) => {
|
|
25
|
+
const foreignTableAlias = $select.alias;
|
|
26
|
+
const conditions = [];
|
|
27
|
+
const tableAlias = sql.identifier(Symbol(table.name));
|
|
28
|
+
relation.localAttributes.forEach((localAttribute, i) => {
|
|
29
|
+
const remoteAttribute = relation.remoteAttributes[i];
|
|
30
|
+
conditions.push(sql.fragment `${tableAlias}.${sql.identifier(remoteAttribute)} = ${foreignTableAlias}.${sql.identifier(localAttribute)}`);
|
|
31
|
+
});
|
|
32
|
+
if (typeof table.from === 'function') {
|
|
33
|
+
throw new Error(`Function source unsupported`);
|
|
34
|
+
}
|
|
35
|
+
// TODO: refactor this to use joins instead of subqueries
|
|
36
|
+
const fragment = sql `(${sql.indent `
|
|
37
|
+
select ${aggregateSpec.sqlAggregateWrap(sql.fragment `${tableAlias}.${sql.identifier(attributeName)}`, attribute.codec)}
|
|
38
|
+
from ${table.from} ${tableAlias}
|
|
39
|
+
where ${sql.join(conditions.map((c) => sql.parens(c)), ' AND ')}`})`;
|
|
40
|
+
$select.orderBy({
|
|
41
|
+
fragment,
|
|
42
|
+
codec: aggregateSpec.pgTypeCodecModifier?.(attribute.codec) ??
|
|
43
|
+
attribute.codec,
|
|
44
|
+
direction
|
|
45
|
+
});
|
|
46
|
+
}, [], 'pgAggregatesApplyOrderByAttribute');
|
|
47
|
+
export const PgAggregatesOrderByAggregatesPlugin = {
|
|
48
|
+
name: 'PgAggregatesOrderByAggregatesPlugin',
|
|
49
|
+
description: 'Adds enum values to the OrderBy enum to allow ordering by aggregates on relations.',
|
|
50
|
+
version,
|
|
51
|
+
provides: ['aggregates'],
|
|
52
|
+
schema: {
|
|
53
|
+
behaviorRegistry: {
|
|
54
|
+
add: {
|
|
55
|
+
'relatedAggregates:orderBy': {
|
|
56
|
+
description: '',
|
|
57
|
+
entities: ['pgResource']
|
|
58
|
+
},
|
|
59
|
+
'aggregates:orderBy': {
|
|
60
|
+
description: '',
|
|
61
|
+
entities: ['pgCodecRelation']
|
|
62
|
+
},
|
|
63
|
+
'aggregate:orderBy': {
|
|
64
|
+
description: '',
|
|
65
|
+
entities: ['pgCodecAttribute']
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
entityBehavior: {
|
|
70
|
+
pgResource: 'resource:relatedAggregates:orderBy',
|
|
71
|
+
pgCodecRelation: ['select', 'manyRelation:aggregates:orderBy'],
|
|
72
|
+
pgCodecAttribute: ['attribute:aggregate:orderBy']
|
|
73
|
+
},
|
|
74
|
+
hooks: {
|
|
75
|
+
GraphQLEnumType_values(values, build, context) {
|
|
76
|
+
const { extend, sql, inflection, dataplanPg: { TYPES }, EXPORTABLE } = build;
|
|
77
|
+
const pgAggregateSpecs = build.pgAggregateSpecs;
|
|
78
|
+
const { scope: { isPgRowSortEnum, pgTypeResource, pgCodec } } = context;
|
|
79
|
+
const foreignTable = pgTypeResource ??
|
|
80
|
+
Object.values(build.input.pgRegistry.pgResources).find((s) => s.codec === pgCodec && !s.parameters);
|
|
81
|
+
if (!isPgRowSortEnum ||
|
|
82
|
+
!foreignTable ||
|
|
83
|
+
foreignTable.parameters ||
|
|
84
|
+
!foreignTable.codec.attributes) {
|
|
85
|
+
return values;
|
|
86
|
+
}
|
|
87
|
+
if (!build.behavior.pgResourceMatches(foreignTable, 'resource:relatedAggregates:orderBy')) {
|
|
88
|
+
return values;
|
|
89
|
+
}
|
|
90
|
+
const relations = foreignTable.getRelations();
|
|
91
|
+
const referenceeRelations = Object.entries(relations).filter(([_, rel]) => rel.isReferencee);
|
|
92
|
+
const newValues = referenceeRelations.reduce((memo, [relationName, relation]) => {
|
|
93
|
+
if (!build.behavior.pgCodecRelationMatches(relation, 'select')) {
|
|
94
|
+
return memo;
|
|
95
|
+
}
|
|
96
|
+
if (!build.behavior.pgCodecRelationMatches(relation, 'manyRelation:aggregates:orderBy')) {
|
|
97
|
+
return memo;
|
|
98
|
+
}
|
|
99
|
+
const table = relation.remoteResource;
|
|
100
|
+
const isUnique = !!relation.isUnique;
|
|
101
|
+
if (isUnique) {
|
|
102
|
+
// No point aggregating over a relation that's unique
|
|
103
|
+
return memo;
|
|
104
|
+
}
|
|
105
|
+
// Add count
|
|
106
|
+
const totalCountBaseName = inflection.orderByCountOfManyRelationByKeys({
|
|
107
|
+
registry: foreignTable.registry,
|
|
108
|
+
codec: foreignTable.codec,
|
|
109
|
+
relationName
|
|
110
|
+
});
|
|
111
|
+
const makeTotalCountApply = (direction) => {
|
|
112
|
+
return EXPORTABLE((TYPES, direction, pgAggregatesApplyOrderByTotalCount, relation, sql, table) => function apply($select) {
|
|
113
|
+
pgAggregatesApplyOrderByTotalCount(TYPES, direction, relation, sql, table, $select);
|
|
114
|
+
}, [
|
|
115
|
+
TYPES,
|
|
116
|
+
direction,
|
|
117
|
+
pgAggregatesApplyOrderByTotalCount,
|
|
118
|
+
relation,
|
|
119
|
+
sql,
|
|
120
|
+
table
|
|
121
|
+
]);
|
|
122
|
+
};
|
|
123
|
+
memo = build.extend(memo, {
|
|
124
|
+
[`${totalCountBaseName}_ASC`]: {
|
|
125
|
+
extensions: {
|
|
126
|
+
grafast: {
|
|
127
|
+
apply: makeTotalCountApply('ASC')
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
[`${totalCountBaseName}_DESC`]: {
|
|
132
|
+
extensions: {
|
|
133
|
+
grafast: {
|
|
134
|
+
apply: makeTotalCountApply('DESC')
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}, `Adding orderBy count to '${foreignTable.name}' using relation '${relationName}'`);
|
|
139
|
+
// Add other aggregates
|
|
140
|
+
pgAggregateSpecs.forEach((aggregateSpec) => {
|
|
141
|
+
if (!build.behavior.pgCodecRelationMatches(relation, `${aggregateSpec.id}:manyRelation:aggregates:orderBy`)) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
for (const [attributeName, attribute] of Object.entries(table.codec.attributes)) {
|
|
145
|
+
if (!build.behavior.pgCodecAttributeMatches([table.codec, attributeName], `${aggregateSpec.id}:attribute:aggregate:orderBy`)) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
if ((aggregateSpec.shouldApplyToEntity &&
|
|
149
|
+
!aggregateSpec.shouldApplyToEntity({
|
|
150
|
+
type: 'attribute',
|
|
151
|
+
codec: table.codec,
|
|
152
|
+
attributeName: attributeName
|
|
153
|
+
})) ||
|
|
154
|
+
!aggregateSpec.isSuitableType(attribute.codec)) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
const baseName = inflection.orderByAttributeAggregateOfManyRelationByKeys({
|
|
158
|
+
registry: foreignTable.registry,
|
|
159
|
+
codec: foreignTable.codec,
|
|
160
|
+
relationName,
|
|
161
|
+
attributeName: attributeName,
|
|
162
|
+
aggregateSpec
|
|
163
|
+
});
|
|
164
|
+
const makeApply = (direction) => {
|
|
165
|
+
return EXPORTABLE((aggregateSpec, attribute, attributeName, direction, pgAggregatesApplyOrderByAttribute, relation, sql, table) => function apply($select) {
|
|
166
|
+
pgAggregatesApplyOrderByAttribute(aggregateSpec, attribute, attributeName, direction, relation, sql, table, $select);
|
|
167
|
+
}, [
|
|
168
|
+
aggregateSpec,
|
|
169
|
+
attribute,
|
|
170
|
+
attributeName,
|
|
171
|
+
direction,
|
|
172
|
+
pgAggregatesApplyOrderByAttribute,
|
|
173
|
+
relation,
|
|
174
|
+
sql,
|
|
175
|
+
table
|
|
176
|
+
]);
|
|
177
|
+
};
|
|
178
|
+
memo = build.extend(memo, {
|
|
179
|
+
[`${baseName}_ASC`]: {
|
|
180
|
+
extensions: {
|
|
181
|
+
grafast: {
|
|
182
|
+
apply: makeApply('ASC')
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
[`${baseName}_DESC`]: {
|
|
187
|
+
extensions: {
|
|
188
|
+
grafast: {
|
|
189
|
+
apply: makeApply('DESC')
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}, `Adding orderBy ${aggregateSpec.id} of '${attributeName}' to '${foreignTable.name}' using constraint '${relationName}'`);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
return memo;
|
|
197
|
+
}, Object.create(null));
|
|
198
|
+
return extend(values, newValues, `Adding aggregate orders to '${foreignTable.name}'`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
};
|
package/esm/index.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { PgAggregatesAddAggregateTypesPlugin } from './AddAggregateTypesPlugin';
|
|
2
|
+
import { PgAggregatesAddConnectionAggregatesPlugin } from './AddConnectionAggregatesPlugin';
|
|
3
|
+
import { PgAggregatesAddConnectionGroupedAggregatesPlugin } from './AddConnectionGroupedAggregatesPlugin';
|
|
4
|
+
import { PgAggregatesAddGroupByAggregateEnumsPlugin } from './AddGroupByAggregateEnumsPlugin';
|
|
5
|
+
import { PgAggregatesAddGroupByAggregateEnumValuesForAttributesPlugin } from './AddGroupByAggregateEnumValuesForAttributesPlugin';
|
|
6
|
+
import { PgAggregatesAddHavingAggregateTypesPlugin } from './AddHavingAggregateTypesPlugin';
|
|
7
|
+
import { PgAggregatesSpecsPlugin } from './AggregateSpecsPlugin';
|
|
8
|
+
import { PgAggregatesSmartTagsPlugin } from './AggregatesSmartTagsPlugin';
|
|
9
|
+
import { PgAggregatesFilterRelationalAggregatesPlugin } from './FilterRelationalAggregatesPlugin';
|
|
10
|
+
import { PgAggregatesInflectorsPlugin } from './InflectionPlugin';
|
|
11
|
+
import { PgAggregatesOrderByAggregatesPlugin } from './OrderByAggregatesPlugin';
|
|
12
|
+
export declare const PgAggregatesPreset: GraphileConfig.Preset;
|
|
13
|
+
export { AggregateGroupBySpec, AggregateSpec, AggregateTargetEntity } from './interfaces';
|
|
14
|
+
export { PgAggregatesAddAggregateTypesPlugin };
|
|
15
|
+
export { PgAggregatesAddConnectionAggregatesPlugin };
|
|
16
|
+
export { PgAggregatesAddConnectionGroupedAggregatesPlugin };
|
|
17
|
+
export { PgAggregatesAddGroupByAggregateEnumsPlugin };
|
|
18
|
+
export { PgAggregatesAddGroupByAggregateEnumValuesForAttributesPlugin };
|
|
19
|
+
export { PgAggregatesAddHavingAggregateTypesPlugin };
|
|
20
|
+
export { PgAggregatesSpecsPlugin };
|
|
21
|
+
export { PgAggregatesSmartTagsPlugin };
|
|
22
|
+
export { PgAggregatesFilterRelationalAggregatesPlugin };
|
|
23
|
+
export { PgAggregatesInflectorsPlugin };
|
|
24
|
+
export { PgAggregatesOrderByAggregatesPlugin };
|
|
25
|
+
declare global {
|
|
26
|
+
namespace GraphileBuild {
|
|
27
|
+
interface AggregateSpecIds {
|
|
28
|
+
sum: true;
|
|
29
|
+
distinctCount: true;
|
|
30
|
+
min: true;
|
|
31
|
+
max: true;
|
|
32
|
+
average: true;
|
|
33
|
+
stddevSample: true;
|
|
34
|
+
stddevPopulation: true;
|
|
35
|
+
varianceSample: true;
|
|
36
|
+
variancePopulation: true;
|
|
37
|
+
}
|
|
38
|
+
interface BehaviorStrings {
|
|
39
|
+
'resource:groupedAggregates': true;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
package/esm/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { PgAggregatesAddAggregateTypesPlugin } from './AddAggregateTypesPlugin';
|
|
2
|
+
import { PgAggregatesAddConnectionAggregatesPlugin } from './AddConnectionAggregatesPlugin';
|
|
3
|
+
import { PgAggregatesAddConnectionGroupedAggregatesPlugin } from './AddConnectionGroupedAggregatesPlugin';
|
|
4
|
+
import { PgAggregatesAddGroupByAggregateEnumsPlugin } from './AddGroupByAggregateEnumsPlugin';
|
|
5
|
+
import { PgAggregatesAddGroupByAggregateEnumValuesForAttributesPlugin } from './AddGroupByAggregateEnumValuesForAttributesPlugin';
|
|
6
|
+
import { PgAggregatesAddHavingAggregateTypesPlugin } from './AddHavingAggregateTypesPlugin';
|
|
7
|
+
import { PgAggregatesSpecsPlugin } from './AggregateSpecsPlugin';
|
|
8
|
+
import { PgAggregatesSmartTagsPlugin } from './AggregatesSmartTagsPlugin';
|
|
9
|
+
import { PgAggregatesFilterRelationalAggregatesPlugin } from './FilterRelationalAggregatesPlugin';
|
|
10
|
+
import { PgAggregatesInflectorsPlugin } from './InflectionPlugin';
|
|
11
|
+
import { PgAggregatesOrderByAggregatesPlugin } from './OrderByAggregatesPlugin';
|
|
12
|
+
export const PgAggregatesPreset = {
|
|
13
|
+
plugins: [
|
|
14
|
+
PgAggregatesInflectorsPlugin,
|
|
15
|
+
PgAggregatesSmartTagsPlugin,
|
|
16
|
+
PgAggregatesSpecsPlugin,
|
|
17
|
+
PgAggregatesAddGroupByAggregateEnumsPlugin,
|
|
18
|
+
PgAggregatesAddGroupByAggregateEnumValuesForAttributesPlugin,
|
|
19
|
+
PgAggregatesAddHavingAggregateTypesPlugin,
|
|
20
|
+
PgAggregatesAddAggregateTypesPlugin,
|
|
21
|
+
PgAggregatesAddConnectionAggregatesPlugin,
|
|
22
|
+
PgAggregatesAddConnectionGroupedAggregatesPlugin,
|
|
23
|
+
PgAggregatesOrderByAggregatesPlugin,
|
|
24
|
+
PgAggregatesFilterRelationalAggregatesPlugin
|
|
25
|
+
]
|
|
26
|
+
};
|
|
27
|
+
export { PgAggregatesAddAggregateTypesPlugin };
|
|
28
|
+
export { PgAggregatesAddConnectionAggregatesPlugin };
|
|
29
|
+
export { PgAggregatesAddConnectionGroupedAggregatesPlugin };
|
|
30
|
+
export { PgAggregatesAddGroupByAggregateEnumsPlugin };
|
|
31
|
+
export { PgAggregatesAddGroupByAggregateEnumValuesForAttributesPlugin };
|
|
32
|
+
export { PgAggregatesAddHavingAggregateTypesPlugin };
|
|
33
|
+
export { PgAggregatesSpecsPlugin };
|
|
34
|
+
export { PgAggregatesSmartTagsPlugin };
|
|
35
|
+
export { PgAggregatesFilterRelationalAggregatesPlugin };
|
|
36
|
+
export { PgAggregatesInflectorsPlugin };
|
|
37
|
+
export { PgAggregatesOrderByAggregatesPlugin };
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import type { PgCodec, PgResource, sql } from '@dataplan/pg';
|
|
2
|
+
type SQL = ReturnType<typeof sql>;
|
|
3
|
+
declare global {
|
|
4
|
+
namespace DataplanPg {
|
|
5
|
+
interface PgCodecExtensions {
|
|
6
|
+
isNumberLike?: boolean;
|
|
7
|
+
isIntervalLike?: boolean;
|
|
8
|
+
}
|
|
9
|
+
interface PgConditionStepExtensions {
|
|
10
|
+
pgFilterAttribute?: {
|
|
11
|
+
codec: PgCodec<any, any, any, any, any, any, any>;
|
|
12
|
+
expression: SQL;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
namespace GraphileBuild {
|
|
17
|
+
interface Inflection {
|
|
18
|
+
filterTableAggregateType(foreignTable: PgResource<any, any, any, any>, spec: AggregateSpec): string;
|
|
19
|
+
}
|
|
20
|
+
interface Build {
|
|
21
|
+
pgAggregateSpecs: AggregateSpec[];
|
|
22
|
+
pgAggregateGroupBySpecs: AggregateGroupBySpec[];
|
|
23
|
+
pgHavingFilterTypeNameForCodec(codec: PgCodec<any, any, any, any>): string | null;
|
|
24
|
+
}
|
|
25
|
+
interface ScopeObject {
|
|
26
|
+
isPgAggregateContainerType?: boolean;
|
|
27
|
+
isPgAggregateType?: boolean;
|
|
28
|
+
pgAggregateSpec?: AggregateSpec;
|
|
29
|
+
}
|
|
30
|
+
interface ScopeInputObject {
|
|
31
|
+
pgTypeResource?: PgResource<any, any, any, any>;
|
|
32
|
+
isPgHavingFilterInputType?: boolean;
|
|
33
|
+
isPgAggregateHavingInputType?: boolean;
|
|
34
|
+
pgHavingFilterSpec?: string;
|
|
35
|
+
isPgConnectionAggregateFilter?: boolean;
|
|
36
|
+
isPgConnectionAggregateAggregateFilter?: boolean;
|
|
37
|
+
pgConnectionAggregateFilterAggregateSpec?: AggregateSpec;
|
|
38
|
+
}
|
|
39
|
+
interface ScopeObjectFieldsField {
|
|
40
|
+
isPgAggregateField?: boolean;
|
|
41
|
+
isPgConnectionAggregateField?: boolean;
|
|
42
|
+
pgFieldResource?: PgResource<any, any, any, any, any>;
|
|
43
|
+
}
|
|
44
|
+
interface ScopeInputObjectFieldsField {
|
|
45
|
+
isPgConnectionFilterAggregatesField?: boolean;
|
|
46
|
+
}
|
|
47
|
+
interface ScopeEnum {
|
|
48
|
+
pgTypeResource?: PgResource<any, any, any, any, any>;
|
|
49
|
+
isPgAggregateGroupEnum?: boolean;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export type AggregateTargetEntity = {
|
|
54
|
+
type: 'attribute';
|
|
55
|
+
/** table codec - NOT attribute codec! */
|
|
56
|
+
codec: PgCodec<any, any, any, any, any, any, any>;
|
|
57
|
+
/** attribute name available on this codec */
|
|
58
|
+
attributeName: string;
|
|
59
|
+
resource?: never;
|
|
60
|
+
} | {
|
|
61
|
+
type: 'computedAttribute';
|
|
62
|
+
resource: PgResource<any, any, any, any, any>;
|
|
63
|
+
codec?: never;
|
|
64
|
+
attributeName?: never;
|
|
65
|
+
};
|
|
66
|
+
export interface AggregateGroupBySpec {
|
|
67
|
+
/** Must not change since it's used in type names/etc */
|
|
68
|
+
id: string;
|
|
69
|
+
/** Return true if we can process this type */
|
|
70
|
+
isSuitableType: (codec: PgCodec<any, any, any, any, any, any, any>) => boolean;
|
|
71
|
+
/** Return false if we cannot process this attribute (default: true) */
|
|
72
|
+
shouldApplyToEntity?: (entity: AggregateTargetEntity) => boolean;
|
|
73
|
+
/** Wraps the SQL to return a derivative (e.g.:
|
|
74
|
+
* ```
|
|
75
|
+
* sqlFrag => sql.fragment`date_trunc('hour', ${sqlFrag})`)
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
sqlWrap: (sqlFrag: SQL) => SQL;
|
|
79
|
+
/**
|
|
80
|
+
* Which codec represents the type returned by sqlWrap?
|
|
81
|
+
*/
|
|
82
|
+
sqlWrapCodec: (codec: PgCodec<any, any, any, any, any, any, any>) => PgCodec<any, any, any, any, any, any, any>;
|
|
83
|
+
}
|
|
84
|
+
export interface AggregateSpec {
|
|
85
|
+
/** Must not change since it's used in type names/etc */
|
|
86
|
+
id: keyof GraphileBuild.AggregateSpecIds;
|
|
87
|
+
/** Used in descriptions, starts with lowercase */
|
|
88
|
+
humanLabel: string;
|
|
89
|
+
/** Used in descriptions, starts with uppercase */
|
|
90
|
+
HumanLabel: string;
|
|
91
|
+
/** Return true if we can process this type */
|
|
92
|
+
isSuitableType: (codec: PgCodec<any, any, any, any>) => boolean;
|
|
93
|
+
/** Return false if we cannot process this attribute (default: true) */
|
|
94
|
+
shouldApplyToEntity?: (entity: AggregateTargetEntity) => boolean;
|
|
95
|
+
/** Wraps the SQL in an aggregate call */
|
|
96
|
+
sqlAggregateWrap: (sqlFrag: SQL, codec: PgCodec<any, any, any, any>) => SQL;
|
|
97
|
+
/**
|
|
98
|
+
* Used to translate the PostgreSQL return type for the aggregate; for example:
|
|
99
|
+
*
|
|
100
|
+
* - Sum over int should give bigint
|
|
101
|
+
* - Average of int should be float
|
|
102
|
+
* - Median of int should be int
|
|
103
|
+
*/
|
|
104
|
+
pgTypeCodecModifier?: (codec: PgCodec<any, any, any, any>) => PgCodec<any, any, any, any>;
|
|
105
|
+
/** Set true if the result is guaranteed to be non-null */
|
|
106
|
+
isNonNull?: boolean;
|
|
107
|
+
}
|
|
108
|
+
export declare const BIGINT_OID = "20";
|
|
109
|
+
export declare const INT2_OID = "21";
|
|
110
|
+
export declare const INT4_OID = "23";
|
|
111
|
+
export declare const FLOAT4_OID = "700";
|
|
112
|
+
export declare const FLOAT8_OID = "701";
|
|
113
|
+
export declare const NUMERIC_OID = "1700";
|
|
114
|
+
export declare const MONEY_OID = "790";
|
|
115
|
+
export declare const INTERVAL_OID = "1186";
|
|
116
|
+
export declare const DATE_OID = "1082";
|
|
117
|
+
export declare const TIMESTAMP_OID = "1114";
|
|
118
|
+
export declare const TIMESTAMPTZ_OID = "1184";
|
|
119
|
+
export declare const TIME_OID = "1083";
|
|
120
|
+
export declare const TIMETZ_OID = "1266";
|
|
121
|
+
export declare const JSON_OID = "114";
|
|
122
|
+
export declare const JSONB_OID = "3802";
|
|
123
|
+
export declare const UUID_OID = "2950";
|
|
124
|
+
export declare const BIT_OID = "1560";
|
|
125
|
+
export declare const VARBIT_OID = "1562";
|
|
126
|
+
export declare const CHAR_OID = "18";
|
|
127
|
+
export declare const TEXT_OID = "25";
|
|
128
|
+
export declare const VARCHAR_OID = "1043";
|
|
129
|
+
export declare const POINT_OID = "600";
|
|
130
|
+
export declare const INET_OID = "869";
|
|
131
|
+
export declare const CIDR_OID = "650";
|
|
132
|
+
export declare const MAC_ADDR_OID = "829";
|
|
133
|
+
export declare const MAC_ADDR8_OID = "774";
|
|
134
|
+
export declare const REG_PROC_OID = "24";
|
|
135
|
+
export declare const REG_PROCEDURE_OID = "2202";
|
|
136
|
+
export declare const REG_OPER_OID = "2203";
|
|
137
|
+
export declare const REG_OPERATOR_OID = "2204";
|
|
138
|
+
export declare const REG_CLASS_OID = "2205";
|
|
139
|
+
export declare const REG_OID = "2206";
|
|
140
|
+
export declare const REG_ROLE_OID = "4096";
|
|
141
|
+
export declare const REG_NAMESPACE_OID = "4089";
|
|
142
|
+
export declare const REG_CONFIG_OID = "3734";
|
|
143
|
+
export declare const REG_DICTIONARY_OID = "3769";
|
|
144
|
+
export declare const CORE_HAVING_FILTER_SPECS: readonly ["int", "bigint", "float", "bigfloat", "datetime", "string"];
|
|
145
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export const BIGINT_OID = '20';
|
|
2
|
+
export const INT2_OID = '21';
|
|
3
|
+
export const INT4_OID = '23';
|
|
4
|
+
export const FLOAT4_OID = '700';
|
|
5
|
+
export const FLOAT8_OID = '701';
|
|
6
|
+
export const NUMERIC_OID = '1700';
|
|
7
|
+
export const MONEY_OID = '790';
|
|
8
|
+
export const INTERVAL_OID = '1186';
|
|
9
|
+
export const DATE_OID = '1082';
|
|
10
|
+
export const TIMESTAMP_OID = '1114';
|
|
11
|
+
export const TIMESTAMPTZ_OID = '1184';
|
|
12
|
+
export const TIME_OID = '1083';
|
|
13
|
+
export const TIMETZ_OID = '1266';
|
|
14
|
+
export const JSON_OID = '114';
|
|
15
|
+
export const JSONB_OID = '3802';
|
|
16
|
+
export const UUID_OID = '2950';
|
|
17
|
+
export const BIT_OID = '1560';
|
|
18
|
+
export const VARBIT_OID = '1562';
|
|
19
|
+
export const CHAR_OID = '18';
|
|
20
|
+
export const TEXT_OID = '25';
|
|
21
|
+
export const VARCHAR_OID = '1043';
|
|
22
|
+
export const POINT_OID = '600';
|
|
23
|
+
export const INET_OID = '869';
|
|
24
|
+
export const CIDR_OID = '650';
|
|
25
|
+
export const MAC_ADDR_OID = '829';
|
|
26
|
+
export const MAC_ADDR8_OID = '774';
|
|
27
|
+
export const REG_PROC_OID = '24';
|
|
28
|
+
export const REG_PROCEDURE_OID = '2202';
|
|
29
|
+
export const REG_OPER_OID = '2203';
|
|
30
|
+
export const REG_OPERATOR_OID = '2204';
|
|
31
|
+
export const REG_CLASS_OID = '2205';
|
|
32
|
+
export const REG_OID = '2206';
|
|
33
|
+
export const REG_ROLE_OID = '4096';
|
|
34
|
+
export const REG_NAMESPACE_OID = '4089';
|
|
35
|
+
export const REG_CONFIG_OID = '3734';
|
|
36
|
+
export const REG_DICTIONARY_OID = '3769';
|
|
37
|
+
export const CORE_HAVING_FILTER_SPECS = [
|
|
38
|
+
'int',
|
|
39
|
+
'bigint',
|
|
40
|
+
'float',
|
|
41
|
+
'bigfloat',
|
|
42
|
+
'datetime',
|
|
43
|
+
'string'
|
|
44
|
+
];
|
package/esm/utils.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { PgResource, PgResourceParameter } from '@dataplan/pg';
|
|
2
|
+
import type { GraphileBuild } from 'graphile-build';
|
|
3
|
+
export declare function getComputedAttributeResources(build: GraphileBuild.Build, resource: PgResource<any, any, any, any>): PgResource<string, import("@dataplan/pg").PgCodecWithAttributes<{
|
|
4
|
+
[x: string]: import("@dataplan/pg").PgCodecAttribute<import("@dataplan/pg").PgCodec<string, /*elided*/ any, any, any, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, undefined, any, any, undefined, any, undefined>>, boolean>;
|
|
5
|
+
}>, readonly import("@dataplan/pg").PgResourceUnique<{
|
|
6
|
+
[x: string]: import("@dataplan/pg").PgCodecAttribute<import("@dataplan/pg").PgCodec<string, /*elided*/ any, any, any, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, undefined, any, any, undefined, any, undefined>>, boolean>;
|
|
7
|
+
}>[], readonly PgResourceParameter<string, import("@dataplan/pg").PgCodec<string, {
|
|
8
|
+
[x: string]: import("@dataplan/pg").PgCodecAttribute<import("@dataplan/pg").PgCodec<string, /*elided*/ any, any, any, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, undefined, any, any, undefined, any, undefined>>, boolean>;
|
|
9
|
+
}, any, any, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, undefined, any, any, undefined, any, undefined>>>[], import("@dataplan/pg").PgRegistry<Record<string, import("@dataplan/pg").PgCodec<string, {
|
|
10
|
+
[x: string]: import("@dataplan/pg").PgCodecAttribute<import("@dataplan/pg").PgCodec<string, /*elided*/ any, any, any, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, undefined, any, any, undefined, any, undefined>>, boolean>;
|
|
11
|
+
}, any, any, any, any, any>>, Record<string, import("@dataplan/pg").PgResourceOptions<string, import("@dataplan/pg").PgCodecWithAttributes<{
|
|
12
|
+
[x: string]: import("@dataplan/pg").PgCodecAttribute<import("@dataplan/pg").PgCodec<string, /*elided*/ any, any, any, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, undefined, any, any, undefined, any, undefined>>, boolean>;
|
|
13
|
+
}>, readonly import("@dataplan/pg").PgResourceUnique<{
|
|
14
|
+
[x: string]: import("@dataplan/pg").PgCodecAttribute<import("@dataplan/pg").PgCodec<string, /*elided*/ any, any, any, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, undefined, any, any, undefined, any, undefined>>, boolean>;
|
|
15
|
+
}>[], readonly PgResourceParameter<string, import("@dataplan/pg").PgCodec<string, {
|
|
16
|
+
[x: string]: import("@dataplan/pg").PgCodecAttribute<import("@dataplan/pg").PgCodec<string, /*elided*/ any, any, any, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, undefined, any, any, undefined, any, undefined>>, boolean>;
|
|
17
|
+
}, any, any, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, undefined, any, any, undefined, any, undefined>>>[]>>, Record<string, Record<string, import("@dataplan/pg").PgCodecRelationConfig<import("@dataplan/pg").PgCodec<string, {
|
|
18
|
+
[x: string]: import("@dataplan/pg").PgCodecAttribute<import("@dataplan/pg").PgCodec<string, /*elided*/ any, any, any, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, undefined, any, any, undefined, any, undefined>>, boolean>;
|
|
19
|
+
}, any, any, undefined, any, undefined>, import("@dataplan/pg").PgResourceOptions<any, import("@dataplan/pg").PgCodecWithAttributes<{
|
|
20
|
+
[x: string]: import("@dataplan/pg").PgCodecAttribute<import("@dataplan/pg").PgCodec<string, /*elided*/ any, any, any, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, any, any, any, any, any, any>, import("@dataplan/pg").PgCodec<string, undefined, any, any, undefined, any, undefined>>, boolean>;
|
|
21
|
+
}>, any, any>>>>, {
|
|
22
|
+
[executorName: string]: import("@dataplan/pg").PgExecutor<any, any>;
|
|
23
|
+
}>>[];
|
package/esm/utils.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function getComputedAttributeResources(build, resource) {
|
|
2
|
+
const computedAttributeResources = Object.values(build.input.pgRegistry.pgResources).filter((s) => {
|
|
3
|
+
if (!s.parameters || s.parameters.length < 1) {
|
|
4
|
+
return false;
|
|
5
|
+
}
|
|
6
|
+
if (s.codec.attributes) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
if (!s.isUnique) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
if (s.codec.arrayOfCodec) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
const firstParameter = s.parameters[0];
|
|
16
|
+
if (firstParameter.codec !== resource.codec) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
return true;
|
|
20
|
+
});
|
|
21
|
+
return computedAttributeResources;
|
|
22
|
+
}
|