graphile-connection-filter 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 (71) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +107 -0
  3. package/augmentations.d.ts +104 -0
  4. package/augmentations.js +11 -0
  5. package/esm/augmentations.d.ts +104 -0
  6. package/esm/augmentations.js +9 -0
  7. package/esm/index.d.ts +55 -0
  8. package/esm/index.js +56 -0
  9. package/esm/plugins/ConnectionFilterArgPlugin.d.ts +13 -0
  10. package/esm/plugins/ConnectionFilterArgPlugin.js +96 -0
  11. package/esm/plugins/ConnectionFilterAttributesPlugin.d.ts +14 -0
  12. package/esm/plugins/ConnectionFilterAttributesPlugin.js +79 -0
  13. package/esm/plugins/ConnectionFilterBackwardRelationsPlugin.d.ts +33 -0
  14. package/esm/plugins/ConnectionFilterBackwardRelationsPlugin.js +398 -0
  15. package/esm/plugins/ConnectionFilterComputedAttributesPlugin.d.ts +19 -0
  16. package/esm/plugins/ConnectionFilterComputedAttributesPlugin.js +133 -0
  17. package/esm/plugins/ConnectionFilterCustomOperatorsPlugin.d.ts +35 -0
  18. package/esm/plugins/ConnectionFilterCustomOperatorsPlugin.js +129 -0
  19. package/esm/plugins/ConnectionFilterForwardRelationsPlugin.d.ts +28 -0
  20. package/esm/plugins/ConnectionFilterForwardRelationsPlugin.js +168 -0
  21. package/esm/plugins/ConnectionFilterInflectionPlugin.d.ts +11 -0
  22. package/esm/plugins/ConnectionFilterInflectionPlugin.js +27 -0
  23. package/esm/plugins/ConnectionFilterLogicalOperatorsPlugin.d.ts +15 -0
  24. package/esm/plugins/ConnectionFilterLogicalOperatorsPlugin.js +86 -0
  25. package/esm/plugins/ConnectionFilterOperatorsPlugin.d.ts +21 -0
  26. package/esm/plugins/ConnectionFilterOperatorsPlugin.js +677 -0
  27. package/esm/plugins/ConnectionFilterTypesPlugin.d.ts +12 -0
  28. package/esm/plugins/ConnectionFilterTypesPlugin.js +225 -0
  29. package/esm/plugins/index.d.ts +11 -0
  30. package/esm/plugins/index.js +11 -0
  31. package/esm/plugins/operatorApply.d.ts +11 -0
  32. package/esm/plugins/operatorApply.js +70 -0
  33. package/esm/preset.d.ts +35 -0
  34. package/esm/preset.js +72 -0
  35. package/esm/types.d.ts +146 -0
  36. package/esm/types.js +4 -0
  37. package/esm/utils.d.ts +44 -0
  38. package/esm/utils.js +112 -0
  39. package/index.d.ts +55 -0
  40. package/index.js +77 -0
  41. package/package.json +58 -0
  42. package/plugins/ConnectionFilterArgPlugin.d.ts +13 -0
  43. package/plugins/ConnectionFilterArgPlugin.js +99 -0
  44. package/plugins/ConnectionFilterAttributesPlugin.d.ts +14 -0
  45. package/plugins/ConnectionFilterAttributesPlugin.js +82 -0
  46. package/plugins/ConnectionFilterBackwardRelationsPlugin.d.ts +33 -0
  47. package/plugins/ConnectionFilterBackwardRelationsPlugin.js +401 -0
  48. package/plugins/ConnectionFilterComputedAttributesPlugin.d.ts +19 -0
  49. package/plugins/ConnectionFilterComputedAttributesPlugin.js +136 -0
  50. package/plugins/ConnectionFilterCustomOperatorsPlugin.d.ts +35 -0
  51. package/plugins/ConnectionFilterCustomOperatorsPlugin.js +132 -0
  52. package/plugins/ConnectionFilterForwardRelationsPlugin.d.ts +28 -0
  53. package/plugins/ConnectionFilterForwardRelationsPlugin.js +171 -0
  54. package/plugins/ConnectionFilterInflectionPlugin.d.ts +11 -0
  55. package/plugins/ConnectionFilterInflectionPlugin.js +30 -0
  56. package/plugins/ConnectionFilterLogicalOperatorsPlugin.d.ts +15 -0
  57. package/plugins/ConnectionFilterLogicalOperatorsPlugin.js +89 -0
  58. package/plugins/ConnectionFilterOperatorsPlugin.d.ts +21 -0
  59. package/plugins/ConnectionFilterOperatorsPlugin.js +680 -0
  60. package/plugins/ConnectionFilterTypesPlugin.d.ts +12 -0
  61. package/plugins/ConnectionFilterTypesPlugin.js +228 -0
  62. package/plugins/index.d.ts +11 -0
  63. package/plugins/index.js +25 -0
  64. package/plugins/operatorApply.d.ts +11 -0
  65. package/plugins/operatorApply.js +73 -0
  66. package/preset.d.ts +35 -0
  67. package/preset.js +75 -0
  68. package/types.d.ts +146 -0
  69. package/types.js +7 -0
  70. package/utils.d.ts +44 -0
  71. package/utils.js +119 -0
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConnectionFilterCustomOperatorsPlugin = void 0;
4
+ require("../augmentations");
5
+ const types_1 = require("../types");
6
+ const operatorApply_1 = require("./operatorApply");
7
+ const version = '1.0.0';
8
+ /**
9
+ * ConnectionFilterCustomOperatorsPlugin
10
+ *
11
+ * Processes declarative operator factories from the preset configuration.
12
+ * Satellite plugins (PostGIS filter, search, pg_trgm, etc.) declare their
13
+ * operators via `connectionFilterOperatorFactories` in their preset's schema
14
+ * options. This plugin processes all factories during its own init hook,
15
+ * populating the filter registry used at schema build time.
16
+ *
17
+ * This declarative approach replaces the previous imperative
18
+ * `build.addConnectionFilterOperator()` API, eliminating timing/ordering
19
+ * dependencies between plugins.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * // In a satellite plugin's preset:
24
+ * const MyPreset = {
25
+ * schema: {
26
+ * connectionFilterOperatorFactories: [
27
+ * (build) => [{
28
+ * typeNames: 'String',
29
+ * operatorName: 'myOp',
30
+ * spec: {
31
+ * description: 'My operator',
32
+ * resolve: (i, v) => build.sql`${i} OP ${v}`,
33
+ * },
34
+ * }],
35
+ * ],
36
+ * },
37
+ * };
38
+ * ```
39
+ */
40
+ exports.ConnectionFilterCustomOperatorsPlugin = {
41
+ name: 'ConnectionFilterCustomOperatorsPlugin',
42
+ version,
43
+ description: 'Processes declarative operator factories for custom filter operator registration',
44
+ schema: {
45
+ hooks: {
46
+ build(build) {
47
+ // Initialize the filter registry
48
+ build[types_1.$$filters] = new Map();
49
+ return build;
50
+ },
51
+ init(_, build) {
52
+ const { inflection } = build;
53
+ const factories = build.options.connectionFilterOperatorFactories;
54
+ if (!factories || !Array.isArray(factories) || factories.length === 0) {
55
+ return _;
56
+ }
57
+ // Process each factory: call it with build, register all returned operators
58
+ for (const factory of factories) {
59
+ const registrations = factory(build);
60
+ if (!registrations || !Array.isArray(registrations)) {
61
+ continue;
62
+ }
63
+ for (const registration of registrations) {
64
+ const { typeNames: typeNameOrNames, operatorName, spec } = registration;
65
+ const typeNames = Array.isArray(typeNameOrNames)
66
+ ? typeNameOrNames
67
+ : [typeNameOrNames];
68
+ for (const typeName of typeNames) {
69
+ const filterTypeName = inflection.filterFieldType(typeName);
70
+ let operatorSpecByFilterName = build[types_1.$$filters].get(filterTypeName);
71
+ if (!operatorSpecByFilterName) {
72
+ operatorSpecByFilterName = new Map();
73
+ build[types_1.$$filters].set(filterTypeName, operatorSpecByFilterName);
74
+ }
75
+ if (operatorSpecByFilterName.has(operatorName)) {
76
+ throw new Error(`Filter '${operatorName}' already registered on '${filterTypeName}'`);
77
+ }
78
+ operatorSpecByFilterName.set(operatorName, spec);
79
+ }
80
+ }
81
+ }
82
+ return _;
83
+ },
84
+ /**
85
+ * Applies custom operators to their respective filter types.
86
+ * When a type like "StringFilter" has custom operators registered,
87
+ * they are added as fields with apply functions.
88
+ */
89
+ GraphQLInputObjectType_fields(inFields, build, context) {
90
+ let fields = inFields;
91
+ const { scope: { pgConnectionFilterOperators }, Self, fieldWithHooks, } = context;
92
+ if (!pgConnectionFilterOperators) {
93
+ return fields;
94
+ }
95
+ const operatorSpecByFilterName = build[types_1.$$filters].get(Self.name);
96
+ if (!operatorSpecByFilterName) {
97
+ return fields;
98
+ }
99
+ const { inputTypeName } = pgConnectionFilterOperators;
100
+ const fieldInputType = build.getTypeByName(inputTypeName);
101
+ if (!fieldInputType) {
102
+ return fields;
103
+ }
104
+ for (const [filterName, spec] of operatorSpecByFilterName.entries()) {
105
+ const { description, resolveInputCodec, resolveType } = spec;
106
+ const firstCodec = pgConnectionFilterOperators.pgCodecs[0];
107
+ const inputCodec = resolveInputCodec
108
+ ? resolveInputCodec(firstCodec)
109
+ : firstCodec;
110
+ const codecGraphQLType = build.getGraphQLTypeByPgCodec(inputCodec, 'input');
111
+ if (!codecGraphQLType) {
112
+ continue;
113
+ }
114
+ const type = resolveType
115
+ ? resolveType(codecGraphQLType)
116
+ : codecGraphQLType;
117
+ fields = build.extend(fields, {
118
+ [filterName]: fieldWithHooks({
119
+ fieldName: filterName,
120
+ isPgConnectionFilterOperator: true,
121
+ }, {
122
+ description,
123
+ type,
124
+ apply: (0, operatorApply_1.makeApplyFromOperatorSpec)(build, Self.name, filterName, spec, type),
125
+ }),
126
+ }, '');
127
+ }
128
+ return fields;
129
+ },
130
+ },
131
+ },
132
+ };
@@ -0,0 +1,28 @@
1
+ import '../augmentations';
2
+ import type { GraphileConfig } from 'graphile-config';
3
+ /**
4
+ * ConnectionFilterForwardRelationsPlugin
5
+ *
6
+ * Adds forward relation filter fields to table filter types.
7
+ * A "forward" relation is one where the current table has a FK referencing another table.
8
+ *
9
+ * For example, if `orders` has `client_id` referencing `clients`,
10
+ * then `OrderFilter` gets a `clientByClientId` field of type `ClientFilter`,
11
+ * allowing queries like:
12
+ *
13
+ * ```graphql
14
+ * allOrders(filter: {
15
+ * clientByClientId: { name: { startsWith: "Acme" } }
16
+ * }) { ... }
17
+ * ```
18
+ *
19
+ * The SQL generated is an EXISTS subquery:
20
+ * ```sql
21
+ * WHERE EXISTS (
22
+ * SELECT 1 FROM clients
23
+ * WHERE clients.id = orders.client_id
24
+ * AND <nested filter conditions>
25
+ * )
26
+ * ```
27
+ */
28
+ export declare const ConnectionFilterForwardRelationsPlugin: GraphileConfig.Plugin;
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConnectionFilterForwardRelationsPlugin = void 0;
4
+ require("../augmentations");
5
+ const utils_1 = require("../utils");
6
+ const version = '1.0.0';
7
+ /**
8
+ * ConnectionFilterForwardRelationsPlugin
9
+ *
10
+ * Adds forward relation filter fields to table filter types.
11
+ * A "forward" relation is one where the current table has a FK referencing another table.
12
+ *
13
+ * For example, if `orders` has `client_id` referencing `clients`,
14
+ * then `OrderFilter` gets a `clientByClientId` field of type `ClientFilter`,
15
+ * allowing queries like:
16
+ *
17
+ * ```graphql
18
+ * allOrders(filter: {
19
+ * clientByClientId: { name: { startsWith: "Acme" } }
20
+ * }) { ... }
21
+ * ```
22
+ *
23
+ * The SQL generated is an EXISTS subquery:
24
+ * ```sql
25
+ * WHERE EXISTS (
26
+ * SELECT 1 FROM clients
27
+ * WHERE clients.id = orders.client_id
28
+ * AND <nested filter conditions>
29
+ * )
30
+ * ```
31
+ */
32
+ exports.ConnectionFilterForwardRelationsPlugin = {
33
+ name: 'ConnectionFilterForwardRelationsPlugin',
34
+ version,
35
+ description: 'Adds forward relation filter fields to connection filter types',
36
+ inflection: {
37
+ add: {
38
+ filterForwardRelationExistsFieldName(_preset, relationFieldName) {
39
+ return `${relationFieldName}Exists`;
40
+ },
41
+ filterSingleRelationFieldName(_preset, fieldName) {
42
+ return fieldName;
43
+ },
44
+ },
45
+ },
46
+ schema: {
47
+ entityBehavior: {
48
+ pgCodecRelation: 'filterBy',
49
+ },
50
+ hooks: {
51
+ GraphQLInputObjectType_fields(inFields, build, context) {
52
+ let fields = inFields;
53
+ // Runtime check: only proceed if relation filters are enabled
54
+ if (!build.options.connectionFilterRelations) {
55
+ return fields;
56
+ }
57
+ const { extend, inflection, sql, graphql: { GraphQLBoolean }, EXPORTABLE, } = build;
58
+ const { fieldWithHooks, scope: { pgCodec, isPgConnectionFilter }, } = context;
59
+ if (!isPgConnectionFilter || !pgCodec || !pgCodec.attributes) {
60
+ return fields;
61
+ }
62
+ const assertAllowed = (0, utils_1.makeAssertAllowed)(build);
63
+ const source = Object.values(build.input.pgRegistry.pgResources).find((s) => s.codec === pgCodec && !s.parameters);
64
+ if (!source)
65
+ return fields;
66
+ const relations = source.getRelations();
67
+ const forwardRelations = Object.entries(relations).filter(([_relationName, relation]) => !relation.isReferencee);
68
+ const requireIndex = build.options.connectionFilterRelationsRequireIndex !== false;
69
+ for (const [relationName, relation] of forwardRelations) {
70
+ const foreignTable = relation.remoteResource;
71
+ if (!build.behavior.pgCodecRelationMatches(relation, 'filterBy')) {
72
+ continue;
73
+ }
74
+ // Skip function-based sources
75
+ if (typeof foreignTable.from === 'function') {
76
+ continue;
77
+ }
78
+ // Skip unindexed relations when requireIndex is enabled.
79
+ // PgIndexBehaviorsPlugin sets relation.extensions.isIndexed = false
80
+ // on backward relations without supporting indexes. For forward
81
+ // relations this is less common (the referenced PK is always indexed)
82
+ // but we check it for consistency.
83
+ if (requireIndex && relation.extensions?.isIndexed === false) {
84
+ continue;
85
+ }
86
+ const fieldName = inflection.singleRelation({
87
+ registry: source.registry,
88
+ codec: source.codec,
89
+ relationName,
90
+ });
91
+ const filterFieldName = inflection.filterSingleRelationFieldName(fieldName);
92
+ const foreignTableTypeName = inflection.tableType(foreignTable.codec);
93
+ const foreignTableFilterTypeName = inflection.filterType(foreignTableTypeName);
94
+ const ForeignTableFilterType = build.getTypeByName(foreignTableFilterTypeName);
95
+ if (!ForeignTableFilterType)
96
+ continue;
97
+ const foreignTableExpression = foreignTable.from;
98
+ const localAttributes = relation.localAttributes;
99
+ const remoteAttributes = relation.remoteAttributes;
100
+ // Add the relation filter field (e.g. clientByClientId: ClientFilter)
101
+ fields = extend(fields, {
102
+ [filterFieldName]: fieldWithHooks({
103
+ fieldName: filterFieldName,
104
+ isPgConnectionFilterField: true,
105
+ }, () => ({
106
+ description: `Filter by the object\u2019s \`${fieldName}\` relation.`,
107
+ type: ForeignTableFilterType,
108
+ apply: EXPORTABLE((assertAllowed, foreignTable, foreignTableExpression, localAttributes, remoteAttributes, sql) => function ($where, value) {
109
+ assertAllowed(value, 'object');
110
+ if (value == null)
111
+ return;
112
+ const $subQuery = $where.existsPlan({
113
+ tableExpression: foreignTableExpression,
114
+ alias: foreignTable.name,
115
+ });
116
+ localAttributes.forEach((localAttribute, i) => {
117
+ const remoteAttribute = remoteAttributes[i];
118
+ $subQuery.where(sql `${$where.alias}.${sql.identifier(localAttribute)} = ${$subQuery.alias}.${sql.identifier(remoteAttribute)}`);
119
+ });
120
+ return $subQuery;
121
+ }, [
122
+ assertAllowed,
123
+ foreignTable,
124
+ foreignTableExpression,
125
+ localAttributes,
126
+ remoteAttributes,
127
+ sql,
128
+ ]),
129
+ })),
130
+ }, `Adding connection filter forward relation field from ${source.name} to ${foreignTable.name}`);
131
+ // Add an "exists" field for nullable FKs (e.g. clientByClientIdExists: Boolean)
132
+ const keyIsNullable = relation.localAttributes.some((col) => !source.codec.attributes[col]?.notNull);
133
+ if (keyIsNullable) {
134
+ const existsFieldName = inflection.filterForwardRelationExistsFieldName(fieldName);
135
+ fields = extend(fields, {
136
+ [existsFieldName]: fieldWithHooks({
137
+ fieldName: existsFieldName,
138
+ isPgConnectionFilterField: true,
139
+ }, () => ({
140
+ description: `A related \`${fieldName}\` exists.`,
141
+ type: GraphQLBoolean,
142
+ apply: EXPORTABLE((assertAllowed, foreignTable, foreignTableExpression, localAttributes, remoteAttributes, sql) => function ($where, value) {
143
+ assertAllowed(value, 'scalar');
144
+ if (value == null)
145
+ return;
146
+ const $subQuery = $where.existsPlan({
147
+ tableExpression: foreignTableExpression,
148
+ alias: foreignTable.name,
149
+ equals: value,
150
+ });
151
+ localAttributes.forEach((localAttribute, i) => {
152
+ const remoteAttribute = remoteAttributes[i];
153
+ $subQuery.where(sql `${$where.alias}.${sql.identifier(localAttribute)} = ${$subQuery.alias}.${sql.identifier(remoteAttribute)}`);
154
+ });
155
+ }, [
156
+ assertAllowed,
157
+ foreignTable,
158
+ foreignTableExpression,
159
+ localAttributes,
160
+ remoteAttributes,
161
+ sql,
162
+ ]),
163
+ })),
164
+ }, `Adding connection filter forward relation exists field for ${fieldName}`);
165
+ }
166
+ }
167
+ return fields;
168
+ },
169
+ },
170
+ },
171
+ };
@@ -0,0 +1,11 @@
1
+ import '../augmentations';
2
+ import type { GraphileConfig } from 'graphile-config';
3
+ /**
4
+ * ConnectionFilterInflectionPlugin
5
+ *
6
+ * Adds inflection methods for naming filter types:
7
+ * - filterType(typeName) -> e.g. "UserFilter"
8
+ * - filterFieldType(typeName) -> e.g. "StringFilter"
9
+ * - filterFieldListType(typeName) -> e.g. "StringListFilter"
10
+ */
11
+ export declare const ConnectionFilterInflectionPlugin: GraphileConfig.Plugin;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConnectionFilterInflectionPlugin = void 0;
4
+ require("../augmentations");
5
+ /**
6
+ * ConnectionFilterInflectionPlugin
7
+ *
8
+ * Adds inflection methods for naming filter types:
9
+ * - filterType(typeName) -> e.g. "UserFilter"
10
+ * - filterFieldType(typeName) -> e.g. "StringFilter"
11
+ * - filterFieldListType(typeName) -> e.g. "StringListFilter"
12
+ */
13
+ exports.ConnectionFilterInflectionPlugin = {
14
+ name: 'ConnectionFilterInflectionPlugin',
15
+ version: '1.0.0',
16
+ description: 'Adds inflection methods for connection filter type naming',
17
+ inflection: {
18
+ add: {
19
+ filterType(_preset, typeName) {
20
+ return `${typeName}Filter`;
21
+ },
22
+ filterFieldType(_preset, typeName) {
23
+ return `${typeName}Filter`;
24
+ },
25
+ filterFieldListType(_preset, typeName) {
26
+ return `${typeName}ListFilter`;
27
+ },
28
+ },
29
+ },
30
+ };
@@ -0,0 +1,15 @@
1
+ import '../augmentations';
2
+ import type { GraphileConfig } from 'graphile-config';
3
+ /**
4
+ * ConnectionFilterLogicalOperatorsPlugin
5
+ *
6
+ * Adds the `and`, `or`, and `not` logical operators to filter types.
7
+ *
8
+ * - `and`: [Filter!] - all conditions must match (uses $where.andPlan())
9
+ * - `or`: [Filter!] - any condition must match (uses $where.orPlan())
10
+ * - `not`: Filter - negates the condition (uses $where.notPlan())
11
+ *
12
+ * These are only added if the filter type has at least one other field
13
+ * (to avoid creating useless logical-only filter types).
14
+ */
15
+ export declare const ConnectionFilterLogicalOperatorsPlugin: GraphileConfig.Plugin;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConnectionFilterLogicalOperatorsPlugin = void 0;
4
+ require("../augmentations");
5
+ const utils_1 = require("../utils");
6
+ const version = '1.0.0';
7
+ /**
8
+ * ConnectionFilterLogicalOperatorsPlugin
9
+ *
10
+ * Adds the `and`, `or`, and `not` logical operators to filter types.
11
+ *
12
+ * - `and`: [Filter!] - all conditions must match (uses $where.andPlan())
13
+ * - `or`: [Filter!] - any condition must match (uses $where.orPlan())
14
+ * - `not`: Filter - negates the condition (uses $where.notPlan())
15
+ *
16
+ * These are only added if the filter type has at least one other field
17
+ * (to avoid creating useless logical-only filter types).
18
+ */
19
+ exports.ConnectionFilterLogicalOperatorsPlugin = {
20
+ name: 'ConnectionFilterLogicalOperatorsPlugin',
21
+ version,
22
+ description: 'Adds and/or/not logical operators to connection filter types',
23
+ schema: {
24
+ hooks: {
25
+ GraphQLInputObjectType_fields(fields, build, context) {
26
+ const { extend, graphql: { GraphQLList, GraphQLNonNull }, EXPORTABLE, } = build;
27
+ const { fieldWithHooks, scope: { isPgConnectionFilter }, Self, } = context;
28
+ if (!isPgConnectionFilter)
29
+ return fields;
30
+ // Check runtime option — allows toggling without removing the plugin
31
+ if (build.options.connectionFilterLogicalOperators === false) {
32
+ return fields;
33
+ }
34
+ // Don't add logical operators if there are no other fields
35
+ if (Object.keys(fields).length === 0) {
36
+ return fields;
37
+ }
38
+ const assertAllowed = (0, utils_1.makeAssertAllowed)(build);
39
+ const logicalOperatorFields = {
40
+ and: fieldWithHooks({
41
+ fieldName: 'and',
42
+ isPgConnectionFilterOperatorLogical: true,
43
+ }, {
44
+ description: 'Checks for all expressions in this list.',
45
+ type: new GraphQLList(new GraphQLNonNull(Self)),
46
+ apply: EXPORTABLE((assertAllowed) => function ($where, value) {
47
+ assertAllowed(value, 'list');
48
+ if (value == null)
49
+ return;
50
+ const $and = $where.andPlan();
51
+ return $and;
52
+ }, [assertAllowed]),
53
+ }),
54
+ or: fieldWithHooks({
55
+ fieldName: 'or',
56
+ isPgConnectionFilterOperatorLogical: true,
57
+ }, {
58
+ description: 'Checks for any expressions in this list.',
59
+ type: new GraphQLList(new GraphQLNonNull(Self)),
60
+ apply: EXPORTABLE((assertAllowed) => function ($where, value) {
61
+ assertAllowed(value, 'list');
62
+ if (value == null)
63
+ return;
64
+ const $or = $where.orPlan();
65
+ // Each entry in the OR list should use AND internally
66
+ return () => $or.andPlan();
67
+ }, [assertAllowed]),
68
+ }),
69
+ not: fieldWithHooks({
70
+ fieldName: 'not',
71
+ isPgConnectionFilterOperatorLogical: true,
72
+ }, {
73
+ description: 'Negates the expression.',
74
+ type: Self,
75
+ apply: EXPORTABLE((assertAllowed) => function ($where, value) {
76
+ assertAllowed(value, 'object');
77
+ if (value == null)
78
+ return;
79
+ const $not = $where.notPlan();
80
+ const $and = $not.andPlan();
81
+ return $and;
82
+ }, [assertAllowed]),
83
+ }),
84
+ };
85
+ return extend(fields, logicalOperatorFields, '');
86
+ },
87
+ },
88
+ },
89
+ };
@@ -0,0 +1,21 @@
1
+ import '../augmentations';
2
+ import type { GraphileConfig } from 'graphile-config';
3
+ /**
4
+ * ConnectionFilterOperatorsPlugin
5
+ *
6
+ * Registers all built-in filter operators on the per-scalar operator types
7
+ * (e.g. StringFilter, IntFilter, DatetimeFilter, etc.).
8
+ *
9
+ * Operator categories:
10
+ * - Standard: isNull, equalTo, notEqualTo, distinctFrom, notDistinctFrom, in, notIn
11
+ * - Sort: lessThan, lessThanOrEqualTo, greaterThan, greaterThanOrEqualTo
12
+ * - Pattern matching (text-like): includes, startsWith, endsWith, like + insensitive variants
13
+ * - Hstore: contains, containsKey, containsAllKeys, containsAnyKeys, containedBy
14
+ * - JSONB: contains, containsKey, containsAllKeys, containsAnyKeys, containedBy
15
+ * - Inet: contains, containsOrEqualTo, containedBy, containedByOrEqualTo, containsOrContainedBy
16
+ * - Array: contains, containedBy, overlaps, anyEqualTo, anyNotEqualTo, any comparison operators
17
+ * - Range: contains, containsElement, containedBy, overlaps, strictlyLeftOf, strictlyRightOf, etc.
18
+ * - Enum: standard + sort operators
19
+ * - Case-insensitive variants of standard and sort operators
20
+ */
21
+ export declare const ConnectionFilterOperatorsPlugin: GraphileConfig.Plugin;