@octaviaflow/flow-rules 0.1.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.
Files changed (146) hide show
  1. package/README.md +96 -0
  2. package/dist/catalog/actions/console-log/config.d.ts +58 -0
  3. package/dist/catalog/actions/console-log/config.js +70 -0
  4. package/dist/catalog/actions/console-log/index.d.ts +7 -0
  5. package/dist/catalog/actions/console-log/index.js +89 -0
  6. package/dist/catalog/actions/delay/config.d.ts +50 -0
  7. package/dist/catalog/actions/delay/config.js +79 -0
  8. package/dist/catalog/actions/delay/index.d.ts +7 -0
  9. package/dist/catalog/actions/delay/index.js +71 -0
  10. package/dist/catalog/actions/delay/migrate.d.ts +18 -0
  11. package/dist/catalog/actions/delay/migrate.js +38 -0
  12. package/dist/catalog/actions/delay/types.d.ts +58 -0
  13. package/dist/catalog/actions/delay/types.js +17 -0
  14. package/dist/catalog/actions/http-request/config.d.ts +114 -0
  15. package/dist/catalog/actions/http-request/config.js +111 -0
  16. package/dist/catalog/actions/http-request/index.d.ts +7 -0
  17. package/dist/catalog/actions/http-request/index.js +223 -0
  18. package/dist/catalog/ai/ai-agent/index.d.ts +12 -0
  19. package/dist/catalog/ai/ai-agent/index.js +72 -0
  20. package/dist/catalog/ai/idp-extract/index.d.ts +18 -0
  21. package/dist/catalog/ai/idp-extract/index.js +90 -0
  22. package/dist/catalog/api/graphql-query/config.d.ts +36 -0
  23. package/dist/catalog/api/graphql-query/config.js +31 -0
  24. package/dist/catalog/api/graphql-query/index.d.ts +7 -0
  25. package/dist/catalog/api/graphql-query/index.js +75 -0
  26. package/dist/catalog/communication/email-send/config.d.ts +80 -0
  27. package/dist/catalog/communication/email-send/config.js +80 -0
  28. package/dist/catalog/communication/email-send/index.d.ts +11 -0
  29. package/dist/catalog/communication/email-send/index.js +152 -0
  30. package/dist/catalog/communication/google-chat/config.d.ts +45 -0
  31. package/dist/catalog/communication/google-chat/config.js +28 -0
  32. package/dist/catalog/communication/google-chat/index.d.ts +5 -0
  33. package/dist/catalog/communication/google-chat/index.js +36 -0
  34. package/dist/catalog/communication/slack-message/config.d.ts +47 -0
  35. package/dist/catalog/communication/slack-message/config.js +36 -0
  36. package/dist/catalog/communication/slack-message/index.d.ts +5 -0
  37. package/dist/catalog/communication/slack-message/index.js +37 -0
  38. package/dist/catalog/communication/teams-message/config.d.ts +48 -0
  39. package/dist/catalog/communication/teams-message/config.js +29 -0
  40. package/dist/catalog/communication/teams-message/index.d.ts +5 -0
  41. package/dist/catalog/communication/teams-message/index.js +39 -0
  42. package/dist/catalog/communication/webhook-call/config.d.ts +36 -0
  43. package/dist/catalog/communication/webhook-call/config.js +31 -0
  44. package/dist/catalog/communication/webhook-call/index.d.ts +5 -0
  45. package/dist/catalog/communication/webhook-call/index.js +43 -0
  46. package/dist/catalog/communication/whatsapp-send/config.d.ts +23 -0
  47. package/dist/catalog/communication/whatsapp-send/config.js +36 -0
  48. package/dist/catalog/communication/whatsapp-send/index.d.ts +15 -0
  49. package/dist/catalog/communication/whatsapp-send/index.js +57 -0
  50. package/dist/catalog/general/query/config.d.ts +36 -0
  51. package/dist/catalog/general/query/config.js +257 -0
  52. package/dist/catalog/general/query/index.d.ts +11 -0
  53. package/dist/catalog/general/query/index.js +271 -0
  54. package/dist/catalog/general/query/types.d.ts +205 -0
  55. package/dist/catalog/general/query/types.js +82 -0
  56. package/dist/catalog/general/transform/config.d.ts +117 -0
  57. package/dist/catalog/general/transform/config.js +95 -0
  58. package/dist/catalog/general/transform/index.d.ts +8 -0
  59. package/dist/catalog/general/transform/index.js +63 -0
  60. package/dist/catalog/index.d.ts +57 -0
  61. package/dist/catalog/index.js +168 -0
  62. package/dist/catalog/logic/condition/config.d.ts +54 -0
  63. package/dist/catalog/logic/condition/config.js +93 -0
  64. package/dist/catalog/logic/condition/index.d.ts +7 -0
  65. package/dist/catalog/logic/condition/index.js +64 -0
  66. package/dist/catalog/logic/for-each/config.d.ts +100 -0
  67. package/dist/catalog/logic/for-each/config.js +75 -0
  68. package/dist/catalog/logic/for-each/index.d.ts +7 -0
  69. package/dist/catalog/logic/for-each/index.js +92 -0
  70. package/dist/catalog/logic/for-each/pathOptions.d.ts +62 -0
  71. package/dist/catalog/logic/for-each/pathOptions.js +151 -0
  72. package/dist/catalog/logic/group/index.d.ts +15 -0
  73. package/dist/catalog/logic/group/index.js +46 -0
  74. package/dist/catalog/policies.d.ts +75 -0
  75. package/dist/catalog/policies.js +62 -0
  76. package/dist/catalog/storage/csv-action/index.d.ts +2 -0
  77. package/dist/catalog/storage/csv-action/index.js +38 -0
  78. package/dist/catalog/storage/dropbox-action/index.d.ts +2 -0
  79. package/dist/catalog/storage/dropbox-action/index.js +33 -0
  80. package/dist/catalog/storage/excel-action/index.d.ts +2 -0
  81. package/dist/catalog/storage/excel-action/index.js +32 -0
  82. package/dist/catalog/storage/file-action/index.d.ts +2 -0
  83. package/dist/catalog/storage/file-action/index.js +119 -0
  84. package/dist/catalog/storage/file-operation/config.d.ts +48 -0
  85. package/dist/catalog/storage/file-operation/config.js +45 -0
  86. package/dist/catalog/storage/file-operation/index.d.ts +8 -0
  87. package/dist/catalog/storage/file-operation/index.js +111 -0
  88. package/dist/catalog/storage/ftp-action/index.d.ts +2 -0
  89. package/dist/catalog/storage/ftp-action/index.js +33 -0
  90. package/dist/catalog/storage/google-drive-action/index.d.ts +2 -0
  91. package/dist/catalog/storage/google-drive-action/index.js +38 -0
  92. package/dist/catalog/storage/json-action/index.d.ts +2 -0
  93. package/dist/catalog/storage/json-action/index.js +31 -0
  94. package/dist/catalog/storage/onedrive-action/index.d.ts +2 -0
  95. package/dist/catalog/storage/onedrive-action/index.js +33 -0
  96. package/dist/catalog/storage/s3-action/index.d.ts +2 -0
  97. package/dist/catalog/storage/s3-action/index.js +36 -0
  98. package/dist/catalog/storage/storage-action/index.d.ts +13 -0
  99. package/dist/catalog/storage/storage-action/index.js +72 -0
  100. package/dist/catalog/storage/storageCapabilities.d.ts +57 -0
  101. package/dist/catalog/storage/storageCapabilities.js +207 -0
  102. package/dist/catalog/storage/xml-action/index.d.ts +2 -0
  103. package/dist/catalog/storage/xml-action/index.js +31 -0
  104. package/dist/catalog/transforms/format/config.d.ts +23 -0
  105. package/dist/catalog/transforms/format/config.js +19 -0
  106. package/dist/catalog/transforms/format/index.d.ts +5 -0
  107. package/dist/catalog/transforms/format/index.js +39 -0
  108. package/dist/catalog/triggers/connector-trigger/index.d.ts +7 -0
  109. package/dist/catalog/triggers/connector-trigger/index.js +72 -0
  110. package/dist/catalog/triggers/manual-trigger/config.d.ts +40 -0
  111. package/dist/catalog/triggers/manual-trigger/config.js +60 -0
  112. package/dist/catalog/triggers/manual-trigger/index.d.ts +10 -0
  113. package/dist/catalog/triggers/manual-trigger/index.js +74 -0
  114. package/dist/catalog/triggers/schedule-trigger/config.d.ts +42 -0
  115. package/dist/catalog/triggers/schedule-trigger/config.js +42 -0
  116. package/dist/catalog/triggers/schedule-trigger/index.d.ts +7 -0
  117. package/dist/catalog/triggers/schedule-trigger/index.js +102 -0
  118. package/dist/catalog/triggers/webhook-trigger/config.d.ts +31 -0
  119. package/dist/catalog/triggers/webhook-trigger/config.js +27 -0
  120. package/dist/catalog/triggers/webhook-trigger/index.d.ts +7 -0
  121. package/dist/catalog/triggers/webhook-trigger/index.js +89 -0
  122. package/dist/catalog/types.d.ts +360 -0
  123. package/dist/catalog/types.js +135 -0
  124. package/dist/catalog/utility/debug/config.d.ts +72 -0
  125. package/dist/catalog/utility/debug/config.js +90 -0
  126. package/dist/catalog/utility/debug/index.d.ts +11 -0
  127. package/dist/catalog/utility/debug/index.js +38 -0
  128. package/dist/catalog/utility/error/config.d.ts +26 -0
  129. package/dist/catalog/utility/error/config.js +25 -0
  130. package/dist/catalog/utility/error/index.d.ts +7 -0
  131. package/dist/catalog/utility/error/index.js +46 -0
  132. package/dist/catalog/utility/variables/config.d.ts +76 -0
  133. package/dist/catalog/utility/variables/config.js +70 -0
  134. package/dist/catalog/utility/variables/index.d.ts +13 -0
  135. package/dist/catalog/utility/variables/index.js +40 -0
  136. package/dist/catalog/workflow.d.ts +308 -0
  137. package/dist/catalog/workflow.js +25 -0
  138. package/dist/ids.d.ts +31 -0
  139. package/dist/ids.js +53 -0
  140. package/dist/index.d.ts +25 -0
  141. package/dist/index.js +28 -0
  142. package/dist/rules/nodeConfigStatus.d.ts +33 -0
  143. package/dist/rules/nodeConfigStatus.js +217 -0
  144. package/dist/rules/workflowValidator.d.ts +53 -0
  145. package/dist/rules/workflowValidator.js +358 -0
  146. package/package.json +41 -0
@@ -0,0 +1,207 @@
1
+ // ============================================
2
+ // Storage capability registry
3
+ // ============================================
4
+ // Single source of truth for the unified `storage_action` config panel. Per
5
+ // storage connector (provider), declares which operations are available and,
6
+ // for each operation, which config fields to render — including the
7
+ // provider-native key each FilePicker path is stored under.
8
+ //
9
+ // The Engine's storageExecutor reads these native keys (cfg.key / cfg.remotePath
10
+ // / cfg.path / cfg.fileId / cfg.folderId ...), so the panel writes them directly
11
+ // here — no Engine-side path mapping needed.
12
+ // ============================================
13
+ // ── shared field fragments ──────────────────────────────────────────────────
14
+ const contentTypeField = {
15
+ key: 'contentType',
16
+ label: 'Content type',
17
+ type: 'string',
18
+ placeholder: 'application/octet-stream',
19
+ advanced: true,
20
+ hint: 'MIME type for the uploaded file.',
21
+ };
22
+ // ── providers ───────────────────────────────────────────────────────────────
23
+ export const STORAGE_PROVIDERS = {
24
+ aws_s3: {
25
+ connectorId: 'aws_s3',
26
+ label: 'Amazon S3',
27
+ browse: true,
28
+ operations: [
29
+ { value: 'list', label: 'List files', path: { key: 'prefix', label: 'Folder', selectMode: 'folder' }, fields: [{ key: 'maxKeys', label: 'Max results', type: 'number', defaultValue: 100, advanced: true }] },
30
+ { value: 'download', label: 'Download file', path: { key: 'key', label: 'File', selectMode: 'both', required: true } },
31
+ { value: 'upload', label: 'Upload file', path: { key: 'key', label: 'Destination key', selectMode: 'both', required: true }, content: true, fields: [contentTypeField] },
32
+ { value: 'delete', label: 'Delete file', path: { key: 'key', label: 'File', selectMode: 'both', required: true } },
33
+ { value: 'copy', label: 'Copy file', path: { key: 'key', label: 'Source file', selectMode: 'both', required: true }, dest: { key: 'destKey', label: 'Destination key', selectMode: 'both', required: true } },
34
+ { value: 'move', label: 'Move / rename', path: { key: 'key', label: 'Source file', selectMode: 'both', required: true }, dest: { key: 'destKey', label: 'Destination key', selectMode: 'both', required: true } },
35
+ { value: 'presign', label: 'Get signed URL', path: { key: 'key', label: 'File', selectMode: 'both', required: true }, fields: [{ key: 'expiresIn', label: 'Expiry (seconds)', type: 'number', defaultValue: 3600, advanced: true }] },
36
+ ],
37
+ },
38
+ ftp_sftp: {
39
+ connectorId: 'ftp_sftp',
40
+ label: 'FTP / SFTP',
41
+ browse: true,
42
+ operations: [
43
+ { value: 'list', label: 'List files', path: { key: 'remotePath', label: 'Folder', selectMode: 'folder' } },
44
+ { value: 'download', label: 'Download file', path: { key: 'remotePath', label: 'File', selectMode: 'both', required: true } },
45
+ { value: 'upload', label: 'Upload file', path: { key: 'remotePath', label: 'Destination path', selectMode: 'both', required: true }, content: true },
46
+ { value: 'delete', label: 'Delete file', path: { key: 'remotePath', label: 'File', selectMode: 'both', required: true } },
47
+ { value: 'move', label: 'Move / rename', path: { key: 'remotePath', label: 'Source file', selectMode: 'both', required: true }, dest: { key: 'destPath', label: 'Destination path', selectMode: 'both', required: true } },
48
+ ],
49
+ },
50
+ dropbox: {
51
+ connectorId: 'dropbox',
52
+ label: 'Dropbox',
53
+ browse: true,
54
+ operations: [
55
+ { value: 'list', label: 'List files', path: { key: 'path', label: 'Folder', selectMode: 'folder' } },
56
+ { value: 'download', label: 'Download file', path: { key: 'path', label: 'File', selectMode: 'both', required: true } },
57
+ { value: 'upload', label: 'Upload file', path: { key: 'path', label: 'Destination path', selectMode: 'both', required: true }, content: true, fields: [{ key: 'mode', label: 'Write mode', type: 'select', options: [{ label: 'Overwrite', value: 'overwrite' }, { label: 'Add (keep both)', value: 'add' }], defaultValue: 'overwrite', advanced: true }] },
58
+ { value: 'delete', label: 'Delete file', path: { key: 'path', label: 'File', selectMode: 'both', required: true } },
59
+ { value: 'copy', label: 'Copy file', path: { key: 'path', label: 'Source file', selectMode: 'both', required: true }, dest: { key: 'destPath', label: 'Destination path', selectMode: 'both', required: true } },
60
+ { value: 'move', label: 'Move / rename', path: { key: 'path', label: 'Source file', selectMode: 'both', required: true }, dest: { key: 'destPath', label: 'Destination path', selectMode: 'both', required: true } },
61
+ ],
62
+ },
63
+ onedrive: {
64
+ connectorId: 'onedrive',
65
+ label: 'OneDrive',
66
+ browse: true,
67
+ operations: [
68
+ { value: 'list', label: 'List files', path: { key: 'path', label: 'Folder', selectMode: 'folder' } },
69
+ { value: 'download', label: 'Download file', path: { key: 'path', label: 'File', selectMode: 'both', required: true } },
70
+ { value: 'upload', label: 'Upload file', path: { key: 'path', label: 'Destination path', selectMode: 'both', required: true }, content: true, fields: [contentTypeField] },
71
+ { value: 'delete', label: 'Delete file', path: { key: 'path', label: 'File', selectMode: 'both', required: true } },
72
+ { value: 'copy', label: 'Copy file', path: { key: 'path', label: 'Source file', selectMode: 'both', required: true }, dest: { key: 'destPath', label: 'Destination path', selectMode: 'both', required: true } },
73
+ { value: 'move', label: 'Move / rename', path: { key: 'path', label: 'Source file', selectMode: 'both', required: true }, dest: { key: 'destPath', label: 'Destination path', selectMode: 'both', required: true } },
74
+ ],
75
+ },
76
+ // Google Drive uses opaque folderIds (not hierarchical paths); the FilePicker
77
+ // navigates by folderId and writes the picked id to fileId / folderId.
78
+ google_drive: {
79
+ connectorId: 'google_drive',
80
+ label: 'Google Drive',
81
+ browse: true,
82
+ operations: [
83
+ { value: 'list', label: 'List files', path: { key: 'folderId', label: 'Folder', selectMode: 'folder' }, fields: [{ key: 'query', label: 'Search query', type: 'string', advanced: true }, { key: 'pageSize', label: 'Max results', type: 'number', defaultValue: 50, advanced: true }] },
84
+ { value: 'download', label: 'Download file', path: { key: 'fileId', label: 'File', selectMode: 'both', required: true } },
85
+ { value: 'upload', label: 'Upload file', path: { key: 'folderId', label: 'Destination folder', selectMode: 'both' }, content: true, fields: [{ key: 'fileName', label: 'File name', type: 'string', required: true }, { key: 'mimeType', label: 'Content type', type: 'string', advanced: true }] },
86
+ { value: 'delete', label: 'Delete file', path: { key: 'fileId', label: 'File', selectMode: 'both', required: true } },
87
+ { value: 'move', label: 'Move', path: { key: 'fileId', label: 'File', selectMode: 'both', required: true }, dest: { key: 'destFolderId', label: 'Destination folder', selectMode: 'both', required: true } },
88
+ { value: 'copy', label: 'Copy', path: { key: 'fileId', label: 'File', selectMode: 'both', required: true }, dest: { key: 'destFolderId', label: 'Destination folder', selectMode: 'both' }, fields: [{ key: 'fileName', label: 'New name', type: 'string' }] },
89
+ { value: 'share', label: 'Share', path: { key: 'fileId', label: 'File', selectMode: 'both', required: true }, fields: [{ key: 'shareEmail', label: 'Share with (email)', type: 'string', required: true }, { key: 'shareRole', label: 'Role', type: 'select', options: [{ label: 'Viewer', value: 'reader' }, { label: 'Editor', value: 'writer' }], defaultValue: 'reader' }] },
90
+ { value: 'create_folder', label: 'Create folder', path: { key: 'folderId', label: 'Parent folder', selectMode: 'both' }, fields: [{ key: 'fileName', label: 'Folder name', type: 'string', required: true }] },
91
+ ],
92
+ },
93
+ // GCS is an S3-like flat object store — paths are object keys written to `key`.
94
+ gcs: {
95
+ connectorId: 'gcs',
96
+ label: 'Google Cloud Storage',
97
+ browse: true,
98
+ operations: [
99
+ { value: 'list', label: 'List files', path: { key: 'prefix', label: 'Folder', selectMode: 'folder' }, fields: [{ key: 'maxKeys', label: 'Max results', type: 'number', defaultValue: 100, advanced: true }] },
100
+ { value: 'download', label: 'Download file', path: { key: 'key', label: 'File', selectMode: 'both', required: true } },
101
+ { value: 'upload', label: 'Upload file', path: { key: 'key', label: 'Destination key', selectMode: 'both', required: true }, content: true, fields: [contentTypeField] },
102
+ { value: 'delete', label: 'Delete file', path: { key: 'key', label: 'File', selectMode: 'both', required: true } },
103
+ { value: 'copy', label: 'Copy file', path: { key: 'key', label: 'Source file', selectMode: 'both', required: true }, dest: { key: 'destKey', label: 'Destination key', selectMode: 'both', required: true } },
104
+ { value: 'move', label: 'Move / rename', path: { key: 'key', label: 'Source file', selectMode: 'both', required: true }, dest: { key: 'destKey', label: 'Destination key', selectMode: 'both', required: true } },
105
+ { value: 'presign', label: 'Get signed URL', path: { key: 'key', label: 'File', selectMode: 'both', required: true }, fields: [{ key: 'expiresIn', label: 'Expiry (seconds)', type: 'number', defaultValue: 3600, advanced: true }] },
106
+ ],
107
+ },
108
+ // Azure Blob is a flat blob store — paths are blob names written to `blob`.
109
+ azure_blob: {
110
+ connectorId: 'azure_blob',
111
+ label: 'Azure Blob Storage',
112
+ browse: true,
113
+ operations: [
114
+ { value: 'list', label: 'List files', path: { key: 'prefix', label: 'Folder', selectMode: 'folder' }, fields: [{ key: 'maxKeys', label: 'Max results', type: 'number', defaultValue: 100, advanced: true }] },
115
+ { value: 'download', label: 'Download file', path: { key: 'blob', label: 'File', selectMode: 'both', required: true } },
116
+ { value: 'upload', label: 'Upload file', path: { key: 'blob', label: 'Destination blob', selectMode: 'both', required: true }, content: true, fields: [contentTypeField] },
117
+ { value: 'delete', label: 'Delete file', path: { key: 'blob', label: 'File', selectMode: 'both', required: true } },
118
+ { value: 'copy', label: 'Copy file', path: { key: 'blob', label: 'Source blob', selectMode: 'both', required: true }, dest: { key: 'destBlob', label: 'Destination blob', selectMode: 'both', required: true } },
119
+ { value: 'move', label: 'Move / rename', path: { key: 'blob', label: 'Source blob', selectMode: 'both', required: true }, dest: { key: 'destBlob', label: 'Destination blob', selectMode: 'both', required: true } },
120
+ { value: 'presign', label: 'Get signed URL', path: { key: 'blob', label: 'File', selectMode: 'both', required: true }, fields: [{ key: 'expiresIn', label: 'Expiry (seconds)', type: 'number', defaultValue: 3600, advanced: true }] },
121
+ ],
122
+ },
123
+ };
124
+ // Google Sheets connectors share Drive access (same token + endpoints).
125
+ STORAGE_PROVIDERS.google_sheets = { ...STORAGE_PROVIDERS.google_drive, connectorId: 'google_sheets' };
126
+ // Cross-connector Transfer — available on every provider as the SOURCE; the
127
+ // destination is a second connector chosen in the panel. Rendered specially by
128
+ // StorageConfigPanel (source FilePicker + destination connector + dest path).
129
+ const transferOp = {
130
+ value: 'transfer',
131
+ label: 'Transfer to another connector',
132
+ path: { key: 'path', label: 'Source file or folder', selectMode: 'both', required: true },
133
+ };
134
+ for (const id of ['aws_s3', 'ftp_sftp', 'dropbox', 'onedrive', 'google_drive', 'gcs', 'azure_blob']) {
135
+ STORAGE_PROVIDERS[id].operations.push(transferOp);
136
+ }
137
+ // Folder SYNC — recursive folder→folder copy to another connector that runs
138
+ // reliably as the BODY of a `cursor`-mode ForEach: each pass is bounded and the
139
+ // engine threads the BFS cursor across passes, so an arbitrarily deep tree never
140
+ // hits the per-step deadline. Rendered specially by StorageConfigPanel.
141
+ const syncOp = {
142
+ value: 'sync',
143
+ label: 'Sync folder to another connector',
144
+ path: { key: 'path', label: 'Source folder', selectMode: 'both', required: true },
145
+ fields: [
146
+ {
147
+ key: 'ifExists',
148
+ label: 'If a file already exists',
149
+ type: 'select',
150
+ options: [
151
+ { label: 'Overwrite', value: 'overwrite' },
152
+ { label: 'Skip it', value: 'skip' },
153
+ { label: 'Keep both (rename)', value: 'rename' },
154
+ ],
155
+ defaultValue: 'overwrite',
156
+ hint: 'What to do when the destination already has the file.',
157
+ },
158
+ {
159
+ key: 'onError',
160
+ label: 'On file error',
161
+ type: 'select',
162
+ options: [
163
+ { label: 'Stop the sync', value: 'abort' },
164
+ { label: 'Skip the file & continue', value: 'skip' },
165
+ ],
166
+ defaultValue: 'abort',
167
+ hint: 'A bad file (timeout, lock, permission) stops the whole sync, or is skipped.',
168
+ },
169
+ ],
170
+ };
171
+ for (const id of ['aws_s3', 'ftp_sftp', 'dropbox', 'onedrive', 'google_drive', 'gcs', 'azure_blob']) {
172
+ STORAGE_PROVIDERS[id].operations.push(syncOp);
173
+ }
174
+ /** Connector ids the unified storage action's connector picker offers.
175
+ * Google Sheets shares Drive access (kept in STORAGE_PROVIDERS for browse
176
+ * compat) but it's a spreadsheet/data connector — not a file store — so it's
177
+ * excluded from the picker (a "Google Sheets" app under Storage confuses
178
+ * users). Use the Google Drive connector for file operations. */
179
+ export const STORAGE_CONNECTOR_IDS = Object.keys(STORAGE_PROVIDERS).filter((id) => id !== 'google_sheets');
180
+ export function getStorageProvider(connectorId) {
181
+ if (!connectorId)
182
+ return undefined;
183
+ // Accept legacy hyphenated ids (e.g. 'aws-s3') as their canonical underscore
184
+ // form ('aws_s3') so connector instances created before the id was canonicalised
185
+ // still resolve to their provider spec.
186
+ return STORAGE_PROVIDERS[connectorId] ?? STORAGE_PROVIDERS[connectorId.replace(/-/g, '_')];
187
+ }
188
+ /** All config keys any operation might write — used to clear stale fields when the operation/provider changes. */
189
+ export function storageConfigKeys() {
190
+ const keys = new Set([
191
+ 'operation', 'connector', 'content', 'outputAs',
192
+ // cross-connector Transfer + folder Sync fields
193
+ 'path', 'destPath', 'destConnector', 'sourceIsDirectory',
194
+ 'cursor', 'fileBudget', 'timeBudgetMs',
195
+ ]);
196
+ for (const provider of Object.values(STORAGE_PROVIDERS)) {
197
+ for (const op of provider.operations) {
198
+ if (op.path)
199
+ keys.add(op.path.key);
200
+ if (op.dest)
201
+ keys.add(op.dest.key);
202
+ for (const f of op.fields ?? [])
203
+ keys.add(f.key);
204
+ }
205
+ }
206
+ return [...keys];
207
+ }
@@ -0,0 +1,2 @@
1
+ import { ActionDefinition } from '../../types';
2
+ export declare const xmlActionDefinition: ActionDefinition;
@@ -0,0 +1,31 @@
1
+ import { ActionCategory, ActionType, ActionStatus, FieldType } from '../../types';
2
+ export const xmlActionDefinition = {
3
+ id: 'xml_action',
4
+ name: 'XML',
5
+ description: 'Parse XML files into structured records or generate XML from workflow data',
6
+ category: ActionCategory.Storage,
7
+ type: ActionType.XmlAction,
8
+ tags: ['xml', 'parse', 'generate', 'file', 'format', 'built-in'],
9
+ status: ActionStatus.Beta,
10
+ icon: 'Code',
11
+ color: '#e65100',
12
+ inputSchema: {
13
+ fields: [
14
+ { key: 'operation', label: 'Operation', type: FieldType.Select, options: [{ label: 'Parse (XML → Records)', value: 'parse' }, { label: 'Generate (Records → XML)', value: 'generate' }], defaultValue: 'parse', validation: { required: true } },
15
+ { key: 'content', label: 'XML Content', type: FieldType.String, description: 'Paste XML or use FX token' },
16
+ { key: 'rootElement', label: 'Root Element', type: FieldType.String, description: 'Root XML element name (for generate)', defaultValue: 'data' },
17
+ { key: 'rowElement', label: 'Row Element', type: FieldType.String, description: 'Element name per record (for generate)', defaultValue: 'row' },
18
+ { key: 'fileName', label: 'Output File Name', type: FieldType.String, defaultValue: 'export.xml' },
19
+ ],
20
+ },
21
+ outputSchema: {
22
+ type: 'object',
23
+ properties: [
24
+ { key: 'data', type: FieldType.Array, description: 'Parsed records (parse mode) — loop these with a ForEach. Generated XML string in generate mode.' },
25
+ { key: 'columns', type: FieldType.JSON, description: 'Field names' },
26
+ { key: 'rowCount', type: FieldType.Number, description: 'Number of records' },
27
+ ],
28
+ sampleOutput: { data: [{ id: 1, name: 'Widget' }], columns: ['id', 'name'], rowCount: 1 },
29
+ },
30
+ version: '1.0.0', createdAt: '2026-03-28T00:00:00Z', updatedAt: '2026-03-28T00:00:00Z', createdBy: 'system', isOfficial: true, testable: false,
31
+ };
@@ -0,0 +1,23 @@
1
+ export interface FormatConfigType {
2
+ input: string;
3
+ format: 'json' | 'csv' | 'xml' | 'yaml';
4
+ }
5
+ export declare const FormatConfig: {
6
+ defaults: FormatConfigType;
7
+ schema: {
8
+ input: {
9
+ type: string;
10
+ required: boolean;
11
+ };
12
+ format: {
13
+ type: string;
14
+ required: boolean;
15
+ };
16
+ };
17
+ validate: (config: Partial<FormatConfigType>) => {
18
+ valid: boolean;
19
+ errors: string[];
20
+ };
21
+ merge: (userConfig: Partial<FormatConfigType>) => FormatConfigType;
22
+ getLabel: (config: FormatConfigType) => string;
23
+ };
@@ -0,0 +1,19 @@
1
+ export const FormatConfig = {
2
+ defaults: { input: '', format: 'json' },
3
+ schema: {
4
+ input: { type: 'expression', required: true },
5
+ format: { type: 'select', required: true },
6
+ },
7
+ validate: (config) => {
8
+ const errors = [];
9
+ if (!config.input)
10
+ errors.push('Input required');
11
+ if (!config.format)
12
+ errors.push('Format required');
13
+ return { valid: errors.length === 0, errors };
14
+ },
15
+ merge: (userConfig) => {
16
+ return { ...FormatConfig.defaults, ...userConfig };
17
+ },
18
+ getLabel: (config) => `Format as ${config.format.toUpperCase()}`,
19
+ };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Format Transform Action
3
+ */
4
+ import { ActionDefinition } from '../../types';
5
+ export declare const formatDefinition: ActionDefinition;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Format Transform Action
3
+ */
4
+ import { ActionCategory, ActionType, ActionStatus, FieldType } from '../../types';
5
+ export const formatDefinition = {
6
+ id: 'format',
7
+ name: 'Format',
8
+ description: 'Format data (JSON, CSV, XML, etc.)',
9
+ category: ActionCategory.Transform,
10
+ type: ActionType.Format,
11
+ tags: ['transform', 'format', 'built-in'],
12
+ status: ActionStatus.Stable,
13
+ icon: 'TextFormatting',
14
+ color: '#24a148',
15
+ inputSchema: {
16
+ fields: [
17
+ { key: 'input', label: 'Input', type: FieldType.Expression, validation: { required: true } },
18
+ { key: 'format', label: 'Format', type: FieldType.Select, options: [
19
+ { label: 'JSON', value: 'json' },
20
+ { label: 'CSV', value: 'csv' },
21
+ { label: 'XML', value: 'xml' },
22
+ { label: 'YAML', value: 'yaml' },
23
+ ], validation: { required: true } },
24
+ ],
25
+ },
26
+ outputSchema: {
27
+ type: 'string',
28
+ properties: [
29
+ { key: 'result', type: FieldType.String, description: 'Formatted output' },
30
+ ],
31
+ sampleOutput: { result: '' },
32
+ },
33
+ version: '1.0.0',
34
+ createdAt: '2025-01-01T00:00:00Z',
35
+ updatedAt: '2025-12-15T00:00:00Z',
36
+ createdBy: 'system',
37
+ isOfficial: true,
38
+ testable: true,
39
+ };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Connector Trigger Action
3
+ *
4
+ * Trigger workflows via connector platform events (e.g. QuickBooks Online webhooks)
5
+ */
6
+ import { ActionDefinition } from '../../types';
7
+ export declare const connectorTriggerDefinition: ActionDefinition;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Connector Trigger Action
3
+ *
4
+ * Trigger workflows via connector platform events (e.g. QuickBooks Online webhooks)
5
+ */
6
+ import { ActionCategory, ActionType, ActionStatus, FieldType } from '../../types';
7
+ export const connectorTriggerDefinition = {
8
+ id: 'connector_trigger',
9
+ name: 'Connector Trigger',
10
+ description: 'Trigger workflow when a connector platform event occurs',
11
+ category: ActionCategory.Trigger,
12
+ type: ActionType.Event,
13
+ tags: ['trigger', 'connector', 'event', 'built-in'],
14
+ status: ActionStatus.Stable,
15
+ icon: 'Connect',
16
+ color: '#6929c4',
17
+ inputSchema: {
18
+ fields: [
19
+ {
20
+ key: 'connectorInstanceId',
21
+ label: 'Connector Instance',
22
+ type: FieldType.String,
23
+ description: 'The connected app instance to listen to',
24
+ validation: { required: true },
25
+ },
26
+ {
27
+ key: 'events',
28
+ label: 'Events',
29
+ type: FieldType.JSON,
30
+ description: 'Entity/operation pairs to subscribe to',
31
+ validation: { required: true },
32
+ },
33
+ ],
34
+ },
35
+ outputSchema: {
36
+ type: 'object',
37
+ properties: [
38
+ {
39
+ key: 'eventType',
40
+ type: FieldType.String,
41
+ description: 'The type of event that occurred',
42
+ },
43
+ {
44
+ key: 'entity',
45
+ type: FieldType.String,
46
+ description: 'The entity that changed (e.g. Invoice)',
47
+ },
48
+ {
49
+ key: 'operation',
50
+ type: FieldType.String,
51
+ description: 'The operation performed (e.g. Create)',
52
+ },
53
+ {
54
+ key: 'payload',
55
+ type: FieldType.JSON,
56
+ description: 'The event payload from the connector',
57
+ },
58
+ ],
59
+ sampleOutput: {
60
+ eventType: 'connector.event',
61
+ entity: 'Invoice',
62
+ operation: 'Create',
63
+ payload: { id: '123', amount: 500 },
64
+ },
65
+ },
66
+ version: '1.0.0',
67
+ createdAt: '2025-01-01T00:00:00Z',
68
+ updatedAt: '2025-12-15T00:00:00Z',
69
+ createdBy: 'system',
70
+ isOfficial: true,
71
+ testable: false,
72
+ };
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Manual Trigger Configuration
3
+ *
4
+ * Defines the configuration structure and default values for the Manual Trigger action
5
+ */
6
+ export interface ManualTriggerConfigType {
7
+ description?: string;
8
+ }
9
+ export declare const ManualTriggerConfig: {
10
+ /**
11
+ * Default configuration for Manual Trigger
12
+ */
13
+ defaults: ManualTriggerConfigType;
14
+ /**
15
+ * Configuration schema for validation
16
+ */
17
+ schema: {
18
+ description: {
19
+ type: string;
20
+ maxLength: number;
21
+ required: boolean;
22
+ description: string;
23
+ };
24
+ };
25
+ /**
26
+ * Validate configuration
27
+ */
28
+ validate: (config: Partial<ManualTriggerConfigType>) => {
29
+ valid: boolean;
30
+ errors: string[];
31
+ };
32
+ /**
33
+ * Merge user config with defaults
34
+ */
35
+ merge: (userConfig: Partial<ManualTriggerConfigType>) => ManualTriggerConfigType;
36
+ /**
37
+ * Get display label for configuration
38
+ */
39
+ getLabel: (config: ManualTriggerConfigType) => string;
40
+ };
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Manual Trigger Configuration
3
+ *
4
+ * Defines the configuration structure and default values for the Manual Trigger action
5
+ */
6
+ export const ManualTriggerConfig = {
7
+ /**
8
+ * Default configuration for Manual Trigger
9
+ */
10
+ defaults: {
11
+ description: '',
12
+ },
13
+ /**
14
+ * Configuration schema for validation
15
+ */
16
+ schema: {
17
+ description: {
18
+ type: 'string',
19
+ maxLength: 500,
20
+ required: false,
21
+ description: 'Optional description for this trigger (shown on node)',
22
+ },
23
+ },
24
+ /**
25
+ * Validate configuration
26
+ */
27
+ validate: (config) => {
28
+ const errors = [];
29
+ if (config.description !== undefined) {
30
+ if (typeof config.description !== 'string') {
31
+ errors.push('Description must be a string');
32
+ }
33
+ if (config.description.length > 500) {
34
+ errors.push('Description must not exceed 500 characters');
35
+ }
36
+ }
37
+ return {
38
+ valid: errors.length === 0,
39
+ errors,
40
+ };
41
+ },
42
+ /**
43
+ * Merge user config with defaults
44
+ */
45
+ merge: (userConfig) => {
46
+ return {
47
+ ...ManualTriggerConfig.defaults,
48
+ ...userConfig,
49
+ };
50
+ },
51
+ /**
52
+ * Get display label for configuration
53
+ */
54
+ getLabel: (config) => {
55
+ if (config.description) {
56
+ return `Manual Trigger: ${config.description}`;
57
+ }
58
+ return 'Manual Trigger';
59
+ },
60
+ };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Manual Trigger Action
3
+ *
4
+ * A built-in trigger action that allows manual workflow execution with optional configuration
5
+ */
6
+ import { ActionDefinition } from '../../types';
7
+ import { ManualTriggerConfig } from './config';
8
+ export declare const manualTriggerDefinition: ActionDefinition;
9
+ export { ManualTriggerConfig };
10
+ export type { ManualTriggerConfigType } from './config';
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Manual Trigger Action
3
+ *
4
+ * A built-in trigger action that allows manual workflow execution with optional configuration
5
+ */
6
+ import { ActionCategory, ActionType, ActionStatus, FieldType } from '../../types';
7
+ import { randomSuffix } from '../../../ids';
8
+ import { ManualTriggerConfig } from './config';
9
+ export const manualTriggerDefinition = {
10
+ id: 'manual_trigger',
11
+ name: 'Manual Trigger',
12
+ description: 'Manually trigger workflow with optional description',
13
+ category: ActionCategory.Trigger,
14
+ type: ActionType.Manual,
15
+ tags: ['trigger', 'manual', 'built-in'],
16
+ status: ActionStatus.Stable,
17
+ icon: 'PlayOutline',
18
+ color: '#0f62fe',
19
+ inputSchema: {
20
+ fields: [
21
+ {
22
+ key: 'description',
23
+ label: 'Description',
24
+ type: FieldType.String,
25
+ description: 'Optional description for this trigger (shown on node)',
26
+ placeholder: 'e.g., Manual data sync, Testing workflow, etc.',
27
+ validation: {
28
+ required: false,
29
+ maxLength: 500,
30
+ },
31
+ },
32
+ ],
33
+ },
34
+ outputSchema: {
35
+ type: 'object',
36
+ properties: [
37
+ {
38
+ key: 'triggeredAt',
39
+ type: FieldType.DateTime,
40
+ description: 'Timestamp when workflow was triggered',
41
+ },
42
+ // `triggeredBy` was declared here but never produced, so the picker
43
+ // offered a token that always resolved to nothing. The Engine DOES have
44
+ // it — `metadata.triggeredBy` / `.triggeredByEmail` exist on the run —
45
+ // but they are not threaded into `executeStep`, which is where the
46
+ // trigger envelope is built. Removed rather than left as a dead token;
47
+ // re-add it together with that threading.
48
+ {
49
+ key: 'executionId',
50
+ type: FieldType.String,
51
+ description: 'Unique execution ID for this workflow run',
52
+ },
53
+ {
54
+ key: 'description',
55
+ type: FieldType.String,
56
+ description: 'The description provided by the user (if any)',
57
+ },
58
+ ],
59
+ sampleOutput: {
60
+ triggeredAt: new Date().toISOString(),
61
+ executionId: `exec_${Date.now()}_${randomSuffix(9)}`,
62
+ description: 'Manual data sync',
63
+ },
64
+ },
65
+ version: '1.0.0',
66
+ createdAt: '2025-01-01T00:00:00Z',
67
+ updatedAt: '2025-12-15T00:00:00Z',
68
+ createdBy: 'system',
69
+ isOfficial: true,
70
+ testable: true,
71
+ };
72
+ // The config PANEL stays in octaviaflow-ui: this package is data and rules,
73
+ // and a React component here would make it unusable from Backend.
74
+ export { ManualTriggerConfig };
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Schedule Trigger Configuration
3
+ */
4
+ export interface ScheduleTriggerConfigType {
5
+ scheduleType: 'interval' | 'cron' | 'specific';
6
+ interval?: number;
7
+ intervalUnit?: 'minutes' | 'hours' | 'days' | 'weeks';
8
+ cronExpression?: string;
9
+ timezone?: string;
10
+ }
11
+ export declare const ScheduleTriggerConfig: {
12
+ defaults: ScheduleTriggerConfigType;
13
+ schema: {
14
+ scheduleType: {
15
+ type: string;
16
+ required: boolean;
17
+ };
18
+ interval: {
19
+ type: string;
20
+ required: boolean;
21
+ min: number;
22
+ };
23
+ intervalUnit: {
24
+ type: string;
25
+ required: boolean;
26
+ };
27
+ cronExpression: {
28
+ type: string;
29
+ required: boolean;
30
+ };
31
+ timezone: {
32
+ type: string;
33
+ required: boolean;
34
+ };
35
+ };
36
+ validate: (config: Partial<ScheduleTriggerConfigType>) => {
37
+ valid: boolean;
38
+ errors: string[];
39
+ };
40
+ merge: (userConfig: Partial<ScheduleTriggerConfigType>) => ScheduleTriggerConfigType;
41
+ getLabel: (config: ScheduleTriggerConfigType) => string;
42
+ };