graphile-plugin-connection-filter-postgis 1.0.0-alpha.7

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 ADDED
@@ -0,0 +1,23 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 Dan Lynch <pyramation@gmail.com>
4
+ Copyright (c) 2025 Hyperweb <developers@hyperweb.io>
5
+ Copyright (c) 2020-present, Interweb, Inc.
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from "graphile-build";
2
+ declare const PgConnectionArgFilterPostgisOperatorsPlugin: Plugin;
3
+ export default PgConnectionArgFilterPostgisOperatorsPlugin;
@@ -0,0 +1,219 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const PgConnectionArgFilterPostgisOperatorsPlugin = (builder) => {
4
+ builder.hook("init", (_, build) => {
5
+ const { addConnectionFilterOperator, inflection, pgSql: sql, pgGISExtension, pgGISGeographyType, pgGISGeometryType, } = build;
6
+ if (!pgGISExtension || !pgGISGeographyType || !pgGISGeometryType) {
7
+ return _;
8
+ }
9
+ const GEOGRAPHY = pgGISGeographyType.name;
10
+ const GEOMETRY = pgGISGeometryType.name;
11
+ const gqlTypeNamesByGisBaseTypeName = {
12
+ geography: [],
13
+ geometry: [],
14
+ };
15
+ gqlTypeNamesByGisBaseTypeName.geography.push(inflection.gisInterfaceName(pgGISGeographyType));
16
+ gqlTypeNamesByGisBaseTypeName.geometry.push(inflection.gisInterfaceName(pgGISGeometryType));
17
+ const subtypes = [0, 1, 2, 3, 4, 5, 6, 7];
18
+ for (const subtype of subtypes) {
19
+ for (const hasZ of [false, true]) {
20
+ for (const hasM of [false, true]) {
21
+ gqlTypeNamesByGisBaseTypeName.geography.push(inflection.gisType(pgGISGeographyType, subtype, hasZ, hasM));
22
+ gqlTypeNamesByGisBaseTypeName.geometry.push(inflection.gisType(pgGISGeometryType, subtype, hasZ, hasM));
23
+ }
24
+ }
25
+ }
26
+ const specs = [];
27
+ const functionSpecs = [
28
+ [
29
+ "ST_3DIntersects",
30
+ [GEOMETRY],
31
+ "intersects3D",
32
+ "They share any portion of space in 3D.",
33
+ ],
34
+ [
35
+ "ST_Contains",
36
+ [GEOMETRY],
37
+ "contains",
38
+ "No points of the specified geometry lie in the exterior, and at least one point of the interior of the specified geometry lies in the interior.",
39
+ ],
40
+ [
41
+ "ST_ContainsProperly",
42
+ [GEOMETRY],
43
+ "containsProperly",
44
+ "The specified geometry intersects the interior but not the boundary (or exterior).",
45
+ ],
46
+ [
47
+ "ST_CoveredBy",
48
+ [GEOMETRY, GEOGRAPHY],
49
+ "coveredBy",
50
+ "No point is outside the specified geometry.",
51
+ ],
52
+ [
53
+ "ST_Covers",
54
+ [GEOMETRY, GEOGRAPHY],
55
+ "covers",
56
+ "No point in the specified geometry is outside.",
57
+ ],
58
+ [
59
+ "ST_Crosses",
60
+ [GEOMETRY],
61
+ "crosses",
62
+ "They have some, but not all, interior points in common.",
63
+ ],
64
+ [
65
+ "ST_Disjoint",
66
+ [GEOMETRY],
67
+ "disjoint",
68
+ "They do not share any space together.",
69
+ ],
70
+ [
71
+ "ST_Equals",
72
+ [GEOMETRY],
73
+ "equals",
74
+ "They represent the same geometry. Directionality is ignored.",
75
+ ],
76
+ [
77
+ "ST_Intersects",
78
+ [GEOMETRY, GEOGRAPHY],
79
+ "intersects",
80
+ "They share any portion of space in 2D.",
81
+ ],
82
+ [
83
+ "ST_OrderingEquals",
84
+ [GEOMETRY],
85
+ "orderingEquals",
86
+ "They represent the same geometry and points are in the same directional order.",
87
+ ],
88
+ [
89
+ "ST_Overlaps",
90
+ [GEOMETRY],
91
+ "overlaps",
92
+ "They share space, are of the same dimension, but are not completely contained by each other.",
93
+ ],
94
+ [
95
+ "ST_Touches",
96
+ [GEOMETRY],
97
+ "touches",
98
+ "They have at least one point in common, but their interiors do not intersect.",
99
+ ],
100
+ [
101
+ "ST_Within",
102
+ [GEOMETRY],
103
+ "within",
104
+ "Completely inside the specified geometry.",
105
+ ],
106
+ ];
107
+ for (const [fn, baseTypeNames, operatorName, description,] of functionSpecs) {
108
+ for (const baseTypeName of baseTypeNames) {
109
+ const sqlGisFunction = pgGISExtension.namespaceName === "public"
110
+ ? sql.identifier(fn.toLowerCase())
111
+ : sql.identifier(pgGISExtension.namespaceName, fn.toLowerCase());
112
+ specs.push({
113
+ typeNames: gqlTypeNamesByGisBaseTypeName[baseTypeName === GEOGRAPHY ? "geography" : "geometry"],
114
+ operatorName,
115
+ description,
116
+ resolveType: (fieldType) => fieldType,
117
+ resolve: (i, v) => sql.query `${sqlGisFunction}(${i}, ${v})`,
118
+ });
119
+ }
120
+ }
121
+ const operatorSpecs = [
122
+ [
123
+ "=",
124
+ [GEOMETRY, GEOGRAPHY],
125
+ "exactlyEquals",
126
+ "Coordinates and coordinate order are the same as specified geometry.",
127
+ ],
128
+ [
129
+ "&&",
130
+ [GEOMETRY, GEOGRAPHY],
131
+ "bboxIntersects2D",
132
+ "2D bounding box intersects the specified geometry's 2D bounding box.",
133
+ ],
134
+ [
135
+ "&&&",
136
+ [GEOMETRY],
137
+ "bboxIntersectsND",
138
+ "n-D bounding box intersects the specified geometry's n-D bounding box.",
139
+ ],
140
+ [
141
+ "&<",
142
+ [GEOMETRY],
143
+ "bboxOverlapsOrLeftOf",
144
+ "Bounding box overlaps or is to the left of the specified geometry's bounding box.",
145
+ ],
146
+ [
147
+ "&<|",
148
+ [GEOMETRY],
149
+ "bboxOverlapsOrBelow",
150
+ "Bounding box overlaps or is below the specified geometry's bounding box.",
151
+ ],
152
+ [
153
+ "&>",
154
+ [GEOMETRY],
155
+ "bboxOverlapsOrRightOf",
156
+ "Bounding box overlaps or is to the right of the specified geometry's bounding box.",
157
+ ],
158
+ [
159
+ "|&>",
160
+ [GEOMETRY],
161
+ "bboxOverlapsOrAbove",
162
+ "Bounding box overlaps or is above the specified geometry's bounding box.",
163
+ ],
164
+ [
165
+ "<<",
166
+ [GEOMETRY],
167
+ "bboxLeftOf",
168
+ "Bounding box is strictly to the left of the specified geometry's bounding box.",
169
+ ],
170
+ [
171
+ "<<|",
172
+ [GEOMETRY],
173
+ "bboxBelow",
174
+ "Bounding box is strictly below the specified geometry's bounding box.",
175
+ ],
176
+ [
177
+ ">>",
178
+ [GEOMETRY],
179
+ "bboxRightOf",
180
+ "Bounding box is strictly to the right of the specified geometry's bounding box.",
181
+ ],
182
+ [
183
+ "|>>",
184
+ [GEOMETRY],
185
+ "bboxAbove",
186
+ "Bounding box is strictly above the specified geometry's bounding box.",
187
+ ],
188
+ [
189
+ "~",
190
+ [GEOMETRY],
191
+ "bboxContains",
192
+ "Bounding box contains the specified geometry's bounding box.",
193
+ ],
194
+ [
195
+ "~=",
196
+ [GEOMETRY],
197
+ "bboxEquals",
198
+ "Bounding box is the same as the specified geometry's bounding box.",
199
+ ],
200
+ ];
201
+ for (const [op, baseTypeNames, operatorName, description,] of operatorSpecs) {
202
+ for (const baseTypeName of baseTypeNames) {
203
+ specs.push({
204
+ typeNames: gqlTypeNamesByGisBaseTypeName[baseTypeName === GEOGRAPHY ? "geography" : "geometry"],
205
+ operatorName,
206
+ description,
207
+ resolveType: (fieldType) => fieldType,
208
+ resolve: (i, v) => sql.query `${i} ${sql.raw(op)} ${v}`,
209
+ });
210
+ }
211
+ }
212
+ specs.sort((a, b) => (a.operatorName > b.operatorName ? 1 : -1));
213
+ for (const spec of specs) {
214
+ addConnectionFilterOperator(spec.typeNames, spec.operatorName, spec.description, spec.resolveType, spec.resolve);
215
+ }
216
+ return _;
217
+ });
218
+ };
219
+ exports.default = PgConnectionArgFilterPostgisOperatorsPlugin;
package/README.md ADDED
@@ -0,0 +1,148 @@
1
+ # graphile-plugin-connection-filter-postgis
2
+
3
+ <p align="center" width="100%">
4
+ <img height="250" src="https://raw.githubusercontent.com/launchql/launchql/refs/heads/main/assets/outline-logo.svg" />
5
+ </p>
6
+
7
+ <p align="center" width="100%">
8
+ <a href="https://github.com/launchql/launchql/actions/workflows/run-tests.yaml">
9
+ <img height="20" src="https://github.com/launchql/launchql/actions/workflows/run-tests.yaml/badge.svg" />
10
+ </a>
11
+ <a href="https://github.com/launchql/launchql/blob/main/LICENSE">
12
+ <img height="20" src="https://img.shields.io/badge/license-MIT-blue.svg"/>
13
+ </a>
14
+ <a href="https://www.npmjs.com/package/graphile-plugin-connection-filter-postgis">
15
+ <img height="20" src="https://img.shields.io/github/package-json/v/launchql/launchql?filename=graphile%2Fgraphile-plugin-connection-filter-postgis%2Fpackage.json"/>
16
+ </a>
17
+ </p>
18
+
19
+ This plugin exposes additional PostGIS-related fields on the `filter` argument of Connections.
20
+
21
+ ## Usage
22
+
23
+ Requires `postgraphile@^4.5.0` and the following plugins appended prior to this plugin:
24
+
25
+ - `@graphile/postgis@0.1.0`
26
+ - `graphile-plugin-connection-filter@^2.0.0`
27
+
28
+ ## Operators
29
+
30
+ | PostGIS function | Types | GraphQL field name |
31
+ | --- | --- | --- |
32
+ | ST_3DIntersects | geometry | intersects3D |
33
+ | ST_Contains | geometry | contains |
34
+ | ST_ContainsProperly | geometry | containsProperly |
35
+ | ST_CoveredBy | geometry, geography | coveredBy |
36
+ | ST_Covers | geometry, geography | covers |
37
+ | ST_Crosses | geometry | crosses |
38
+ | ST_Disjoint | geometry | disjoint |
39
+ | ST_Equals | geometry | equals |
40
+ | ST_Intersects | geometry, geography | intersects |
41
+ | ST_OrderingEquals | geometry | orderingEquals |
42
+ | ST_Overlaps | geometry | overlaps |
43
+ | ST_Touches | geometry | touches |
44
+ | ST_Within | geometry | within |
45
+
46
+ | PostGIS operator | Types | GraphQL field name |
47
+ | --- | --- | --- |
48
+ | = | geometry, geography | exactlyEquals |
49
+ | && | geometry, geography | bboxIntersects2D |
50
+ | &&& | geometry | bboxIntersectsND |
51
+ | &< | geometry | bboxOverlapsOrLeftOf |
52
+ | &<\| | geometry | bboxOverlapsOrBelow |
53
+ | &> | geometry | bboxOverlapsOrRightOf |
54
+ | \|&> | geometry | bboxOverlapsOrAbove |
55
+ | << | geometry | bboxLeftOf |
56
+ | <<\| | geometry | bboxBelow |
57
+ | >> | geometry | bboxRightOf |
58
+ | \|>> | geometry | bboxAbove |
59
+ | ~ | geometry | bboxContains |
60
+ | ~= | geometry | bboxEquals |
61
+
62
+ ## Development
63
+
64
+ To establish a test environment, create an empty PostgreSQL database and set a `TEST_DATABASE_URL` environment variable with your database connection string.
65
+
66
+ ```bash
67
+ createdb graphile_test
68
+ export TEST_DATABASE_URL=postgres://localhost:5432/graphile_test
69
+ yarn
70
+ yarn test
71
+ ```
72
+
73
+ ---
74
+
75
+ ## Education and Tutorials
76
+
77
+ 1. 🚀 [Quickstart: Getting Up and Running](https://launchql.com/learn/quickstart)
78
+ Get started with modular databases in minutes. Install prerequisites and deploy your first module.
79
+
80
+ 2. 📦 [Modular PostgreSQL Development with Database Packages](https://launchql.com/learn/modular-postgres)
81
+ Learn to organize PostgreSQL projects with pgpm workspaces and reusable database modules.
82
+
83
+ 3. ✏️ [Authoring Database Changes](https://launchql.com/learn/authoring-database-changes)
84
+ Master the workflow for adding, organizing, and managing database changes with pgpm.
85
+
86
+ 4. 🧪 [End-to-End PostgreSQL Testing with TypeScript](https://launchql.com/learn/e2e-postgres-testing)
87
+ Master end-to-end PostgreSQL testing with ephemeral databases, RLS testing, and CI/CD automation.
88
+
89
+ 5. ⚡ [Supabase Testing](https://launchql.com/learn/supabase)
90
+ Use TypeScript-first tools to test Supabase projects with realistic RLS, policies, and auth contexts.
91
+
92
+ 6. 💧 [Drizzle ORM Testing](https://launchql.com/learn/drizzle-testing)
93
+ Run full-stack tests with Drizzle ORM, including database setup, teardown, and RLS enforcement.
94
+
95
+ 7. 🔧 [Troubleshooting](https://launchql.com/learn/troubleshooting)
96
+ Common issues and solutions for pgpm, PostgreSQL, and testing.
97
+
98
+ ## Related LaunchQL Tooling
99
+
100
+ ### 🧪 Testing
101
+
102
+ * [launchql/pgsql-test](https://github.com/launchql/launchql/tree/main/packages/pgsql-test): **📊 Isolated testing environments** with per-test transaction rollbacks—ideal for integration tests, complex migrations, and RLS simulation.
103
+ * [launchql/supabase-test](https://github.com/launchql/launchql/tree/main/packages/supabase-test): **🧪 Supabase-native test harness** preconfigured for the local Supabase stack—per-test rollbacks, JWT/role context helpers, and CI/GitHub Actions ready.
104
+ * [launchql/graphile-test](https://github.com/launchql/launchql/tree/main/packages/graphile-test): **🔐 Authentication mocking** for Graphile-focused test helpers and emulating row-level security contexts.
105
+ * [launchql/pg-query-context](https://github.com/launchql/launchql/tree/main/packages/pg-query-context): **🔒 Session context injection** to add session-local context (e.g., `SET LOCAL`) into queries—ideal for setting `role`, `jwt.claims`, and other session settings.
106
+
107
+ ### 🧠 Parsing & AST
108
+
109
+ * [launchql/pgsql-parser](https://github.com/launchql/pgsql-parser): **🔄 SQL conversion engine** that interprets and converts PostgreSQL syntax.
110
+ * [launchql/libpg-query-node](https://github.com/launchql/libpg-query-node): **🌉 Node.js bindings** for `libpg_query`, converting SQL into parse trees.
111
+ * [launchql/pg-proto-parser](https://github.com/launchql/pg-proto-parser): **📦 Protobuf parser** for parsing PostgreSQL Protocol Buffers definitions to generate TypeScript interfaces, utility functions, and JSON mappings for enums.
112
+ * [@pgsql/enums](https://github.com/launchql/pgsql-parser/tree/main/packages/enums): **🏷️ TypeScript enums** for PostgreSQL AST for safe and ergonomic parsing logic.
113
+ * [@pgsql/types](https://github.com/launchql/pgsql-parser/tree/main/packages/types): **📝 Type definitions** for PostgreSQL AST nodes in TypeScript.
114
+ * [@pgsql/utils](https://github.com/launchql/pgsql-parser/tree/main/packages/utils): **🛠️ AST utilities** for constructing and transforming PostgreSQL syntax trees.
115
+ * [launchql/pg-ast](https://github.com/launchql/launchql/tree/main/packages/pg-ast): **🔍 Low-level AST tools** and transformations for Postgres query structures.
116
+
117
+ ### 🚀 API & Dev Tools
118
+
119
+ * [launchql/server](https://github.com/launchql/launchql/tree/main/packages/server): **⚡ Express-based API server** powered by PostGraphile to expose a secure, scalable GraphQL API over your Postgres database.
120
+ * [launchql/explorer](https://github.com/launchql/launchql/tree/main/packages/explorer): **🔎 Visual API explorer** with GraphiQL for browsing across all databases and schemas—useful for debugging, documentation, and API prototyping.
121
+
122
+ ### 🔁 Streaming & Uploads
123
+
124
+ * [launchql/s3-streamer](https://github.com/launchql/launchql/tree/main/packages/s3-streamer): **📤 Direct S3 streaming** for large files with support for metadata injection and content validation.
125
+ * [launchql/etag-hash](https://github.com/launchql/launchql/tree/main/packages/etag-hash): **🏷️ S3-compatible ETags** created by streaming and hashing file uploads in chunks.
126
+ * [launchql/etag-stream](https://github.com/launchql/launchql/tree/main/packages/etag-stream): **🔄 ETag computation** via Node stream transformer during upload or transfer.
127
+ * [launchql/uuid-hash](https://github.com/launchql/launchql/tree/main/packages/uuid-hash): **🆔 Deterministic UUIDs** generated from hashed content, great for deduplication and asset referencing.
128
+ * [launchql/uuid-stream](https://github.com/launchql/launchql/tree/main/packages/uuid-stream): **🌊 Streaming UUID generation** based on piped file content—ideal for upload pipelines.
129
+ * [launchql/upload-names](https://github.com/launchql/launchql/tree/main/packages/upload-names): **📂 Collision-resistant filenames** utility for structured and unique file names for uploads.
130
+
131
+ ### 🧰 CLI & Codegen
132
+
133
+ * [pgpm](https://github.com/launchql/launchql/tree/main/packages/pgpm): **🖥️ PostgreSQL Package Manager** for modular Postgres development. Works with database workspaces, scaffolding, migrations, seeding, and installing database packages.
134
+ * [@launchql/cli](https://github.com/launchql/launchql/tree/main/packages/cli): **🖥️ Command-line toolkit** for managing LaunchQL projects—supports database scaffolding, migrations, seeding, code generation, and automation.
135
+ * [launchql/launchql-gen](https://github.com/launchql/launchql/tree/main/packages/launchql-gen): **✨ Auto-generated GraphQL** mutations and queries dynamically built from introspected schema data.
136
+ * [@launchql/query-builder](https://github.com/launchql/launchql/tree/main/packages/query-builder): **🏗️ SQL constructor** providing a robust TypeScript-based query builder for dynamic generation of `SELECT`, `INSERT`, `UPDATE`, `DELETE`, and stored procedure calls—supports advanced SQL features like `JOIN`, `GROUP BY`, and schema-qualified queries.
137
+ * [@launchql/query](https://github.com/launchql/launchql/tree/main/packages/query): **🧩 Fluent GraphQL builder** for PostGraphile schemas. ⚡ Schema-aware via introspection, 🧩 composable and ergonomic for building deeply nested queries.
138
+
139
+ ## Credits
140
+
141
+ 🛠 Built by LaunchQL — if you like our tools, please checkout and contribute to [our github ⚛️](https://github.com/launchql)
142
+
143
+
144
+ ## Disclaimer
145
+
146
+ AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED "AS IS", AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND.
147
+
148
+ No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value.
@@ -0,0 +1,217 @@
1
+ const PgConnectionArgFilterPostgisOperatorsPlugin = (builder) => {
2
+ builder.hook("init", (_, build) => {
3
+ const { addConnectionFilterOperator, inflection, pgSql: sql, pgGISExtension, pgGISGeographyType, pgGISGeometryType, } = build;
4
+ if (!pgGISExtension || !pgGISGeographyType || !pgGISGeometryType) {
5
+ return _;
6
+ }
7
+ const GEOGRAPHY = pgGISGeographyType.name;
8
+ const GEOMETRY = pgGISGeometryType.name;
9
+ const gqlTypeNamesByGisBaseTypeName = {
10
+ geography: [],
11
+ geometry: [],
12
+ };
13
+ gqlTypeNamesByGisBaseTypeName.geography.push(inflection.gisInterfaceName(pgGISGeographyType));
14
+ gqlTypeNamesByGisBaseTypeName.geometry.push(inflection.gisInterfaceName(pgGISGeometryType));
15
+ const subtypes = [0, 1, 2, 3, 4, 5, 6, 7];
16
+ for (const subtype of subtypes) {
17
+ for (const hasZ of [false, true]) {
18
+ for (const hasM of [false, true]) {
19
+ gqlTypeNamesByGisBaseTypeName.geography.push(inflection.gisType(pgGISGeographyType, subtype, hasZ, hasM));
20
+ gqlTypeNamesByGisBaseTypeName.geometry.push(inflection.gisType(pgGISGeometryType, subtype, hasZ, hasM));
21
+ }
22
+ }
23
+ }
24
+ const specs = [];
25
+ const functionSpecs = [
26
+ [
27
+ "ST_3DIntersects",
28
+ [GEOMETRY],
29
+ "intersects3D",
30
+ "They share any portion of space in 3D.",
31
+ ],
32
+ [
33
+ "ST_Contains",
34
+ [GEOMETRY],
35
+ "contains",
36
+ "No points of the specified geometry lie in the exterior, and at least one point of the interior of the specified geometry lies in the interior.",
37
+ ],
38
+ [
39
+ "ST_ContainsProperly",
40
+ [GEOMETRY],
41
+ "containsProperly",
42
+ "The specified geometry intersects the interior but not the boundary (or exterior).",
43
+ ],
44
+ [
45
+ "ST_CoveredBy",
46
+ [GEOMETRY, GEOGRAPHY],
47
+ "coveredBy",
48
+ "No point is outside the specified geometry.",
49
+ ],
50
+ [
51
+ "ST_Covers",
52
+ [GEOMETRY, GEOGRAPHY],
53
+ "covers",
54
+ "No point in the specified geometry is outside.",
55
+ ],
56
+ [
57
+ "ST_Crosses",
58
+ [GEOMETRY],
59
+ "crosses",
60
+ "They have some, but not all, interior points in common.",
61
+ ],
62
+ [
63
+ "ST_Disjoint",
64
+ [GEOMETRY],
65
+ "disjoint",
66
+ "They do not share any space together.",
67
+ ],
68
+ [
69
+ "ST_Equals",
70
+ [GEOMETRY],
71
+ "equals",
72
+ "They represent the same geometry. Directionality is ignored.",
73
+ ],
74
+ [
75
+ "ST_Intersects",
76
+ [GEOMETRY, GEOGRAPHY],
77
+ "intersects",
78
+ "They share any portion of space in 2D.",
79
+ ],
80
+ [
81
+ "ST_OrderingEquals",
82
+ [GEOMETRY],
83
+ "orderingEquals",
84
+ "They represent the same geometry and points are in the same directional order.",
85
+ ],
86
+ [
87
+ "ST_Overlaps",
88
+ [GEOMETRY],
89
+ "overlaps",
90
+ "They share space, are of the same dimension, but are not completely contained by each other.",
91
+ ],
92
+ [
93
+ "ST_Touches",
94
+ [GEOMETRY],
95
+ "touches",
96
+ "They have at least one point in common, but their interiors do not intersect.",
97
+ ],
98
+ [
99
+ "ST_Within",
100
+ [GEOMETRY],
101
+ "within",
102
+ "Completely inside the specified geometry.",
103
+ ],
104
+ ];
105
+ for (const [fn, baseTypeNames, operatorName, description,] of functionSpecs) {
106
+ for (const baseTypeName of baseTypeNames) {
107
+ const sqlGisFunction = pgGISExtension.namespaceName === "public"
108
+ ? sql.identifier(fn.toLowerCase())
109
+ : sql.identifier(pgGISExtension.namespaceName, fn.toLowerCase());
110
+ specs.push({
111
+ typeNames: gqlTypeNamesByGisBaseTypeName[baseTypeName === GEOGRAPHY ? "geography" : "geometry"],
112
+ operatorName,
113
+ description,
114
+ resolveType: (fieldType) => fieldType,
115
+ resolve: (i, v) => sql.query `${sqlGisFunction}(${i}, ${v})`,
116
+ });
117
+ }
118
+ }
119
+ const operatorSpecs = [
120
+ [
121
+ "=",
122
+ [GEOMETRY, GEOGRAPHY],
123
+ "exactlyEquals",
124
+ "Coordinates and coordinate order are the same as specified geometry.",
125
+ ],
126
+ [
127
+ "&&",
128
+ [GEOMETRY, GEOGRAPHY],
129
+ "bboxIntersects2D",
130
+ "2D bounding box intersects the specified geometry's 2D bounding box.",
131
+ ],
132
+ [
133
+ "&&&",
134
+ [GEOMETRY],
135
+ "bboxIntersectsND",
136
+ "n-D bounding box intersects the specified geometry's n-D bounding box.",
137
+ ],
138
+ [
139
+ "&<",
140
+ [GEOMETRY],
141
+ "bboxOverlapsOrLeftOf",
142
+ "Bounding box overlaps or is to the left of the specified geometry's bounding box.",
143
+ ],
144
+ [
145
+ "&<|",
146
+ [GEOMETRY],
147
+ "bboxOverlapsOrBelow",
148
+ "Bounding box overlaps or is below the specified geometry's bounding box.",
149
+ ],
150
+ [
151
+ "&>",
152
+ [GEOMETRY],
153
+ "bboxOverlapsOrRightOf",
154
+ "Bounding box overlaps or is to the right of the specified geometry's bounding box.",
155
+ ],
156
+ [
157
+ "|&>",
158
+ [GEOMETRY],
159
+ "bboxOverlapsOrAbove",
160
+ "Bounding box overlaps or is above the specified geometry's bounding box.",
161
+ ],
162
+ [
163
+ "<<",
164
+ [GEOMETRY],
165
+ "bboxLeftOf",
166
+ "Bounding box is strictly to the left of the specified geometry's bounding box.",
167
+ ],
168
+ [
169
+ "<<|",
170
+ [GEOMETRY],
171
+ "bboxBelow",
172
+ "Bounding box is strictly below the specified geometry's bounding box.",
173
+ ],
174
+ [
175
+ ">>",
176
+ [GEOMETRY],
177
+ "bboxRightOf",
178
+ "Bounding box is strictly to the right of the specified geometry's bounding box.",
179
+ ],
180
+ [
181
+ "|>>",
182
+ [GEOMETRY],
183
+ "bboxAbove",
184
+ "Bounding box is strictly above the specified geometry's bounding box.",
185
+ ],
186
+ [
187
+ "~",
188
+ [GEOMETRY],
189
+ "bboxContains",
190
+ "Bounding box contains the specified geometry's bounding box.",
191
+ ],
192
+ [
193
+ "~=",
194
+ [GEOMETRY],
195
+ "bboxEquals",
196
+ "Bounding box is the same as the specified geometry's bounding box.",
197
+ ],
198
+ ];
199
+ for (const [op, baseTypeNames, operatorName, description,] of operatorSpecs) {
200
+ for (const baseTypeName of baseTypeNames) {
201
+ specs.push({
202
+ typeNames: gqlTypeNamesByGisBaseTypeName[baseTypeName === GEOGRAPHY ? "geography" : "geometry"],
203
+ operatorName,
204
+ description,
205
+ resolveType: (fieldType) => fieldType,
206
+ resolve: (i, v) => sql.query `${i} ${sql.raw(op)} ${v}`,
207
+ });
208
+ }
209
+ }
210
+ specs.sort((a, b) => (a.operatorName > b.operatorName ? 1 : -1));
211
+ for (const spec of specs) {
212
+ addConnectionFilterOperator(spec.typeNames, spec.operatorName, spec.description, spec.resolveType, spec.resolve);
213
+ }
214
+ return _;
215
+ });
216
+ };
217
+ export default PgConnectionArgFilterPostgisOperatorsPlugin;
package/esm/index.js ADDED
@@ -0,0 +1,23 @@
1
+ import PostgisOperatorsPlugin from "./PgConnectionArgFilterPostgisOperatorsPlugin";
2
+ import pkg from "../package.json";
3
+ const PostGraphileConnectionFilterPostgisPlugin = (builder, options) => {
4
+ builder.hook("build", (build) => {
5
+ if (!build.versions) {
6
+ throw new Error(`Plugin ${pkg.name}@${pkg.version} requires graphile-build@^4.1.0 in order to check dependencies (current version: ${build.graphileBuildVersion})`);
7
+ }
8
+ const depends = (name, range) => {
9
+ if (!build.hasVersion(name, range)) {
10
+ throw new Error(`Plugin ${pkg.name}@${pkg.version} requires ${name}@${range} (${build.versions[name]
11
+ ? `current version: ${build.versions[name]}`
12
+ : "not found"})`);
13
+ }
14
+ };
15
+ depends("graphile-build-pg", "^4.5.0");
16
+ depends("graphile-plugin-connection-filter", "^2.0.0");
17
+ build.versions = build.extend(build.versions, { [pkg.name]: pkg.version });
18
+ return build;
19
+ });
20
+ PostgisOperatorsPlugin(builder, options);
21
+ };
22
+ export { PostGraphileConnectionFilterPostgisPlugin };
23
+ export default PostGraphileConnectionFilterPostgisPlugin;
package/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import type { Plugin } from "graphile-build";
2
+ declare const PostGraphileConnectionFilterPostgisPlugin: Plugin;
3
+ export { PostGraphileConnectionFilterPostgisPlugin };
4
+ export default PostGraphileConnectionFilterPostgisPlugin;
package/index.js ADDED
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PostGraphileConnectionFilterPostgisPlugin = void 0;
7
+ const PgConnectionArgFilterPostgisOperatorsPlugin_1 = __importDefault(require("./PgConnectionArgFilterPostgisOperatorsPlugin"));
8
+ const package_json_1 = __importDefault(require("../package.json"));
9
+ const PostGraphileConnectionFilterPostgisPlugin = (builder, options) => {
10
+ builder.hook("build", (build) => {
11
+ if (!build.versions) {
12
+ throw new Error(`Plugin ${package_json_1.default.name}@${package_json_1.default.version} requires graphile-build@^4.1.0 in order to check dependencies (current version: ${build.graphileBuildVersion})`);
13
+ }
14
+ const depends = (name, range) => {
15
+ if (!build.hasVersion(name, range)) {
16
+ throw new Error(`Plugin ${package_json_1.default.name}@${package_json_1.default.version} requires ${name}@${range} (${build.versions[name]
17
+ ? `current version: ${build.versions[name]}`
18
+ : "not found"})`);
19
+ }
20
+ };
21
+ depends("graphile-build-pg", "^4.5.0");
22
+ depends("graphile-plugin-connection-filter", "^2.0.0");
23
+ build.versions = build.extend(build.versions, { [package_json_1.default.name]: package_json_1.default.version });
24
+ return build;
25
+ });
26
+ (0, PgConnectionArgFilterPostgisOperatorsPlugin_1.default)(builder, options);
27
+ };
28
+ exports.PostGraphileConnectionFilterPostgisPlugin = PostGraphileConnectionFilterPostgisPlugin;
29
+ exports.default = PostGraphileConnectionFilterPostgisPlugin;
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "graphile-plugin-connection-filter-postgis",
3
+ "version": "1.0.0-alpha.7",
4
+ "description": "PostGIS filtering options in PostGraphile",
5
+ "author": "Matt Bretl",
6
+ "homepage": "https://github.com/launchql/launchql",
7
+ "license": "MIT",
8
+ "main": "index.js",
9
+ "module": "esm/index.js",
10
+ "types": "index.d.ts",
11
+ "scripts": {
12
+ "clean": "makage clean",
13
+ "copy": "makage assets",
14
+ "prepack": "pnpm run build",
15
+ "build": "makage build",
16
+ "build:dev": "makage build --dev",
17
+ "lint": "eslint . --fix",
18
+ "test": "jest",
19
+ "test:watch": "jest --watch"
20
+ },
21
+ "publishConfig": {
22
+ "access": "public",
23
+ "directory": "dist"
24
+ },
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/launchql/launchql"
28
+ },
29
+ "bugs": {
30
+ "url": "https://github.com/launchql/launchql/issues"
31
+ },
32
+ "keywords": [
33
+ "postgraphile",
34
+ "graphile",
35
+ "plugin",
36
+ "postgres",
37
+ "postgresql",
38
+ "postgis",
39
+ "filters",
40
+ "launchql"
41
+ ],
42
+ "dependencies": {
43
+ "@graphile/postgis": "^0.1.0",
44
+ "graphile-build": "^4.14.1",
45
+ "graphile-build-pg": "^4.14.1",
46
+ "graphile-plugin-connection-filter": "^2.3.2"
47
+ },
48
+ "peerDependencies": {
49
+ "@graphile/postgis": "^0.1.0",
50
+ "graphile-plugin-connection-filter": "workspace:^",
51
+ "postgraphile": "^4.14.1"
52
+ },
53
+ "devDependencies": {
54
+ "@types/pg": "^8.15.6",
55
+ "graphile-plugin-connection-filter": "workspace:^",
56
+ "graphile-test": "^2.8.10",
57
+ "graphql": "15.10.1",
58
+ "makage": "^0.1.6",
59
+ "pg": "^8.16.0",
60
+ "pgsql-test": "^2.14.13",
61
+ "postgraphile": "^4.14.1"
62
+ },
63
+ "gitHead": "4e1ff9771c2b07808a9830281abc24d12c689187"
64
+ }