@octaviaflow/flow-rules 0.9.0 → 0.10.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.
- package/dist/catalog/triggers/connector-trigger/events.d.ts +46 -0
- package/dist/index.cjs +125 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +125 -1
- package/package.json +2 -2
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a Connector Trigger can subscribe to, per connector.
|
|
3
|
+
*
|
|
4
|
+
* ONE vocabulary for the editor's panel and for an agent authoring over MCP.
|
|
5
|
+
* The trigger's `events` — `[{ entity, operations }]` — is what registers the
|
|
6
|
+
* flow's connector subscription, the record every inbound provider event is
|
|
7
|
+
* matched against: an entity name outside this list (or in the wrong case —
|
|
8
|
+
* HubSpot is lowercase, Salesforce is capitalised) registers a subscription
|
|
9
|
+
* that never fires, with no error anywhere. An agent wrote `lead` for a
|
|
10
|
+
* HubSpot contact trigger on 2026-09-26 and spent an hour on it.
|
|
11
|
+
*
|
|
12
|
+
* Copied as-is from octaviaflow-ui's ConnectorTriggerPanel (the panel's tables
|
|
13
|
+
* were the only copy); the panel is to import from here in its next flow-rules
|
|
14
|
+
* upgrade.
|
|
15
|
+
*/
|
|
16
|
+
export interface ConnectorEventEntity {
|
|
17
|
+
entity: string;
|
|
18
|
+
supportedOperations: string[];
|
|
19
|
+
}
|
|
20
|
+
/** One subscribed pair, as stored in a trigger step's `events`. */
|
|
21
|
+
export interface ConnectorTriggerEvent {
|
|
22
|
+
entity: string;
|
|
23
|
+
operations: string[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Connector ids that emit events a flow trigger can subscribe to. Database /
|
|
27
|
+
* http / openapi / ftp / etc. connectors are intentionally excluded: they
|
|
28
|
+
* cannot push events.
|
|
29
|
+
*/
|
|
30
|
+
export declare const EVENT_CAPABLE_CONNECTOR_IDS: ReadonlySet<string>;
|
|
31
|
+
/** Every subscribable entity, by connector id. */
|
|
32
|
+
export declare const CONNECTOR_EVENT_ENTITIES: Readonly<Record<string, ConnectorEventEntity[]>>;
|
|
33
|
+
export declare function getEntitiesForConnector(connectorId: string): ConnectorEventEntity[];
|
|
34
|
+
/** True when this connector type can drive an event trigger. */
|
|
35
|
+
export declare function isEventCapableConnector(connectorId: string): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* The one-line summary the canvas shows under a Connector Trigger
|
|
38
|
+
* (`Hubspot · 4 events`) — the same string the panel writes.
|
|
39
|
+
*/
|
|
40
|
+
export declare function summarizeConnectorTriggerEvents(connectorName: string, events: ConnectorTriggerEvent[]): string;
|
|
41
|
+
/**
|
|
42
|
+
* Why `events` cannot register a trigger on this connector — or `null` when
|
|
43
|
+
* it can. Names are matched EXACTLY, because the inbound matcher matches them
|
|
44
|
+
* exactly; a case-only miss says what was meant.
|
|
45
|
+
*/
|
|
46
|
+
export declare function validateConnectorTriggerEvents(connectorId: string, events: unknown): string | null;
|
package/dist/index.cjs
CHANGED
|
@@ -45,9 +45,11 @@ __export(exports_src, {
|
|
|
45
45
|
AggregateFunction: () => AggregateFunction,
|
|
46
46
|
CONDITION_OPERATORS: () => CONDITION_OPERATORS,
|
|
47
47
|
CONFIG_CONTRACTS: () => CONFIG_CONTRACTS,
|
|
48
|
+
CONNECTOR_EVENT_ENTITIES: () => CONNECTOR_EVENT_ENTITIES,
|
|
48
49
|
ConditionConfig: () => ConditionConfig,
|
|
49
50
|
DATABASE_CONNECTOR_IDS: () => DATABASE_CONNECTOR_IDS,
|
|
50
51
|
DebugConfig: () => DebugConfig,
|
|
52
|
+
EVENT_CAPABLE_CONNECTOR_IDS: () => EVENT_CAPABLE_CONNECTOR_IDS,
|
|
51
53
|
EdgeType: () => EdgeType,
|
|
52
54
|
EmailConfig: () => EmailConfig,
|
|
53
55
|
FieldType: () => FieldType,
|
|
@@ -89,20 +91,24 @@ __export(exports_src, {
|
|
|
89
91
|
getActionsByCategory: () => getActionsByCategory,
|
|
90
92
|
getAllActions: () => getAllActions,
|
|
91
93
|
getEdgeValidationStatus: () => getEdgeValidationStatus,
|
|
94
|
+
getEntitiesForConnector: () => getEntitiesForConnector,
|
|
92
95
|
getNodeConfigStatus: () => getNodeConfigStatus,
|
|
93
96
|
getNodeValidationStatus: () => getNodeValidationStatus,
|
|
94
97
|
getStorageProvider: () => getStorageProvider,
|
|
95
98
|
inferSchemaFromSample: () => inferSchemaFromSample,
|
|
96
99
|
isEditorPrivateKey: () => isEditorPrivateKey,
|
|
100
|
+
isEventCapableConnector: () => isEventCapableConnector,
|
|
97
101
|
isMappingFunction: () => isMappingFunction,
|
|
98
102
|
isQueryableConnector: () => isQueryableConnector,
|
|
99
103
|
mappingTransformFunctionName: () => mappingTransformFunctionName,
|
|
100
104
|
migrateDelayConfig: () => migrateDelayConfig,
|
|
101
105
|
queryDefinition: () => queryDefinition,
|
|
102
106
|
storageConfigKeys: () => storageConfigKeys,
|
|
107
|
+
summarizeConnectorTriggerEvents: () => summarizeConnectorTriggerEvents,
|
|
103
108
|
transformConnectionToEdge: () => transformConnectionToEdge,
|
|
104
109
|
transformFlowToWorkflow: () => transformFlowToWorkflow,
|
|
105
110
|
transformStepToNode: () => transformStepToNode,
|
|
111
|
+
validateConnectorTriggerEvents: () => validateConnectorTriggerEvents,
|
|
106
112
|
validateEdge: () => validateEdge,
|
|
107
113
|
validateFlowData: () => validateFlowData,
|
|
108
114
|
validateNode: () => validateNode,
|
|
@@ -555,7 +561,7 @@ var connectorTriggerDefinition = {
|
|
|
555
561
|
key: "events",
|
|
556
562
|
label: "Events",
|
|
557
563
|
type: "json" /* JSON */,
|
|
558
|
-
description:
|
|
564
|
+
description: 'Entity/operation pairs to subscribe to, as [{ "entity": "contact", "operations": ["Create", "Update"] }]. ' + "This is what registers the trigger — the platform derives the flow's connector subscription from it. " + "Entity and operation names are per connector (describe_action_type lists them); a name outside that list never fires.",
|
|
559
565
|
validation: { required: true }
|
|
560
566
|
}
|
|
561
567
|
]
|
|
@@ -3974,6 +3980,124 @@ function storageConfigKeys() {
|
|
|
3974
3980
|
}
|
|
3975
3981
|
return [...keys];
|
|
3976
3982
|
}
|
|
3983
|
+
// src/catalog/triggers/connector-trigger/events.ts
|
|
3984
|
+
var EVENT_CAPABLE_CONNECTOR_IDS = new Set([
|
|
3985
|
+
"quickbooks_online",
|
|
3986
|
+
"shopify",
|
|
3987
|
+
"hubspot",
|
|
3988
|
+
"salesforce",
|
|
3989
|
+
"google_sheets",
|
|
3990
|
+
"whatsapp"
|
|
3991
|
+
]);
|
|
3992
|
+
var QBO_ENTITIES = [
|
|
3993
|
+
{ entity: "Invoice", supportedOperations: ["Create", "Update", "Delete", "Void", "Emailed"] },
|
|
3994
|
+
{ entity: "Customer", supportedOperations: ["Create", "Update", "Delete", "Merge"] },
|
|
3995
|
+
{ entity: "Payment", supportedOperations: ["Create", "Update", "Delete", "Void"] },
|
|
3996
|
+
{ entity: "Bill", supportedOperations: ["Create", "Update", "Delete", "Void"] },
|
|
3997
|
+
{ entity: "Estimate", supportedOperations: ["Create", "Update", "Delete"] },
|
|
3998
|
+
{ entity: "SalesReceipt", supportedOperations: ["Create", "Update", "Delete", "Void", "Emailed"] },
|
|
3999
|
+
{ entity: "CreditMemo", supportedOperations: ["Create", "Update", "Delete", "Void", "Emailed"] },
|
|
4000
|
+
{ entity: "Vendor", supportedOperations: ["Create", "Update", "Delete", "Merge"] },
|
|
4001
|
+
{ entity: "Item", supportedOperations: ["Create", "Update", "Delete"] },
|
|
4002
|
+
{ entity: "Account", supportedOperations: ["Create", "Update", "Delete", "Merge"] },
|
|
4003
|
+
{ entity: "JournalEntry", supportedOperations: ["Create", "Update", "Delete", "Void"] },
|
|
4004
|
+
{ entity: "PurchaseOrder", supportedOperations: ["Create", "Update", "Delete"] }
|
|
4005
|
+
];
|
|
4006
|
+
var SALESFORCE_ENTITIES = [
|
|
4007
|
+
{ entity: "Lead", supportedOperations: ["Create", "Update", "Delete", "Undelete"] },
|
|
4008
|
+
{ entity: "Account", supportedOperations: ["Create", "Update", "Delete", "Undelete"] },
|
|
4009
|
+
{ entity: "Contact", supportedOperations: ["Create", "Update", "Delete", "Undelete"] },
|
|
4010
|
+
{ entity: "Opportunity", supportedOperations: ["Create", "Update", "Delete", "Undelete"] },
|
|
4011
|
+
{ entity: "Case", supportedOperations: ["Create", "Update", "Delete", "Undelete"] }
|
|
4012
|
+
];
|
|
4013
|
+
var HUBSPOT_ENTITIES = [
|
|
4014
|
+
{ entity: "contact", supportedOperations: ["Create", "Update", "Delete", "Merge", "Restore", "AssociationChange"] },
|
|
4015
|
+
{ entity: "company", supportedOperations: ["Create", "Update", "Delete", "Merge", "Restore", "AssociationChange"] },
|
|
4016
|
+
{ entity: "deal", supportedOperations: ["Create", "Update", "Delete", "Merge", "Restore", "AssociationChange"] },
|
|
4017
|
+
{ entity: "ticket", supportedOperations: ["Create", "Update", "Delete", "Merge", "Restore", "AssociationChange"] },
|
|
4018
|
+
{ entity: "product", supportedOperations: ["Create", "Update", "Delete", "Restore"] },
|
|
4019
|
+
{ entity: "line_item", supportedOperations: ["Create", "Update", "Delete", "Restore"] },
|
|
4020
|
+
{ entity: "lead", supportedOperations: ["Create", "Update", "Delete", "Restore"] },
|
|
4021
|
+
{ entity: "quote", supportedOperations: ["Create", "Update", "Delete", "Restore"] },
|
|
4022
|
+
{ entity: "call", supportedOperations: ["Create", "Update", "Delete"] },
|
|
4023
|
+
{ entity: "email", supportedOperations: ["Create", "Update", "Delete"] },
|
|
4024
|
+
{ entity: "meeting_event", supportedOperations: ["Create", "Update", "Delete"] },
|
|
4025
|
+
{ entity: "task", supportedOperations: ["Create", "Update", "Delete"] },
|
|
4026
|
+
{ entity: "note", supportedOperations: ["Create", "Update", "Delete"] },
|
|
4027
|
+
{ entity: "order", supportedOperations: ["Create", "Update", "Delete"] },
|
|
4028
|
+
{ entity: "cart", supportedOperations: ["Create", "Update", "Delete"] },
|
|
4029
|
+
{ entity: "invoice", supportedOperations: ["Create", "Update", "Delete"] }
|
|
4030
|
+
];
|
|
4031
|
+
var SHOPIFY_ENTITIES = [
|
|
4032
|
+
{ entity: "Order", supportedOperations: ["Create", "Update", "Paid", "Fulfilled", "Cancelled"] },
|
|
4033
|
+
{ entity: "Product", supportedOperations: ["Create", "Update"] },
|
|
4034
|
+
{ entity: "Customer", supportedOperations: ["Create", "Update"] }
|
|
4035
|
+
];
|
|
4036
|
+
var GOOGLE_SHEETS_ENTITIES = [
|
|
4037
|
+
{ entity: "Row", supportedOperations: ["Create", "Update", "Delete"] },
|
|
4038
|
+
{ entity: "Sheet", supportedOperations: ["Create", "Update"] }
|
|
4039
|
+
];
|
|
4040
|
+
var WHATSAPP_ENTITIES = [
|
|
4041
|
+
{ entity: "Message", supportedOperations: ["Received"] }
|
|
4042
|
+
];
|
|
4043
|
+
var CONNECTOR_EVENT_ENTITIES = {
|
|
4044
|
+
quickbooks_online: QBO_ENTITIES,
|
|
4045
|
+
salesforce: SALESFORCE_ENTITIES,
|
|
4046
|
+
hubspot: HUBSPOT_ENTITIES,
|
|
4047
|
+
shopify: SHOPIFY_ENTITIES,
|
|
4048
|
+
google_sheets: GOOGLE_SHEETS_ENTITIES,
|
|
4049
|
+
whatsapp: WHATSAPP_ENTITIES
|
|
4050
|
+
};
|
|
4051
|
+
function getEntitiesForConnector(connectorId) {
|
|
4052
|
+
return CONNECTOR_EVENT_ENTITIES[connectorId] ?? [];
|
|
4053
|
+
}
|
|
4054
|
+
function isEventCapableConnector(connectorId) {
|
|
4055
|
+
return EVENT_CAPABLE_CONNECTOR_IDS.has(connectorId) && getEntitiesForConnector(connectorId).length > 0;
|
|
4056
|
+
}
|
|
4057
|
+
function summarizeConnectorTriggerEvents(connectorName, events) {
|
|
4058
|
+
const eventCount = events.reduce((acc, ev) => acc + ev.operations.length, 0);
|
|
4059
|
+
if (eventCount === 0)
|
|
4060
|
+
return connectorName;
|
|
4061
|
+
const noun = eventCount === 1 ? "event" : "events";
|
|
4062
|
+
return `${connectorName} · ${eventCount} ${noun}`;
|
|
4063
|
+
}
|
|
4064
|
+
function validateConnectorTriggerEvents(connectorId, events) {
|
|
4065
|
+
const entities = getEntitiesForConnector(connectorId);
|
|
4066
|
+
if (!isEventCapableConnector(connectorId)) {
|
|
4067
|
+
return `"${connectorId}" does not emit events a trigger can subscribe to. ` + `Event-capable connectors: ${[...EVENT_CAPABLE_CONNECTOR_IDS].join(", ")}.`;
|
|
4068
|
+
}
|
|
4069
|
+
if (!Array.isArray(events) || events.length === 0) {
|
|
4070
|
+
return 'events must be a non-empty array of { "entity": string, "operations": string[] }.';
|
|
4071
|
+
}
|
|
4072
|
+
const seen = new Set;
|
|
4073
|
+
for (const ev of events) {
|
|
4074
|
+
const entity = ev?.entity;
|
|
4075
|
+
const operations = ev?.operations;
|
|
4076
|
+
if (typeof entity !== "string" || !entity) {
|
|
4077
|
+
return 'Each event needs an "entity" (string).';
|
|
4078
|
+
}
|
|
4079
|
+
const known = entities.find((e) => e.entity === entity);
|
|
4080
|
+
if (!known) {
|
|
4081
|
+
const caseHit = entities.find((e) => e.entity.toLowerCase() === entity.toLowerCase());
|
|
4082
|
+
const hint = caseHit ? ` Did you mean "${caseHit.entity}"? Names are case-sensitive.` : "";
|
|
4083
|
+
return `Unknown entity "${entity}" for ${connectorId}.${hint} Entities: ${entities.map((e) => e.entity).join(", ")}.`;
|
|
4084
|
+
}
|
|
4085
|
+
if (seen.has(entity))
|
|
4086
|
+
return `Entity "${entity}" is listed twice — give it one entry with all its operations.`;
|
|
4087
|
+
seen.add(entity);
|
|
4088
|
+
if (!Array.isArray(operations) || operations.length === 0) {
|
|
4089
|
+
return `Event "${entity}" needs a non-empty "operations" array. Operations: ${known.supportedOperations.join(", ")}.`;
|
|
4090
|
+
}
|
|
4091
|
+
for (const op of operations) {
|
|
4092
|
+
if (typeof op !== "string" || !known.supportedOperations.includes(op)) {
|
|
4093
|
+
const caseHit = typeof op === "string" ? known.supportedOperations.find((o) => o.toLowerCase() === op.toLowerCase()) : undefined;
|
|
4094
|
+
const hint = caseHit ? ` Did you mean "${caseHit}"?` : "";
|
|
4095
|
+
return `Unknown operation "${String(op)}" for ${connectorId} ${entity}.${hint} Operations: ${known.supportedOperations.join(", ")}.`;
|
|
4096
|
+
}
|
|
4097
|
+
}
|
|
4098
|
+
}
|
|
4099
|
+
return null;
|
|
4100
|
+
}
|
|
3977
4101
|
// src/catalog/workflow.ts
|
|
3978
4102
|
var NodeStatus;
|
|
3979
4103
|
((NodeStatus) => {
|
package/dist/index.d.ts
CHANGED
|
@@ -40,6 +40,7 @@ export { DATABASE_CONNECTOR_IDS, type FieldMapping, TRANSFORM_OPERATIONS, Transf
|
|
|
40
40
|
export { STORAGE_CONNECTOR_IDS, type StorageExtraField, type StoragePathField, getStorageProvider, storageConfigKeys, } from "./catalog/storage/storageCapabilities";
|
|
41
41
|
export { ManualTriggerConfig } from "./catalog/triggers/manual-trigger/index";
|
|
42
42
|
export { type ManualTriggerConfigType } from "./catalog/triggers/manual-trigger/config";
|
|
43
|
+
export { CONNECTOR_EVENT_ENTITIES, EVENT_CAPABLE_CONNECTOR_IDS, getEntitiesForConnector, isEventCapableConnector, summarizeConnectorTriggerEvents, validateConnectorTriggerEvents, type ConnectorEventEntity, type ConnectorTriggerEvent, } from "./catalog/triggers/connector-trigger/events";
|
|
43
44
|
export * from "./catalog/workflow";
|
|
44
45
|
export { type FlowConnection, type FlowData, type FlowStep, generateConnectionsFromSteps, transformConnectionToEdge, transformFlowToWorkflow, transformStepToNode, validateFlowData, } from "./rules/flowShape";
|
|
45
46
|
export { flattenNestedWorkflow } from "./rules/flattenNestedWorkflow";
|
package/dist/index.js
CHANGED
|
@@ -441,7 +441,7 @@ var connectorTriggerDefinition = {
|
|
|
441
441
|
key: "events",
|
|
442
442
|
label: "Events",
|
|
443
443
|
type: "json" /* JSON */,
|
|
444
|
-
description:
|
|
444
|
+
description: 'Entity/operation pairs to subscribe to, as [{ "entity": "contact", "operations": ["Create", "Update"] }]. ' + "This is what registers the trigger — the platform derives the flow's connector subscription from it. " + "Entity and operation names are per connector (describe_action_type lists them); a name outside that list never fires.",
|
|
445
445
|
validation: { required: true }
|
|
446
446
|
}
|
|
447
447
|
]
|
|
@@ -3860,6 +3860,124 @@ function storageConfigKeys() {
|
|
|
3860
3860
|
}
|
|
3861
3861
|
return [...keys];
|
|
3862
3862
|
}
|
|
3863
|
+
// src/catalog/triggers/connector-trigger/events.ts
|
|
3864
|
+
var EVENT_CAPABLE_CONNECTOR_IDS = new Set([
|
|
3865
|
+
"quickbooks_online",
|
|
3866
|
+
"shopify",
|
|
3867
|
+
"hubspot",
|
|
3868
|
+
"salesforce",
|
|
3869
|
+
"google_sheets",
|
|
3870
|
+
"whatsapp"
|
|
3871
|
+
]);
|
|
3872
|
+
var QBO_ENTITIES = [
|
|
3873
|
+
{ entity: "Invoice", supportedOperations: ["Create", "Update", "Delete", "Void", "Emailed"] },
|
|
3874
|
+
{ entity: "Customer", supportedOperations: ["Create", "Update", "Delete", "Merge"] },
|
|
3875
|
+
{ entity: "Payment", supportedOperations: ["Create", "Update", "Delete", "Void"] },
|
|
3876
|
+
{ entity: "Bill", supportedOperations: ["Create", "Update", "Delete", "Void"] },
|
|
3877
|
+
{ entity: "Estimate", supportedOperations: ["Create", "Update", "Delete"] },
|
|
3878
|
+
{ entity: "SalesReceipt", supportedOperations: ["Create", "Update", "Delete", "Void", "Emailed"] },
|
|
3879
|
+
{ entity: "CreditMemo", supportedOperations: ["Create", "Update", "Delete", "Void", "Emailed"] },
|
|
3880
|
+
{ entity: "Vendor", supportedOperations: ["Create", "Update", "Delete", "Merge"] },
|
|
3881
|
+
{ entity: "Item", supportedOperations: ["Create", "Update", "Delete"] },
|
|
3882
|
+
{ entity: "Account", supportedOperations: ["Create", "Update", "Delete", "Merge"] },
|
|
3883
|
+
{ entity: "JournalEntry", supportedOperations: ["Create", "Update", "Delete", "Void"] },
|
|
3884
|
+
{ entity: "PurchaseOrder", supportedOperations: ["Create", "Update", "Delete"] }
|
|
3885
|
+
];
|
|
3886
|
+
var SALESFORCE_ENTITIES = [
|
|
3887
|
+
{ entity: "Lead", supportedOperations: ["Create", "Update", "Delete", "Undelete"] },
|
|
3888
|
+
{ entity: "Account", supportedOperations: ["Create", "Update", "Delete", "Undelete"] },
|
|
3889
|
+
{ entity: "Contact", supportedOperations: ["Create", "Update", "Delete", "Undelete"] },
|
|
3890
|
+
{ entity: "Opportunity", supportedOperations: ["Create", "Update", "Delete", "Undelete"] },
|
|
3891
|
+
{ entity: "Case", supportedOperations: ["Create", "Update", "Delete", "Undelete"] }
|
|
3892
|
+
];
|
|
3893
|
+
var HUBSPOT_ENTITIES = [
|
|
3894
|
+
{ entity: "contact", supportedOperations: ["Create", "Update", "Delete", "Merge", "Restore", "AssociationChange"] },
|
|
3895
|
+
{ entity: "company", supportedOperations: ["Create", "Update", "Delete", "Merge", "Restore", "AssociationChange"] },
|
|
3896
|
+
{ entity: "deal", supportedOperations: ["Create", "Update", "Delete", "Merge", "Restore", "AssociationChange"] },
|
|
3897
|
+
{ entity: "ticket", supportedOperations: ["Create", "Update", "Delete", "Merge", "Restore", "AssociationChange"] },
|
|
3898
|
+
{ entity: "product", supportedOperations: ["Create", "Update", "Delete", "Restore"] },
|
|
3899
|
+
{ entity: "line_item", supportedOperations: ["Create", "Update", "Delete", "Restore"] },
|
|
3900
|
+
{ entity: "lead", supportedOperations: ["Create", "Update", "Delete", "Restore"] },
|
|
3901
|
+
{ entity: "quote", supportedOperations: ["Create", "Update", "Delete", "Restore"] },
|
|
3902
|
+
{ entity: "call", supportedOperations: ["Create", "Update", "Delete"] },
|
|
3903
|
+
{ entity: "email", supportedOperations: ["Create", "Update", "Delete"] },
|
|
3904
|
+
{ entity: "meeting_event", supportedOperations: ["Create", "Update", "Delete"] },
|
|
3905
|
+
{ entity: "task", supportedOperations: ["Create", "Update", "Delete"] },
|
|
3906
|
+
{ entity: "note", supportedOperations: ["Create", "Update", "Delete"] },
|
|
3907
|
+
{ entity: "order", supportedOperations: ["Create", "Update", "Delete"] },
|
|
3908
|
+
{ entity: "cart", supportedOperations: ["Create", "Update", "Delete"] },
|
|
3909
|
+
{ entity: "invoice", supportedOperations: ["Create", "Update", "Delete"] }
|
|
3910
|
+
];
|
|
3911
|
+
var SHOPIFY_ENTITIES = [
|
|
3912
|
+
{ entity: "Order", supportedOperations: ["Create", "Update", "Paid", "Fulfilled", "Cancelled"] },
|
|
3913
|
+
{ entity: "Product", supportedOperations: ["Create", "Update"] },
|
|
3914
|
+
{ entity: "Customer", supportedOperations: ["Create", "Update"] }
|
|
3915
|
+
];
|
|
3916
|
+
var GOOGLE_SHEETS_ENTITIES = [
|
|
3917
|
+
{ entity: "Row", supportedOperations: ["Create", "Update", "Delete"] },
|
|
3918
|
+
{ entity: "Sheet", supportedOperations: ["Create", "Update"] }
|
|
3919
|
+
];
|
|
3920
|
+
var WHATSAPP_ENTITIES = [
|
|
3921
|
+
{ entity: "Message", supportedOperations: ["Received"] }
|
|
3922
|
+
];
|
|
3923
|
+
var CONNECTOR_EVENT_ENTITIES = {
|
|
3924
|
+
quickbooks_online: QBO_ENTITIES,
|
|
3925
|
+
salesforce: SALESFORCE_ENTITIES,
|
|
3926
|
+
hubspot: HUBSPOT_ENTITIES,
|
|
3927
|
+
shopify: SHOPIFY_ENTITIES,
|
|
3928
|
+
google_sheets: GOOGLE_SHEETS_ENTITIES,
|
|
3929
|
+
whatsapp: WHATSAPP_ENTITIES
|
|
3930
|
+
};
|
|
3931
|
+
function getEntitiesForConnector(connectorId) {
|
|
3932
|
+
return CONNECTOR_EVENT_ENTITIES[connectorId] ?? [];
|
|
3933
|
+
}
|
|
3934
|
+
function isEventCapableConnector(connectorId) {
|
|
3935
|
+
return EVENT_CAPABLE_CONNECTOR_IDS.has(connectorId) && getEntitiesForConnector(connectorId).length > 0;
|
|
3936
|
+
}
|
|
3937
|
+
function summarizeConnectorTriggerEvents(connectorName, events) {
|
|
3938
|
+
const eventCount = events.reduce((acc, ev) => acc + ev.operations.length, 0);
|
|
3939
|
+
if (eventCount === 0)
|
|
3940
|
+
return connectorName;
|
|
3941
|
+
const noun = eventCount === 1 ? "event" : "events";
|
|
3942
|
+
return `${connectorName} · ${eventCount} ${noun}`;
|
|
3943
|
+
}
|
|
3944
|
+
function validateConnectorTriggerEvents(connectorId, events) {
|
|
3945
|
+
const entities = getEntitiesForConnector(connectorId);
|
|
3946
|
+
if (!isEventCapableConnector(connectorId)) {
|
|
3947
|
+
return `"${connectorId}" does not emit events a trigger can subscribe to. ` + `Event-capable connectors: ${[...EVENT_CAPABLE_CONNECTOR_IDS].join(", ")}.`;
|
|
3948
|
+
}
|
|
3949
|
+
if (!Array.isArray(events) || events.length === 0) {
|
|
3950
|
+
return 'events must be a non-empty array of { "entity": string, "operations": string[] }.';
|
|
3951
|
+
}
|
|
3952
|
+
const seen = new Set;
|
|
3953
|
+
for (const ev of events) {
|
|
3954
|
+
const entity = ev?.entity;
|
|
3955
|
+
const operations = ev?.operations;
|
|
3956
|
+
if (typeof entity !== "string" || !entity) {
|
|
3957
|
+
return 'Each event needs an "entity" (string).';
|
|
3958
|
+
}
|
|
3959
|
+
const known = entities.find((e) => e.entity === entity);
|
|
3960
|
+
if (!known) {
|
|
3961
|
+
const caseHit = entities.find((e) => e.entity.toLowerCase() === entity.toLowerCase());
|
|
3962
|
+
const hint = caseHit ? ` Did you mean "${caseHit.entity}"? Names are case-sensitive.` : "";
|
|
3963
|
+
return `Unknown entity "${entity}" for ${connectorId}.${hint} Entities: ${entities.map((e) => e.entity).join(", ")}.`;
|
|
3964
|
+
}
|
|
3965
|
+
if (seen.has(entity))
|
|
3966
|
+
return `Entity "${entity}" is listed twice — give it one entry with all its operations.`;
|
|
3967
|
+
seen.add(entity);
|
|
3968
|
+
if (!Array.isArray(operations) || operations.length === 0) {
|
|
3969
|
+
return `Event "${entity}" needs a non-empty "operations" array. Operations: ${known.supportedOperations.join(", ")}.`;
|
|
3970
|
+
}
|
|
3971
|
+
for (const op of operations) {
|
|
3972
|
+
if (typeof op !== "string" || !known.supportedOperations.includes(op)) {
|
|
3973
|
+
const caseHit = typeof op === "string" ? known.supportedOperations.find((o) => o.toLowerCase() === op.toLowerCase()) : undefined;
|
|
3974
|
+
const hint = caseHit ? ` Did you mean "${caseHit}"?` : "";
|
|
3975
|
+
return `Unknown operation "${String(op)}" for ${connectorId} ${entity}.${hint} Operations: ${known.supportedOperations.join(", ")}.`;
|
|
3976
|
+
}
|
|
3977
|
+
}
|
|
3978
|
+
}
|
|
3979
|
+
return null;
|
|
3980
|
+
}
|
|
3863
3981
|
// src/catalog/workflow.ts
|
|
3864
3982
|
var NodeStatus;
|
|
3865
3983
|
((NodeStatus) => {
|
|
@@ -5067,9 +5185,11 @@ export {
|
|
|
5067
5185
|
AggregateFunction,
|
|
5068
5186
|
CONDITION_OPERATORS,
|
|
5069
5187
|
CONFIG_CONTRACTS,
|
|
5188
|
+
CONNECTOR_EVENT_ENTITIES,
|
|
5070
5189
|
ConditionConfig,
|
|
5071
5190
|
DATABASE_CONNECTOR_IDS,
|
|
5072
5191
|
DebugConfig,
|
|
5192
|
+
EVENT_CAPABLE_CONNECTOR_IDS,
|
|
5073
5193
|
EdgeType,
|
|
5074
5194
|
EmailConfig,
|
|
5075
5195
|
FieldType,
|
|
@@ -5111,20 +5231,24 @@ export {
|
|
|
5111
5231
|
getActionsByCategory,
|
|
5112
5232
|
getAllActions,
|
|
5113
5233
|
getEdgeValidationStatus,
|
|
5234
|
+
getEntitiesForConnector,
|
|
5114
5235
|
getNodeConfigStatus,
|
|
5115
5236
|
getNodeValidationStatus,
|
|
5116
5237
|
getStorageProvider,
|
|
5117
5238
|
inferSchemaFromSample,
|
|
5118
5239
|
isEditorPrivateKey,
|
|
5240
|
+
isEventCapableConnector,
|
|
5119
5241
|
isMappingFunction,
|
|
5120
5242
|
isQueryableConnector,
|
|
5121
5243
|
mappingTransformFunctionName,
|
|
5122
5244
|
migrateDelayConfig,
|
|
5123
5245
|
queryDefinition,
|
|
5124
5246
|
storageConfigKeys,
|
|
5247
|
+
summarizeConnectorTriggerEvents,
|
|
5125
5248
|
transformConnectionToEdge,
|
|
5126
5249
|
transformFlowToWorkflow,
|
|
5127
5250
|
transformStepToNode,
|
|
5251
|
+
validateConnectorTriggerEvents,
|
|
5128
5252
|
validateEdge,
|
|
5129
5253
|
validateFlowData,
|
|
5130
5254
|
validateNode,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@octaviaflow/flow-rules",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "The flow action catalog and the rules engine behind Flow Doctor
|
|
3
|
+
"version": "0.10.0",
|
|
4
|
+
"description": "The flow action catalog and the rules engine behind Flow Doctor — one definition of what a step accepts and what makes a flow valid, shared by the editor and the server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.js",
|