Skip to content

Instantly share code, notes, and snippets.

@hos
Created February 27, 2025 18:43
Show Gist options
  • Save hos/017c0790e617064a659db0b73db0572a to your computer and use it in GitHub Desktop.
Save hos/017c0790e617064a659db0b73db0572a to your computer and use it in GitHub Desktop.
import type { PgCodec } from '@dataplan/pg';
import { EXPORTABLE } from 'graphile-build';
import { sql } from 'pg-sql2';
import { Geometry } from 'wkx';
interface State {
geometryCodec: PgCodec<string, any, any, any, undefined, any, any>;
}
declare global {
namespace GraphileConfig {
interface Plugins {
PgGeometryPlugin: true;
}
}
}
export const PgGeometryPlugin: GraphileConfig.Plugin = {
name: 'PgGeometryPlugin',
gather: {
initialState(): State {
const geometryCodec: PgCodec<string, any, any, any, undefined, any, any> = EXPORTABLE(
(sql) => ({
name: 'geometry',
sqlType: sql`geometry`,
toPg(str) {
return str;
},
fromPg(str) {
return Geometry.parse(Buffer.from(str, 'hex')).toGeoJSON();
},
executor: null,
attributes: undefined,
}),
[sql]
);
return { geometryCodec };
},
hooks: {
async pgCodecs_findPgCodec(info, event) {
// If another plugin has already supplied a codec; skip
if (event.pgCodec) return;
const { serviceName, pgType } = event;
const geometryExt = await info.helpers.pgIntrospection.getExtensionByName(
serviceName,
'postgis'
);
if (!geometryExt || pgType.typnamespace !== geometryExt.extnamespace) {
return;
}
if (pgType.typname === 'geometry') {
event.pgCodec = info.state.geometryCodec;
}
},
},
},
schema: {
hooks: {
init(_, build) {
const codec = build.input.pgRegistry.pgCodecs.geometry;
if (codec) {
const geometryTypeName = build.inflection.builtin('Geometry');
build.registerScalarType(
geometryTypeName,
{ pgCodec: codec },
() => ({
description:
'Represents an `geometry` type https://postgis.net/workshops/postgis-intro/geometries.html',
}),
'Adding "Geometry" scalar type from PgGeometryPlugin.'
);
build.setGraphQLTypeForPgCodec(codec, 'output', geometryTypeName);
build.setGraphQLTypeForPgCodec(codec, 'input', geometryTypeName);
}
return _;
},
},
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment