diff --git a/packages/node-type-registry/src/blueprint-types.generated.ts b/packages/node-type-registry/src/blueprint-types.generated.ts index 72731033d..9d3bff30d 100644 --- a/packages/node-type-registry/src/blueprint-types.generated.ts +++ b/packages/node-type-registry/src/blueprint-types.generated.ts @@ -35,6 +35,23 @@ export interface TriggerCondition { /** Negated condition. */ NOT?: TriggerCondition; } +/** + * =========================================================================== + * Billing node type parameters + * =========================================================================== + */ +; +/** Declaratively attaches billing usage-recording triggers to a table. On INSERT the named meter is incremented via record_usage; on DELETE it is decremented (reversal). On UPDATE, if the entity_field changes, the old entity is decremented and the new entity is incremented. Requires a provisioned billing_module for the target database. */ +export interface BillingMeterParams { + /* Slug of the billing meter to record usage against (must match a meters table entry, e.g. "databases", "seats") */ + meter_slug: string; + /* Column on the target table that holds the entity id for billing */ + entity_field?: string; + /* Units to record per event (default 1) */ + quantity?: number; + /* Which DML events to attach triggers for */ + events?: ('INSERT' | 'DELETE' | 'UPDATE')[]; +} /** * =========================================================================== * Check node type parameters @@ -77,26 +94,6 @@ export interface CheckOneOfParams { * =========================================================================== */ ; -/** Declaratively attaches aggregate limit-tracking triggers to a table. On INSERT the named limit is incremented per entity; on DELETE it is decremented. Uses org_limit_aggregates_inc/dec for per-entity (org-level) aggregate limits rather than per-user limits. Requires a provisioned limits_module for the target database. */ -export interface DataAggregateLimitCounterParams { - /* Name of the aggregate limit to track (must match a default_limits entry, e.g. "databases", "members") */ - limit_name: string; - /* Column on the target table that holds the entity id for aggregate limit lookup */ - entity_field?: string; - /* Which DML events to attach triggers for */ - events?: ('INSERT' | 'DELETE' | 'UPDATE')[]; -} -/** Declaratively attaches billing usage-recording triggers to a table. On INSERT the named meter is incremented via record_usage; on DELETE it is decremented (reversal). On UPDATE, if the entity_field changes, the old entity is decremented and the new entity is incremented. Requires a provisioned billing_module for the target database. */ -export interface DataBillingMeterParams { - /* Slug of the billing meter to record usage against (must match a meters table entry, e.g. "databases", "seats") */ - meter_slug: string; - /* Column on the target table that holds the entity id for billing */ - entity_field?: string; - /* Units to record per event (default 1) */ - quantity?: number; - /* Which DML events to attach triggers for */ - events?: ('INSERT' | 'DELETE' | 'UPDATE')[]; -} /** Enables bulk mutation smart tags on a table. When provisioned, adds @behavior tags for the selected bulk operations (insert, upsert, update, delete). Requires the graphile-bulk-mutations plugin. */ export interface DataBulkParams { /* Enable bulk insert (+bulkInsert) */ @@ -108,29 +105,6 @@ export interface DataBulkParams { /* Enable bulk delete (+bulkDelete) */ delete?: boolean; } -/** Creates a chunked-embedding child table for any parent table. Provisions the chunks table with content, chunk_index, embedding vector, metadata, HNSW index, inherited RLS, and optional job trigger for automatic text splitting. Composed internally by DataFileEmbedding (enabled by default in extract mode) but can also be used standalone. */ -export interface DataChunksParams { - /* Name of the text content column in the chunks table */ - content_field_name?: string; - /* Maximum number of characters per chunk */ - chunk_size?: number; - /* Number of overlapping characters between consecutive chunks */ - chunk_overlap?: number; - /* Strategy for splitting text into chunks */ - chunk_strategy?: 'fixed' | 'sentence' | 'paragraph' | 'semantic'; - /* Vector dimensions for per-chunk embeddings */ - dimensions?: number; - /* Distance metric for the HNSW index on chunk embeddings */ - metric?: 'cosine' | 'l2' | 'ip'; - /* Override the chunks table name. Defaults to {parent_table}_chunks. */ - chunks_table_name?: string; - /* Field names from the parent table to copy into chunk metadata */ - metadata_fields?: string[]; - /* Whether to create a job trigger that auto-enqueues chunking on parent INSERT/UPDATE */ - enqueue_chunking_job?: boolean; - /* Task identifier for the chunking job queue */ - chunking_task_name?: string; -} /** Creates a derived text field that automatically concatenates multiple source fields via BEFORE INSERT/UPDATE triggers. Used to produce a unified text representation (e.g., embedding_text) from multiple columns on a table. The trigger fires with '_000' prefix to run before Search* triggers alphabetically. */ export interface DataCompositeFieldParams { /* Name of the derived text field to create (default: 'embedding_text') */ @@ -158,59 +132,6 @@ export interface DataEntityMembershipParams { /* If true, adds a foreign key constraint from entity_id to the users table */ include_user_fk?: boolean; } -/** Generic, MIME-scoped embedding node for file tables. Supports two modes: direct (whole-file to single vector, e.g. CLIP for images) when extraction is omitted, or extract (file to text to chunks to per-chunk vectors) when extraction config is provided. Composes SearchVector + DataJobTrigger + DataChunks (enabled by default in extract mode) internally. Multiple instances can coexist on the same table with different MIME scopes, field names, and embedding strategies. */ -export interface DataFileEmbeddingParams { - /* Name of the vector embedding column */ - field_name?: string; - /* Vector dimensions (e.g. 512 for CLIP, 768 for nomic, 1536 for ada-002) */ - dimensions?: number; - /* Index type for similarity search */ - index_method?: 'hnsw' | 'ivfflat'; - /* Distance metric */ - metric?: 'cosine' | 'l2' | 'ip'; - /* Index-specific options. HNSW: {m, ef_construction}. IVFFlat: {lists}. */ - index_options?: { - [key: string]: unknown; - }; - /* MIME type LIKE patterns to match. Multiple patterns are OR'd together. Examples: ['image/%'], ['application/pdf', 'text/%'], ['audio/%']. */ - mime_patterns?: string[]; - /* Job task identifier for the worker. In direct mode this is the embedding worker; in extract mode this is the extraction worker. */ - task_identifier?: string; - /* Trigger events that fire the job */ - events?: ('INSERT' | 'UPDATE')[]; - /* Custom payload key-to-column mapping for the job trigger */ - payload_custom?: { - [key: string]: unknown; - }; - /* Additional compound conditions beyond MIME filtering. Merged with the auto-generated MIME conditions via AND. Use this to add status checks, field guards, etc. */ - trigger_conditions?: TriggerCondition | TriggerCondition[]; - /* Text extraction configuration. When present, the generator creates extraction output fields on the table and configures SearchVector with source_fields + stale tracking. When absent, the node operates in direct mode (single vector per file, no text extraction). */ - extraction?: { - /* Field to store extracted text/markdown */text_field?: string; - /* JSONB field for extraction metadata (page count, language, etc.) */metadata_field?: string; - }; - /* Whether to create a chunks table via DataChunks. Defaults to true when extraction is provided, false in direct mode. Set explicitly to override. */ - include_chunks?: boolean; - /* Chunking configuration passed through to DataChunks. When include_chunks is true (or defaults to true in extract mode), these params configure the chunks table, embedding dimensions, strategy, etc. */ - chunks?: { - /* Name of the text content column in the chunks table */content_field_name?: string; - /* Maximum number of characters per chunk */chunk_size?: number; - /* Number of overlapping characters between consecutive chunks */chunk_overlap?: number; - /* Strategy for splitting text into chunks */chunk_strategy?: 'fixed' | 'sentence' | 'paragraph' | 'semantic'; - /* Field names from parent to copy into chunk metadata */metadata_fields?: string[]; - /* Whether to auto-enqueue a chunking job on insert/update */enqueue_chunking_job?: boolean; - /* Task identifier for the chunking job queue */chunking_task_name?: string; - }; -} -/** Gates a table behind a feature flag backed by the cap tables. Attaches a BEFORE INSERT trigger that checks whether the named feature cap value is > 0. Features are modeled as caps with max=0 (disabled) or max=1 (enabled) in limit_caps / limit_caps_defaults tables. Resolution: COALESCE(per-entity cap, scope default, 0). */ -export interface DataFeatureFlagParams { - /* Cap name representing this feature (must match a limit_caps_defaults entry with max=0 or max=1) */ - feature_name: string; - /* Feature scope: "app" (membership_type=1, app-level caps) or "org" (membership_type=2, per-entity caps) */ - scope?: 'app' | 'org'; - /* Column on the target table that holds the entity id for per-entity cap lookups (only used for org scope) */ - entity_field?: 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() */ @@ -221,50 +142,6 @@ export interface DataIdParams { /* Column name for the primary key */ field_name?: string; } -/** Image-specific preset of DataFileEmbedding. Delegates to DataFileEmbedding with image-oriented defaults: dimensions=512 (CLIP), mime_patterns=['image/%'], task_identifier='process_image_embedding', direct mode (no extraction). Accepts all DataFileEmbedding parameters — any overrides are forwarded through. */ -export interface DataImageEmbeddingParams { - /* Name of the vector embedding column */ - field_name?: string; - /* Vector dimensions (default 512 for CLIP-style image embeddings) */ - dimensions?: number; - /* Index type for similarity search */ - index_method?: 'hnsw' | 'ivfflat'; - /* Distance metric */ - metric?: 'cosine' | 'l2' | 'ip'; - /* Index-specific options. HNSW: {m, ef_construction}. IVFFlat: {lists}. */ - index_options?: { - [key: string]: unknown; - }; - /* MIME type LIKE patterns to match. Multiple patterns are OR'd together. */ - mime_patterns?: string[]; - /* Job task identifier for the image embedding worker */ - task_identifier?: string; - /* Trigger events that fire the job */ - events?: ('INSERT' | 'UPDATE')[]; - /* Custom payload key-to-column mapping for the job trigger */ - payload_custom?: { - [key: string]: unknown; - }; - /* Additional compound conditions beyond MIME filtering. Merged with the auto-generated MIME conditions via AND. */ - trigger_conditions?: TriggerCondition | TriggerCondition[]; - /* Text extraction configuration. Forwarded to DataFileEmbedding. When present, enables extract mode (e.g., OCR for images). */ - extraction?: { - /* Field to store extracted text */text_field?: string; - /* JSONB field for extraction metadata */metadata_field?: string; - }; - /* Chunking configuration. Forwarded to DataFileEmbedding. Only meaningful when extraction is also provided. */ - chunks?: { - content_field_name?: string; - chunk_size?: number; - chunk_overlap?: number; - chunk_strategy?: 'fixed' | 'sentence' | 'paragraph' | 'semantic'; - metadata_fields?: { - [key: string]: unknown; - }; - enqueue_chunking_job?: boolean; - chunking_task_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"]) */ @@ -288,54 +165,6 @@ export interface DataInheritFromParentParams { /* Parent table schema (optional, defaults to same schema as child table) */ parent_schema?: string; } -/** 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; - /* Compound conditions for the trigger WHEN clause. Accepts a single leaf condition, an array of conditions (implicitly AND), or a nested combinator tree ({AND: [...], OR: [...], NOT: {...}}). Each leaf is {field, op, value?, row?, ref?}. Column types are resolved automatically from the table schema. Cannot be combined with condition_field or watch_fields. */ - conditions?: TriggerCondition | TriggerCondition[]; - /* 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; -} -/** Declaratively attaches limit-tracking triggers to a table. On INSERT the named limit is incremented; on DELETE it is decremented. Requires a provisioned limits_module for the target scope. */ -export interface DataLimitCounterParams { - /* Name of the limit to track (must match a default_limits entry, e.g. "projects", "members") */ - limit_name: string; - /* Limit scope: "app" (membership_type=1, user-level) or "org" (membership_type=2, entity-level) */ - scope?: 'app' | 'org'; - /* Column on the target table that holds the actor or entity id used for limit lookup */ - actor_field?: string; - /* Which DML events to attach triggers for */ - events?: ('INSERT' | 'DELETE' | 'UPDATE')[]; -} /** 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 */ @@ -445,6 +274,41 @@ export type TableOrganizationSettingsParams = {}; export type TableUserProfilesParams = {}; /** Creates a user settings table for user-specific configuration. Uses AuthzDirectOwner for access control. */ export type TableUserSettingsParams = {}; +/** + * =========================================================================== + * Limit node type parameters + * =========================================================================== + */ +; +/** Declaratively attaches aggregate limit-tracking triggers to a table. On INSERT the named limit is incremented per entity; on DELETE it is decremented. Uses org_limit_aggregates_inc/dec for per-entity (org-level) aggregate limits rather than per-user limits. Requires a provisioned limits_module for the target database. */ +export interface LimitAggregateParams { + /* Name of the aggregate limit to track (must match a default_limits entry, e.g. "databases", "members") */ + limit_name: string; + /* Column on the target table that holds the entity id for aggregate limit lookup */ + entity_field?: string; + /* Which DML events to attach triggers for */ + events?: ('INSERT' | 'DELETE' | 'UPDATE')[]; +} +/** Gates a table behind a feature flag backed by the cap tables. Attaches a BEFORE INSERT trigger that checks whether the named feature cap value is > 0. Features are modeled as caps with max=0 (disabled) or max=1 (enabled) in limit_caps / limit_caps_defaults tables. Resolution: COALESCE(per-entity cap, scope default, 0). */ +export interface LimitFeatureFlagParams { + /* Cap name representing this feature (must match a limit_caps_defaults entry with max=0 or max=1) */ + feature_name: string; + /* Feature scope: "app" (membership_type=1, app-level caps) or "org" (membership_type=2, per-entity caps) */ + scope?: 'app' | 'org'; + /* Column on the target table that holds the entity id for per-entity cap lookups (only used for org scope) */ + entity_field?: string; +} +/** Declaratively attaches limit-tracking triggers to a table. On INSERT the named limit is incremented; on DELETE it is decremented. Requires a provisioned limits_module for the target scope. */ +export interface LimitCounterParams { + /* Name of the limit to track (must match a default_limits entry, e.g. "projects", "members") */ + limit_name: string; + /* Limit scope: "app" (membership_type=1, user-level) or "org" (membership_type=2, entity-level) */ + scope?: 'app' | 'org'; + /* Column on the target table that holds the actor or entity id used for limit lookup */ + actor_field?: string; + /* Which DML events to attach triggers for */ + events?: ('INSERT' | 'DELETE' | 'UPDATE')[]; +} /** * =========================================================================== * Search node type parameters @@ -606,6 +470,221 @@ export interface SearchVectorParams { /* Task identifier for the chunking job queue */chunking_task_name?: string; }; } +/** + * =========================================================================== + * Job node type parameters + * =========================================================================== + */ +; +/** 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 JobTriggerParams { + /* 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; + /* Compound conditions for the trigger WHEN clause. Accepts a single leaf condition, an array of conditions (implicitly AND), or a nested combinator tree ({AND: [...], OR: [...], NOT: {...}}). Each leaf is {field, op, value?, row?, ref?}. Column types are resolved automatically from the table schema. Cannot be combined with condition_field or watch_fields. */ + conditions?: TriggerCondition | TriggerCondition[]; + /* 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; +} +/** + * =========================================================================== + * Process node type parameters + * =========================================================================== + */ +; +/** Creates a chunked-embedding child table for any parent table. Provisions the chunks table with content, chunk_index, embedding vector, metadata, HNSW index, inherited RLS, and optional job trigger for automatic text splitting. Composed internally by ProcessFileEmbedding (enabled by default in extract mode) but can also be used standalone. */ +export interface ProcessChunksParams { + /* Name of the text content column in the chunks table */ + content_field_name?: string; + /* Maximum number of characters per chunk */ + chunk_size?: number; + /* Number of overlapping characters between consecutive chunks */ + chunk_overlap?: number; + /* Strategy for splitting text into chunks */ + chunk_strategy?: 'fixed' | 'sentence' | 'paragraph' | 'semantic'; + /* Vector dimensions for per-chunk embeddings */ + dimensions?: number; + /* Distance metric for the HNSW index on chunk embeddings */ + metric?: 'cosine' | 'l2' | 'ip'; + /* Override the chunks table name. Defaults to {parent_table}_chunks. */ + chunks_table_name?: string; + /* Field names from the parent table to copy into chunk metadata */ + metadata_fields?: string[]; + /* Whether to create a job trigger that auto-enqueues chunking on parent INSERT/UPDATE */ + enqueue_chunking_job?: boolean; + /* Task identifier for the chunking job queue */ + chunking_task_name?: string; +} +/** Generic, MIME-scoped embedding node for file tables. Supports two modes: direct (whole-file to single vector, e.g. CLIP for images) when extraction is omitted, or extract (file to text to chunks to per-chunk vectors) when extraction config is provided. Composes SearchVector + JobTrigger + ProcessChunks (enabled by default in extract mode) internally. Multiple instances can coexist on the same table with different MIME scopes, field names, and embedding strategies. */ +export interface ProcessFileEmbeddingParams { + /* Name of the vector embedding column */ + field_name?: string; + /* Vector dimensions (e.g. 512 for CLIP, 768 for nomic, 1536 for ada-002) */ + dimensions?: number; + /* Index type for similarity search */ + index_method?: 'hnsw' | 'ivfflat'; + /* Distance metric */ + metric?: 'cosine' | 'l2' | 'ip'; + /* Index-specific options. HNSW: {m, ef_construction}. IVFFlat: {lists}. */ + index_options?: { + [key: string]: unknown; + }; + /* MIME type LIKE patterns to match. Multiple patterns are OR'd together. Examples: ['image/%'], ['application/pdf', 'text/%'], ['audio/%']. */ + mime_patterns?: string[]; + /* Job task identifier for the worker. In direct mode this is the embedding worker; in extract mode this is the extraction worker. */ + task_identifier?: string; + /* Trigger events that fire the job */ + events?: ('INSERT' | 'UPDATE')[]; + /* Custom payload key-to-column mapping for the job trigger */ + payload_custom?: { + [key: string]: unknown; + }; + /* Additional compound conditions beyond MIME filtering. Merged with the auto-generated MIME conditions via AND. Use this to add status checks, field guards, etc. */ + trigger_conditions?: TriggerCondition | TriggerCondition[]; + /* Text extraction configuration. When present, the generator creates extraction output fields on the table and configures SearchVector with source_fields + stale tracking. When absent, the node operates in direct mode (single vector per file, no text extraction). */ + extraction?: { + /* Field to store extracted text/markdown */text_field?: string; + /* JSONB field for extraction metadata (page count, language, etc.) */metadata_field?: string; + }; + /* Whether to create a chunks table via ProcessChunks. Defaults to true when extraction is provided, false in direct mode. Set explicitly to override. */ + include_chunks?: boolean; + /* Chunking configuration passed through to ProcessChunks. When include_chunks is true (or defaults to true in extract mode), these params configure the chunks table, embedding dimensions, strategy, etc. */ + chunks?: { + /* Name of the text content column in the chunks table */content_field_name?: string; + /* Maximum number of characters per chunk */chunk_size?: number; + /* Number of overlapping characters between consecutive chunks */chunk_overlap?: number; + /* Strategy for splitting text into chunks */chunk_strategy?: 'fixed' | 'sentence' | 'paragraph' | 'semantic'; + /* Field names from parent to copy into chunk metadata */metadata_fields?: string[]; + /* Whether to auto-enqueue a chunking job on insert/update */enqueue_chunking_job?: boolean; + /* Task identifier for the chunking job queue */chunking_task_name?: string; + }; +} +/** Image-specific preset of ProcessFileEmbedding. Delegates to ProcessFileEmbedding with image-oriented defaults: dimensions=512 (CLIP), mime_patterns=['image/%'], task_identifier='process_image_embedding', direct mode (no extraction). Accepts all ProcessFileEmbedding parameters — any overrides are forwarded through. */ +export interface ProcessImageEmbeddingParams { + /* Name of the vector embedding column */ + field_name?: string; + /* Vector dimensions (default 512 for CLIP-style image embeddings) */ + dimensions?: number; + /* Index type for similarity search */ + index_method?: 'hnsw' | 'ivfflat'; + /* Distance metric */ + metric?: 'cosine' | 'l2' | 'ip'; + /* Index-specific options. HNSW: {m, ef_construction}. IVFFlat: {lists}. */ + index_options?: { + [key: string]: unknown; + }; + /* MIME type LIKE patterns to match. Multiple patterns are OR'd together. */ + mime_patterns?: string[]; + /* Job task identifier for the image embedding worker */ + task_identifier?: string; + /* Trigger events that fire the job */ + events?: ('INSERT' | 'UPDATE')[]; + /* Custom payload key-to-column mapping for the job trigger */ + payload_custom?: { + [key: string]: unknown; + }; + /* Additional compound conditions beyond MIME filtering. Merged with the auto-generated MIME conditions via AND. */ + trigger_conditions?: TriggerCondition | TriggerCondition[]; + /* Text extraction configuration. Forwarded to ProcessFileEmbedding. When present, enables extract mode (e.g., OCR for images). */ + extraction?: { + /* Field to store extracted text */text_field?: string; + /* JSONB field for extraction metadata */metadata_field?: string; + }; + /* Chunking configuration. Forwarded to ProcessFileEmbedding. Only meaningful when extraction is also provided. */ + chunks?: { + content_field_name?: string; + chunk_size?: number; + chunk_overlap?: number; + chunk_strategy?: 'fixed' | 'sentence' | 'paragraph' | 'semantic'; + metadata_fields?: { + [key: string]: unknown; + }; + enqueue_chunking_job?: boolean; + chunking_task_name?: string; + }; +} +/** Creates extraction output fields and a job trigger for file text extraction. Fires when a file is uploaded (status = 'uploaded') or on INSERT. The external worker extracts text/metadata from the file (PDF, DOCX, HTML, etc.) and writes the result back to the configured output fields. Typically used upstream of ProcessFileEmbedding or ProcessChunks. */ +export interface ProcessExtractionParams { + /* Field to store extracted text/markdown */ + text_field?: string; + /* JSONB field for extraction metadata (page count, language, etc.) */ + metadata_field?: string; + /* MIME type LIKE patterns to match. Multiple patterns are OR'd together. Examples: ['application/pdf', 'text/%'], ['application/vnd.openxmlformats%']. */ + mime_patterns?: string[]; + /* Job task identifier for the extraction worker */ + task_identifier?: string; + /* Trigger events that fire the job */ + events?: ('INSERT' | 'UPDATE')[]; + /* Custom payload key-to-column mapping for the job trigger */ + payload_custom?: { + [key: string]: unknown; + }; + /* Additional compound conditions beyond MIME filtering. Merged with the auto-generated MIME conditions via AND. Use this to add status checks (e.g., status = 'uploaded'). */ + trigger_conditions?: TriggerCondition | TriggerCondition[]; + /* Job queue name for extraction tasks */ + queue_name?: string; + /* Maximum number of retry attempts */ + max_attempts?: number; + /* Job priority (lower = higher priority) */ + priority?: number; +} +/** Creates a job trigger for image variant generation. Fires when an image file is uploaded (status = 'uploaded') or on INSERT. The external worker generates resized, cropped, or reformatted versions (thumbnails, previews, WebP conversions, etc.) and stores them as new file records linked to the source image. */ +export interface ProcessImageVersionsParams { + /* Array of version definitions. Each version specifies dimensions, format, and quality for a generated image variant. Required — the blueprint must explicitly define what variants to generate. */ + versions: { + /* Version identifier (e.g., "thumb", "preview", "hero") */name: string; + /* Target width in pixels */width?: number; + /* Target height in pixels */height?: number; + /* Resize fitting strategy */fit?: 'cover' | 'contain' | 'fill' | 'inside' | 'outside'; + /* Output image format */format?: 'jpeg' | 'png' | 'webp' | 'avif'; + /* Output quality (1-100) */quality?: number; + }[]; + /* MIME type LIKE patterns to match. Defaults to all image types. */ + mime_patterns?: string[]; + /* Job task identifier for the image processing worker */ + task_identifier?: string; + /* Trigger events that fire the job */ + events?: ('INSERT' | 'UPDATE')[]; + /* Custom payload key-to-column mapping for the job trigger */ + payload_custom?: { + [key: string]: unknown; + }; + /* Additional compound conditions beyond MIME filtering. Merged with the auto-generated MIME conditions via AND. */ + trigger_conditions?: TriggerCondition | TriggerCondition[]; + /* Job queue name for image processing tasks */ + queue_name?: string; + /* Maximum number of retry attempts */ + max_attempts?: number; + /* Job priority (lower = higher priority) */ + priority?: number; +} /** * =========================================================================== * Authz node type parameters @@ -1192,7 +1271,7 @@ export interface BlueprintEntityType { */ ; /** String shorthand -- just the node type name. */ -export type BlueprintNodeShorthand = 'AuthzAllowAll' | 'AuthzAppMembership' | 'AuthzComposite' | 'AuthzDenyAll' | 'AuthzFilePath' | 'AuthzDirectOwner' | 'AuthzDirectOwnerAny' | 'AuthzEntityMembership' | 'AuthzMemberList' | 'AuthzNotReadOnly' | 'AuthzOrgHierarchy' | 'AuthzPeerOwnership' | 'AuthzPublishable' | 'AuthzRelatedEntityMembership' | 'AuthzRelatedMemberList' | 'AuthzRelatedPeerOwnership' | 'AuthzTemporal' | 'CheckGreaterThan' | 'CheckLessThan' | 'CheckNotEqual' | 'CheckOneOf' | 'DataAggregateLimitCounter' | 'DataBillingMeter' | 'DataBulk' | 'DataChunks' | 'DataCompositeField' | 'DataDirectOwner' | 'DataEntityMembership' | 'DataFileEmbedding' | 'DataFeatureFlag' | 'DataForceCurrentUser' | 'DataId' | 'DataImageEmbedding' | 'DataImmutableFields' | 'DataInflection' | 'DataInheritFromParent' | 'DataJobTrigger' | 'DataLimitCounter' | 'DataJsonb' | 'DataOwnedFields' | 'DataOwnershipInEntity' | 'DataPeoplestamps' | 'DataPublishable' | 'DataRealtime' | 'DataSlug' | 'DataSoftDelete' | 'DataStatusField' | 'DataTags' | 'DataTimestamps' | 'SearchBm25' | 'SearchFullText' | 'SearchSpatial' | 'SearchSpatialAggregate' | 'SearchTrgm' | 'SearchUnified' | 'SearchVector' | 'TableOrganizationSettings' | 'TableUserProfiles' | 'TableUserSettings'; +export type BlueprintNodeShorthand = 'AuthzAllowAll' | 'AuthzAppMembership' | 'AuthzComposite' | 'AuthzDenyAll' | 'AuthzFilePath' | 'AuthzDirectOwner' | 'AuthzDirectOwnerAny' | 'AuthzEntityMembership' | 'AuthzMemberList' | 'AuthzNotReadOnly' | 'AuthzOrgHierarchy' | 'AuthzPeerOwnership' | 'AuthzPublishable' | 'AuthzRelatedEntityMembership' | 'AuthzRelatedMemberList' | 'AuthzRelatedPeerOwnership' | 'AuthzTemporal' | 'CheckGreaterThan' | 'CheckLessThan' | 'CheckNotEqual' | 'CheckOneOf' | 'LimitAggregate' | 'BillingMeter' | 'DataBulk' | 'ProcessChunks' | 'DataCompositeField' | 'DataDirectOwner' | 'DataEntityMembership' | 'ProcessFileEmbedding' | 'LimitFeatureFlag' | 'DataForceCurrentUser' | 'DataId' | 'ProcessImageEmbedding' | 'DataImmutableFields' | 'DataInflection' | 'DataInheritFromParent' | 'JobTrigger' | 'LimitCounter' | 'DataJsonb' | 'DataOwnedFields' | 'ProcessExtraction' | 'ProcessImageVersions' | 'DataOwnershipInEntity' | 'DataPeoplestamps' | 'DataPublishable' | 'DataRealtime' | 'DataSlug' | 'DataSoftDelete' | 'DataStatusField' | 'DataTags' | 'DataTimestamps' | 'SearchBm25' | 'SearchFullText' | 'SearchSpatial' | 'SearchSpatialAggregate' | 'SearchTrgm' | 'SearchUnified' | 'SearchVector' | 'TableOrganizationSettings' | 'TableUserProfiles' | 'TableUserSettings'; /** Object form -- { $type, data } with typed parameters. */ export type BlueprintNodeObject = { $type: 'AuthzAllowAll'; @@ -1258,17 +1337,17 @@ export type BlueprintNodeObject = { $type: 'CheckOneOf'; data: CheckOneOfParams; } | { - $type: 'DataAggregateLimitCounter'; - data: DataAggregateLimitCounterParams; + $type: 'LimitAggregate'; + data: LimitAggregateParams; } | { - $type: 'DataBillingMeter'; - data: DataBillingMeterParams; + $type: 'BillingMeter'; + data: BillingMeterParams; } | { $type: 'DataBulk'; data: DataBulkParams; } | { - $type: 'DataChunks'; - data: DataChunksParams; + $type: 'ProcessChunks'; + data: ProcessChunksParams; } | { $type: 'DataCompositeField'; data: DataCompositeFieldParams; @@ -1279,11 +1358,11 @@ export type BlueprintNodeObject = { $type: 'DataEntityMembership'; data: DataEntityMembershipParams; } | { - $type: 'DataFileEmbedding'; - data: DataFileEmbeddingParams; + $type: 'ProcessFileEmbedding'; + data: ProcessFileEmbeddingParams; } | { - $type: 'DataFeatureFlag'; - data: DataFeatureFlagParams; + $type: 'LimitFeatureFlag'; + data: LimitFeatureFlagParams; } | { $type: 'DataForceCurrentUser'; data: DataForceCurrentUserParams; @@ -1291,8 +1370,8 @@ export type BlueprintNodeObject = { $type: 'DataId'; data: DataIdParams; } | { - $type: 'DataImageEmbedding'; - data: DataImageEmbeddingParams; + $type: 'ProcessImageEmbedding'; + data: ProcessImageEmbeddingParams; } | { $type: 'DataImmutableFields'; data: DataImmutableFieldsParams; @@ -1303,17 +1382,23 @@ export type BlueprintNodeObject = { $type: 'DataInheritFromParent'; data: DataInheritFromParentParams; } | { - $type: 'DataJobTrigger'; - data: DataJobTriggerParams; + $type: 'JobTrigger'; + data: JobTriggerParams; } | { - $type: 'DataLimitCounter'; - data: DataLimitCounterParams; + $type: 'LimitCounter'; + data: LimitCounterParams; } | { $type: 'DataJsonb'; data: DataJsonbParams; } | { $type: 'DataOwnedFields'; data: DataOwnedFieldsParams; +} | { + $type: 'ProcessExtraction'; + data: ProcessExtractionParams; +} | { + $type: 'ProcessImageVersions'; + data: ProcessImageVersionsParams; } | { $type: 'DataOwnershipInEntity'; data: DataOwnershipInEntityParams; diff --git a/packages/node-type-registry/src/codegen/generate-types.ts b/packages/node-type-registry/src/codegen/generate-types.ts index 4f93933ac..a95b6f5a4 100644 --- a/packages/node-type-registry/src/codegen/generate-types.ts +++ b/packages/node-type-registry/src/codegen/generate-types.ts @@ -1139,7 +1139,7 @@ function buildProgram(meta?: MetaTableInfo[]): string { statements.push(buildTriggerConditionInterface()); // -- Parameter interfaces grouped by category -- - const categoryOrder = ['check', 'data', 'search', 'authz', 'relation', 'view']; + const categoryOrder = ['billing', 'check', 'data', 'limit', 'search', 'job', 'process', 'authz', 'relation', 'view']; for (const cat of categoryOrder) { const nts = categories.get(cat); if (!nts || nts.length === 0) continue; diff --git a/packages/node-type-registry/src/data/data-aggregate-limit-counter.ts b/packages/node-type-registry/src/data/data-aggregate-limit-counter.ts index 0b9ba25ab..2a0822732 100644 --- a/packages/node-type-registry/src/data/data-aggregate-limit-counter.ts +++ b/packages/node-type-registry/src/data/data-aggregate-limit-counter.ts @@ -1,9 +1,9 @@ import type { NodeTypeDefinition } from '../types'; -export const DataAggregateLimitCounter: NodeTypeDefinition = { - name: 'DataAggregateLimitCounter', +export const LimitAggregate: NodeTypeDefinition = { + name: 'LimitAggregate', slug: 'data_aggregate_limit_counter', - category: 'data', + category: 'limit', display_name: 'Aggregate Limit Counter', description: 'Declaratively attaches aggregate limit-tracking triggers to a table. On INSERT the named limit is incremented per entity; on DELETE it is decremented. Uses org_limit_aggregates_inc/dec for per-entity (org-level) aggregate limits rather than per-user limits. Requires a provisioned limits_module for the target database.', diff --git a/packages/node-type-registry/src/data/data-billing-meter.ts b/packages/node-type-registry/src/data/data-billing-meter.ts index e03e45642..5e8b979f9 100644 --- a/packages/node-type-registry/src/data/data-billing-meter.ts +++ b/packages/node-type-registry/src/data/data-billing-meter.ts @@ -1,9 +1,9 @@ import type { NodeTypeDefinition } from '../types'; -export const DataBillingMeter: NodeTypeDefinition = { - name: 'DataBillingMeter', +export const BillingMeter: NodeTypeDefinition = { + name: 'BillingMeter', slug: 'data_billing_meter', - category: 'data', + category: 'billing', display_name: 'Billing Meter', description: 'Declaratively attaches billing usage-recording triggers to a table. On INSERT the named meter is incremented via record_usage; on DELETE it is decremented (reversal). On UPDATE, if the entity_field changes, the old entity is decremented and the new entity is incremented. Requires a provisioned billing_module for the target database.', diff --git a/packages/node-type-registry/src/data/data-chunks.ts b/packages/node-type-registry/src/data/data-chunks.ts index 9e89d56e1..6305a1a88 100644 --- a/packages/node-type-registry/src/data/data-chunks.ts +++ b/packages/node-type-registry/src/data/data-chunks.ts @@ -12,20 +12,20 @@ import type { NodeTypeDefinition } from '../types'; * - RLS policies inherited from parent * - Optional job trigger for automatic chunking on INSERT/UPDATE * - * This node is also composed internally by DataFileEmbedding (enabled by + * This node is also composed internally by ProcessFileEmbedding (enabled by * default in extract mode). Use it standalone when you want a chunks table * without the full file-embedding pipeline. */ -export const DataChunks: NodeTypeDefinition = { - name: 'DataChunks', +export const ProcessChunks: NodeTypeDefinition = { + name: 'ProcessChunks', slug: 'data_chunks', - category: 'data', + category: 'process', display_name: 'Chunks', description: 'Creates a chunked-embedding child table for any parent table. ' + 'Provisions the chunks table with content, chunk_index, embedding vector, ' + 'metadata, HNSW index, inherited RLS, and optional job trigger for ' + - 'automatic text splitting. Composed internally by DataFileEmbedding ' + + 'automatic text splitting. Composed internally by ProcessFileEmbedding ' + '(enabled by default in extract mode) but can also be used standalone.', parameter_schema: { type: 'object', diff --git a/packages/node-type-registry/src/data/data-feature-flag.ts b/packages/node-type-registry/src/data/data-feature-flag.ts index bd31de956..e96517382 100644 --- a/packages/node-type-registry/src/data/data-feature-flag.ts +++ b/packages/node-type-registry/src/data/data-feature-flag.ts @@ -1,9 +1,9 @@ import type { NodeTypeDefinition } from '../types'; -export const DataFeatureFlag: NodeTypeDefinition = { - name: 'DataFeatureFlag', +export const LimitFeatureFlag: NodeTypeDefinition = { + name: 'LimitFeatureFlag', slug: 'data_feature_flag', - category: 'data', + category: 'limit', display_name: 'Feature Flag', description: 'Gates a table behind a feature flag backed by the cap tables. Attaches a BEFORE INSERT trigger that checks whether the named feature cap value is > 0. Features are modeled as caps with max=0 (disabled) or max=1 (enabled) in limit_caps / limit_caps_defaults tables. Resolution: COALESCE(per-entity cap, scope default, 0).', diff --git a/packages/node-type-registry/src/data/data-file-embedding.ts b/packages/node-type-registry/src/data/data-file-embedding.ts index e57deaf4e..2f91d9f22 100644 --- a/packages/node-type-registry/src/data/data-file-embedding.ts +++ b/packages/node-type-registry/src/data/data-file-embedding.ts @@ -1,16 +1,16 @@ import type { NodeTypeDefinition } from '../types'; -export const DataFileEmbedding: NodeTypeDefinition = { - name: 'DataFileEmbedding', +export const ProcessFileEmbedding: NodeTypeDefinition = { + name: 'ProcessFileEmbedding', slug: 'data_file_embedding', - category: 'data', + category: 'process', display_name: 'File Embedding', description: 'Generic, MIME-scoped embedding node for file tables. Supports two modes: ' + 'direct (whole-file to single vector, e.g. CLIP for images) when extraction ' + 'is omitted, or extract (file to text to chunks to per-chunk vectors) when ' + - 'extraction config is provided. Composes SearchVector + DataJobTrigger + ' + - 'DataChunks (enabled by default in extract mode) internally. Multiple ' + + 'extraction config is provided. Composes SearchVector + JobTrigger + ' + + 'ProcessChunks (enabled by default in extract mode) internally. Multiple ' + 'instances can coexist on the same table with different MIME scopes, field ' + 'names, and embedding strategies.', parameter_schema: { @@ -122,14 +122,14 @@ export const DataFileEmbedding: NodeTypeDefinition = { include_chunks: { type: 'boolean', description: - 'Whether to create a chunks table via DataChunks. Defaults to true ' + + 'Whether to create a chunks table via ProcessChunks. Defaults to true ' + 'when extraction is provided, false in direct mode. Set explicitly ' + 'to override.', }, chunks: { type: 'object', description: - 'Chunking configuration passed through to DataChunks. When ' + + 'Chunking configuration passed through to ProcessChunks. When ' + 'include_chunks is true (or defaults to true in extract mode), these ' + 'params configure the chunks table, embedding dimensions, strategy, etc.', properties: { diff --git a/packages/node-type-registry/src/data/data-image-embedding.ts b/packages/node-type-registry/src/data/data-image-embedding.ts index f9905850b..e562d74f9 100644 --- a/packages/node-type-registry/src/data/data-image-embedding.ts +++ b/packages/node-type-registry/src/data/data-image-embedding.ts @@ -1,32 +1,32 @@ import type { NodeTypeDefinition } from '../types'; /** - * Image-specific preset of DataFileEmbedding. + * Image-specific preset of ProcessFileEmbedding. * * At the SQL layer, data_image_embedding delegates entirely to * data_file_embedding, merging image-specific defaults before forwarding. - * The parameter schema here is intentionally identical to DataFileEmbedding; + * The parameter schema here is intentionally identical to ProcessFileEmbedding; * only the defaults differ (dimensions: 512, task: process_image_embedding, * mime_patterns: ['image/%']). * * Kept as a separate node type for backward compatibility — existing - * blueprints that reference DataImageEmbedding continue to work unchanged. + * blueprints that reference ProcessImageEmbedding continue to work unchanged. */ -export const DataImageEmbedding: NodeTypeDefinition = { - name: 'DataImageEmbedding', +export const ProcessImageEmbedding: NodeTypeDefinition = { + name: 'ProcessImageEmbedding', slug: 'data_image_embedding', - category: 'data', + category: 'process', display_name: 'Image Embedding', description: - 'Image-specific preset of DataFileEmbedding. Delegates to DataFileEmbedding ' + + 'Image-specific preset of ProcessFileEmbedding. Delegates to ProcessFileEmbedding ' + 'with image-oriented defaults: dimensions=512 (CLIP), mime_patterns=[\'image/%\'], ' + 'task_identifier=\'process_image_embedding\', direct mode (no extraction). ' + - 'Accepts all DataFileEmbedding parameters — any overrides are forwarded through.', + 'Accepts all ProcessFileEmbedding parameters — any overrides are forwarded through.', parameter_schema: { type: 'object', properties: { - // ── Vector config (passed through to DataFileEmbedding) ────────── + // ── Vector config (passed through to ProcessFileEmbedding) ────────── field_name: { type: 'string', format: 'column-ref', @@ -103,7 +103,7 @@ export const DataImageEmbedding: NodeTypeDefinition = { extraction: { type: 'object', description: - 'Text extraction configuration. Forwarded to DataFileEmbedding. ' + + 'Text extraction configuration. Forwarded to ProcessFileEmbedding. ' + 'When present, enables extract mode (e.g., OCR for images).', properties: { text_field: { @@ -121,11 +121,11 @@ export const DataImageEmbedding: NodeTypeDefinition = { } }, - // ── Chunking config (optional — forwarded to DataFileEmbedding) ─ + // ── Chunking config (optional — forwarded to ProcessFileEmbedding) ─ chunks: { type: 'object', description: - 'Chunking configuration. Forwarded to DataFileEmbedding. ' + + 'Chunking configuration. Forwarded to ProcessFileEmbedding. ' + 'Only meaningful when extraction is also provided.', properties: { content_field_name: { diff --git a/packages/node-type-registry/src/data/data-job-trigger.ts b/packages/node-type-registry/src/data/data-job-trigger.ts index 490b7d640..b7ceb1554 100644 --- a/packages/node-type-registry/src/data/data-job-trigger.ts +++ b/packages/node-type-registry/src/data/data-job-trigger.ts @@ -26,10 +26,10 @@ const triggerConditionSchema = { } }; -export const DataJobTrigger: NodeTypeDefinition = { - name: 'DataJobTrigger', +export const JobTrigger: NodeTypeDefinition = { + name: 'JobTrigger', slug: 'data_job_trigger', - category: 'data', + category: 'job', display_name: 'Job Trigger', description: '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).', parameter_schema: { diff --git a/packages/node-type-registry/src/data/data-limit-counter.ts b/packages/node-type-registry/src/data/data-limit-counter.ts index 9ee48a058..4d7d9ea76 100644 --- a/packages/node-type-registry/src/data/data-limit-counter.ts +++ b/packages/node-type-registry/src/data/data-limit-counter.ts @@ -1,9 +1,9 @@ import type { NodeTypeDefinition } from '../types'; -export const DataLimitCounter: NodeTypeDefinition = { - name: 'DataLimitCounter', +export const LimitCounter: NodeTypeDefinition = { + name: 'LimitCounter', slug: 'data_limit_counter', - category: 'data', + category: 'limit', display_name: 'Limit Counter', description: 'Declaratively attaches limit-tracking triggers to a table. On INSERT the named limit is incremented; on DELETE it is decremented. Requires a provisioned limits_module for the target scope.', diff --git a/packages/node-type-registry/src/data/index.ts b/packages/node-type-registry/src/data/index.ts index 9edbe8103..6cdeab7b8 100644 --- a/packages/node-type-registry/src/data/index.ts +++ b/packages/node-type-registry/src/data/index.ts @@ -2,25 +2,27 @@ export { CheckGreaterThan } from './check-greater-than'; export { CheckLessThan } from './check-less-than'; export { CheckNotEqual } from './check-not-equal'; export { CheckOneOf } from './check-one-of'; -export { DataAggregateLimitCounter } from './data-aggregate-limit-counter'; -export { DataBillingMeter } from './data-billing-meter'; +export { LimitAggregate } from './data-aggregate-limit-counter'; +export { BillingMeter } from './data-billing-meter'; export { DataBulk } from './data-bulk'; -export { DataChunks } from './data-chunks'; +export { ProcessChunks } from './data-chunks'; export { DataCompositeField } from './data-composite-field'; export { DataDirectOwner } from './data-direct-owner'; export { DataEntityMembership } from './data-entity-membership'; -export { DataFileEmbedding } from './data-file-embedding'; -export { DataFeatureFlag } from './data-feature-flag'; +export { ProcessFileEmbedding } from './data-file-embedding'; +export { LimitFeatureFlag } from './data-feature-flag'; export { DataForceCurrentUser } from './data-force-current-user'; export { DataId } from './data-id'; -export { DataImageEmbedding } from './data-image-embedding'; +export { ProcessImageEmbedding } from './data-image-embedding'; export { DataImmutableFields } from './data-immutable-fields'; export { DataInflection } from './data-inflection'; export { DataInheritFromParent } from './data-inherit-from-parent'; -export { DataJobTrigger } from './data-job-trigger'; -export { DataLimitCounter } from './data-limit-counter'; +export { JobTrigger } from './data-job-trigger'; +export { LimitCounter } from './data-limit-counter'; export { DataJsonb } from './data-jsonb'; export { DataOwnedFields } from './data-owned-fields'; +export { ProcessExtraction } from './process-extraction'; +export { ProcessImageVersions } from './process-image-versions'; export { DataOwnershipInEntity } from './data-ownership-in-entity'; export { DataPeoplestamps } from './data-peoplestamps'; export { DataPublishable } from './data-publishable'; diff --git a/packages/node-type-registry/src/data/process-extraction.ts b/packages/node-type-registry/src/data/process-extraction.ts new file mode 100644 index 000000000..2b73276fd --- /dev/null +++ b/packages/node-type-registry/src/data/process-extraction.ts @@ -0,0 +1,114 @@ +import type { NodeTypeDefinition } from '../types'; + +/** + * File extraction processing node. + * + * Composes a JobTrigger that fires when a file transitions to status = 'uploaded' + * (or on INSERT if confirm_upload is not enabled). The trigger enqueues a + * text-extraction job that converts the file contents (PDF, DOCX, HTML, etc.) + * into plain text or markdown, storing the result in configurable output fields. + * + * The extraction worker is external (Knative function) — this node only creates + * the trigger infrastructure and output fields. The worker calls back into the + * database to write extracted text and metadata. + */ +export const ProcessExtraction: NodeTypeDefinition = { + name: 'ProcessExtraction', + slug: 'process_extraction', + category: 'process', + display_name: 'File Extraction', + description: + 'Creates extraction output fields and a job trigger for file text extraction. ' + + 'Fires when a file is uploaded (status = \'uploaded\') or on INSERT. ' + + 'The external worker extracts text/metadata from the file (PDF, DOCX, HTML, etc.) ' + + 'and writes the result back to the configured output fields. ' + + 'Typically used upstream of ProcessFileEmbedding or ProcessChunks.', + parameter_schema: { + type: 'object', + properties: { + + // ── Output fields ───────────────────────────────────────────── + text_field: { + type: 'string', + format: 'column-ref', + description: 'Field to store extracted text/markdown', + default: 'extracted_text' + }, + metadata_field: { + type: 'string', + format: 'column-ref', + description: 'JSONB field for extraction metadata (page count, language, etc.)', + default: 'extracted_metadata' + }, + + // ── MIME scoping ────────────────────────────────────────────── + mime_patterns: { + type: 'array', + items: { type: 'string' }, + description: + 'MIME type LIKE patterns to match. Multiple patterns are OR\'d together. ' + + 'Examples: [\'application/pdf\', \'text/%\'], [\'application/vnd.openxmlformats%\'].', + default: ['application/pdf', 'text/%'] + }, + + // ── Job routing ─────────────────────────────────────────────── + task_identifier: { + type: 'string', + description: 'Job task identifier for the extraction worker', + default: 'extract_file_text' + }, + events: { + type: 'array', + items: { type: 'string', enum: ['INSERT', 'UPDATE'] }, + description: 'Trigger events that fire the job', + default: ['INSERT'] + }, + payload_custom: { + type: 'object', + additionalProperties: { type: 'string', format: 'column-ref' }, + description: 'Custom payload key-to-column mapping for the job trigger', + default: { + file_id: 'id', + key: 'key', + mime_type: 'mime_type', + bucket_id: 'bucket_id' + } + }, + trigger_conditions: { + description: + 'Additional compound conditions beyond MIME filtering. ' + + 'Merged with the auto-generated MIME conditions via AND. ' + + 'Use this to add status checks (e.g., status = \'uploaded\').', + 'x-codegen-type': 'TriggerCondition | TriggerCondition[]', + oneOf: [ + { $ref: '#/$defs/triggerCondition' }, + { type: 'array', items: { $ref: '#/$defs/triggerCondition' } } + ] + }, + + // ── Job options ─────────────────────────────────────────────── + queue_name: { + type: 'string', + description: 'Job queue name for extraction tasks', + default: 'extraction' + }, + max_attempts: { + type: 'integer', + description: 'Maximum number of retry attempts', + default: 5 + }, + priority: { + type: 'integer', + description: 'Job priority (lower = higher priority)', + default: 0 + } + } + }, + tags: [ + 'extraction', + 'files', + 'processing', + 'jobs', + 'text' + ] +}; diff --git a/packages/node-type-registry/src/data/process-image-versions.ts b/packages/node-type-registry/src/data/process-image-versions.ts new file mode 100644 index 000000000..7ab9b1426 --- /dev/null +++ b/packages/node-type-registry/src/data/process-image-versions.ts @@ -0,0 +1,145 @@ +import type { NodeTypeDefinition } from '../types'; + +/** + * Image version processing node. + * + * Composes a JobTrigger that fires when an image file transitions to + * status = 'uploaded' (or on INSERT if confirm_upload is not enabled). + * The trigger enqueues an image-processing job that generates resized, + * cropped, or reformatted variants of the source image. + * + * The image processing worker is external (Knative function) — this node + * only creates the trigger infrastructure. The worker generates the variants + * and writes them back to the storage system as new file records linked to + * the source file. + */ +export const ProcessImageVersions: NodeTypeDefinition = { + name: 'ProcessImageVersions', + slug: 'process_image_versions', + category: 'process', + display_name: 'Image Versions', + description: + 'Creates a job trigger for image variant generation. ' + + 'Fires when an image file is uploaded (status = \'uploaded\') or on INSERT. ' + + 'The external worker generates resized, cropped, or reformatted versions ' + + '(thumbnails, previews, WebP conversions, etc.) and stores them as new ' + + 'file records linked to the source image.', + parameter_schema: { + type: 'object', + required: ['versions'], + properties: { + + // ── Version definitions ─────────────────────────────────────── + versions: { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string', + description: 'Version identifier (e.g., "thumb", "preview", "hero")' + }, + width: { + type: 'integer', + description: 'Target width in pixels' + }, + height: { + type: 'integer', + description: 'Target height in pixels' + }, + fit: { + type: 'string', + enum: ['cover', 'contain', 'fill', 'inside', 'outside'], + description: 'Resize fitting strategy', + default: 'cover' + }, + format: { + type: 'string', + enum: ['jpeg', 'png', 'webp', 'avif'], + description: 'Output image format', + default: 'webp' + }, + quality: { + type: 'integer', + description: 'Output quality (1-100)', + default: 80 + } + }, + required: ['name'] + }, + description: + 'Array of version definitions. Each version specifies dimensions, ' + + 'format, and quality for a generated image variant. ' + + 'Required — the blueprint must explicitly define what variants to generate.', + minItems: 1 + }, + + // ── MIME scoping ────────────────────────────────────────────── + mime_patterns: { + type: 'array', + items: { type: 'string' }, + description: 'MIME type LIKE patterns to match. Defaults to all image types.', + default: ['image/%'] + }, + + // ── Job routing ─────────────────────────────────────────────── + task_identifier: { + type: 'string', + description: 'Job task identifier for the image processing worker', + default: 'process_image_versions' + }, + events: { + type: 'array', + items: { type: 'string', enum: ['INSERT', 'UPDATE'] }, + description: 'Trigger events that fire the job', + default: ['INSERT'] + }, + payload_custom: { + type: 'object', + additionalProperties: { type: 'string', format: 'column-ref' }, + description: 'Custom payload key-to-column mapping for the job trigger', + default: { + file_id: 'id', + key: 'key', + mime_type: 'mime_type', + bucket_id: 'bucket_id' + } + }, + trigger_conditions: { + description: + 'Additional compound conditions beyond MIME filtering. ' + + 'Merged with the auto-generated MIME conditions via AND.', + 'x-codegen-type': 'TriggerCondition | TriggerCondition[]', + oneOf: [ + { $ref: '#/$defs/triggerCondition' }, + { type: 'array', items: { $ref: '#/$defs/triggerCondition' } } + ] + }, + + // ── Job options ─────────────────────────────────────────────── + queue_name: { + type: 'string', + description: 'Job queue name for image processing tasks', + default: 'image_processing' + }, + max_attempts: { + type: 'integer', + description: 'Maximum number of retry attempts', + default: 5 + }, + priority: { + type: 'integer', + description: 'Job priority (lower = higher priority)', + default: 0 + } + } + }, + tags: [ + 'images', + 'processing', + 'jobs', + 'resize', + 'thumbnails', + 'files' + ] +};