@hostwebhook/node-types 1.20.0 → 1.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,12 @@
1
1
  /**
2
2
  * API dispatch config — service names, collection names, filter support.
3
3
  * Only imported by the API. Broker and Dashboard don't need this.
4
+ *
5
+ * `pipelineDispatch` is required by the type system so a new node type
6
+ * cannot be added without picking a dispatch shape — the api derives
7
+ * its loop directly from this field, so forgetting it would silently
8
+ * orphan the node (the symptom Vector Store / AI / Markdown / Code /
9
+ * File Transform all hit before this refactor).
4
10
  */
5
11
  import type { NodeType, NodeDispatchConfig } from './types';
6
12
  export declare const NODE_DISPATCH: Record<NodeType, NodeDispatchConfig>;
package/dist/dispatch.js CHANGED
@@ -2,50 +2,57 @@
2
2
  /**
3
3
  * API dispatch config — service names, collection names, filter support.
4
4
  * Only imported by the API. Broker and Dashboard don't need this.
5
+ *
6
+ * `pipelineDispatch` is required by the type system so a new node type
7
+ * cannot be added without picking a dispatch shape — the api derives
8
+ * its loop directly from this field, so forgetting it would silently
9
+ * orphan the node (the symptom Vector Store / AI / Markdown / Code /
10
+ * File Transform all hit before this refactor).
5
11
  */
6
12
  Object.defineProperty(exports, "__esModule", { value: true });
7
13
  exports.NODE_DISPATCH = void 0;
8
14
  exports.getAllNodeCollections = getAllNodeCollections;
9
15
  exports.getNodeDispatchConfig = getNodeDispatchConfig;
