@antelopejs/dms-automation 0.0.1

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 (305) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +95 -0
  3. package/dist/cluster/bus.d.ts +17 -0
  4. package/dist/cluster/bus.js +82 -0
  5. package/dist/cluster/bus.js.map +1 -0
  6. package/dist/cluster/instance.d.ts +1 -0
  7. package/dist/cluster/instance.js +6 -0
  8. package/dist/cluster/instance.js.map +1 -0
  9. package/dist/cluster/leader.d.ts +7 -0
  10. package/dist/cluster/leader.js +123 -0
  11. package/dist/cluster/leader.js.map +1 -0
  12. package/dist/cluster/mode.d.ts +3 -0
  13. package/dist/cluster/mode.js +25 -0
  14. package/dist/cluster/mode.js.map +1 -0
  15. package/dist/data/procedures-table.d.ts +66 -0
  16. package/dist/data/procedures-table.js +271 -0
  17. package/dist/data/procedures-table.js.map +1 -0
  18. package/dist/data/runs-table.d.ts +23 -0
  19. package/dist/data/runs-table.js +125 -0
  20. package/dist/data/runs-table.js.map +1 -0
  21. package/dist/db/index.d.ts +7 -0
  22. package/dist/db/index.js +24 -0
  23. package/dist/db/index.js.map +1 -0
  24. package/dist/db/models/automation_template.model.d.ts +58 -0
  25. package/dist/db/models/automation_template.model.js +134 -0
  26. package/dist/db/models/automation_template.model.js.map +1 -0
  27. package/dist/db/models/index.d.ts +3 -0
  28. package/dist/db/models/index.js +20 -0
  29. package/dist/db/models/index.js.map +1 -0
  30. package/dist/db/models/procedure.model.d.ts +25 -0
  31. package/dist/db/models/procedure.model.js +28 -0
  32. package/dist/db/models/procedure.model.js.map +1 -0
  33. package/dist/db/models/procedure_run.model.d.ts +34 -0
  34. package/dist/db/models/procedure_run.model.js +39 -0
  35. package/dist/db/models/procedure_run.model.js.map +1 -0
  36. package/dist/db/models/stats.model.d.ts +73 -0
  37. package/dist/db/models/stats.model.js +267 -0
  38. package/dist/db/models/stats.model.js.map +1 -0
  39. package/dist/db/models/type_config.model.d.ts +47 -0
  40. package/dist/db/models/type_config.model.js +51 -0
  41. package/dist/db/models/type_config.model.js.map +1 -0
  42. package/dist/db/tables/action_type_config.table.d.ts +7 -0
  43. package/dist/db/tables/action_type_config.table.js +35 -0
  44. package/dist/db/tables/action_type_config.table.js.map +1 -0
  45. package/dist/db/tables/automation_template.table.d.ts +11 -0
  46. package/dist/db/tables/automation_template.table.js +52 -0
  47. package/dist/db/tables/automation_template.table.js.map +1 -0
  48. package/dist/db/tables/index.d.ts +5 -0
  49. package/dist/db/tables/index.js +22 -0
  50. package/dist/db/tables/index.js.map +1 -0
  51. package/dist/db/tables/procedure.table.d.ts +10 -0
  52. package/dist/db/tables/procedure.table.js +48 -0
  53. package/dist/db/tables/procedure.table.js.map +1 -0
  54. package/dist/db/tables/procedure_run.table.d.ts +13 -0
  55. package/dist/db/tables/procedure_run.table.js +57 -0
  56. package/dist/db/tables/procedure_run.table.js.map +1 -0
  57. package/dist/db/tables/trigger_type_config.table.d.ts +7 -0
  58. package/dist/db/tables/trigger_type_config.table.js +35 -0
  59. package/dist/db/tables/trigger_type_config.table.js.map +1 -0
  60. package/dist/implementations/dms-automation/index.d.ts +19 -0
  61. package/dist/implementations/dms-automation/index.js +50 -0
  62. package/dist/implementations/dms-automation/index.js.map +1 -0
  63. package/dist/index.d.ts +14 -0
  64. package/dist/index.js +121 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/pages/builder.d.ts +10 -0
  67. package/dist/pages/builder.js +28 -0
  68. package/dist/pages/builder.js.map +1 -0
  69. package/dist/pages/category.d.ts +1 -0
  70. package/dist/pages/category.js +10 -0
  71. package/dist/pages/category.js.map +1 -0
  72. package/dist/pages/index.d.ts +6 -0
  73. package/dist/pages/index.js +9 -0
  74. package/dist/pages/index.js.map +1 -0
  75. package/dist/pages/library.d.ts +10 -0
  76. package/dist/pages/library.js +28 -0
  77. package/dist/pages/library.js.map +1 -0
  78. package/dist/pages/overview.d.ts +10 -0
  79. package/dist/pages/overview.js +28 -0
  80. package/dist/pages/overview.js.map +1 -0
  81. package/dist/pages/procedures.d.ts +10 -0
  82. package/dist/pages/procedures.js +72 -0
  83. package/dist/pages/procedures.js.map +1 -0
  84. package/dist/pages/runs.d.ts +11 -0
  85. package/dist/pages/runs.js +61 -0
  86. package/dist/pages/runs.js.map +1 -0
  87. package/dist/routes/action-types.d.ts +23 -0
  88. package/dist/routes/action-types.js +80 -0
  89. package/dist/routes/action-types.js.map +1 -0
  90. package/dist/routes/data-node-types.d.ts +6 -0
  91. package/dist/routes/data-node-types.js +36 -0
  92. package/dist/routes/data-node-types.js.map +1 -0
  93. package/dist/routes/graphSchema.d.ts +92 -0
  94. package/dist/routes/graphSchema.js +60 -0
  95. package/dist/routes/graphSchema.js.map +1 -0
  96. package/dist/routes/index.d.ts +8 -0
  97. package/dist/routes/index.js +11 -0
  98. package/dist/routes/index.js.map +1 -0
  99. package/dist/routes/node-kinds.d.ts +9 -0
  100. package/dist/routes/node-kinds.js +35 -0
  101. package/dist/routes/node-kinds.js.map +1 -0
  102. package/dist/routes/procedures.d.ts +23 -0
  103. package/dist/routes/procedures.js +181 -0
  104. package/dist/routes/procedures.js.map +1 -0
  105. package/dist/routes/runs.d.ts +7 -0
  106. package/dist/routes/runs.js +81 -0
  107. package/dist/routes/runs.js.map +1 -0
  108. package/dist/routes/stats.d.ts +6 -0
  109. package/dist/routes/stats.js +35 -0
  110. package/dist/routes/stats.js.map +1 -0
  111. package/dist/routes/templates.d.ts +20 -0
  112. package/dist/routes/templates.js +243 -0
  113. package/dist/routes/templates.js.map +1 -0
  114. package/dist/routes/trigger-types.d.ts +24 -0
  115. package/dist/routes/trigger-types.js +80 -0
  116. package/dist/routes/trigger-types.js.map +1 -0
  117. package/dist/routes/typeConfigShared.d.ts +22 -0
  118. package/dist/routes/typeConfigShared.js +37 -0
  119. package/dist/routes/typeConfigShared.js.map +1 -0
  120. package/dist/runtime/builtins/actions/http.d.ts +13 -0
  121. package/dist/runtime/builtins/actions/http.js +47 -0
  122. package/dist/runtime/builtins/actions/http.js.map +1 -0
  123. package/dist/runtime/builtins/actions/index.d.ts +2 -0
  124. package/dist/runtime/builtins/actions/index.js +7 -0
  125. package/dist/runtime/builtins/actions/index.js.map +1 -0
  126. package/dist/runtime/builtins/actions/log.d.ts +13 -0
  127. package/dist/runtime/builtins/actions/log.js +49 -0
  128. package/dist/runtime/builtins/actions/log.js.map +1 -0
  129. package/dist/runtime/builtins/data/boolean.d.ts +2 -0
  130. package/dist/runtime/builtins/data/boolean.js +39 -0
  131. package/dist/runtime/builtins/data/boolean.js.map +1 -0
  132. package/dist/runtime/builtins/data/compare.d.ts +2 -0
  133. package/dist/runtime/builtins/data/compare.js +29 -0
  134. package/dist/runtime/builtins/data/compare.js.map +1 -0
  135. package/dist/runtime/builtins/data/constant.d.ts +2 -0
  136. package/dist/runtime/builtins/data/constant.js +29 -0
  137. package/dist/runtime/builtins/data/constant.js.map +1 -0
  138. package/dist/runtime/builtins/data/index.d.ts +2 -0
  139. package/dist/runtime/builtins/data/index.js +20 -0
  140. package/dist/runtime/builtins/data/index.js.map +1 -0
  141. package/dist/runtime/builtins/data/json.d.ts +2 -0
  142. package/dist/runtime/builtins/data/json.js +46 -0
  143. package/dist/runtime/builtins/data/json.js.map +1 -0
  144. package/dist/runtime/builtins/data/math.d.ts +2 -0
  145. package/dist/runtime/builtins/data/math.js +53 -0
  146. package/dist/runtime/builtins/data/math.js.map +1 -0
  147. package/dist/runtime/builtins/data/object.d.ts +2 -0
  148. package/dist/runtime/builtins/data/object.js +121 -0
  149. package/dist/runtime/builtins/data/object.js.map +1 -0
  150. package/dist/runtime/builtins/data/string.d.ts +2 -0
  151. package/dist/runtime/builtins/data/string.js +143 -0
  152. package/dist/runtime/builtins/data/string.js.map +1 -0
  153. package/dist/runtime/builtins/index.d.ts +17 -0
  154. package/dist/runtime/builtins/index.js +24 -0
  155. package/dist/runtime/builtins/index.js.map +1 -0
  156. package/dist/runtime/builtins/nodes/action.d.ts +1 -0
  157. package/dist/runtime/builtins/nodes/action.js +36 -0
  158. package/dist/runtime/builtins/nodes/action.js.map +1 -0
  159. package/dist/runtime/builtins/nodes/data.d.ts +1 -0
  160. package/dist/runtime/builtins/nodes/data.js +28 -0
  161. package/dist/runtime/builtins/nodes/data.js.map +1 -0
  162. package/dist/runtime/builtins/nodes/delay.d.ts +1 -0
  163. package/dist/runtime/builtins/nodes/delay.js +41 -0
  164. package/dist/runtime/builtins/nodes/delay.js.map +1 -0
  165. package/dist/runtime/builtins/nodes/forRange.d.ts +1 -0
  166. package/dist/runtime/builtins/nodes/forRange.js +52 -0
  167. package/dist/runtime/builtins/nodes/forRange.js.map +1 -0
  168. package/dist/runtime/builtins/nodes/foreach.d.ts +1 -0
  169. package/dist/runtime/builtins/nodes/foreach.js +31 -0
  170. package/dist/runtime/builtins/nodes/foreach.js.map +1 -0
  171. package/dist/runtime/builtins/nodes/groupInput.d.ts +1 -0
  172. package/dist/runtime/builtins/nodes/groupInput.js +11 -0
  173. package/dist/runtime/builtins/nodes/groupInput.js.map +1 -0
  174. package/dist/runtime/builtins/nodes/groupOutput.d.ts +1 -0
  175. package/dist/runtime/builtins/nodes/groupOutput.js +11 -0
  176. package/dist/runtime/builtins/nodes/groupOutput.js.map +1 -0
  177. package/dist/runtime/builtins/nodes/if.d.ts +1 -0
  178. package/dist/runtime/builtins/nodes/if.js +23 -0
  179. package/dist/runtime/builtins/nodes/if.js.map +1 -0
  180. package/dist/runtime/builtins/nodes/parallel.d.ts +1 -0
  181. package/dist/runtime/builtins/nodes/parallel.js +34 -0
  182. package/dist/runtime/builtins/nodes/parallel.js.map +1 -0
  183. package/dist/runtime/builtins/nodes/retry.d.ts +1 -0
  184. package/dist/runtime/builtins/nodes/retry.js +46 -0
  185. package/dist/runtime/builtins/nodes/retry.js.map +1 -0
  186. package/dist/runtime/builtins/nodes/setVariable.d.ts +1 -0
  187. package/dist/runtime/builtins/nodes/setVariable.js +31 -0
  188. package/dist/runtime/builtins/nodes/setVariable.js.map +1 -0
  189. package/dist/runtime/builtins/nodes/switch.d.ts +1 -0
  190. package/dist/runtime/builtins/nodes/switch.js +33 -0
  191. package/dist/runtime/builtins/nodes/switch.js.map +1 -0
  192. package/dist/runtime/builtins/nodes/trigger.d.ts +1 -0
  193. package/dist/runtime/builtins/nodes/trigger.js +25 -0
  194. package/dist/runtime/builtins/nodes/trigger.js.map +1 -0
  195. package/dist/runtime/builtins/nodes/tryCatch.d.ts +1 -0
  196. package/dist/runtime/builtins/nodes/tryCatch.js +35 -0
  197. package/dist/runtime/builtins/nodes/tryCatch.js.map +1 -0
  198. package/dist/runtime/builtins/triggers/cron.d.ts +9 -0
  199. package/dist/runtime/builtins/triggers/cron.js +52 -0
  200. package/dist/runtime/builtins/triggers/cron.js.map +1 -0
  201. package/dist/runtime/builtins/triggers/index.d.ts +2 -0
  202. package/dist/runtime/builtins/triggers/index.js +12 -0
  203. package/dist/runtime/builtins/triggers/index.js.map +1 -0
  204. package/dist/runtime/builtins/triggers/manual.d.ts +3 -0
  205. package/dist/runtime/builtins/triggers/manual.js +20 -0
  206. package/dist/runtime/builtins/triggers/manual.js.map +1 -0
  207. package/dist/runtime/builtins/triggers/webhook.d.ts +14 -0
  208. package/dist/runtime/builtins/triggers/webhook.js +90 -0
  209. package/dist/runtime/builtins/triggers/webhook.js.map +1 -0
  210. package/dist/runtime/executionResult.d.ts +6 -0
  211. package/dist/runtime/executionResult.js +3 -0
  212. package/dist/runtime/executionResult.js.map +1 -0
  213. package/dist/runtime/executor.d.ts +9 -0
  214. package/dist/runtime/executor.js +300 -0
  215. package/dist/runtime/executor.js.map +1 -0
  216. package/dist/runtime/flatten.d.ts +3 -0
  217. package/dist/runtime/flatten.js +188 -0
  218. package/dist/runtime/flatten.js.map +1 -0
  219. package/dist/runtime/nodeKinds.d.ts +64 -0
  220. package/dist/runtime/nodeKinds.js +43 -0
  221. package/dist/runtime/nodeKinds.js.map +1 -0
  222. package/dist/runtime/reconcileDiff.d.ts +9 -0
  223. package/dist/runtime/reconcileDiff.js +26 -0
  224. package/dist/runtime/reconcileDiff.js.map +1 -0
  225. package/dist/runtime/registry.d.ts +19 -0
  226. package/dist/runtime/registry.js +47 -0
  227. package/dist/runtime/registry.js.map +1 -0
  228. package/dist/runtime/resolveInputs.d.ts +14 -0
  229. package/dist/runtime/resolveInputs.js +64 -0
  230. package/dist/runtime/resolveInputs.js.map +1 -0
  231. package/dist/runtime/resolveSubgraph.d.ts +7 -0
  232. package/dist/runtime/resolveSubgraph.js +15 -0
  233. package/dist/runtime/resolveSubgraph.js.map +1 -0
  234. package/dist/runtime/subscriptions.d.ts +16 -0
  235. package/dist/runtime/subscriptions.js +419 -0
  236. package/dist/runtime/subscriptions.js.map +1 -0
  237. package/dist/runtime/subwalk.d.ts +17 -0
  238. package/dist/runtime/subwalk.js +74 -0
  239. package/dist/runtime/subwalk.js.map +1 -0
  240. package/dist/runtime/topo.d.ts +3 -0
  241. package/dist/runtime/topo.js +75 -0
  242. package/dist/runtime/topo.js.map +1 -0
  243. package/dist/runtime/typeOrigin.d.ts +7 -0
  244. package/dist/runtime/typeOrigin.js +24 -0
  245. package/dist/runtime/typeOrigin.js.map +1 -0
  246. package/dist/runtime/validate.d.ts +10 -0
  247. package/dist/runtime/validate.js +185 -0
  248. package/dist/runtime/validate.js.map +1 -0
  249. package/dist/runtime/validateTemplate.d.ts +3 -0
  250. package/dist/runtime/validateTemplate.js +54 -0
  251. package/dist/runtime/validateTemplate.js.map +1 -0
  252. package/dist/types/constants.d.ts +6 -0
  253. package/dist/types/constants.js +10 -0
  254. package/dist/types/constants.js.map +1 -0
  255. package/dist/types/graph.d.ts +51 -0
  256. package/dist/types/graph.js +23 -0
  257. package/dist/types/graph.js.map +1 -0
  258. package/dist/types/pagination.d.ts +8 -0
  259. package/dist/types/pagination.js +3 -0
  260. package/dist/types/pagination.js.map +1 -0
  261. package/dist/types/runLog.d.ts +26 -0
  262. package/dist/types/runLog.js +3 -0
  263. package/dist/types/runLog.js.map +1 -0
  264. package/frontend-vue/.prettierignore +4 -0
  265. package/frontend-vue/app/components/Actions.vue +141 -0
  266. package/frontend-vue/app/components/Catalog/TypeConfigForm.vue +166 -0
  267. package/frontend-vue/app/components/Catalog/TypeList.vue +198 -0
  268. package/frontend-vue/app/components/DataNodes.vue +259 -0
  269. package/frontend-vue/app/components/Editor/BuilderPalette.vue +234 -0
  270. package/frontend-vue/app/components/Editor/GraphCanvas.vue +994 -0
  271. package/frontend-vue/app/components/Editor/GroupPortEditor.vue +289 -0
  272. package/frontend-vue/app/components/Editor/JsonField.vue +63 -0
  273. package/frontend-vue/app/components/Editor/NodeInspector.vue +356 -0
  274. package/frontend-vue/app/components/Editor/ProcedureList.vue +156 -0
  275. package/frontend-vue/app/components/Editor/RunsDrawer.vue +312 -0
  276. package/frontend-vue/app/components/Editor/WiredField.vue +42 -0
  277. package/frontend-vue/app/components/Editor/nodes/GenericNode.vue +161 -0
  278. package/frontend-vue/app/components/Editor/nodes/GroupInputNode.vue +19 -0
  279. package/frontend-vue/app/components/Editor/nodes/GroupNode.vue +200 -0
  280. package/frontend-vue/app/components/Editor/nodes/GroupOutputNode.vue +19 -0
  281. package/frontend-vue/app/components/Editor/nodes/GroupSentinel.vue +161 -0
  282. package/frontend-vue/app/components/Editor/nodes/styles.ts +53 -0
  283. package/frontend-vue/app/components/Editor.vue +2504 -0
  284. package/frontend-vue/app/components/Library.vue +67 -0
  285. package/frontend-vue/app/components/Overview.vue +503 -0
  286. package/frontend-vue/app/components/RunDetailDrawer.vue +165 -0
  287. package/frontend-vue/app/components/RunFireTree.vue +170 -0
  288. package/frontend-vue/app/components/RunTraceDrawer.vue +59 -0
  289. package/frontend-vue/app/components/RunsStats.vue +126 -0
  290. package/frontend-vue/app/components/RunsTimelineDisplay.vue +287 -0
  291. package/frontend-vue/app/components/Templates.vue +663 -0
  292. package/frontend-vue/app/components/Triggers.vue +137 -0
  293. package/frontend-vue/app/composables/useAutomationNodeKinds.ts +48 -0
  294. package/frontend-vue/app/composables/useAutomationRuns.ts +75 -0
  295. package/frontend-vue/app/composables/useGraphConnect.ts +542 -0
  296. package/frontend-vue/app/plugins/runs-timeline-display.client.ts +16 -0
  297. package/frontend-vue/app/utils/automation.ts +51 -0
  298. package/frontend-vue/dms.frontend.ts +26 -0
  299. package/frontend-vue/eslint.config.mjs +24 -0
  300. package/frontend-vue/i18n/locales/dms-automation-en-GB.json +369 -0
  301. package/frontend-vue/i18n/locales/dms-automation-fr-FR.json +369 -0
  302. package/frontend-vue/package.json +33 -0
  303. package/frontend-vue/pnpm-lock.yaml +6483 -0
  304. package/frontend-vue/pnpm-workspace.yaml +2 -0
  305. package/package.json +81 -0
