graphile-postgis 1.1.1 → 2.2.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 (76) hide show
  1. package/README.md +22 -45
  2. package/constants.d.ts +1 -0
  3. package/constants.js +10 -1
  4. package/esm/constants.d.ts +13 -0
  5. package/esm/constants.js +9 -0
  6. package/esm/index.d.ts +24 -0
  7. package/esm/index.js +25 -33
  8. package/esm/plugins/codec.d.ts +19 -0
  9. package/esm/plugins/codec.js +174 -0
  10. package/esm/plugins/detect-extension.d.ts +14 -0
  11. package/esm/plugins/detect-extension.js +57 -0
  12. package/esm/plugins/geometry-fields.d.ts +21 -0
  13. package/esm/plugins/geometry-fields.js +245 -0
  14. package/esm/plugins/inflection.d.ts +8 -0
  15. package/esm/plugins/inflection.js +52 -0
  16. package/esm/plugins/register-types.d.ts +22 -0
  17. package/esm/plugins/register-types.js +319 -0
  18. package/esm/preset.d.ts +18 -0
  19. package/esm/preset.js +30 -0
  20. package/esm/types.d.ts +84 -0
  21. package/esm/utils.d.ts +21 -0
  22. package/esm/utils.js +18 -7
  23. package/index.d.ts +24 -15
  24. package/index.js +39 -47
  25. package/package.json +23 -18
  26. package/plugins/codec.d.ts +19 -0
  27. package/plugins/codec.js +180 -0
  28. package/plugins/detect-extension.d.ts +14 -0
  29. package/plugins/detect-extension.js +60 -0
  30. package/plugins/geometry-fields.d.ts +21 -0
  31. package/plugins/geometry-fields.js +248 -0
  32. package/plugins/inflection.d.ts +8 -0
  33. package/plugins/inflection.js +55 -0
  34. package/plugins/register-types.d.ts +22 -0
  35. package/plugins/register-types.js +325 -0
  36. package/preset.d.ts +18 -0
  37. package/preset.js +33 -0
  38. package/types.d.ts +69 -44
  39. package/utils.d.ts +16 -0
  40. package/utils.js +17 -6
  41. package/PostgisExtensionDetectionPlugin.d.ts +0 -3
  42. package/PostgisExtensionDetectionPlugin.js +0 -28
  43. package/PostgisInflectionPlugin.d.ts +0 -3
  44. package/PostgisInflectionPlugin.js +0 -36
  45. package/PostgisRegisterTypesPlugin.d.ts +0 -3
  46. package/PostgisRegisterTypesPlugin.js +0 -234
  47. package/PostgisVersionPlugin.d.ts +0 -3
  48. package/PostgisVersionPlugin.js +0 -24
  49. package/Postgis_GeometryCollection_GeometriesPlugin.d.ts +0 -3
  50. package/Postgis_GeometryCollection_GeometriesPlugin.js +0 -43
  51. package/Postgis_LineString_PointsPlugin.d.ts +0 -3
  52. package/Postgis_LineString_PointsPlugin.js +0 -40
  53. package/Postgis_MultiLineString_LineStringsPlugin.d.ts +0 -3
  54. package/Postgis_MultiLineString_LineStringsPlugin.js +0 -38
  55. package/Postgis_MultiPoint_PointsPlugin.d.ts +0 -3
  56. package/Postgis_MultiPoint_PointsPlugin.js +0 -38
  57. package/Postgis_MultiPolygon_PolygonsPlugin.d.ts +0 -3
  58. package/Postgis_MultiPolygon_PolygonsPlugin.js +0 -38
  59. package/Postgis_Point_LatitudeLongitudePlugin.d.ts +0 -3
  60. package/Postgis_Point_LatitudeLongitudePlugin.js +0 -43
  61. package/Postgis_Polygon_RingsPlugin.d.ts +0 -3
  62. package/Postgis_Polygon_RingsPlugin.js +0 -49
  63. package/esm/PostgisExtensionDetectionPlugin.js +0 -26
  64. package/esm/PostgisInflectionPlugin.js +0 -34
  65. package/esm/PostgisRegisterTypesPlugin.js +0 -229
  66. package/esm/PostgisVersionPlugin.js +0 -22
  67. package/esm/Postgis_GeometryCollection_GeometriesPlugin.js +0 -41
  68. package/esm/Postgis_LineString_PointsPlugin.js +0 -38
  69. package/esm/Postgis_MultiLineString_LineStringsPlugin.js +0 -36
  70. package/esm/Postgis_MultiPoint_PointsPlugin.js +0 -36
  71. package/esm/Postgis_MultiPolygon_PolygonsPlugin.js +0 -36
  72. package/esm/Postgis_Point_LatitudeLongitudePlugin.js +0 -41
  73. package/esm/Postgis_Polygon_RingsPlugin.js +0 -47
  74. package/esm/makeGeoJSONType.js +0 -39
  75. package/makeGeoJSONType.d.ts +0 -1
  76. package/makeGeoJSONType.js +0 -42
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PostgisExtensionDetectionPlugin = void 0;
4
+ require("graphile-build");
5
+ require("graphile-build-pg");
6
+ /**
7
+ * PostgisExtensionDetectionPlugin
8
+ *
9
+ * Detects PostGIS presence in the database by searching for geometry/geography
10
+ * codecs in the pgRegistry. Stores detected info on the build object for
11
+ * downstream plugins.
12
+ *
13
+ * Gracefully degrades if PostGIS is not installed.
14
+ */
15
+ exports.PostgisExtensionDetectionPlugin = {
16
+ name: 'PostgisExtensionDetectionPlugin',
17
+ version: '2.0.0',
18
+ description: 'Detects PostGIS extension in the database',
19
+ schema: {
20
+ hooks: {
21
+ build(build) {
22
+ const pgRegistry = build.input?.pgRegistry;
23
+ if (!pgRegistry) {
24
+ return build;
25
+ }
26
+ let geometryCodec = null;
27
+ let geographyCodec = null;
28
+ let schemaName = 'public';
29
+ // Search through codecs for geometry and geography types
30
+ for (const codec of Object.values(pgRegistry.pgCodecs)) {
31
+ const pg = codec?.extensions?.pg;
32
+ if (!pg)
33
+ continue;
34
+ if (pg.name === 'geometry') {
35
+ geometryCodec = codec;
36
+ schemaName = pg.schemaName || 'public';
37
+ }
38
+ else if (pg.name === 'geography') {
39
+ geographyCodec = codec;
40
+ }
41
+ }
42
+ // PostGIS requires at least the geometry codec to be present.
43
+ // Geography is optional — not all databases use geography columns,
44
+ // so PostGraphile may not introspect the geography type at all.
45
+ if (!geometryCodec) {
46
+ return build;
47
+ }
48
+ const postgisInfo = {
49
+ schemaName,
50
+ geometryCodec,
51
+ geographyCodec
52
+ };
53
+ return build.extend(build, {
54
+ pgGISExtensionInfo: postgisInfo,
55
+ pgGISGraphQLTypesByCodecAndSubtype: {}
56
+ }, 'PostgisExtensionDetectionPlugin adding PostGIS build state');
57
+ }
58
+ }
59
+ }
60
+ };
@@ -0,0 +1,21 @@
1
+ import 'graphile-build';
2
+ import 'graphile-build-pg';
3
+ import type { GraphileConfig } from 'graphile-config';
4
+ import '../types';
5
+ /**
6
+ * PostgisGeometryFieldsPlugin
7
+ *
8
+ * Enhances PostGIS geometry object types with subtype-specific fields:
9
+ *
10
+ * - Point: x/longitude, y/latitude, optional z/height
11
+ * - LineString: points array
12
+ * - Polygon: exterior ring, interiors array
13
+ * - MultiPoint: points array
14
+ * - MultiLineString: lines array
15
+ * - MultiPolygon: polygons array
16
+ * - GeometryCollection: geometries array (uses dimension interface)
17
+ *
18
+ * Uses the GraphQLObjectType_fields hook to add fields based on the
19
+ * type's scope (isPgGISType, pgGISCodecName, pgGISTypeDetails).
20
+ */
21
+ export declare const PostgisGeometryFieldsPlugin: GraphileConfig.Plugin;
@@ -0,0 +1,248 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PostgisGeometryFieldsPlugin = void 0;
4
+ require("graphile-build");
5
+ require("graphile-build-pg");
6
+ const constants_1 = require("../constants");
7
+ const utils_1 = require("../utils");
8
+ // Import types.ts for Build/Inflection/Scope augmentation side effects
9
+ require("../types");
10
+ /**
11
+ * PostgisGeometryFieldsPlugin
12
+ *
13
+ * Enhances PostGIS geometry object types with subtype-specific fields:
14
+ *
15
+ * - Point: x/longitude, y/latitude, optional z/height
16
+ * - LineString: points array
17
+ * - Polygon: exterior ring, interiors array
18
+ * - MultiPoint: points array
19
+ * - MultiLineString: lines array
20
+ * - MultiPolygon: polygons array
21
+ * - GeometryCollection: geometries array (uses dimension interface)
22
+ *
23
+ * Uses the GraphQLObjectType_fields hook to add fields based on the
24
+ * type's scope (isPgGISType, pgGISCodecName, pgGISTypeDetails).
25
+ */
26
+ exports.PostgisGeometryFieldsPlugin = {
27
+ name: 'PostgisGeometryFieldsPlugin',
28
+ version: '2.0.0',
29
+ description: 'Adds subtype-specific fields to PostGIS geometry types',
30
+ after: ['PostgisRegisterTypesPlugin', 'PostgisInflectionPlugin'],
31
+ schema: {
32
+ hooks: {
33
+ GraphQLObjectType_fields(fields, build, context) {
34
+ const { isPgGISType, pgGISCodecName, pgGISTypeDetails } = context.scope;
35
+ if (!isPgGISType || !pgGISCodecName || !pgGISTypeDetails) {
36
+ return fields;
37
+ }
38
+ const { graphql: { GraphQLNonNull, GraphQLFloat, GraphQLList }, inflection } = build;
39
+ const typeDetails = pgGISTypeDetails;
40
+ const { subtype, hasZ, hasM, srid } = typeDetails;
41
+ const getType = build.getPostgisTypeByGeometryType;
42
+ switch (subtype) {
43
+ case constants_1.GisSubtype.Point:
44
+ return addPointFields(fields, build, pgGISCodecName, hasZ, GraphQLNonNull, GraphQLFloat, inflection);
45
+ case constants_1.GisSubtype.LineString:
46
+ return addLineStringFields(fields, build, pgGISCodecName, hasZ, hasM, srid, GraphQLList, getType);
47
+ case constants_1.GisSubtype.Polygon:
48
+ return addPolygonFields(fields, build, pgGISCodecName, hasZ, hasM, srid, GraphQLList, getType);
49
+ case constants_1.GisSubtype.MultiPoint:
50
+ return addMultiPointFields(fields, build, pgGISCodecName, hasZ, hasM, srid, GraphQLList, getType);
51
+ case constants_1.GisSubtype.MultiLineString:
52
+ return addMultiLineStringFields(fields, build, pgGISCodecName, hasZ, hasM, srid, GraphQLList, getType);
53
+ case constants_1.GisSubtype.MultiPolygon:
54
+ return addMultiPolygonFields(fields, build, pgGISCodecName, hasZ, hasM, srid, GraphQLList, getType);
55
+ case constants_1.GisSubtype.GeometryCollection:
56
+ return addGeometryCollectionFields(fields, build, pgGISCodecName, hasZ, hasM, GraphQLList);
57
+ default:
58
+ return fields;
59
+ }
60
+ }
61
+ }
62
+ }
63
+ };
64
+ function addPointFields(fields, build, codecName, hasZ, GraphQLNonNull, GraphQLFloat, inflection) {
65
+ const xFieldName = inflection.gisXFieldName(codecName);
66
+ const yFieldName = inflection.gisYFieldName(codecName);
67
+ const zFieldName = inflection.gisZFieldName(codecName);
68
+ const newFields = {
69
+ [xFieldName]: {
70
+ type: new GraphQLNonNull(GraphQLFloat),
71
+ resolve(data) {
72
+ const coords = data.__geojson.coordinates;
73
+ if (coords.length < 1) {
74
+ throw new Error('Point geometry has no x coordinate');
75
+ }
76
+ return coords[0];
77
+ }
78
+ },
79
+ [yFieldName]: {
80
+ type: new GraphQLNonNull(GraphQLFloat),
81
+ resolve(data) {
82
+ const coords = data.__geojson.coordinates;
83
+ if (coords.length < 2) {
84
+ throw new Error('Point geometry has no y coordinate');
85
+ }
86
+ return coords[1];
87
+ }
88
+ }
89
+ };
90
+ if (hasZ) {
91
+ newFields[zFieldName] = {
92
+ type: new GraphQLNonNull(GraphQLFloat),
93
+ resolve(data) {
94
+ const coords = data.__geojson.coordinates;
95
+ if (coords.length < 3) {
96
+ throw new Error('Point geometry has no z coordinate');
97
+ }
98
+ return coords[2];
99
+ }
100
+ };
101
+ }
102
+ return build.extend(fields, newFields, 'PostgisGeometryFieldsPlugin adding Point fields');
103
+ }
104
+ function addLineStringFields(fields, build, codecName, hasZ, hasM, srid, GraphQLList, getType) {
105
+ const PointType = getType?.(codecName, constants_1.GisSubtype.Point, hasZ, hasM, srid);
106
+ if (!PointType)
107
+ return fields;
108
+ return build.extend(fields, {
109
+ points: {
110
+ type: new GraphQLList(PointType),
111
+ resolve(data) {
112
+ const lineString = data.__geojson;
113
+ return lineString.coordinates.map((coord) => ({
114
+ __gisType: (0, utils_1.getGISTypeName)(constants_1.GisSubtype.Point, hasZ, hasM),
115
+ __srid: data.__srid,
116
+ __geojson: {
117
+ type: 'Point',
118
+ coordinates: coord
119
+ }
120
+ }));
121
+ }
122
+ }
123
+ }, 'PostgisGeometryFieldsPlugin adding LineString fields');
124
+ }
125
+ function addPolygonFields(fields, build, codecName, hasZ, hasM, srid, GraphQLList, getType) {
126
+ const LineStringType = getType?.(codecName, constants_1.GisSubtype.LineString, hasZ, hasM, srid);
127
+ if (!LineStringType)
128
+ return fields;
129
+ return build.extend(fields, {
130
+ exterior: {
131
+ type: LineStringType,
132
+ resolve(data) {
133
+ const polygon = data.__geojson;
134
+ return {
135
+ __gisType: (0, utils_1.getGISTypeName)(constants_1.GisSubtype.LineString, hasZ, hasM),
136
+ __srid: data.__srid,
137
+ __geojson: {
138
+ type: 'LineString',
139
+ coordinates: polygon.coordinates[0]
140
+ }
141
+ };
142
+ }
143
+ },
144
+ interiors: {
145
+ type: new GraphQLList(LineStringType),
146
+ resolve(data) {
147
+ const polygon = data.__geojson;
148
+ return polygon.coordinates.slice(1).map((coord) => ({
149
+ __gisType: (0, utils_1.getGISTypeName)(constants_1.GisSubtype.LineString, hasZ, hasM),
150
+ __srid: data.__srid,
151
+ __geojson: {
152
+ type: 'LineString',
153
+ coordinates: coord
154
+ }
155
+ }));
156
+ }
157
+ }
158
+ }, 'PostgisGeometryFieldsPlugin adding Polygon fields');
159
+ }
160
+ function addMultiPointFields(fields, build, codecName, hasZ, hasM, srid, GraphQLList, getType) {
161
+ const PointType = getType?.(codecName, constants_1.GisSubtype.Point, hasZ, hasM, srid);
162
+ if (!PointType)
163
+ return fields;
164
+ return build.extend(fields, {
165
+ points: {
166
+ type: new GraphQLList(PointType),
167
+ resolve(data) {
168
+ const multiPoint = data.__geojson;
169
+ return multiPoint.coordinates.map((coord) => ({
170
+ __gisType: (0, utils_1.getGISTypeName)(constants_1.GisSubtype.Point, hasZ, hasM),
171
+ __srid: data.__srid,
172
+ __geojson: {
173
+ type: 'Point',
174
+ coordinates: coord
175
+ }
176
+ }));
177
+ }
178
+ }
179
+ }, 'PostgisGeometryFieldsPlugin adding MultiPoint fields');
180
+ }
181
+ function addMultiLineStringFields(fields, build, codecName, hasZ, hasM, srid, GraphQLList, getType) {
182
+ const LineStringType = getType?.(codecName, constants_1.GisSubtype.LineString, hasZ, hasM, srid);
183
+ if (!LineStringType)
184
+ return fields;
185
+ return build.extend(fields, {
186
+ lines: {
187
+ type: new GraphQLList(LineStringType),
188
+ resolve(data) {
189
+ const multiLineString = data.__geojson;
190
+ return multiLineString.coordinates.map((coord) => ({
191
+ __gisType: (0, utils_1.getGISTypeName)(constants_1.GisSubtype.LineString, hasZ, hasM),
192
+ __srid: data.__srid,
193
+ __geojson: {
194
+ type: 'LineString',
195
+ coordinates: coord
196
+ }
197
+ }));
198
+ }
199
+ }
200
+ }, 'PostgisGeometryFieldsPlugin adding MultiLineString fields');
201
+ }
202
+ function addMultiPolygonFields(fields, build, codecName, hasZ, hasM, srid, GraphQLList, getType) {
203
+ const PolygonType = getType?.(codecName, constants_1.GisSubtype.Polygon, hasZ, hasM, srid);
204
+ if (!PolygonType)
205
+ return fields;
206
+ return build.extend(fields, {
207
+ polygons: {
208
+ type: new GraphQLList(PolygonType),
209
+ resolve(data) {
210
+ const multiPolygon = data.__geojson;
211
+ return multiPolygon.coordinates.map((coord) => ({
212
+ __gisType: (0, utils_1.getGISTypeName)(constants_1.GisSubtype.Polygon, hasZ, hasM),
213
+ __srid: data.__srid,
214
+ __geojson: {
215
+ type: 'Polygon',
216
+ coordinates: coord
217
+ }
218
+ }));
219
+ }
220
+ }
221
+ }, 'PostgisGeometryFieldsPlugin adding MultiPolygon fields');
222
+ }
223
+ function addGeometryCollectionFields(fields, build, codecName, hasZ, hasM, GraphQLList) {
224
+ const dimInterfaceName = build.inflection.gisDimensionInterfaceName(codecName, hasZ, hasM);
225
+ const Interface = build.getTypeByName(dimInterfaceName);
226
+ if (!Interface) {
227
+ return fields;
228
+ }
229
+ return build.extend(fields, {
230
+ geometries: {
231
+ type: new GraphQLList(Interface),
232
+ resolve(data) {
233
+ const geometryCollection = data.__geojson;
234
+ return geometryCollection.geometries.map((geom) => {
235
+ const subtypeValue = constants_1.GisSubtype[geom.type];
236
+ if (subtypeValue === undefined) {
237
+ throw new Error(`Unsupported geometry subtype ${geom.type}`);
238
+ }
239
+ return {
240
+ __gisType: (0, utils_1.getGISTypeName)(subtypeValue, hasZ, hasM),
241
+ __srid: data.__srid,
242
+ __geojson: geom
243
+ };
244
+ });
245
+ }
246
+ }
247
+ }, 'PostgisGeometryFieldsPlugin adding GeometryCollection fields');
248
+ }
@@ -0,0 +1,8 @@
1
+ import type { GraphileConfig } from 'graphile-config';
2
+ import '../types';
3
+ /**
4
+ * PostgisInflectionPlugin
5
+ *
6
+ * Adds inflection methods for generating PostGIS-related GraphQL type names.
7
+ */
8
+ export declare const PostgisInflectionPlugin: GraphileConfig.Plugin;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PostgisInflectionPlugin = void 0;
4
+ const constants_1 = require("../constants");
5
+ // Import types.ts for the Inflection augmentation side effects
6
+ require("../types");
7
+ /**
8
+ * PostgisInflectionPlugin
9
+ *
10
+ * Adds inflection methods for generating PostGIS-related GraphQL type names.
11
+ */
12
+ exports.PostgisInflectionPlugin = {
13
+ name: 'PostgisInflectionPlugin',
14
+ version: '2.0.0',
15
+ description: 'Adds PostGIS-related inflection methods',
16
+ inflection: {
17
+ add: {
18
+ gisType(_options, typeName, subtype, hasZ, hasM, _srid) {
19
+ return this.upperCamelCase([
20
+ typeName,
21
+ constants_1.SUBTYPE_STRING_BY_SUBTYPE[subtype],
22
+ hasZ ? 'z' : null,
23
+ hasM ? 'm' : null
24
+ ]
25
+ .filter(Boolean)
26
+ .join('-'));
27
+ },
28
+ gisInterfaceName(_options, typeName) {
29
+ return this.upperCamelCase(`${typeName}-interface`);
30
+ },
31
+ gisDimensionInterfaceName(_options, typeName, hasZ, hasM) {
32
+ return this.upperCamelCase([
33
+ typeName,
34
+ constants_1.SUBTYPE_STRING_BY_SUBTYPE[constants_1.GisSubtype.Geometry],
35
+ hasZ ? 'z' : null,
36
+ hasM ? 'm' : null
37
+ ]
38
+ .filter(Boolean)
39
+ .join('-'));
40
+ },
41
+ geojsonFieldName() {
42
+ return 'geojson';
43
+ },
44
+ gisXFieldName(_options, typeName) {
45
+ return typeName === 'geography' ? 'longitude' : 'x';
46
+ },
47
+ gisYFieldName(_options, typeName) {
48
+ return typeName === 'geography' ? 'latitude' : 'y';
49
+ },
50
+ gisZFieldName(_options, typeName) {
51
+ return typeName === 'geography' ? 'height' : 'z';
52
+ }
53
+ }
54
+ }
55
+ };
@@ -0,0 +1,22 @@
1
+ import 'graphile-build';
2
+ import 'graphile-build-pg';
3
+ import type { GraphileConfig } from 'graphile-config';
4
+ import '../types';
5
+ /**
6
+ * PostgisRegisterTypesPlugin
7
+ *
8
+ * The core plugin that:
9
+ * 1. Registers a GeoJSON scalar type
10
+ * 2. Creates GraphQL interfaces for geometry/geography base types
11
+ * 3. Creates GraphQL interfaces for each dimension combination (XY, XYZ, XYM, XYZM)
12
+ * 4. Creates concrete GraphQL object types for each subtype/dimension combo
13
+ * 5. Registers codec-to-type mappings so PostGraphile knows how to handle
14
+ * geometry/geography columns
15
+ *
16
+ * In v5, type registration is done during the init hook using
17
+ * build.registerObjectType / build.registerInterfaceType / build.registerScalarType.
18
+ *
19
+ * The SQL tweak wraps geometry/geography values in json_build_object() containing
20
+ * __gisType, __srid, and __geojson fields, which downstream resolvers use.
21
+ */
22
+ export declare const PostgisRegisterTypesPlugin: GraphileConfig.Plugin;