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
package/esm/preset.js ADDED
@@ -0,0 +1,30 @@
1
+ import { PostgisCodecPlugin } from './plugins/codec';
2
+ import { PostgisInflectionPlugin } from './plugins/inflection';
3
+ import { PostgisExtensionDetectionPlugin } from './plugins/detect-extension';
4
+ import { PostgisRegisterTypesPlugin } from './plugins/register-types';
5
+ import { PostgisGeometryFieldsPlugin } from './plugins/geometry-fields';
6
+ /**
7
+ * GraphilePostgisPreset
8
+ *
9
+ * A preset that includes all PostGIS plugins for PostGraphile v5.
10
+ * Use this as the recommended way to add PostGIS support.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { GraphilePostgisPreset } from 'graphile-postgis';
15
+ *
16
+ * const preset = {
17
+ * extends: [GraphilePostgisPreset]
18
+ * };
19
+ * ```
20
+ */
21
+ export const GraphilePostgisPreset = {
22
+ plugins: [
23
+ PostgisCodecPlugin,
24
+ PostgisInflectionPlugin,
25
+ PostgisExtensionDetectionPlugin,
26
+ PostgisRegisterTypesPlugin,
27
+ PostgisGeometryFieldsPlugin
28
+ ]
29
+ };
30
+ export default GraphilePostgisPreset;
package/esm/types.d.ts ADDED
@@ -0,0 +1,84 @@
1
+ import type { PgCodec } from '@dataplan/pg';
2
+ import type { Geometry } from 'geojson';
3
+ import type { GraphQLInterfaceType, GraphQLObjectType } from 'graphql';
4
+ import type { SQL } from 'pg-sql2';
5
+ import type { GisSubtype } from './constants';
6
+ export interface GisTypeDetails {
7
+ subtype: GisSubtype;
8
+ hasZ: boolean;
9
+ hasM: boolean;
10
+ srid: number;
11
+ }
12
+ export interface GisFieldValue {
13
+ __gisType: string;
14
+ __srid: number;
15
+ __geojson: Geometry;
16
+ }
17
+ /**
18
+ * PostGIS extension detection result stored on the build object.
19
+ */
20
+ export interface PostgisExtensionInfo {
21
+ /** The schema name where PostGIS is installed (e.g. 'public') */
22
+ schemaName: string;
23
+ /** The geometry codec from the registry */
24
+ geometryCodec: PgCodec;
25
+ /** The geography codec from the registry (optional — not all databases use geography columns) */
26
+ geographyCodec: PgCodec | null;
27
+ }
28
+ /**
29
+ * Module augmentations for PostGraphile v5 types.
30
+ *
31
+ * These declare the custom properties that our PostGIS plugins add to the
32
+ * build object, inflection, and scope interfaces. This allows downstream
33
+ * code (including our own plugins) to use these properties without `any` casts.
34
+ */
35
+ declare global {
36
+ namespace GraphileBuild {
37
+ interface Build {
38
+ /** PostGIS extension info (set by PostgisExtensionDetectionPlugin) */
39
+ pgGISExtensionInfo?: PostgisExtensionInfo;
40
+ /** Map of codec name -> gisTypeKey -> GraphQL type name (for resolveType) */
41
+ pgGISGraphQLTypesByCodecAndSubtype?: Record<string, Record<string | number, string>>;
42
+ /** Gets a registered PostGIS GraphQL type by geometry type, subtype, and dimension */
43
+ getPostgisTypeByGeometryType?(gisCodecName: string, subtype: GisSubtype, hasZ?: boolean, hasM?: boolean, srid?: number): GraphQLObjectType | GraphQLInterfaceType | undefined;
44
+ /** Wraps a geometry/geography SQL expression in json_build_object() with metadata */
45
+ pgGISWrapExpression?(fragment: SQL): SQL;
46
+ /** Creates an SQL fragment to convert GeoJSON input to a geometry value */
47
+ pgGISFromGeoJSON?(value: Record<string, unknown>, codecName: string): SQL;
48
+ }
49
+ interface Inflection {
50
+ /** Generate GraphQL type name for a PostGIS concrete type */
51
+ gisType(typeName: string, subtype: GisSubtype, hasZ: boolean, hasM: boolean, srid?: number): string;
52
+ /** Generate interface name for a PostGIS base type (e.g. GeometryInterface) */
53
+ gisInterfaceName(typeName: string): string;
54
+ /** Generate dimension interface name (e.g. GeometryGeometryZ) */
55
+ gisDimensionInterfaceName(typeName: string, hasZ: boolean, hasM: boolean): string;
56
+ /** Generate GeoJSON field name */
57
+ geojsonFieldName(): string;
58
+ /** Generate X coordinate field name */
59
+ gisXFieldName(typeName: string): string;
60
+ /** Generate Y coordinate field name */
61
+ gisYFieldName(typeName: string): string;
62
+ /** Generate Z coordinate field name */
63
+ gisZFieldName(typeName: string): string;
64
+ }
65
+ interface ScopeObject {
66
+ /** Whether this is a PostGIS concrete type */
67
+ isPgGISType?: boolean;
68
+ /** The codec name (geometry/geography) this type belongs to */
69
+ pgGISCodecName?: string;
70
+ /** The type details (subtype, hasZ, hasM, srid) */
71
+ pgGISTypeDetails?: GisTypeDetails;
72
+ }
73
+ interface ScopeInterface {
74
+ /** Whether this is a PostGIS base interface */
75
+ isPgGISInterface?: boolean;
76
+ /** Whether this is a PostGIS dimension interface */
77
+ isPgGISDimensionInterface?: boolean;
78
+ /** The codec name (geometry/geography) this interface belongs to */
79
+ pgGISCodecName?: string;
80
+ /** The ZM flag (-1 for base, 0-3 for dimension) */
81
+ pgGISZMFlag?: number;
82
+ }
83
+ }
84
+ }
package/esm/utils.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ import { GisSubtype } from './constants';
2
+ import type { GisTypeDetails } from './types';
3
+ /**
4
+ * Decodes a PostGIS type modifier into its component parts.
5
+ *
6
+ * Implements the C macro bit layout from liblwgeom.h:
7
+ * - SRID: bits 8-28
8
+ * - Subtype: bits 2-7
9
+ * - hasZ: bit 1
10
+ * - hasM: bit 0
11
+ */
12
+ export declare const getGISTypeDetails: (modifier: number) => GisTypeDetails;
13
+ /**
14
+ * Encodes PostGIS type details into a type modifier integer.
15
+ */
16
+ export declare const getGISTypeModifier: (subtype: GisSubtype, hasZ: boolean, hasM: boolean, srid: number) => number;
17
+ /**
18
+ * Returns the GIS type name string for a given subtype and Z/M flags.
19
+ * E.g. "PointZ", "MultiPolygonZM", "LineString"
20
+ */
21
+ export declare const getGISTypeName: (subtype: GisSubtype, hasZ: boolean, hasM: boolean) => string;
package/esm/utils.js CHANGED
@@ -1,4 +1,13 @@
1
- import { GIS_SUBTYPE_NAME, GisSubtype } from './constants';
1
+ import { GisSubtype, GIS_SUBTYPE_NAME } from './constants';
2
+ /**
3
+ * Decodes a PostGIS type modifier into its component parts.
4
+ *
5
+ * Implements the C macro bit layout from liblwgeom.h:
6
+ * - SRID: bits 8-28
7
+ * - Subtype: bits 2-7
8
+ * - hasZ: bit 1
9
+ * - hasM: bit 0
10
+ */
2
11
  export const getGISTypeDetails = (modifier) => {
3
12
  const allZeroesHopefully = modifier >> 24;
4
13
  if (allZeroesHopefully !== 0) {
@@ -24,13 +33,11 @@ export const getGISTypeDetails = (modifier) => {
24
33
  throw new Error(`Unsupported PostGIS modifier, expected 0-7, received ${subtypeNumeric} (${modifier})`);
25
34
  }
26
35
  const subtype = subtypeNumeric;
27
- return {
28
- subtype,
29
- hasZ,
30
- hasM,
31
- srid
32
- };
36
+ return { subtype, hasZ, hasM, srid };
33
37
  };
38
+ /**
39
+ * Encodes PostGIS type details into a type modifier integer.
40
+ */
34
41
  export const getGISTypeModifier = (subtype, hasZ, hasM, srid) => {
35
42
  // Ref: https://github.com/postgis/postgis/blob/2.5.2/liblwgeom/liblwgeom.h.in#L156-L173
36
43
  // #define TYPMOD_SET_SRID(typmod, srid) ((typmod) = (((typmod) & 0xE00000FF) | ((srid & 0x001FFFFF)<<8)))
@@ -42,6 +49,10 @@ export const getGISTypeModifier = (subtype, hasZ, hasM, srid) => {
42
49
  (hasZ ? 0x00000002 : 0) +
43
50
  (hasM ? 0x00000001 : 0));
44
51
  };
52
+ /**
53
+ * Returns the GIS type name string for a given subtype and Z/M flags.
54
+ * E.g. "PointZ", "MultiPolygonZM", "LineString"
55
+ */
45
56
  export const getGISTypeName = (subtype, hasZ, hasM) => {
46
57
  return `${GIS_SUBTYPE_NAME[subtype]}${hasZ ? 'Z' : ''}${hasM ? 'M' : ''}`;
47
58
  };
package/index.d.ts CHANGED
@@ -1,15 +1,24 @@
1
- import type { Plugin } from 'graphile-build';
2
- import PostgisExtensionDetectionPlugin from './PostgisExtensionDetectionPlugin';
3
- import PostgisInflectionPlugin from './PostgisInflectionPlugin';
4
- import PostgisRegisterTypesPlugin from './PostgisRegisterTypesPlugin';
5
- import PostgisVersionPlugin from './PostgisVersionPlugin';
6
- import Postgis_GeometryCollection_GeometriesPlugin from './Postgis_GeometryCollection_GeometriesPlugin';
7
- import Postgis_LineString_PointsPlugin from './Postgis_LineString_PointsPlugin';
8
- import Postgis_MultiLineString_LineStringsPlugin from './Postgis_MultiLineString_LineStringsPlugin';
9
- import Postgis_MultiPoint_PointsPlugin from './Postgis_MultiPoint_PointsPlugin';
10
- import Postgis_MultiPolygon_PolygonsPlugin from './Postgis_MultiPolygon_PolygonsPlugin';
11
- import Postgis_Point_LatitudeLongitudePlugin from './Postgis_Point_LatitudeLongitudePlugin';
12
- import Postgis_Polygon_RingsPlugin from './Postgis_Polygon_RingsPlugin';
13
- declare const PostgisPlugin: Plugin;
14
- export { PostgisExtensionDetectionPlugin, PostgisInflectionPlugin, PostgisRegisterTypesPlugin, PostgisVersionPlugin, Postgis_GeometryCollection_GeometriesPlugin, Postgis_LineString_PointsPlugin, Postgis_MultiLineString_LineStringsPlugin, Postgis_MultiPoint_PointsPlugin, Postgis_MultiPolygon_PolygonsPlugin, Postgis_Point_LatitudeLongitudePlugin, Postgis_Polygon_RingsPlugin };
15
- export default PostgisPlugin;
1
+ /**
2
+ * PostGraphile v5 PostGIS Plugin
3
+ *
4
+ * Provides PostGIS geometry/geography type support for PostGraphile v5.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { GraphilePostgisPreset } from 'graphile-postgis';
9
+ *
10
+ * const preset = {
11
+ * extends: [GraphilePostgisPreset]
12
+ * };
13
+ * ```
14
+ */
15
+ export { GraphilePostgisPreset } from './preset';
16
+ export { PostgisCodecPlugin } from './plugins/codec';
17
+ export { PostgisInflectionPlugin } from './plugins/inflection';
18
+ export { PostgisExtensionDetectionPlugin } from './plugins/detect-extension';
19
+ export { PostgisRegisterTypesPlugin } from './plugins/register-types';
20
+ export { PostgisGeometryFieldsPlugin } from './plugins/geometry-fields';
21
+ export { GisSubtype, SUBTYPE_STRING_BY_SUBTYPE, GIS_SUBTYPE_NAME, CONCRETE_SUBTYPES } from './constants';
22
+ export { getGISTypeDetails, getGISTypeModifier, getGISTypeName } from './utils';
23
+ export type { GisTypeDetails, GisFieldValue } from './types';
24
+ export type { PostgisExtensionInfo } from './plugins/detect-extension';
package/index.js CHANGED
@@ -1,49 +1,41 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
2
+ /**
3
+ * PostGraphile v5 PostGIS Plugin
4
+ *
5
+ * Provides PostGIS geometry/geography type support for PostGraphile v5.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { GraphilePostgisPreset } from 'graphile-postgis';
10
+ *
11
+ * const preset = {
12
+ * extends: [GraphilePostgisPreset]
13
+ * };
14
+ * ```
15
+ */
5
16
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.Postgis_Polygon_RingsPlugin = exports.Postgis_Point_LatitudeLongitudePlugin = exports.Postgis_MultiPolygon_PolygonsPlugin = exports.Postgis_MultiPoint_PointsPlugin = exports.Postgis_MultiLineString_LineStringsPlugin = exports.Postgis_LineString_PointsPlugin = exports.Postgis_GeometryCollection_GeometriesPlugin = exports.PostgisVersionPlugin = exports.PostgisRegisterTypesPlugin = exports.PostgisInflectionPlugin = exports.PostgisExtensionDetectionPlugin = void 0;
7
- const PostgisExtensionDetectionPlugin_1 = __importDefault(require("./PostgisExtensionDetectionPlugin"));
8
- exports.PostgisExtensionDetectionPlugin = PostgisExtensionDetectionPlugin_1.default;
9
- const PostgisInflectionPlugin_1 = __importDefault(require("./PostgisInflectionPlugin"));
10
- exports.PostgisInflectionPlugin = PostgisInflectionPlugin_1.default;
11
- const PostgisRegisterTypesPlugin_1 = __importDefault(require("./PostgisRegisterTypesPlugin"));
12
- exports.PostgisRegisterTypesPlugin = PostgisRegisterTypesPlugin_1.default;
13
- const PostgisVersionPlugin_1 = __importDefault(require("./PostgisVersionPlugin"));
14
- exports.PostgisVersionPlugin = PostgisVersionPlugin_1.default;
15
- const Postgis_GeometryCollection_GeometriesPlugin_1 = __importDefault(require("./Postgis_GeometryCollection_GeometriesPlugin"));
16
- exports.Postgis_GeometryCollection_GeometriesPlugin = Postgis_GeometryCollection_GeometriesPlugin_1.default;
17
- const Postgis_LineString_PointsPlugin_1 = __importDefault(require("./Postgis_LineString_PointsPlugin"));
18
- exports.Postgis_LineString_PointsPlugin = Postgis_LineString_PointsPlugin_1.default;
19
- const Postgis_MultiLineString_LineStringsPlugin_1 = __importDefault(require("./Postgis_MultiLineString_LineStringsPlugin"));
20
- exports.Postgis_MultiLineString_LineStringsPlugin = Postgis_MultiLineString_LineStringsPlugin_1.default;
21
- const Postgis_MultiPoint_PointsPlugin_1 = __importDefault(require("./Postgis_MultiPoint_PointsPlugin"));
22
- exports.Postgis_MultiPoint_PointsPlugin = Postgis_MultiPoint_PointsPlugin_1.default;
23
- const Postgis_MultiPolygon_PolygonsPlugin_1 = __importDefault(require("./Postgis_MultiPolygon_PolygonsPlugin"));
24
- exports.Postgis_MultiPolygon_PolygonsPlugin = Postgis_MultiPolygon_PolygonsPlugin_1.default;
25
- const Postgis_Point_LatitudeLongitudePlugin_1 = __importDefault(require("./Postgis_Point_LatitudeLongitudePlugin"));
26
- exports.Postgis_Point_LatitudeLongitudePlugin = Postgis_Point_LatitudeLongitudePlugin_1.default;
27
- const Postgis_Polygon_RingsPlugin_1 = __importDefault(require("./Postgis_Polygon_RingsPlugin"));
28
- exports.Postgis_Polygon_RingsPlugin = Postgis_Polygon_RingsPlugin_1.default;
29
- const PostgisPlugin = async (builder, options) => {
30
- await (0, PostgisVersionPlugin_1.default)(builder, options);
31
- await (0, PostgisInflectionPlugin_1.default)(builder, options);
32
- await (0, PostgisExtensionDetectionPlugin_1.default)(builder, options);
33
- await (0, PostgisRegisterTypesPlugin_1.default)(builder, options);
34
- // Enhancing the `Point` type:
35
- await (0, Postgis_Point_LatitudeLongitudePlugin_1.default)(builder, options);
36
- // Enhancing the `LineString` type:
37
- await (0, Postgis_LineString_PointsPlugin_1.default)(builder, options);
38
- // Enhancing the `Polygon` type:
39
- await (0, Postgis_Polygon_RingsPlugin_1.default)(builder, options);
40
- // Enhancing the `MultiPoint` type:
41
- await (0, Postgis_MultiPoint_PointsPlugin_1.default)(builder, options);
42
- // Enhancing the `MultiLineString` type:
43
- await (0, Postgis_MultiLineString_LineStringsPlugin_1.default)(builder, options);
44
- // Enhancing the `MultiPolygon` type:
45
- await (0, Postgis_MultiPolygon_PolygonsPlugin_1.default)(builder, options);
46
- // Enhancing the `GeometryCollection` type:
47
- await (0, Postgis_GeometryCollection_GeometriesPlugin_1.default)(builder, options);
48
- };
49
- exports.default = PostgisPlugin;
17
+ exports.getGISTypeName = exports.getGISTypeModifier = exports.getGISTypeDetails = exports.CONCRETE_SUBTYPES = exports.GIS_SUBTYPE_NAME = exports.SUBTYPE_STRING_BY_SUBTYPE = exports.GisSubtype = exports.PostgisGeometryFieldsPlugin = exports.PostgisRegisterTypesPlugin = exports.PostgisExtensionDetectionPlugin = exports.PostgisInflectionPlugin = exports.PostgisCodecPlugin = exports.GraphilePostgisPreset = void 0;
18
+ // Preset (recommended entry point)
19
+ var preset_1 = require("./preset");
20
+ Object.defineProperty(exports, "GraphilePostgisPreset", { enumerable: true, get: function () { return preset_1.GraphilePostgisPreset; } });
21
+ // Individual plugins
22
+ var codec_1 = require("./plugins/codec");
23
+ Object.defineProperty(exports, "PostgisCodecPlugin", { enumerable: true, get: function () { return codec_1.PostgisCodecPlugin; } });
24
+ var inflection_1 = require("./plugins/inflection");
25
+ Object.defineProperty(exports, "PostgisInflectionPlugin", { enumerable: true, get: function () { return inflection_1.PostgisInflectionPlugin; } });
26
+ var detect_extension_1 = require("./plugins/detect-extension");
27
+ Object.defineProperty(exports, "PostgisExtensionDetectionPlugin", { enumerable: true, get: function () { return detect_extension_1.PostgisExtensionDetectionPlugin; } });
28
+ var register_types_1 = require("./plugins/register-types");
29
+ Object.defineProperty(exports, "PostgisRegisterTypesPlugin", { enumerable: true, get: function () { return register_types_1.PostgisRegisterTypesPlugin; } });
30
+ var geometry_fields_1 = require("./plugins/geometry-fields");
31
+ Object.defineProperty(exports, "PostgisGeometryFieldsPlugin", { enumerable: true, get: function () { return geometry_fields_1.PostgisGeometryFieldsPlugin; } });
32
+ // Constants and utilities
33
+ var constants_1 = require("./constants");
34
+ Object.defineProperty(exports, "GisSubtype", { enumerable: true, get: function () { return constants_1.GisSubtype; } });
35
+ Object.defineProperty(exports, "SUBTYPE_STRING_BY_SUBTYPE", { enumerable: true, get: function () { return constants_1.SUBTYPE_STRING_BY_SUBTYPE; } });
36
+ Object.defineProperty(exports, "GIS_SUBTYPE_NAME", { enumerable: true, get: function () { return constants_1.GIS_SUBTYPE_NAME; } });
37
+ Object.defineProperty(exports, "CONCRETE_SUBTYPES", { enumerable: true, get: function () { return constants_1.CONCRETE_SUBTYPES; } });
38
+ var utils_1 = require("./utils");
39
+ Object.defineProperty(exports, "getGISTypeDetails", { enumerable: true, get: function () { return utils_1.getGISTypeDetails; } });
40
+ Object.defineProperty(exports, "getGISTypeModifier", { enumerable: true, get: function () { return utils_1.getGISTypeModifier; } });
41
+ Object.defineProperty(exports, "getGISTypeName", { enumerable: true, get: function () { return utils_1.getGISTypeName; } });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "graphile-postgis",
3
- "version": "1.1.1",
4
- "description": "Graphile/PostGraphile PostGIS integration plugin",
3
+ "version": "2.2.0",
4
+ "description": "PostGIS support for PostGraphile v5",
5
5
  "author": "Constructive <developers@constructive.io>",
6
6
  "homepage": "https://github.com/constructive-io/constructive",
7
7
  "license": "MIT",
@@ -10,12 +10,11 @@
10
10
  "types": "index.d.ts",
11
11
  "scripts": {
12
12
  "clean": "makage clean",
13
- "copy": "makage assets",
14
- "prepack": "pnpm run build",
13
+ "prepack": "npm run build",
15
14
  "build": "makage build",
16
15
  "build:dev": "makage build --dev",
17
16
  "lint": "eslint . --fix",
18
- "test": "jest --passWithNoTests",
17
+ "test": "jest",
19
18
  "test:watch": "jest --watch"
20
19
  },
21
20
  "publishConfig": {
@@ -33,24 +32,30 @@
33
32
  "postgres",
34
33
  "graphql",
35
34
  "constructive",
36
- "pgpm"
35
+ "pgpm",
36
+ "geojson",
37
+ "geometry",
38
+ "geography"
37
39
  ],
38
40
  "bugs": {
39
41
  "url": "https://github.com/constructive-io/constructive/issues"
40
42
  },
43
+ "peerDependencies": {
44
+ "@dataplan/pg": "^1.0.0-rc.5",
45
+ "grafast": "^1.0.0-rc.7",
46
+ "graphile-build": "^5.0.0-rc.4",
47
+ "graphile-build-pg": "^5.0.0-rc.5",
48
+ "graphile-config": "^1.0.0-rc.5",
49
+ "graphql": "^16.9.0",
50
+ "pg-sql2": "^5.0.0-rc.4",
51
+ "postgraphile": "^5.0.0-rc.4"
52
+ },
41
53
  "devDependencies": {
42
54
  "@types/geojson": "^7946.0.14",
43
- "graphile-test": "^3.1.1",
44
- "makage": "^0.1.12",
45
- "pgsql-test": "^3.1.1"
46
- },
47
- "dependencies": {
48
- "find-and-require-package-json": "^0.9.0",
49
- "graphile-build": "^4.14.1",
50
- "graphile-build-pg": "^4.14.1",
51
- "graphile-utils": "^4.14.1",
52
- "graphql": "15.10.1",
53
- "pg": "^8.17.1"
55
+ "@types/node": "^22.19.1",
56
+ "graphile-test": "^4.2.0",
57
+ "makage": "^0.1.10",
58
+ "pgsql-test": "^4.2.0"
54
59
  },
55
- "gitHead": "49049ad3ddd762d35625f657cb42fa0862b829a0"
60
+ "gitHead": "b758178b808ce0bf451e86c0bd7e92079155db7c"
56
61
  }