@@ -0,0 +1,166 @@
1
+ <script setup lang="ts">
2
+ import { computed, ref, watch } from 'vue'
3
+ import type { JsonSchema } from '../../composables/useGraphConnect'
4
+
5
+ interface CatalogType {
6
+ id: string
7
+ name: string
8
+ description?: string
9
+ icon?: string
10
+ }
11
+
12
+ // `schema` is the JSON schema of the selected type's configuration, read from
13
+ // whichever field the catalog exposes it under (trigger types: `configSchema`,
14
+ // action types: `inputSchema`). Rendered read-only next to the config editor.
15
+ const props = defineProps<{
16
+ type: CatalogType | null
17
+ schema?: JsonSchema
18
+ savedConfig: string | null
19
+ savedEnabled: boolean
20
+ }>()
21
+
22
+ const emit = defineEmits<{
23
+ (e: 'save', payload: { enabled: boolean; config: string }): void
24
+ }>()
25
+
26
+ const enabled = ref<boolean>(props.savedEnabled)
27
+ const configText = ref<string>(props.savedConfig ?? '{}')
28
+ const parseError = ref<string | null>(null)
29
+
30
+ watch(
31
+ () => props.type?.id,
32
+ () => {
33
+ enabled.value = props.savedEnabled
34
+ configText.value = props.savedConfig ?? '{}'
35
+ parseError.value = null
36
+ },
37
+ )
38
+
39
+ watch(
40
+ () => props.savedConfig,
41
+ (v) => {
42
+ if (v !== null && v !== undefined) {
43
+ configText.value = v
44
+ }
45
+ },
46
+ )
47
+
48
+ watch(
49
+ () => props.savedEnabled,
50
+ (v) => {
51
+ enabled.value = v
52
+ },
53
+ )
54
+
55
+ function validate() {
56
+ try {
57
+ JSON.parse(configText.value || '{}')
58
+ parseError.value = null
59
+ return true
60
+ } catch (e) {
61
+ parseError.value = (e as Error).message
62
+ return false
63
+ }
64
+ }
65
+
66
+ const schemaPretty = computed(() =>
67
+ props.schema ? JSON.stringify(props.schema, null, 2) : '',
68
+ )
69
+
70
+ function onSave() {
71
+ if (!validate()) return
72
+ emit('save', {
73
+ enabled: enabled.value,
74
+ config: configText.value || '{}',
75
+ })
76
+ }
77
+ </script>
78
+
79
+ <template>
80
+ <DmsCard
81
+ v-if="!type"
82
+ class="flex min-h-[16rem] items-center justify-center text-center"
83
+ >
84
+ <div class="flex flex-col items-center gap-3 text-dimmed">
85
+ <UIcon name="i-ph-faders" class="size-8" />
86
+ <p class="max-w-xs text-sm">
87
+ {{ $t('dms_automation.catalog.selectPrompt') }}
88
+ </p>
89
+ </div>
90
+ </DmsCard>
91
+
92
+ <DmsCard v-else :padded="false" class="flex flex-col">
93
+ <div class="flex items-start gap-3 border-b border-default px-5 py-4 sm:px-6">
94
+ <div
95
+ class="grid size-10 shrink-0 place-items-center rounded-lg bg-primary/10 text-primary ring ring-primary/20"
96
+ >
97
+ <UIcon :name="type.icon || 'i-ph-puzzle-piece'" class="size-5" />
98
+ </div>
99
+ <div class="min-w-0 flex-1">
100
+ <h2 class="truncate text-lg font-semibold text-highlighted">
101
+ {{ type.name }}
102
+ </h2>
103
+ <p v-if="type.description" class="text-sm text-muted">
104
+ {{ type.description }}
105
+ </p>
106
+ <p class="mt-1 font-mono text-xs text-dimmed">{{ type.id }}</p>
107
+ </div>
108
+ </div>
109
+
110
+ <div class="flex flex-col gap-5 px-5 py-4 sm:px-6">
111
+ <div class="flex items-center justify-between gap-4">
112
+ <div>
113
+ <div class="text-sm font-medium text-highlighted">
114
+ {{ $t('dms_automation.catalog.enabled') }}
115
+ </div>
116
+ <div class="text-xs text-muted">
117
+ {{ $t('dms_automation.catalog.enabledHelp') }}
118
+ </div>
119
+ </div>
120
+ <USwitch v-model="enabled" />
121
+ </div>
122
+
123
+ <div v-if="schemaPretty" class="flex flex-col gap-1.5">
124
+ <div class="text-sm font-medium text-highlighted">
125
+ {{ $t('dms_automation.catalog.configSchema') }}
126
+ </div>
127
+ <pre
128
+ class="max-h-48 overflow-auto rounded-lg border border-default bg-muted p-3 font-mono text-xs text-toned"
129
+ >{{ schemaPretty }}</pre>
130
+ </div>
131
+
132
+ <div class="flex flex-col gap-1.5">
133
+ <div class="text-sm font-medium text-highlighted">
134
+ {{ $t('dms_automation.catalog.globalConfig') }}
135
+ </div>
136
+ <UTextarea
137
+ v-model="configText"
138
+ :rows="10"
139
+ class="w-full font-mono"
140
+ autoresize
141
+ @blur="validate"
142
+ />
143
+ </div>
144
+
145
+ <UAlert
146
+ v-if="parseError"
147
+ color="error"
148
+ variant="subtle"
149
+ icon="i-ph-warning"
150
+ :title="$t('dms_automation.catalog.invalidJson')"
151
+ :description="parseError"
152
+ />
153
+
154
+ <div class="flex justify-end">
155
+ <UButton
156
+ color="primary"
157
+ icon="i-ph-floppy-disk"
158
+ :disabled="!!parseError"
159
+ @click="onSave"
160
+ >
161
+ {{ $t('dms_automation.catalog.save') }}
162
+ </UButton>
163
+ </div>
164
+ </div>
165
+ </DmsCard>
166
+ </template>
@@ -0,0 +1,198 @@
1
+ <script lang="ts">
2
+ // The `generic` attribute is compiled into the component's module scope, where
3
+ // a type declared inside `<script setup>` does not exist yet. Catalog entries
4
+ // therefore describe themselves here.
5
+ export interface CatalogType {
6
+ id: string
7
+ name: string
8
+ description?: string
9
+ icon?: string
10
+ }
11
+ </script>
12
+
13
+ <script setup lang="ts" generic="T extends CatalogType">
14
+ import { computed, ref } from 'vue'
15
+
16
+ const props = withDefaults(
17
+ defineProps<{
18
+ types: T[]
19
+ modelValue: string | null
20
+ groupBy?: (t: T) => string
21
+ title?: string
22
+ /** Show the inline search box (on by default). */
23
+ searchable?: boolean
24
+ /** Placeholder for the search box; falls back to a generic label. */
25
+ searchPlaceholder?: string
26
+ }>(),
27
+ // A bare `boolean` prop defaults to `false` when omitted, which would
28
+ // silently hide search on every catalog; pin the intended on-by-default.
29
+ { searchable: true },
30
+ )
31
+
32
+ const emit = defineEmits<{
33
+ (e: 'update:modelValue', value: string): void
34
+ }>()
35
+
36
+ function select(id: string) {
37
+ emit('update:modelValue', id)
38
+ }
39
+
40
+ const isSelected = (id: string) => props.modelValue === id
41
+
42
+ // Search defaults to on; pass `:searchable="false"` to opt out.
43
+ const searchEnabled = computed(() => props.searchable !== false)
44
+ const query = ref('')
45
+
46
+ // Case-insensitive substring filter over name / description / id. Catalogs hold
47
+ // at most a few hundred registered types, so a per-keystroke scan is cheap and
48
+ // avoids pulling in a fuzzy-match dependency.
49
+ const visibleTypes = computed<T[]>(() => {
50
+ const q = query.value.trim().toLowerCase()
51
+ if (!searchEnabled.value || !q) return props.types
52
+ return props.types.filter(
53
+ (t) =>
54
+ t.name?.toLowerCase().includes(q) ||
55
+ t.description?.toLowerCase().includes(q) ||
56
+ t.id?.toLowerCase().includes(q),
57
+ )
58
+ })
59
+
60
+ // Group the types by the optional groupBy callback. Preserve insertion order:
61
+ // groups appear in the order of their first-seen member.
62
+ const grouped = computed<Array<{ key: string; items: T[] }> | null>(() => {
63
+ if (!props.groupBy) return null
64
+ const order: string[] = []
65
+ const byKey = new Map<string, T[]>()
66
+ for (const t of visibleTypes.value) {
67
+ const key = props.groupBy(t)
68
+ const bucket = byKey.get(key)
69
+ if (bucket) {
70
+ bucket.push(t)
71
+ } else {
72
+ byKey.set(key, [t])
73
+ order.push(key)
74
+ }
75
+ }
76
+ return order.map((key) => ({ key, items: byKey.get(key) as T[] }))
77
+ })
78
+
79
+ const itemClass = (id: string) =>
80
+ isSelected(id)
81
+ ? 'bg-primary/10 text-primary ring-1 ring-primary/20'
82
+ : 'text-toned hover:bg-elevated/60'
83
+ </script>
84
+
85
+ <template>
86
+ <DmsCard :padded="false" class="flex flex-col overflow-hidden">
87
+ <div
88
+ v-if="title"
89
+ class="flex items-center justify-between gap-2 border-b border-default px-4 py-3"
90
+ >
91
+ <h2 class="text-sm font-semibold text-highlighted">{{ title }}</h2>
92
+ <UBadge color="neutral" variant="subtle" size="sm" class="tabular-nums">
93
+ {{ visibleTypes.length }}
94
+ </UBadge>
95
+ </div>
96
+
97
+ <div
98
+ v-if="searchEnabled && types.length"
99
+ class="border-b border-default px-3 py-2"
100
+ >
101
+ <UInput
102
+ v-model="query"
103
+ :placeholder="searchPlaceholder || $t('dms_automation.catalog.search')"
104
+ icon="i-ph-magnifying-glass"
105
+ size="sm"
106
+ autocomplete="off"
107
+ class="w-full"
108
+ />
109
+ </div>
110
+
111
+ <div class="flex-1 overflow-y-auto p-2">
112
+ <div
113
+ v-if="!types || types.length === 0"
114
+ class="px-3 py-6 text-center text-sm text-dimmed"
115
+ >
116
+ {{ $t('dms_automation.catalog.empty') }}
117
+ </div>
118
+
119
+ <div
120
+ v-else-if="visibleTypes.length === 0"
121
+ class="px-3 py-6 text-center text-sm text-dimmed"
122
+ >
123
+ {{ $t('dms_automation.catalog.noResults') }}
124
+ </div>
125
+
126
+ <template v-else-if="grouped">
127
+ <div
128
+ v-for="group in grouped"
129
+ :key="group.key"
130
+ class="mb-2 flex flex-col gap-1 last:mb-0"
131
+ >
132
+ <div
133
+ class="px-3 pb-1 pt-2 text-xs font-semibold uppercase tracking-wide text-dimmed"
134
+ >
135
+ {{ group.key }}
136
+ </div>
137
+ <ul class="flex flex-col gap-1">
138
+ <li v-for="t in group.items" :key="t.id">
139
+ <button
140
+ type="button"
141
+ class="flex w-full items-start gap-3 rounded-lg px-3 py-2 text-left transition-colors"
142
+ :class="itemClass(t.id)"
143
+ @click="select(t.id)"
144
+ >
145
+ <UIcon
146
+ v-if="t.icon"
147
+ :name="t.icon"
148
+ class="mt-0.5 size-4 shrink-0"
149
+ :class="isSelected(t.id) ? 'text-primary' : 'text-dimmed'"
150
+ />
151
+ <div class="min-w-0 flex-1">
152
+ <div
153
+ class="truncate text-sm font-medium"
154
+ :class="isSelected(t.id) ? 'text-primary' : 'text-highlighted'"
155
+ >
156
+ {{ t.name }}
157
+ </div>
158
+ <div v-if="t.description" class="truncate text-xs text-muted">
159
+ {{ t.description }}
160
+ </div>
161
+ </div>
162
+ </button>
163
+ </li>
164
+ </ul>
165
+ </div>
166
+ </template>
167
+
168
+ <ul v-else class="flex flex-col gap-1">
169
+ <li v-for="t in visibleTypes" :key="t.id">
170
+ <button
171
+ type="button"
172
+ class="flex w-full items-start gap-3 rounded-lg px-3 py-2 text-left transition-colors"
173
+ :class="itemClass(t.id)"
174
+ @click="select(t.id)"
175
+ >
176
+ <UIcon
177
+ v-if="t.icon"
178
+ :name="t.icon"
179
+ class="mt-0.5 size-4 shrink-0"
180
+ :class="isSelected(t.id) ? 'text-primary' : 'text-dimmed'"
181
+ />
182
+ <div class="min-w-0 flex-1">
183
+ <div
184
+ class="truncate text-sm font-medium"
185
+ :class="isSelected(t.id) ? 'text-primary' : 'text-highlighted'"
186
+ >
187
+ {{ t.name }}
188
+ </div>
189
+ <div v-if="t.description" class="truncate text-xs text-muted">
190
+ {{ t.description }}
191
+ </div>
192
+ </div>
193
+ </button>
194
+ </li>
195
+ </ul>
196
+ </div>
197
+ </DmsCard>
198
+ </template>
@@ -0,0 +1,259 @@
1
+ <script setup lang="ts">
2
+ import { computed, ref } from 'vue'
3
+ import { type ListEnvelope, unwrapList } from '../utils/automation'
4
+ import type {
5
+ DataNodeType,
6
+ JsonSchema,
7
+ JsonSchemaProperty,
8
+ } from '../composables/useGraphConnect'
9
+
10
+ // Catalog-side shape: backend returns DataNodeType minus `evaluate`.
11
+ type DataNodeTypeItem = Omit<DataNodeType, 'inputSchema' | 'outputSchema'> & {
12
+ inputSchema?: JsonSchema
13
+ outputSchema?: JsonSchema
14
+ }
15
+
16
+ type JsonSchemaProp = JsonSchemaProperty
17
+
18
+ interface PortRow {
19
+ name: string
20
+ type: string | string[]
21
+ description?: string
22
+ }
23
+
24
+ // `embedded` drops the page-head when this catalog is rendered inside a Library tab.
25
+ defineProps<{ embedded?: boolean }>()
26
+
27
+ const { $authFetch } = useAuthFetch()
28
+
29
+ const items = ref<DataNodeTypeItem[]>([])
30
+ const loading = ref(false)
31
+ const loadError = ref<string | null>(null)
32
+ const selectedId = ref<string | null>(null)
33
+
34
+ async function loadList() {
35
+ loading.value = true
36
+ loadError.value = null
37
+ try {
38
+ const data = await $authFetch<DataNodeTypeItem[] | ListEnvelope<DataNodeTypeItem>>(
39
+ '/api/automation/data-node-types',
40
+ )
41
+ items.value = unwrapList(data)
42
+ if (!selectedId.value && items.value[0]) {
43
+ selectedId.value = items.value[0].id
44
+ }
45
+ } catch (e) {
46
+ loadError.value = (e as Error).message ?? 'Failed to load data node types'
47
+ } finally {
48
+ loading.value = false
49
+ }
50
+ }
51
+
52
+ await loadList()
53
+
54
+ const selectedType = computed<DataNodeTypeItem | null>(
55
+ () => items.value.find((t) => t.id === selectedId.value) ?? null,
56
+ )
57
+
58
+ function propsOf(schema: JsonSchema | undefined): PortRow[] {
59
+ const props = schema?.properties ?? {}
60
+ return Object.entries(props).map(([name, p]) => ({
61
+ name,
62
+ type: (p as JsonSchemaProp)?.type ?? 'any',
63
+ description: (p as JsonSchemaProp)?.description,
64
+ }))
65
+ }
66
+
67
+ const inputs = computed<PortRow[]>(() => propsOf(selectedType.value?.inputSchema))
68
+ const outputs = computed<PortRow[]>(() => propsOf(selectedType.value?.outputSchema))
69
+
70
+ function categoryOf(t: DataNodeTypeItem): string {
71
+ return t.category ?? 'other'
72
+ }
73
+ </script>
74
+
75
+ <template>
76
+ <div :class="embedded ? 'flex flex-col gap-5' : 'flex flex-col gap-6 p-4 sm:p-6'">
77
+ <section v-if="!embedded" class="flex flex-wrap items-center gap-4">
78
+ <div
79
+ class="grid size-11 shrink-0 place-items-center rounded-xl bg-primary/10 text-primary ring ring-primary/20"
80
+ >
81
+ <UIcon name="i-ph-cube" class="size-6" />
82
+ </div>
83
+ <div class="min-w-0 flex-1">
84
+ <h1 class="text-2xl font-semibold tracking-tight text-highlighted">
85
+ {{ $t('dms_automation.data_nodes.title') }}
86
+ </h1>
87
+ <p class="text-sm text-muted">
88
+ {{ $t('dms_automation.data_nodes.description') }}
89
+ </p>
90
+ </div>
91
+ <UButton
92
+ class="ml-auto"
93
+ color="neutral"
94
+ variant="outline"
95
+ icon="i-ph-arrows-clockwise"
96
+ :loading="loading"
97
+ @click="loadList"
98
+ >
99
+ {{ $t('dms_automation.data_nodes.refresh') }}
100
+ </UButton>
101
+ </section>
102
+
103
+ <UAlert
104
+ v-if="loadError"
105
+ color="error"
106
+ variant="subtle"
107
+ icon="i-ph-warning"
108
+ :title="$t('dms_automation.data_nodes.loadError')"
109
+ :description="loadError"
110
+ />
111
+
112
+ <div
113
+ class="grid grid-cols-1 gap-5 lg:grid-cols-[minmax(280px,340px)_1fr] lg:items-start"
114
+ >
115
+ <DmsAutomationTypeList
116
+ :types="items"
117
+ :model-value="selectedId"
118
+ :group-by="categoryOf"
119
+ :title="$t('dms_automation.data_nodes.listLabel')"
120
+ class="lg:max-h-[calc(100vh-12rem)]"
121
+ @update:model-value="selectedId = $event"
122
+ />
123
+
124
+ <DmsCard v-if="selectedType" :padded="false" class="flex flex-col">
125
+ <div class="flex items-start gap-3 border-b border-default px-5 py-4 sm:px-6">
126
+ <div
127
+ class="grid size-10 shrink-0 place-items-center rounded-lg bg-primary/10 text-primary ring ring-primary/20"
128
+ >
129
+ <UIcon :name="selectedType.icon || 'i-ph-cube'" class="size-5" />
130
+ </div>
131
+ <div class="min-w-0 flex-1">
132
+ <h2 class="truncate text-lg font-semibold text-highlighted">
133
+ {{ selectedType.name }}
134
+ </h2>
135
+ <p class="mt-1 font-mono text-xs text-dimmed">{{ selectedType.id }}</p>
136
+ </div>
137
+ <UBadge
138
+ v-if="selectedType.category"
139
+ color="neutral"
140
+ variant="subtle"
141
+ class="shrink-0"
142
+ >
143
+ {{ selectedType.category }}
144
+ </UBadge>
145
+ </div>
146
+
147
+ <div class="flex flex-col gap-6 px-5 py-4 sm:px-6">
148
+ <p v-if="selectedType.description" class="text-sm text-toned">
149
+ {{ selectedType.description }}
150
+ </p>
151
+
152
+ <div class="flex flex-col gap-2">
153
+ <div class="text-sm font-semibold text-highlighted">
154
+ {{ $t('dms_automation.data_nodes.inputs') }}
155
+ </div>
156
+ <div v-if="inputs.length === 0" class="text-sm text-dimmed">
157
+ {{ $t('dms_automation.data_nodes.noPorts') }}
158
+ </div>
159
+ <div
160
+ v-else
161
+ class="overflow-hidden rounded-lg border border-default"
162
+ >
163
+ <table class="w-full text-sm">
164
+ <thead>
165
+ <tr class="border-b border-default bg-muted">
166
+ <th class="px-4 py-2.5 text-left text-xs font-semibold text-dimmed">
167
+ {{ $t('dms_automation.data_nodes.col.name') }}
168
+ </th>
169
+ <th class="px-4 py-2.5 text-left text-xs font-semibold text-dimmed">
170
+ {{ $t('dms_automation.data_nodes.col.type') }}
171
+ </th>
172
+ <th class="px-4 py-2.5 text-left text-xs font-semibold text-dimmed">
173
+ {{ $t('dms_automation.data_nodes.col.description') }}
174
+ </th>
175
+ </tr>
176
+ </thead>
177
+ <tbody>
178
+ <tr
179
+ v-for="row in inputs"
180
+ :key="`in-${row.name}`"
181
+ class="border-b border-default/60 last:border-0"
182
+ >
183
+ <td class="px-4 py-2.5 font-mono text-highlighted">
184
+ {{ row.name }}
185
+ </td>
186
+ <td class="whitespace-nowrap px-4 py-2.5 font-mono text-primary">
187
+ {{ row.type }}
188
+ </td>
189
+ <td class="px-4 py-2.5 text-muted">
190
+ {{ row.description ?? '' }}
191
+ </td>
192
+ </tr>
193
+ </tbody>
194
+ </table>
195
+ </div>
196
+ </div>
197
+
198
+ <div class="flex flex-col gap-2">
199
+ <div class="text-sm font-semibold text-highlighted">
200
+ {{ $t('dms_automation.data_nodes.outputs') }}
201
+ </div>
202
+ <div v-if="outputs.length === 0" class="text-sm text-dimmed">
203
+ {{ $t('dms_automation.data_nodes.noPorts') }}
204
+ </div>
205
+ <div
206
+ v-else
207
+ class="overflow-hidden rounded-lg border border-default"
208
+ >
209
+ <table class="w-full text-sm">
210
+ <thead>
211
+ <tr class="border-b border-default bg-muted">
212
+ <th class="px-4 py-2.5 text-left text-xs font-semibold text-dimmed">
213
+ {{ $t('dms_automation.data_nodes.col.name') }}
214
+ </th>
215
+ <th class="px-4 py-2.5 text-left text-xs font-semibold text-dimmed">
216
+ {{ $t('dms_automation.data_nodes.col.type') }}
217
+ </th>
218
+ <th class="px-4 py-2.5 text-left text-xs font-semibold text-dimmed">
219
+ {{ $t('dms_automation.data_nodes.col.description') }}
220
+ </th>
221
+ </tr>
222
+ </thead>
223
+ <tbody>
224
+ <tr
225
+ v-for="row in outputs"
226
+ :key="`out-${row.name}`"
227
+ class="border-b border-default/60 last:border-0"
228
+ >
229
+ <td class="px-4 py-2.5 font-mono text-highlighted">
230
+ {{ row.name }}
231
+ </td>
232
+ <td class="whitespace-nowrap px-4 py-2.5 font-mono text-primary">
233
+ {{ row.type }}
234
+ </td>
235
+ <td class="px-4 py-2.5 text-muted">
236
+ {{ row.description ?? '' }}
237
+ </td>
238
+ </tr>
239
+ </tbody>
240
+ </table>
241
+ </div>
242
+ </div>
243
+ </div>
244
+ </DmsCard>
245
+
246
+ <DmsCard
247
+ v-else
248
+ class="flex min-h-[16rem] items-center justify-center text-center"
249
+ >
250
+ <div class="flex flex-col items-center gap-3 text-dimmed">
251
+ <UIcon name="i-ph-cube" class="size-8" />
252
+ <p class="max-w-xs text-sm">
253
+ {{ $t('dms_automation.data_nodes.empty') }}
254
+ </p>
255
+ </div>
256
+ </DmsCard>
257
+ </div>
258
+ </div>
259
+ </template>