Skip to content

Commit e57ad4f

Browse files
authored
Merge pull request #997 from constructive-io/feat/node-type-registry-relation-spatial
feat(node-type-registry): add RelationSpatial node type (v0.13.0)
2 parents df0918a + 39d99c2 commit e57ad4f

4 files changed

Lines changed: 96 additions & 2 deletions

File tree

graphql/node-type-registry/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "node-type-registry",
3-
"version": "0.12.0",
3+
"version": "0.13.0",
44
"description": "Node type definitions for the Constructive blueprint system. Single source of truth for all Authz*, Data*, Relation*, and View* node types.",
55
"author": "Constructive <developers@constructive.io>",
66
"main": "index.js",

graphql/node-type-registry/src/blueprint-types.generated.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,23 @@ export interface RelationManyToManyParams {
627627
[key: string]: unknown;
628628
};
629629
}
630+
/** Declares a spatial predicate between two existing geometry/geography columns. Inserts a metaschema_public.spatial_relation row; the sync_spatial_relation_tags trigger then projects a @spatialRelation smart tag onto the owner column so graphile-postgis' PostgisSpatialRelationsPlugin can expose it as a cross-table filter in GraphQL. Metadata-only: both source_field and target_field must already exist on their tables. Idempotent on (source_table_id, name). One direction per tag — author two RelationSpatial entries if symmetry is desired. */
631+
export interface RelationSpatialParams {
632+
/* Table that owns the relation (the @spatialRelation tag is emitted on the owner column of this table) */
633+
source_table_id: string;
634+
/* Geometry/geography column on source_table that carries the @spatialRelation smart tag */
635+
source_field_id: string;
636+
/* Table being referenced by the spatial predicate */
637+
target_table_id: string;
638+
/* Geometry/geography column on target_table that the predicate is evaluated against */
639+
target_field_id: string;
640+
/* Relation name (stable, snake_case). Becomes the generated filter field name in GraphQL (e.g. nearby_clinic). Unique per (source_table_id, name) — idempotency key. */
641+
name: string;
642+
/* PostGIS spatial predicate. One of the 8 whitelisted operators. st_dwithin requires param_name. */
643+
operator: "st_contains" | "st_within" | "st_intersects" | "st_covers" | "st_coveredby" | "st_overlaps" | "st_touches" | "st_dwithin";
644+
/* Parameter name for parametric operators (currently only st_dwithin, which needs a distance argument). Must be NULL for all other operators. Enforced by table CHECK. */
645+
param_name?: string;
646+
}
630647
/**
631648
* ===========================================================================
632649
* View node type parameters
@@ -1031,7 +1048,13 @@ export type BlueprintRelation = {
10311048
target_table: string;
10321049
source_schema_name?: string;
10331050
target_schema_name?: string;
1034-
} & Partial<RelationManyToManyParams>;
1051+
} & Partial<RelationManyToManyParams> | {
1052+
$type: "RelationSpatial";
1053+
source_table: string;
1054+
target_table: string;
1055+
source_schema_name?: string;
1056+
target_schema_name?: string;
1057+
} & Partial<RelationSpatialParams>;
10351058
/**
10361059
* ===========================================================================
10371060
* Blueprint table and definition

graphql/node-type-registry/src/relation/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export { RelationBelongsTo } from './relation-belongs-to';
22
export { RelationHasOne } from './relation-has-one';
33
export { RelationHasMany } from './relation-has-many';
44
export { RelationManyToMany } from './relation-many-to-many';
5+
export { RelationSpatial } from './relation-spatial';
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import type { NodeTypeDefinition } from '../types';
2+
3+
export const RelationSpatial: NodeTypeDefinition = {
4+
"name": "RelationSpatial",
5+
"slug": "relation_spatial",
6+
"category": "relation",
7+
"display_name": "Spatial Relation",
8+
"description": "Declares a spatial predicate between two existing geometry/geography columns. Inserts a metaschema_public.spatial_relation row; the sync_spatial_relation_tags trigger then projects a @spatialRelation smart tag onto the owner column so graphile-postgis' PostgisSpatialRelationsPlugin can expose it as a cross-table filter in GraphQL. Metadata-only: both source_field and target_field must already exist on their tables. Idempotent on (source_table_id, name). One direction per tag — author two RelationSpatial entries if symmetry is desired.",
9+
"parameter_schema": {
10+
"type": "object",
11+
"properties": {
12+
"source_table_id": {
13+
"type": "string",
14+
"format": "uuid",
15+
"description": "Table that owns the relation (the @spatialRelation tag is emitted on the owner column of this table)"
16+
},
17+
"source_field_id": {
18+
"type": "string",
19+
"format": "uuid",
20+
"description": "Geometry/geography column on source_table that carries the @spatialRelation smart tag"
21+
},
22+
"target_table_id": {
23+
"type": "string",
24+
"format": "uuid",
25+
"description": "Table being referenced by the spatial predicate"
26+
},
27+
"target_field_id": {
28+
"type": "string",
29+
"format": "uuid",
30+
"description": "Geometry/geography column on target_table that the predicate is evaluated against"
31+
},
32+
"name": {
33+
"type": "string",
34+
"description": "Relation name (stable, snake_case). Becomes the generated filter field name in GraphQL (e.g. nearby_clinic). Unique per (source_table_id, name) — idempotency key."
35+
},
36+
"operator": {
37+
"type": "string",
38+
"enum": [
39+
"st_contains",
40+
"st_within",
41+
"st_intersects",
42+
"st_covers",
43+
"st_coveredby",
44+
"st_overlaps",
45+
"st_touches",
46+
"st_dwithin"
47+
],
48+
"description": "PostGIS spatial predicate. One of the 8 whitelisted operators. st_dwithin requires param_name."
49+
},
50+
"param_name": {
51+
"type": "string",
52+
"description": "Parameter name for parametric operators (currently only st_dwithin, which needs a distance argument). Must be NULL for all other operators. Enforced by table CHECK."
53+
}
54+
},
55+
"required": [
56+
"source_table_id",
57+
"source_field_id",
58+
"target_table_id",
59+
"target_field_id",
60+
"name",
61+
"operator"
62+
]
63+
},
64+
"tags": [
65+
"relation",
66+
"spatial",
67+
"postgis",
68+
"schema"
69+
]
70+
};

0 commit comments

Comments
 (0)