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.
- package/LICENSE +23 -0
- package/README.md +107 -0
- package/augmentations.d.ts +104 -0
- package/augmentations.js +11 -0
- package/esm/augmentations.d.ts +104 -0
- package/esm/augmentations.js +9 -0
- package/esm/index.d.ts +55 -0
- package/esm/index.js +56 -0
- package/esm/plugins/ConnectionFilterArgPlugin.d.ts +13 -0
- package/esm/plugins/ConnectionFilterArgPlugin.js +96 -0
- package/esm/plugins/ConnectionFilterAttributesPlugin.d.ts +14 -0
- package/esm/plugins/ConnectionFilterAttributesPlugin.js +79 -0
- package/esm/plugins/ConnectionFilterBackwardRelationsPlugin.d.ts +33 -0
- package/esm/plugins/ConnectionFilterBackwardRelationsPlugin.js +398 -0
- package/esm/plugins/ConnectionFilterComputedAttributesPlugin.d.ts +19 -0
- package/esm/plugins/ConnectionFilterComputedAttributesPlugin.js +133 -0
- package/esm/plugins/ConnectionFilterCustomOperatorsPlugin.d.ts +35 -0
- package/esm/plugins/ConnectionFilterCustomOperatorsPlugin.js +129 -0
- package/esm/plugins/ConnectionFilterForwardRelationsPlugin.d.ts +28 -0
- package/esm/plugins/ConnectionFilterForwardRelationsPlugin.js +168 -0
- package/esm/plugins/ConnectionFilterInflectionPlugin.d.ts +11 -0
- package/esm/plugins/ConnectionFilterInflectionPlugin.js +27 -0
- package/esm/plugins/ConnectionFilterLogicalOperatorsPlugin.d.ts +15 -0
- package/esm/plugins/ConnectionFilterLogicalOperatorsPlugin.js +86 -0
- package/esm/plugins/ConnectionFilterOperatorsPlugin.d.ts +21 -0
- package/esm/plugins/ConnectionFilterOperatorsPlugin.js +677 -0
- package/esm/plugins/ConnectionFilterTypesPlugin.d.ts +12 -0
- package/esm/plugins/ConnectionFilterTypesPlugin.js +225 -0
- package/esm/plugins/index.d.ts +11 -0
- package/esm/plugins/index.js +11 -0
- package/esm/plugins/operatorApply.d.ts +11 -0
- package/esm/plugins/operatorApply.js +70 -0
- package/esm/preset.d.ts +35 -0
- package/esm/preset.js +72 -0
- package/esm/types.d.ts +146 -0
- package/esm/types.js +4 -0
- package/esm/utils.d.ts +44 -0
- package/esm/utils.js +112 -0
- package/index.d.ts +55 -0
- package/index.js +77 -0
- package/package.json +58 -0
- package/plugins/ConnectionFilterArgPlugin.d.ts +13 -0
- package/plugins/ConnectionFilterArgPlugin.js +99 -0
- package/plugins/ConnectionFilterAttributesPlugin.d.ts +14 -0
- package/plugins/ConnectionFilterAttributesPlugin.js +82 -0
- package/plugins/ConnectionFilterBackwardRelationsPlugin.d.ts +33 -0
- package/plugins/ConnectionFilterBackwardRelationsPlugin.js +401 -0
- package/plugins/ConnectionFilterComputedAttributesPlugin.d.ts +19 -0
- package/plugins/ConnectionFilterComputedAttributesPlugin.js +136 -0
- package/plugins/ConnectionFilterCustomOperatorsPlugin.d.ts +35 -0
- package/plugins/ConnectionFilterCustomOperatorsPlugin.js +132 -0
- package/plugins/ConnectionFilterForwardRelationsPlugin.d.ts +28 -0
- package/plugins/ConnectionFilterForwardRelationsPlugin.js +171 -0
- package/plugins/ConnectionFilterInflectionPlugin.d.ts +11 -0
- package/plugins/ConnectionFilterInflectionPlugin.js +30 -0
- package/plugins/ConnectionFilterLogicalOperatorsPlugin.d.ts +15 -0
- package/plugins/ConnectionFilterLogicalOperatorsPlugin.js +89 -0
- package/plugins/ConnectionFilterOperatorsPlugin.d.ts +21 -0
- package/plugins/ConnectionFilterOperatorsPlugin.js +680 -0
- package/plugins/ConnectionFilterTypesPlugin.d.ts +12 -0
- package/plugins/ConnectionFilterTypesPlugin.js +228 -0
- package/plugins/index.d.ts +11 -0
- package/plugins/index.js +25 -0
- package/plugins/operatorApply.d.ts +11 -0
- package/plugins/operatorApply.js +73 -0
- package/preset.d.ts +35 -0
- package/preset.js +75 -0
- package/types.d.ts +146 -0
- package/types.js +7 -0
- package/utils.d.ts +44 -0
- package/utils.js +119 -0
package/utils.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for the connection filter plugin.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Check if a value is an empty object (no own enumerable keys).
|
|
6
|
+
*/
|
|
7
|
+
export declare function isEmpty(o: unknown): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Check if a pgResource is a computed scalar attribute function.
|
|
10
|
+
* A computed attribute is a function that:
|
|
11
|
+
* - has parameters
|
|
12
|
+
* - returns a scalar (no attributes on codec)
|
|
13
|
+
* - is unique (returns single row)
|
|
14
|
+
* - first parameter's codec has attributes (i.e. takes a table row)
|
|
15
|
+
*/
|
|
16
|
+
export declare function isComputedScalarAttributeResource(s: any): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Get all computed attribute resources for a given source.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getComputedAttributeResources(build: any, source: any): any[];
|
|
21
|
+
/**
|
|
22
|
+
* Walks from a PgCondition up to the PgSelectQueryBuilder.
|
|
23
|
+
* Uses the .parent property on PgCondition to traverse up the chain,
|
|
24
|
+
* following Benjie's pattern from postgraphile-plugin-fulltext-filter.
|
|
25
|
+
*
|
|
26
|
+
* This is used by satellite plugins (search, BM25, pgvector) that need
|
|
27
|
+
* to access the query builder from within a filter's apply callback
|
|
28
|
+
* to inject SELECT expressions (for ranking/scoring) and ORDER BY clauses.
|
|
29
|
+
*
|
|
30
|
+
* @param build - The Graphile Build object (needs build.dataplanPg.PgCondition)
|
|
31
|
+
* @param $condition - The PgCondition instance from the filter apply callback
|
|
32
|
+
* @returns The PgSelectQueryBuilder if found, or null
|
|
33
|
+
*/
|
|
34
|
+
export declare function getQueryBuilder(build: GraphileBuild.Build, $condition: any): any | null;
|
|
35
|
+
/**
|
|
36
|
+
* Creates an assertion function that validates filter input values.
|
|
37
|
+
*
|
|
38
|
+
* Rejects empty objects in nested contexts (logical operators, relation filters)
|
|
39
|
+
* and optionally rejects null literals based on the connectionFilterAllowNullInput option.
|
|
40
|
+
*
|
|
41
|
+
* Note: Top-level empty filter `{}` is handled in ConnectionFilterArgPlugin's
|
|
42
|
+
* applyPlan — it's treated as "no filter" and skipped, not rejected.
|
|
43
|
+
*/
|
|
44
|
+
export declare function makeAssertAllowed(build: any): (value: unknown, mode: 'object' | 'list') => void;
|
package/utils.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Utility functions for the connection filter plugin.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isEmpty = isEmpty;
|
|
7
|
+
exports.isComputedScalarAttributeResource = isComputedScalarAttributeResource;
|
|
8
|
+
exports.getComputedAttributeResources = getComputedAttributeResources;
|
|
9
|
+
exports.getQueryBuilder = getQueryBuilder;
|
|
10
|
+
exports.makeAssertAllowed = makeAssertAllowed;
|
|
11
|
+
/**
|
|
12
|
+
* Check if a value is an empty object (no own enumerable keys).
|
|
13
|
+
*/
|
|
14
|
+
function isEmpty(o) {
|
|
15
|
+
return typeof o === 'object' && o !== null && Object.keys(o).length === 0;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Check if a pgResource is a computed scalar attribute function.
|
|
19
|
+
* A computed attribute is a function that:
|
|
20
|
+
* - has parameters
|
|
21
|
+
* - returns a scalar (no attributes on codec)
|
|
22
|
+
* - is unique (returns single row)
|
|
23
|
+
* - first parameter's codec has attributes (i.e. takes a table row)
|
|
24
|
+
*/
|
|
25
|
+
function isComputedScalarAttributeResource(s) {
|
|
26
|
+
if (!s.parameters || s.parameters.length < 1) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
if (s.codec.attributes) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
if (!s.isUnique) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
const firstParameter = s.parameters[0];
|
|
36
|
+
if (!firstParameter?.codec.attributes) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get all computed attribute resources for a given source.
|
|
43
|
+
*/
|
|
44
|
+
function getComputedAttributeResources(build, source) {
|
|
45
|
+
const computedAttributeSources = Object.values(build.input.pgRegistry.pgResources).filter((s) => isComputedScalarAttributeResource(s) &&
|
|
46
|
+
s.parameters[0].codec === source.codec);
|
|
47
|
+
return computedAttributeSources;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Walks from a PgCondition up to the PgSelectQueryBuilder.
|
|
51
|
+
* Uses the .parent property on PgCondition to traverse up the chain,
|
|
52
|
+
* following Benjie's pattern from postgraphile-plugin-fulltext-filter.
|
|
53
|
+
*
|
|
54
|
+
* This is used by satellite plugins (search, BM25, pgvector) that need
|
|
55
|
+
* to access the query builder from within a filter's apply callback
|
|
56
|
+
* to inject SELECT expressions (for ranking/scoring) and ORDER BY clauses.
|
|
57
|
+
*
|
|
58
|
+
* @param build - The Graphile Build object (needs build.dataplanPg.PgCondition)
|
|
59
|
+
* @param $condition - The PgCondition instance from the filter apply callback
|
|
60
|
+
* @returns The PgSelectQueryBuilder if found, or null
|
|
61
|
+
*/
|
|
62
|
+
function getQueryBuilder(build, $condition) {
|
|
63
|
+
const PgCondition = build.dataplanPg?.PgCondition;
|
|
64
|
+
if (!PgCondition)
|
|
65
|
+
return null;
|
|
66
|
+
let current = $condition;
|
|
67
|
+
const { alias } = current;
|
|
68
|
+
// Walk up through nested PgConditions (e.g. and/or/not)
|
|
69
|
+
// Note: PgCondition.parent is protected, so we use bracket notation
|
|
70
|
+
// to access it from outside the class hierarchy.
|
|
71
|
+
while (current &&
|
|
72
|
+
current instanceof PgCondition &&
|
|
73
|
+
current.alias === alias) {
|
|
74
|
+
current = current['parent'];
|
|
75
|
+
}
|
|
76
|
+
// Verify we found a query builder with matching alias
|
|
77
|
+
// Using duck-typing per Benjie's pattern
|
|
78
|
+
if (current &&
|
|
79
|
+
typeof current.selectAndReturnIndex === 'function' &&
|
|
80
|
+
current.alias === alias) {
|
|
81
|
+
return current;
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Creates an assertion function that validates filter input values.
|
|
87
|
+
*
|
|
88
|
+
* Rejects empty objects in nested contexts (logical operators, relation filters)
|
|
89
|
+
* and optionally rejects null literals based on the connectionFilterAllowNullInput option.
|
|
90
|
+
*
|
|
91
|
+
* Note: Top-level empty filter `{}` is handled in ConnectionFilterArgPlugin's
|
|
92
|
+
* applyPlan — it's treated as "no filter" and skipped, not rejected.
|
|
93
|
+
*/
|
|
94
|
+
function makeAssertAllowed(build) {
|
|
95
|
+
const { options, EXPORTABLE } = build;
|
|
96
|
+
const { connectionFilterAllowNullInput, } = options;
|
|
97
|
+
const assertAllowed = EXPORTABLE((connectionFilterAllowNullInput, isEmpty) => function (value, mode) {
|
|
98
|
+
// Reject empty objects in nested filter contexts (and/or/not, relation filters)
|
|
99
|
+
if (mode === 'object' && isEmpty(value)) {
|
|
100
|
+
throw Object.assign(new Error('Empty objects are forbidden in filter argument input.'), {});
|
|
101
|
+
}
|
|
102
|
+
if (mode === 'list') {
|
|
103
|
+
const arr = value;
|
|
104
|
+
if (arr) {
|
|
105
|
+
const l = arr.length;
|
|
106
|
+
for (let i = 0; i < l; i++) {
|
|
107
|
+
if (isEmpty(arr[i])) {
|
|
108
|
+
throw Object.assign(new Error('Empty objects are forbidden in filter argument input.'), {});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// For all modes, check null
|
|
114
|
+
if (!connectionFilterAllowNullInput && value === null) {
|
|
115
|
+
throw Object.assign(new Error('Null literals are forbidden in filter argument input.'), {});
|
|
116
|
+
}
|
|
117
|
+
}, [connectionFilterAllowNullInput, isEmpty]);
|
|
118
|
+
return assertAllowed;
|
|
119
|
+
}
|