@@ -0,0 +1,19 @@
1
+ import 'graphile-build-pg';
2
+ import type { GraphileConfig } from 'graphile-config';
3
+ /**
4
+ * PostgisCodecPlugin
5
+ *
6
+ * Teaches PostGraphile v5 how to handle PostgreSQL's geometry and geography types.
7
+ *
8
+ * This plugin:
9
+ * 1. Creates codecs for geometry/geography via gather.hooks.pgCodecs_findPgCodec
10
+ * 2. The registered codecs use castFromPg to wrap geometry values in
11
+ * json_build_object() with __gisType, __srid, __geojson metadata
12
+ * 3. fromPg normalizes the geometry type names for resolveType lookups
13
+ *
14
+ * Without castFromPg, PostGraphile defaults to `column::text` which returns
15
+ * WKB hex — unusable for GraphQL. The json_build_object wrapper provides
16
+ * structured metadata that downstream plugins use for type resolution and
17
+ * field values (x/y coordinates, GeoJSON, SRID, etc.).
18
+ */
19
+ export declare const PostgisCodecPlugin: GraphileConfig.Plugin;
@@ -0,0 +1,180 @@
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.PostgisCodecPlugin = void 0;
7
+ require("graphile-build-pg");
8
+ const pg_sql2_1 = __importDefault(require("pg-sql2"));
9
+ /**
10
+ * Map from PostGIS uppercase geometry type names (from geometrytype()) to
11
+ * our mixed-case format used by resolveType lookups.
12
+ *
13
+ * PostGIS `geometrytype()` returns uppercase: 'POINT', 'POINTZ', 'MULTIPOLYGON', etc.
14
+ * Our GIS_SUBTYPE_NAME uses mixed case: 'Point', 'LineString', 'MultiPolygon', etc.
15
+ * The getGISTypeName() utility produces: 'Point', 'PointZ', 'MultiPolygonZM', etc.
16
+ */
17
+ const GIS_TYPE_NORMALIZE = {
18
+ POINT: 'Point',
19
+ POINTZ: 'PointZ',
20
+ POINTM: 'PointM',
21
+ POINTZM: 'PointZM',
22
+ LINESTRING: 'LineString',
23
+ LINESTRINGZ: 'LineStringZ',
24
+ LINESTRINGM: 'LineStringM',
25
+ LINESTRINGZM: 'LineStringZM',
26
+ POLYGON: 'Polygon',
27
+ POLYGONZ: 'PolygonZ',
28
+ POLYGONM: 'PolygonM',
29
+ POLYGONZM: 'PolygonZM',
30
+ MULTIPOINT: 'MultiPoint',
31
+ MULTIPOINTZ: 'MultiPointZ',
32
+ MULTIPOINTM: 'MultiPointM',
33
+ MULTIPOINTZM: 'MultiPointZM',
34
+ MULTILINESTRING: 'MultiLineString',
35
+ MULTILINESTRINGZ: 'MultiLineStringZ',
36
+ MULTILINESTRINGM: 'MultiLineStringM',
37
+ MULTILINESTRINGZM: 'MultiLineStringZM',
38
+ MULTIPOLYGON: 'MultiPolygon',
39
+ MULTIPOLYGONZ: 'MultiPolygonZ',
40
+ MULTIPOLYGONM: 'MultiPolygonM',
41
+ MULTIPOLYGONZM: 'MultiPolygonZM',
42
+ GEOMETRYCOLLECTION: 'GeometryCollection',
43
+ GEOMETRYCOLLECTIONZ: 'GeometryCollectionZ',
44
+ GEOMETRYCOLLECTIONM: 'GeometryCollectionM',
45
+ GEOMETRYCOLLECTIONZM: 'GeometryCollectionZM'
46
+ };
47
+ /**
48
+ * Normalize the __gisType from PostGIS uppercase to our mixed-case format.
49
+ * Falls back to the raw value if not in the map.
50
+ */
51
+ function normalizeGisType(raw) {
52
+ return GIS_TYPE_NORMALIZE[raw] ?? raw;
53
+ }
54
+ /**
55
+ * Build a codec for a PostGIS geometry or geography type.
56
+ *
57
+ * The codec:
58
+ * - castFromPg: wraps the SQL column in json_build_object() with __gisType,
59
+ * __srid, and __geojson fields (using PostGIS functions ST_SRID, ST_AsGeoJSON,
60
+ * geometrytype). This replaces the default ::text cast.
61
+ * - fromPg: parses the JSON text result and normalizes __gisType case.
62
+ * - toPg: converts GeoJSON input back to a PostGIS-compatible value using
63
+ * ST_GeomFromGeoJSON.
64
+ */
65
+ function buildGisCodec(typeName, schemaName, typeOid, serviceName) {
66
+ return {
67
+ name: typeName,
68
+ sqlType: pg_sql2_1.default.identifier(schemaName, typeName),
69
+ /**
70
+ * castFromPg replaces the default `::text` cast. PostGraphile calls this
71
+ * to determine the SQL expression for selecting the column value.
72
+ *
73
+ * We wrap in json_build_object() so the result contains:
74
+ * - __gisType: geometry subtype name (e.g. "POINT", "POLYGON")
75
+ * - __srid: spatial reference ID
76
+ * - __geojson: the GeoJSON representation
77
+ *
78
+ * The result is cast to ::text so PostgreSQL sends it as a string,
79
+ * which fromPg then JSON.parses.
80
+ */
81
+ // NOTE: `fragment` is evaluated 4 times in the SQL. This is acceptable because
82
+ // PostGraphile v5 always passes simple column references here.
83
+ // If this changes, consider wrapping in a LATERAL subexpression.
84
+ castFromPg(fragment) {
85
+ return pg_sql2_1.default.fragment `(case when (${fragment}) is null then null else json_build_object(
86
+ '__gisType', ${pg_sql2_1.default.identifier(schemaName, 'geometrytype')}(${fragment}),
87
+ '__srid', ${pg_sql2_1.default.identifier(schemaName, 'st_srid')}(${fragment}),
88
+ '__geojson', ${pg_sql2_1.default.identifier(schemaName, 'st_asgeojson')}(${fragment})::json
89
+ )::text end)`;
90
+ },
91
+ /**
92
+ * fromPg receives the text value from PostgreSQL (output of castFromPg)
93
+ * and converts it to a JavaScript object.
94
+ *
95
+ * If castFromPg is working correctly, the value is always valid JSON.
96
+ * We normalize __gisType from PostGIS uppercase to our mixed-case format.
97
+ */
98
+ fromPg(value) {
99
+ let parsed;
100
+ try {
101
+ parsed = JSON.parse(value);
102
+ }
103
+ catch (e) {
104
+ throw new Error(`Failed to parse PostGIS geometry value: ${e instanceof Error ? e.message : String(e)}. ` +
105
+ `Raw value (first 200 chars): ${String(value).slice(0, 200)}`);
106
+ }
107
+ if (parsed && typeof parsed === 'object' && parsed.__gisType) {
108
+ parsed.__gisType = normalizeGisType(parsed.__gisType);
109
+ }
110
+ return parsed;
111
+ },
112
+ /**
113
+ * toPg serializes a JavaScript value for insertion into PostgreSQL.
114
+ * Accepts GeoJSON objects and converts them to a JSON string that
115
+ * PostgreSQL can process via ST_GeomFromGeoJSON.
116
+ */
117
+ toPg(value) {
118
+ if (value && typeof value === 'object' && '__geojson' in value) {
119
+ return JSON.stringify(value.__geojson);
120
+ }
121
+ return JSON.stringify(value);
122
+ },
123
+ attributes: undefined,
124
+ executor: undefined,
125
+ extensions: {
126
+ oid: typeOid,
127
+ pg: {
128
+ serviceName,
129
+ schemaName,
130
+ name: typeName
131
+ }
132
+ }
133
+ };
134
+ }
135
+ /**
136
+ * PostgisCodecPlugin
137
+ *
138
+ * Teaches PostGraphile v5 how to handle PostgreSQL's geometry and geography types.
139
+ *
140
+ * This plugin:
141
+ * 1. Creates codecs for geometry/geography via gather.hooks.pgCodecs_findPgCodec
142
+ * 2. The registered codecs use castFromPg to wrap geometry values in
143
+ * json_build_object() with __gisType, __srid, __geojson metadata
144
+ * 3. fromPg normalizes the geometry type names for resolveType lookups
145
+ *
146
+ * Without castFromPg, PostGraphile defaults to `column::text` which returns
147
+ * WKB hex — unusable for GraphQL. The json_build_object wrapper provides
148
+ * structured metadata that downstream plugins use for type resolution and
149
+ * field values (x/y coordinates, GeoJSON, SRID, etc.).
150
+ */
151
+ exports.PostgisCodecPlugin = {
152
+ name: 'PostgisCodecPlugin',
153
+ version: '2.0.0',
154
+ description: 'Registers codecs for PostGIS geometry and geography types',
155
+ gather: {
156
+ hooks: {
157
+ async pgCodecs_findPgCodec(info, event) {
158
+ if (event.pgCodec) {
159
+ return;
160
+ }
161
+ const { pgType: type, serviceName } = event;
162
+ // Find the namespace for this type by its OID
163
+ const typeNamespace = await info.helpers.pgIntrospection.getNamespace(serviceName, type.typnamespace);
164
+ if (!typeNamespace) {
165
+ return;
166
+ }
167
+ // We look for geometry/geography types in any schema (PostGIS can be
168
+ // installed in different schemas, commonly 'public' or 'postgis')
169
+ if (type.typname === 'geometry') {
170
+ event.pgCodec = buildGisCodec('geometry', typeNamespace.nspname, type._id, serviceName);
171
+ return;
172
+ }
173
+ if (type.typname === 'geography') {
174
+ event.pgCodec = buildGisCodec('geography', typeNamespace.nspname, type._id, serviceName);
175
+ return;
176
+ }
177
+ }
178
+ }
179
+ }
180
+ };
@@ -0,0 +1,14 @@
1
+ import 'graphile-build';
2
+ import 'graphile-build-pg';
3
+ import type { GraphileConfig } from 'graphile-config';
4
+ export type { PostgisExtensionInfo } from '../types';
5
+ /**
6
+ * PostgisExtensionDetectionPlugin
7
+ *
8
+ * Detects PostGIS presence in the database by searching for geometry/geography
9
+ * codecs in the pgRegistry. Stores detected info on the build object for
10
+ * downstream plugins.
11
+ *
12
+ * Gracefully degrades if PostGIS is not installed.
13
+ */
14
+ export declare const PostgisExtensionDetectionPlugin: GraphileConfig.Plugin;