diff --git a/graphile/graphile-postgis/src/plugins/detect-extension.ts b/graphile/graphile-postgis/src/plugins/detect-extension.ts index e4a8ffa70..5b8f6c1e1 100644 --- a/graphile/graphile-postgis/src/plugins/detect-extension.ts +++ b/graphile/graphile-postgis/src/plugins/detect-extension.ts @@ -50,7 +50,7 @@ export const PostgisExtensionDetectionPlugin: GraphileConfig.Plugin = { // PostGIS is detected when at least one of geometry or geography // codecs is present. Some databases use only geography columns - // (e.g. use_geography: true in DataPostGIS), so PostGraphile may + // (e.g. use_geography: true in SearchSpatial), so PostGraphile may // introspect geography but not geometry. if (!geometryCodec && !geographyCodec) { return build; diff --git a/graphile/graphile-search/src/plugin.ts b/graphile/graphile-search/src/plugin.ts index 85cf1b2bf..5f77475f0 100644 --- a/graphile/graphile-search/src/plugin.ts +++ b/graphile/graphile-search/src/plugin.ts @@ -68,7 +68,7 @@ interface SearchScoreDetails { /** * Per-table search configuration read from the @searchConfig smart tag. - * Written by DataFullTextSearch, DataBm25, and DataSearch in constructive-db. + * Written by SearchFullText, SearchBm25, and SearchUnified in constructive-db. */ interface SearchConfig { weights?: Record; @@ -488,7 +488,7 @@ export function createUnifiedSearchPlugin( } } - // Read per-table @searchConfig smart tag (written by DataSearch/DataFullTextSearch/DataBm25) + // Read per-table @searchConfig smart tag (written by SearchUnified/SearchFullText/SearchBm25) // Per-table config overrides global searchScoreWeights const tableSearchConfig = getSearchConfig(codec); diff --git a/graphql/node-type-registry/src/blueprint-types.generated.ts b/graphql/node-type-registry/src/blueprint-types.generated.ts index ecd1c1a62..b27d8fcb8 100644 --- a/graphql/node-type-registry/src/blueprint-types.generated.ts +++ b/graphql/node-type-registry/src/blueprint-types.generated.ts @@ -64,8 +64,130 @@ export interface DataSoftDeleteParams { /* If true, also adds a UUID primary key column with auto-generation */ include_id?: boolean; } +/** Dynamically creates PostgreSQL triggers that enqueue jobs via app_jobs.add_job() when table rows are inserted, updated, or deleted. Supports configurable payload strategies (full row, row ID, selected fields, or custom mapping), conditional firing via WHEN clauses, watched field changes, and extended job options (queue, priority, delay, max attempts). */ +export interface DataJobTriggerParams { + /* Job task identifier passed to add_job (e.g., process_invoice, sync_to_stripe) */ + task_identifier: string; + /* How to build the job payload: row (full NEW/OLD), row_id (just id), fields (selected columns), custom (mapped columns) */ + payload_strategy?: "row" | "row_id" | "fields" | "custom"; + /* Column names to include in payload (only for fields strategy) */ + payload_fields?: string[]; + /* Key-to-column mapping for custom payload (e.g., {"invoice_id": "id", "total": "amount"}) */ + payload_custom?: { + [key: string]: unknown; + }; + /* Trigger events to create */ + events?: ("INSERT" | "UPDATE" | "DELETE")[]; + /* Include OLD row in payload (for UPDATE triggers) */ + include_old?: boolean; + /* Include table/schema metadata in payload */ + include_meta?: boolean; + /* Column name for conditional WHEN clause (fires only when field equals condition_value) */ + condition_field?: string; + /* Value to compare against condition_field in WHEN clause */ + condition_value?: string; + /* For UPDATE triggers, only fire when these fields change (uses DISTINCT FROM) */ + watch_fields?: string[]; + /* Static job key for upsert semantics (prevents duplicate jobs) */ + job_key?: string; + /* Job queue name for routing to specific workers */ + queue_name?: string; + /* Job priority (lower = higher priority) */ + priority?: number; + /* Delay before job runs as PostgreSQL interval (e.g., 30 seconds, 5 minutes) */ + run_at_delay?: string; + /* Maximum retry attempts for the job */ + max_attempts?: number; +} +/** Adds a citext[] tags column with GIN index for efficient array containment queries (@>, &&). Standard tagging pattern for categorization and filtering. */ +export interface DataTagsParams { + /* Column name for the tags array */ + field_name?: string; + /* Default value expression for the tags column */ + default_value?: string; + /* Whether the column has a NOT NULL constraint */ + is_required?: boolean; +} +/** Adds a status column with B-tree index for efficient equality filtering and sorting. Optionally constrains values via CHECK constraint when allowed_values is provided. */ +export interface DataStatusFieldParams { + /* Column name for the status field */ + field_name?: string; + /* Column type (text or citext) */ + type?: string; + /* Default value expression (e.g., active) */ + default_value?: string; + /* Whether the column has a NOT NULL constraint */ + is_required?: boolean; + /* If provided, creates a CHECK constraint restricting the column to these values */ + allowed_values?: string[]; +} +/** Adds a JSONB column with optional GIN index for containment queries (@>, ?, ?|, ?&). Standard pattern for semi-structured metadata. */ +export interface DataJsonbParams { + /* Column name for the JSONB field */ + field_name?: string; + /* Default value expression */ + default_value?: string; + /* Whether the column has a NOT NULL constraint */ + is_required?: boolean; + /* Whether to create a GIN index */ + create_index?: boolean; +} +/** Auto-generates URL-friendly slugs from field values on insert/update. Attaches BEFORE INSERT and BEFORE UPDATE triggers that call inflection.slugify() on the target field. References fields by name in data jsonb. */ +export interface DataSlugParams { + /* Name of the field to slugify */ + field_name: string; + /* Optional source field name (defaults to field_name) */ + source_field_name?: string; +} +/** Transforms field values using inflection operations (snake_case, camelCase, slugify, plural, singular, etc). Attaches BEFORE INSERT and BEFORE UPDATE triggers. References fields by name in data jsonb. */ +export interface DataInflectionParams { + /* Name of the field to transform */ + field_name: string; + /* Inflection operations to apply in order */ + ops: ("plural" | "singular" | "camel" | "pascal" | "dashed" | "slugify" | "underscore" | "lower" | "upper")[]; +} +/** Restricts which user can modify specific columns in shared objects. Creates an AFTER UPDATE trigger that throws OWNED_PROPS when a non-owner tries to change protected fields. References fields by name in data jsonb. */ +export interface DataOwnedFieldsParams { + /* Name of the field identifying the owner (e.g. sender_id) */ + role_key_field_name: string; + /* Names of fields only this owner can modify */ + protected_field_names: string[]; +} +/** BEFORE INSERT trigger that copies specified fields from a parent table via a foreign key. The parent row is looked up through RLS (SECURITY INVOKER), so the insert fails if the caller cannot see the parent. Used by the storage module to inherit owner_id and is_public from buckets to files. */ +export interface DataInheritFromParentParams { + /* Name of the FK field on this table that references the parent (e.g. bucket_id) */ + parent_fk_field: string; + /* Field names to copy from the parent row (e.g. ["owner_id", "is_public"]) */ + fields: string[]; + /* Parent table name (optional fallback if FK not yet registered in metaschema) */ + parent_table?: string; + /* Parent table schema (optional, defaults to same schema as child table) */ + parent_schema?: string; +} +/** BEFORE INSERT trigger that forces a field to the value of jwt_public.current_user_id(). Prevents clients from spoofing the actor/uploader identity. The field value is always overwritten regardless of what the client provides. */ +export interface DataForceCurrentUserParams { + /* Name of the field to force to current_user_id() */ + field_name?: string; +} +/** BEFORE UPDATE trigger that prevents changes to a list of specified fields after INSERT. Raises an exception if any of the listed fields have changed. Unlike FieldImmutable (single-field), this handles multiple fields in a single trigger for efficiency. */ +export interface DataImmutableFieldsParams { + /* Field names that cannot be modified after INSERT (e.g. ["key", "bucket_id", "owner_id"]) */ + fields: string[]; +} +/** Creates a user profiles table with standard profile fields (profile_picture, bio, first_name, last_name, tags, desired). Uses AuthzDirectOwner for edit access and AuthzAllowAll for select. */ +export type TableUserProfilesParams = {}; +/** Creates an organization settings table with standard business fields (legal_name, address fields). Uses AuthzEntityMembership for access control. */ +export type TableOrganizationSettingsParams = {}; +/** Creates a user settings table for user-specific configuration. Uses AuthzDirectOwner for access control. */ +export type TableUserSettingsParams = {}; +/** + * =========================================================================== + * Search node type parameters + * =========================================================================== + */ +; /** Adds a vector embedding column with HNSW or IVFFlat index for similarity search. Supports configurable dimensions, distance metrics (cosine, l2, ip), stale tracking strategies (column, null, hash), and automatic job enqueue triggers for embedding generation. */ -export interface DataEmbeddingParams { +export interface SearchVectorParams { /* Name of the vector column */ field_name?: string; /* Vector dimensions (e.g. 384, 768, 1536, 3072) */ @@ -102,7 +224,7 @@ export interface DataEmbeddingParams { }; } /** Adds a tsvector column with GIN index and automatic trigger population from source fields. Enables PostgreSQL full-text search with configurable weights and language support. Leverages the existing metaschema full_text_search infrastructure. */ -export interface DataFullTextSearchParams { +export interface SearchFullTextParams { /* Name of the tsvector column */ field_name?: string; /* Source columns that feed the tsvector. Each has a field name, weight (A-D), and language config. */ @@ -115,7 +237,7 @@ export interface DataFullTextSearchParams { search_score_weight?: number; } /** Creates a BM25 index on an existing text column using pg_textsearch. Enables statistical relevance ranking with configurable k1 and b parameters. The BM25 index is auto-detected by graphile-search. */ -export interface DataBm25Params { +export interface SearchBm25Params { /* Name of existing text column to index with BM25 */ field_name: string; /* PostgreSQL text search configuration for BM25 */ @@ -128,8 +250,8 @@ export interface DataBm25Params { search_score_weight?: number; } /** Composite node type that orchestrates multiple search modalities (full-text search, BM25, embeddings, trigram) on a single table. Configures per-table search score weights, normalization strategy, and recency boost via the @searchConfig smart tag. */ -export interface DataSearchParams { - /* DataFullTextSearch parameters. Omit to skip FTS setup. */ +export interface SearchUnifiedParams { + /* SearchFullText parameters. Omit to skip FTS setup. */ full_text_search?: { field_name?: string; source_fields?: { @@ -139,7 +261,7 @@ export interface DataSearchParams { }[]; search_score_weight?: number; }; - /* DataBm25 parameters. Omit to skip BM25 setup. */ + /* SearchBm25 parameters. Omit to skip BM25 setup. */ bm25?: { field_name?: string; text_config?: string; @@ -147,7 +269,7 @@ export interface DataSearchParams { b?: number; search_score_weight?: number; }; - /* DataEmbedding parameters. Omit to skip embedding setup. */ + /* SearchVector parameters. Omit to skip embedding setup. */ embedding?: { field_name?: string; dimensions?: number; @@ -181,7 +303,7 @@ export interface DataSearchParams { }; } /** Adds a PostGIS geometry or geography column with a spatial index (GiST or SP-GiST). Supports configurable geometry types (Point, Polygon, etc.), SRID, and dimensionality. The graphile-postgis plugin auto-detects geometry/geography columns by codec type for spatial filtering (ST_Contains, ST_DWithin, bbox operators). */ -export interface DataPostGISParams { +export interface SearchSpatialParams { /* Name of the geometry/geography column */ field_name?: string; /* PostGIS geometry type constraint */ @@ -196,7 +318,7 @@ export interface DataPostGISParams { index_method?: "gist" | "spgist"; } /** Creates a derived/materialized geometry field on the parent table that automatically aggregates geometries from a source (child) table via triggers. When child rows are inserted/updated/deleted, the parent aggregate field is recalculated using the specified PostGIS aggregation function (ST_Union, ST_Collect, ST_ConvexHull, ST_ConcaveHull). Useful for materializing spatial boundaries from collections of points or polygons. */ -export interface DataPostGISAggregateParams { +export interface SearchSpatialAggregateParams { /* Name of the aggregate geometry column on the parent table */ field_name?: string; /* UUID of the source (child) table containing individual geometries */ @@ -218,127 +340,11 @@ export interface DataPostGISAggregateParams { /* Spatial index method for the aggregate field */ index_method?: "gist" | "spgist"; } -/** Dynamically creates PostgreSQL triggers that enqueue jobs via app_jobs.add_job() when table rows are inserted, updated, or deleted. Supports configurable payload strategies (full row, row ID, selected fields, or custom mapping), conditional firing via WHEN clauses, watched field changes, and extended job options (queue, priority, delay, max attempts). */ -export interface DataJobTriggerParams { - /* Job task identifier passed to add_job (e.g., process_invoice, sync_to_stripe) */ - task_identifier: string; - /* How to build the job payload: row (full NEW/OLD), row_id (just id), fields (selected columns), custom (mapped columns) */ - payload_strategy?: "row" | "row_id" | "fields" | "custom"; - /* Column names to include in payload (only for fields strategy) */ - payload_fields?: string[]; - /* Key-to-column mapping for custom payload (e.g., {"invoice_id": "id", "total": "amount"}) */ - payload_custom?: { - [key: string]: unknown; - }; - /* Trigger events to create */ - events?: ("INSERT" | "UPDATE" | "DELETE")[]; - /* Include OLD row in payload (for UPDATE triggers) */ - include_old?: boolean; - /* Include table/schema metadata in payload */ - include_meta?: boolean; - /* Column name for conditional WHEN clause (fires only when field equals condition_value) */ - condition_field?: string; - /* Value to compare against condition_field in WHEN clause */ - condition_value?: string; - /* For UPDATE triggers, only fire when these fields change (uses DISTINCT FROM) */ - watch_fields?: string[]; - /* Static job key for upsert semantics (prevents duplicate jobs) */ - job_key?: string; - /* Job queue name for routing to specific workers */ - queue_name?: string; - /* Job priority (lower = higher priority) */ - priority?: number; - /* Delay before job runs as PostgreSQL interval (e.g., 30 seconds, 5 minutes) */ - run_at_delay?: string; - /* Maximum retry attempts for the job */ - max_attempts?: number; -} -/** Adds a citext[] tags column with GIN index for efficient array containment queries (@>, &&). Standard tagging pattern for categorization and filtering. */ -export interface DataTagsParams { - /* Column name for the tags array */ - field_name?: string; - /* Default value expression for the tags column */ - default_value?: string; - /* Whether the column has a NOT NULL constraint */ - is_required?: boolean; -} -/** Adds a status column with B-tree index for efficient equality filtering and sorting. Optionally constrains values via CHECK constraint when allowed_values is provided. */ -export interface DataStatusFieldParams { - /* Column name for the status field */ - field_name?: string; - /* Column type (text or citext) */ - type?: string; - /* Default value expression (e.g., active) */ - default_value?: string; - /* Whether the column has a NOT NULL constraint */ - is_required?: boolean; - /* If provided, creates a CHECK constraint restricting the column to these values */ - allowed_values?: string[]; -} -/** Adds a JSONB column with optional GIN index for containment queries (@>, ?, ?|, ?&). Standard pattern for semi-structured metadata. */ -export interface DataJsonbParams { - /* Column name for the JSONB field */ - field_name?: string; - /* Default value expression */ - default_value?: string; - /* Whether the column has a NOT NULL constraint */ - is_required?: boolean; - /* Whether to create a GIN index */ - create_index?: boolean; -} /** Creates GIN trigram indexes (gin_trgm_ops) on specified text/citext fields for fuzzy LIKE/ILIKE/similarity search. Adds @trgmSearch smart tag for PostGraphile integration. Fields must already exist on the table. */ -export interface DataTrgmParams { +export interface SearchTrgmParams { /* Field names to create trigram indexes on (fields must already exist on the table) */ fields: string[]; } -/** Auto-generates URL-friendly slugs from field values on insert/update. Attaches BEFORE INSERT and BEFORE UPDATE triggers that call inflection.slugify() on the target field. References fields by name in data jsonb. */ -export interface DataSlugParams { - /* Name of the field to slugify */ - field_name: string; - /* Optional source field name (defaults to field_name) */ - source_field_name?: string; -} -/** Transforms field values using inflection operations (snake_case, camelCase, slugify, plural, singular, etc). Attaches BEFORE INSERT and BEFORE UPDATE triggers. References fields by name in data jsonb. */ -export interface DataInflectionParams { - /* Name of the field to transform */ - field_name: string; - /* Inflection operations to apply in order */ - ops: ("plural" | "singular" | "camel" | "pascal" | "dashed" | "slugify" | "underscore" | "lower" | "upper")[]; -} -/** Restricts which user can modify specific columns in shared objects. Creates an AFTER UPDATE trigger that throws OWNED_PROPS when a non-owner tries to change protected fields. References fields by name in data jsonb. */ -export interface DataOwnedFieldsParams { - /* Name of the field identifying the owner (e.g. sender_id) */ - role_key_field_name: string; - /* Names of fields only this owner can modify */ - protected_field_names: string[]; -} -/** BEFORE INSERT trigger that copies specified fields from a parent table via a foreign key. The parent row is looked up through RLS (SECURITY INVOKER), so the insert fails if the caller cannot see the parent. Used by the storage module to inherit owner_id and is_public from buckets to files. */ -export interface DataInheritFromParentParams { - /* Name of the FK field on this table that references the parent (e.g. bucket_id) */ - parent_fk_field: string; - /* Field names to copy from the parent row (e.g. ["owner_id", "is_public"]) */ - fields: string[]; - /* Parent table name (optional fallback if FK not yet registered in metaschema) */ - parent_table?: string; - /* Parent table schema (optional, defaults to same schema as child table) */ - parent_schema?: string; -} -/** BEFORE INSERT trigger that forces a field to the value of jwt_public.current_user_id(). Prevents clients from spoofing the actor/uploader identity. The field value is always overwritten regardless of what the client provides. */ -export interface DataForceCurrentUserParams { - /* Name of the field to force to current_user_id() */ - field_name?: string; -} -/** BEFORE UPDATE trigger that prevents changes to a list of specified fields after INSERT. Raises an exception if any of the listed fields have changed. Unlike FieldImmutable (single-field), this handles multiple fields in a single trigger for efficiency. */ -export interface DataImmutableFieldsParams { - /* Field names that cannot be modified after INSERT (e.g. ["key", "bucket_id", "owner_id"]) */ - fields: string[]; -} -/** Creates a user profiles table with standard profile fields (profile_picture, bio, first_name, last_name, tags, desired). Uses AuthzDirectOwner for edit access and AuthzAllowAll for select. */ -export type TableUserProfilesParams = {}; -/** Creates an organization settings table with standard business fields (legal_name, address fields). Uses AuthzEntityMembership for access control. */ -export type TableOrganizationSettingsParams = {}; -/** Creates a user settings table for user-specific configuration. Uses AuthzDirectOwner for access control. */ -export type TableUserSettingsParams = {}; /** * =========================================================================== * Authz node type parameters @@ -788,7 +794,7 @@ export interface BlueprintTableUniqueConstraint { */ ; /** String shorthand -- just the node type name. */ -export type BlueprintNodeShorthand = "AuthzDirectOwner" | "AuthzDirectOwnerAny" | "AuthzMembership" | "AuthzEntityMembership" | "AuthzRelatedEntityMembership" | "AuthzOrgHierarchy" | "AuthzTemporal" | "AuthzPublishable" | "AuthzMemberList" | "AuthzRelatedMemberList" | "AuthzAllowAll" | "AuthzDenyAll" | "AuthzComposite" | "AuthzPeerOwnership" | "AuthzRelatedPeerOwnership" | "DataId" | "DataDirectOwner" | "DataEntityMembership" | "DataOwnershipInEntity" | "DataTimestamps" | "DataPeoplestamps" | "DataPublishable" | "DataSoftDelete" | "DataEmbedding" | "DataFullTextSearch" | "DataBm25" | "DataSearch" | "DataPostGIS" | "DataPostGISAggregate" | "DataJobTrigger" | "DataTags" | "DataStatusField" | "DataJsonb" | "DataTrgm" | "DataSlug" | "DataInflection" | "DataOwnedFields" | "DataInheritFromParent" | "DataForceCurrentUser" | "DataImmutableFields" | "TableUserProfiles" | "TableOrganizationSettings" | "TableUserSettings"; +export type BlueprintNodeShorthand = "AuthzDirectOwner" | "AuthzDirectOwnerAny" | "AuthzMembership" | "AuthzEntityMembership" | "AuthzRelatedEntityMembership" | "AuthzOrgHierarchy" | "AuthzTemporal" | "AuthzPublishable" | "AuthzMemberList" | "AuthzRelatedMemberList" | "AuthzAllowAll" | "AuthzDenyAll" | "AuthzComposite" | "AuthzPeerOwnership" | "AuthzRelatedPeerOwnership" | "DataId" | "DataDirectOwner" | "DataEntityMembership" | "DataOwnershipInEntity" | "DataTimestamps" | "DataPeoplestamps" | "DataPublishable" | "DataSoftDelete" | "SearchVector" | "SearchFullText" | "SearchBm25" | "SearchUnified" | "SearchSpatial" | "SearchSpatialAggregate" | "DataJobTrigger" | "DataTags" | "DataStatusField" | "DataJsonb" | "SearchTrgm" | "DataSlug" | "DataInflection" | "DataOwnedFields" | "DataInheritFromParent" | "DataForceCurrentUser" | "DataImmutableFields" | "TableUserProfiles" | "TableOrganizationSettings" | "TableUserSettings"; /** Object form -- { $type, data } with typed parameters. */ export type BlueprintNodeObject = { $type: "AuthzDirectOwner"; @@ -860,23 +866,23 @@ export type BlueprintNodeObject = { $type: "DataSoftDelete"; data: DataSoftDeleteParams; } | { - $type: "DataEmbedding"; - data: DataEmbeddingParams; + $type: "SearchVector"; + data: SearchVectorParams; } | { - $type: "DataFullTextSearch"; - data: DataFullTextSearchParams; + $type: "SearchFullText"; + data: SearchFullTextParams; } | { - $type: "DataBm25"; - data: DataBm25Params; + $type: "SearchBm25"; + data: SearchBm25Params; } | { - $type: "DataSearch"; - data: DataSearchParams; + $type: "SearchUnified"; + data: SearchUnifiedParams; } | { - $type: "DataPostGIS"; - data: DataPostGISParams; + $type: "SearchSpatial"; + data: SearchSpatialParams; } | { - $type: "DataPostGISAggregate"; - data: DataPostGISAggregateParams; + $type: "SearchSpatialAggregate"; + data: SearchSpatialAggregateParams; } | { $type: "DataJobTrigger"; data: DataJobTriggerParams; @@ -890,8 +896,8 @@ export type BlueprintNodeObject = { $type: "DataJsonb"; data: DataJsonbParams; } | { - $type: "DataTrgm"; - data: DataTrgmParams; + $type: "SearchTrgm"; + data: SearchTrgmParams; } | { $type: "DataSlug"; data: DataSlugParams; diff --git a/graphql/node-type-registry/src/codegen/generate-types.ts b/graphql/node-type-registry/src/codegen/generate-types.ts index 7c7309fce..7bff7815f 100644 --- a/graphql/node-type-registry/src/codegen/generate-types.ts +++ b/graphql/node-type-registry/src/codegen/generate-types.ts @@ -755,7 +755,7 @@ function buildProgram(meta?: MetaTableInfo[]): string { const authzNodes = allNodeTypes.filter((nt) => nt.category === 'authz'); // -- Parameter interfaces grouped by category -- - const categoryOrder = ['data', 'authz', 'relation', 'view']; + const categoryOrder = ['data', 'search', 'authz', 'relation', 'view']; for (const cat of categoryOrder) { const nts = categories.get(cat); if (!nts || nts.length === 0) continue; diff --git a/graphql/node-type-registry/src/data/index.ts b/graphql/node-type-registry/src/data/index.ts index 62fbe91c3..e51ecdf9d 100644 --- a/graphql/node-type-registry/src/data/index.ts +++ b/graphql/node-type-registry/src/data/index.ts @@ -6,17 +6,17 @@ export { DataTimestamps } from './data-timestamps'; export { DataPeoplestamps } from './data-peoplestamps'; export { DataPublishable } from './data-publishable'; export { DataSoftDelete } from './data-soft-delete'; -export { DataEmbedding } from './data-embedding'; -export { DataFullTextSearch } from './data-full-text-search'; -export { DataBm25 } from './data-bm25'; -export { DataSearch } from './data-search'; -export { DataPostGIS } from './data-postgis'; -export { DataPostGISAggregate } from './data-postgis-aggregate'; +export { SearchVector } from './search-vector'; +export { SearchFullText } from './search-full-text'; +export { SearchBm25 } from './search-bm25'; +export { SearchUnified } from './search-unified'; +export { SearchSpatial } from './search-spatial'; +export { SearchSpatialAggregate } from './search-spatial-aggregate'; export { DataJobTrigger } from './data-job-trigger'; export { DataTags } from './data-tags'; export { DataStatusField } from './data-status-field'; export { DataJsonb } from './data-jsonb'; -export { DataTrgm } from './data-trgm'; +export { SearchTrgm } from './search-trgm'; export { DataSlug } from './data-slug'; export { DataInflection } from './data-inflection'; export { DataOwnedFields } from './data-owned-fields'; diff --git a/graphql/node-type-registry/src/data/data-bm25.ts b/graphql/node-type-registry/src/data/search-bm25.ts similarity index 91% rename from graphql/node-type-registry/src/data/data-bm25.ts rename to graphql/node-type-registry/src/data/search-bm25.ts index 442c310c7..60690606b 100644 --- a/graphql/node-type-registry/src/data/data-bm25.ts +++ b/graphql/node-type-registry/src/data/search-bm25.ts @@ -1,9 +1,9 @@ import type { NodeTypeDefinition } from '../types'; -export const DataBm25: NodeTypeDefinition = { - "name": "DataBm25", - "slug": "data_bm25", - "category": "data", +export const SearchBm25: NodeTypeDefinition = { + "name": "SearchBm25", + "slug": "search_bm25", + "category": "search", "display_name": "BM25 Search", "description": "Creates a BM25 index on an existing text column using pg_textsearch. Enables statistical relevance ranking with configurable k1 and b parameters. The BM25 index is auto-detected by graphile-search.", "parameter_schema": { diff --git a/graphql/node-type-registry/src/data/data-full-text-search.ts b/graphql/node-type-registry/src/data/search-full-text.ts similarity index 92% rename from graphql/node-type-registry/src/data/data-full-text-search.ts rename to graphql/node-type-registry/src/data/search-full-text.ts index f632c84f6..37800bc40 100644 --- a/graphql/node-type-registry/src/data/data-full-text-search.ts +++ b/graphql/node-type-registry/src/data/search-full-text.ts @@ -1,9 +1,9 @@ import type { NodeTypeDefinition } from '../types'; -export const DataFullTextSearch: NodeTypeDefinition = { - "name": "DataFullTextSearch", - "slug": "data_full_text_search", - "category": "data", +export const SearchFullText: NodeTypeDefinition = { + "name": "SearchFullText", + "slug": "search_full_text", + "category": "search", "display_name": "Full-Text Search", "description": "Adds a tsvector column with GIN index and automatic trigger population from source fields. Enables PostgreSQL full-text search with configurable weights and language support. Leverages the existing metaschema full_text_search infrastructure.", "parameter_schema": { diff --git a/graphql/node-type-registry/src/data/data-postgis-aggregate.ts b/graphql/node-type-registry/src/data/search-spatial-aggregate.ts similarity index 93% rename from graphql/node-type-registry/src/data/data-postgis-aggregate.ts rename to graphql/node-type-registry/src/data/search-spatial-aggregate.ts index ffd9858a4..4575bbc44 100644 --- a/graphql/node-type-registry/src/data/data-postgis-aggregate.ts +++ b/graphql/node-type-registry/src/data/search-spatial-aggregate.ts @@ -1,10 +1,10 @@ import type { NodeTypeDefinition } from '../types'; -export const DataPostGISAggregate: NodeTypeDefinition = { - "name": "DataPostGISAggregate", - "slug": "data_postgis_aggregate", - "category": "data", - "display_name": "PostGIS Aggregate Geometry", +export const SearchSpatialAggregate: NodeTypeDefinition = { + "name": "SearchSpatialAggregate", + "slug": "search_spatial_aggregate", + "category": "search", + "display_name": "Spatial Aggregate Search", "description": "Creates a derived/materialized geometry field on the parent table that automatically aggregates geometries from a source (child) table via triggers. When child rows are inserted/updated/deleted, the parent aggregate field is recalculated using the specified PostGIS aggregation function (ST_Union, ST_Collect, ST_ConvexHull, ST_ConcaveHull). Useful for materializing spatial boundaries from collections of points or polygons.", "parameter_schema": { "type": "object", diff --git a/graphql/node-type-registry/src/data/data-postgis.ts b/graphql/node-type-registry/src/data/search-spatial.ts similarity index 91% rename from graphql/node-type-registry/src/data/data-postgis.ts rename to graphql/node-type-registry/src/data/search-spatial.ts index 6dbbf16ea..f18991210 100644 --- a/graphql/node-type-registry/src/data/data-postgis.ts +++ b/graphql/node-type-registry/src/data/search-spatial.ts @@ -1,10 +1,10 @@ import type { NodeTypeDefinition } from '../types'; -export const DataPostGIS: NodeTypeDefinition = { - "name": "DataPostGIS", - "slug": "data_postgis", - "category": "data", - "display_name": "PostGIS Geometry", +export const SearchSpatial: NodeTypeDefinition = { + "name": "SearchSpatial", + "slug": "search_spatial", + "category": "search", + "display_name": "Spatial Search", "description": "Adds a PostGIS geometry or geography column with a spatial index (GiST or SP-GiST). Supports configurable geometry types (Point, Polygon, etc.), SRID, and dimensionality. The graphile-postgis plugin auto-detects geometry/geography columns by codec type for spatial filtering (ST_Contains, ST_DWithin, bbox operators).", "parameter_schema": { "type": "object", diff --git a/graphql/node-type-registry/src/data/data-trgm.ts b/graphql/node-type-registry/src/data/search-trgm.ts similarity index 85% rename from graphql/node-type-registry/src/data/data-trgm.ts rename to graphql/node-type-registry/src/data/search-trgm.ts index bf7f3bfa8..9795e3064 100644 --- a/graphql/node-type-registry/src/data/data-trgm.ts +++ b/graphql/node-type-registry/src/data/search-trgm.ts @@ -1,9 +1,9 @@ import type { NodeTypeDefinition } from '../types'; -export const DataTrgm: NodeTypeDefinition = { - "name": "DataTrgm", - "slug": "data_trgm", - "category": "data", +export const SearchTrgm: NodeTypeDefinition = { + "name": "SearchTrgm", + "slug": "search_trgm", + "category": "search", "display_name": "Trigram Search", "description": "Creates GIN trigram indexes (gin_trgm_ops) on specified text/citext fields for fuzzy LIKE/ILIKE/similarity search. Adds @trgmSearch smart tag for PostGraphile integration. Fields must already exist on the table.", "parameter_schema": { diff --git a/graphql/node-type-registry/src/data/data-search.ts b/graphql/node-type-registry/src/data/search-unified.ts similarity index 94% rename from graphql/node-type-registry/src/data/data-search.ts rename to graphql/node-type-registry/src/data/search-unified.ts index 6cafb9d2e..1d103305d 100644 --- a/graphql/node-type-registry/src/data/data-search.ts +++ b/graphql/node-type-registry/src/data/search-unified.ts @@ -1,9 +1,9 @@ import type { NodeTypeDefinition } from '../types'; -export const DataSearch: NodeTypeDefinition = { - "name": "DataSearch", - "slug": "data_search", - "category": "data", +export const SearchUnified: NodeTypeDefinition = { + "name": "SearchUnified", + "slug": "search_unified", + "category": "search", "display_name": "Unified Search", "description": "Composite node type that orchestrates multiple search modalities (full-text search, BM25, embeddings, trigram) on a single table. Configures per-table search score weights, normalization strategy, and recency boost via the @searchConfig smart tag.", "parameter_schema": { @@ -11,7 +11,7 @@ export const DataSearch: NodeTypeDefinition = { "properties": { "full_text_search": { "type": "object", - "description": "DataFullTextSearch parameters. Omit to skip FTS setup.", + "description": "SearchFullText parameters. Omit to skip FTS setup.", "properties": { "field_name": { "type": "string", @@ -51,7 +51,7 @@ export const DataSearch: NodeTypeDefinition = { }, "bm25": { "type": "object", - "description": "DataBm25 parameters. Omit to skip BM25 setup.", + "description": "SearchBm25 parameters. Omit to skip BM25 setup.", "properties": { "field_name": { "type": "string" @@ -74,7 +74,7 @@ export const DataSearch: NodeTypeDefinition = { }, "embedding": { "type": "object", - "description": "DataEmbedding parameters. Omit to skip embedding setup.", + "description": "SearchVector parameters. Omit to skip embedding setup.", "properties": { "field_name": { "type": "string", diff --git a/graphql/node-type-registry/src/data/data-embedding.ts b/graphql/node-type-registry/src/data/search-vector.ts similarity index 96% rename from graphql/node-type-registry/src/data/data-embedding.ts rename to graphql/node-type-registry/src/data/search-vector.ts index 2ec31c6f1..93166682a 100644 --- a/graphql/node-type-registry/src/data/data-embedding.ts +++ b/graphql/node-type-registry/src/data/search-vector.ts @@ -1,10 +1,10 @@ import type { NodeTypeDefinition } from '../types'; -export const DataEmbedding: NodeTypeDefinition = { - "name": "DataEmbedding", - "slug": "data_embedding", - "category": "data", - "display_name": "Embedding", +export const SearchVector: NodeTypeDefinition = { + "name": "SearchVector", + "slug": "search_vector", + "category": "search", + "display_name": "Vector Search", "description": "Adds a vector embedding column with HNSW or IVFFlat index for similarity search. Supports configurable dimensions, distance metrics (cosine, l2, ip), stale tracking strategies (column, null, hash), and automatic job enqueue triggers for embedding generation.", "parameter_schema": { "type": "object",