10
16
  exports.NODE_DISPATCH = {
11
- // ── Pipeline processing (generic dispatch) ──
12
- filter: { service: 'filterNodesService', collection: 'filternodes', hasFilters: true, outputFields: ['outputNodes'], customDispatch: false },
13
- transform: { service: 'transformNodesService', collection: 'transformnodes', hasFilters: false, outputFields: ['outputNodes'], customDispatch: false },
14
- schemaValidator: { service: 'schemaValidatorsService', collection: 'schemavalidators', hasFilters: false, outputFields: ['outputNodes', 'invalidOutputNodes'], customDispatch: true },
15
- delay: { service: 'delayNodesService', collection: 'delaynodes', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true },
16
- rateLimiter: { service: 'rateLimiterNodesService', collection: 'ratelimiternodes', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true },
17
- aggregator: { service: 'aggregatorNodesService', collection: 'aggregatornodes', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true },
18
- cache: { service: 'cacheNodesService', collection: 'cachenodes', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true },
19
- code: { service: 'codeNodesService', collection: 'codenodes', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true },
20
- ai: { service: 'aiNodesService', collection: 'ainodes', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true },
21
- // ── Flow control ──
22
- split: { service: 'splitNodesService', collection: 'splitnodes', hasFilters: false, outputFields: ['outputNodes', 'remainderOutputNodes'], customDispatch: true },
23
- conditional: { service: 'conditionalNodesService', collection: 'conditionalnodes', hasFilters: false, outputFields: ['outputNodes', 'elseOutputNodes'], customDispatch: true },
24
- merge: { service: 'mergeNodesService', collection: 'mergenodes', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true },
25
- approval: { service: 'approvalNodesService', collection: 'approvalnodes', hasFilters: false, outputFields: ['outputNodes', 'rejectionOutputNodes'], customDispatch: true },
26
- loop: { service: 'loopNodesService', collection: 'loopnodes', hasFilters: false, outputFields: ['loopOutputNodes', 'doneOutputNodes'], customDispatch: true },
27
- // ── Routing ──
28
- router: { service: 'routersService', collection: 'routers', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true },
29
- // ── Action nodes ──
30
- emailAction: { service: 'emailActionsService', collection: 'emailactions', hasFilters: true, outputFields: [], customDispatch: true },
31
- httpAction: { service: 'httpActionsService', collection: 'httpactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true },
32
- mongoAction: { service: 'mongoActionsService', collection: 'mongoactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true },
33
- notificationAction: { service: 'notificationActionsService', collection: 'notificationactions', hasFilters: true, outputFields: [], customDispatch: true },
34
- sheetsAction: { service: 'sheetsActionsService', collection: 'sheetsactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true },
35
- calendarAction: { service: 'calendarActionsService', collection: 'calendaractions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true },
36
- docsAction: { service: 'docsActionsService', collection: 'docsactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true },
37
- firecrawlAction: { service: 'firecrawlActionsService', collection: 'firecrawlactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true },
38
- vectorStore: { service: 'vectorStoreNodesService', collection: 'vectorstorenodes', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true },
39
- markdown: { service: 'markdownNodesService', collection: 'markdownnodes', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true },
40
- fileTransform: { service: 'fileTransformNodesService', collection: 'filetransformnodes', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true },
41
- // ── Source + monitoring ──
42
- alert: { service: 'alertService', collection: 'alerts', hasFilters: false, outputFields: [], customDispatch: true },
43
- endpoint: { service: 'endpointsService', collection: 'endpoints', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true },
44
- scheduledWebhook: { service: 'scheduledWebhooksService', collection: 'scheduledwebhooks', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true },
45
- chatTrigger: { service: 'chatTriggersService', collection: 'chattriggers', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true },
46
- serviceTrigger: { service: 'serviceTriggersService', collection: 'servicetriggers', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true },
47
- // ── Annotations ──
48
- stickyNote: { service: 'stickyNotesService', collection: 'stickynotes', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true },
17
+ // ── Pipeline processing — generic dispatch off endpoint ──
18
+ filter: { service: 'filterNodesService', collection: 'filternodes', hasFilters: true, outputFields: ['outputNodes'], customDispatch: false, pipelineDispatch: 'generic' },
19
+ transform: { service: 'transformNodesService', collection: 'transformnodes', hasFilters: false, outputFields: ['outputNodes'], customDispatch: false, pipelineDispatch: 'generic' },
20
+ code: { service: 'codeNodesService', collection: 'codenodes', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'generic' },
21
+ ai: { service: 'aiNodesService', collection: 'ainodes', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'generic' },
22
+ markdown: { service: 'markdownNodesService', collection: 'markdownnodes', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'generic' },
23
+ fileTransform: { service: 'fileTransformNodesService', collection: 'filetransformnodes', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'generic' },
24
+ vectorStore: { service: 'vectorStoreNodesService', collection: 'vectorstorenodes', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'generic' },
25
+ // ── Pipeline processing — custom dispatch (dedicated switch case) ──
26
+ schemaValidator: { service: 'schemaValidatorsService', collection: 'schemavalidators', hasFilters: false, outputFields: ['outputNodes', 'invalidOutputNodes'], customDispatch: true, pipelineDispatch: 'custom' },
27
+ delay: { service: 'delayNodesService', collection: 'delaynodes', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'custom' },
28
+ rateLimiter: { service: 'rateLimiterNodesService', collection: 'ratelimiternodes', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'custom' },
29
+ aggregator: { service: 'aggregatorNodesService', collection: 'aggregatornodes', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'custom' },
30
+ cache: { service: 'cacheNodesService', collection: 'cachenodes', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'custom' },
31
+ // ── Flow control — custom dispatch (branching / merging / loops) ──
32
+ split: { service: 'splitNodesService', collection: 'splitnodes', hasFilters: false, outputFields: ['outputNodes', 'remainderOutputNodes'], customDispatch: true, pipelineDispatch: 'custom' },
33
+ conditional: { service: 'conditionalNodesService', collection: 'conditionalnodes', hasFilters: false, outputFields: ['outputNodes', 'elseOutputNodes'], customDispatch: true, pipelineDispatch: 'custom' },
34
+ merge: { service: 'mergeNodesService', collection: 'mergenodes', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'custom' },
35
+ approval: { service: 'approvalNodesService', collection: 'approvalnodes', hasFilters: false, outputFields: ['outputNodes', 'rejectionOutputNodes'], customDispatch: true, pipelineDispatch: 'custom' },
36
+ loop: { service: 'loopNodesService', collection: 'loopnodes', hasFilters: false, outputFields: ['loopOutputNodes', 'doneOutputNodes'], customDispatch: true, pipelineDispatch: 'custom' },
37
+ // ── Routing — custom dispatch ──
38
+ router: { service: 'routersService', collection: 'routers', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'custom' },
39
+ // ── Action nodes — fired in onDeliveryResult, excluded from endpoint dispatch ──
40
+ emailAction: { service: 'emailActionsService', collection: 'emailactions', hasFilters: true, outputFields: [], customDispatch: true, pipelineDispatch: 'excluded' },
41
+ httpAction: { service: 'httpActionsService', collection: 'httpactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded' },
42
+ mongoAction: { service: 'mongoActionsService', collection: 'mongoactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded' },
43
+ notificationAction: { service: 'notificationActionsService', collection: 'notificationactions', hasFilters: true, outputFields: [], customDispatch: true, pipelineDispatch: 'excluded' },
44
+ sheetsAction: { service: 'sheetsActionsService', collection: 'sheetsactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded' },
45
+ calendarAction: { service: 'calendarActionsService', collection: 'calendaractions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded' },
46
+ docsAction: { service: 'docsActionsService', collection: 'docsactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded' },
47
+ firecrawlAction: { service: 'firecrawlActionsService', collection: 'firecrawlactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded' },
48
+ // ── Sources — start the flow themselves, not dispatched ──
49
+ endpoint: { service: 'endpointsService', collection: 'endpoints', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded' },
50
+ scheduledWebhook: { service: 'scheduledWebhooksService', collection: 'scheduledwebhooks', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded' },
51
+ chatTrigger: { service: 'chatTriggersService', collection: 'chattriggers', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded' },
52
+ serviceTrigger: { service: 'serviceTriggersService', collection: 'servicetriggers', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded' },
53
+ // ── Monitoring + annotation — never executed in pipeline ──
54
+ alert: { service: 'alertService', collection: 'alerts', hasFilters: false, outputFields: [], customDispatch: true, pipelineDispatch: 'excluded' },
55
+ stickyNote: { service: 'stickyNotesService', collection: 'stickynotes', hasFilters: false, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded' },
49
56
  };
50
57
  /** Get all MongoDB collection names for cascade cleanup */
51
58
  function getAllNodeCollections() {
package/dist/types.d.ts CHANGED
@@ -72,13 +72,43 @@ export interface NodeUIConfig {
72
72
  loopBackAllowed?: boolean;
73
73
  };
74
74
  }
75
+ /**
76
+ * How the event pipeline routes a payload to this node when an
77
+ * upstream endpoint connects to it directly. Required so adding a
78
+ * new node type at compile time is impossible without picking one.
79
+ *
80
+ * - 'generic': dispatchConnectedNodes loops findActiveByInputEndpoint
81
+ * on the service and dispatches every active match. Use for
82
+ * pipeline-style nodes that ingest endpoint payloads (filter,
83
+ * transform, ai, code, markdown, fileTransform, vectorStore).
84
+ *
85
+ * - 'custom': has a dedicated `case` in the dispatchOutputNodes
86
+ * switch that calls the node's specific service method. Used
87
+ * when the node needs scheduling, branching, gating, or queueing
88
+ * (delay, cache, aggregator, rateLimiter, conditional, split,
89
+ * loop, merge, approval, schemaValidator, router). The generic
90
+ * loop must NOT process these — would dispatch twice.
91
+ *
92
+ * - 'excluded': not dispatched in the endpoint flow at all. Action
93
+ * nodes (email/http/mongo/notification/sheets/calendar/docs/
94
+ * firecrawl) are fired post-delivery in onDeliveryResult with
95
+ * their own loops; ingress nodes (endpoint/scheduledWebhook/
96
+ * chatTrigger/serviceTrigger) start the flow themselves; alerts
97
+ * are observability-only; stickyNote is purely visual.
98
+ */
99
+ export type PipelineDispatchKind = 'generic' | 'custom' | 'excluded';
75
100
  /** API dispatch config — how the event pipeline processes each node */
76
101
  export interface NodeDispatchConfig {
77
102
  service: string;
78
103
  collection: string;
79
104
  hasFilters: boolean;
80
105
  outputFields: string[];
106
+ /** @deprecated Use `pipelineDispatch` instead. Kept for backwards compat
107
+ * during the migration; will be removed once every consumer reads
108
+ * `pipelineDispatch`. */
81
109
  customDispatch: boolean;
110
+ /** Required. See PipelineDispatchKind for the contract per value. */
111
+ pipelineDispatch: PipelineDispatchKind;
82
112
  }
83
113
  /** Standardized payload metadata — every node output MUST include _meta */
84
114
  export interface PayloadMeta {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hostwebhook/node-types",
3
- "version": "1.20.0",
3
+ "version": "1.21.0",
4
4
  "description": "Shared node type definitions, connection rules, and dispatch config for HostWebhook",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",