@revenexx/studio-integrations 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 (106) hide show
  1. package/README.md +51 -0
  2. package/dist/module.d.mts +6 -0
  3. package/dist/module.json +9 -0
  4. package/dist/module.mjs +45 -0
  5. package/dist/runtime/components/Integrations/Layout.d.vue.ts +12 -0
  6. package/dist/runtime/components/Integrations/Layout.vue +20 -0
  7. package/dist/runtime/components/Integrations/Layout.vue.d.ts +12 -0
  8. package/dist/runtime/components/Integrations/NodeInspector.d.vue.ts +16 -0
  9. package/dist/runtime/components/Integrations/NodeInspector.vue +450 -0
  10. package/dist/runtime/components/Integrations/NodeInspector.vue.d.ts +16 -0
  11. package/dist/runtime/components/Integrations/NodePalette.d.vue.ts +2 -0
  12. package/dist/runtime/components/Integrations/NodePalette.vue +140 -0
  13. package/dist/runtime/components/Integrations/NodePalette.vue.d.ts +2 -0
  14. package/dist/runtime/components/Integrations/RunDetailDialog.d.vue.ts +11 -0
  15. package/dist/runtime/components/Integrations/RunDetailDialog.vue +169 -0
  16. package/dist/runtime/components/Integrations/RunDetailDialog.vue.d.ts +11 -0
  17. package/dist/runtime/components/Integrations/Sidebar.d.vue.ts +2 -0
  18. package/dist/runtime/components/Integrations/Sidebar.vue +32 -0
  19. package/dist/runtime/components/Integrations/Sidebar.vue.d.ts +2 -0
  20. package/dist/runtime/components/Integrations/WorkflowEdgeView.d.vue.ts +23 -0
  21. package/dist/runtime/components/Integrations/WorkflowEdgeView.vue +86 -0
  22. package/dist/runtime/components/Integrations/WorkflowEdgeView.vue.d.ts +23 -0
  23. package/dist/runtime/components/Integrations/WorkflowEditor.d.vue.ts +14 -0
  24. package/dist/runtime/components/Integrations/WorkflowEditor.vue +419 -0
  25. package/dist/runtime/components/Integrations/WorkflowEditor.vue.d.ts +14 -0
  26. package/dist/runtime/components/Integrations/WorkflowNodeView.d.vue.ts +11 -0
  27. package/dist/runtime/components/Integrations/WorkflowNodeView.vue +200 -0
  28. package/dist/runtime/components/Integrations/WorkflowNodeView.vue.d.ts +11 -0
  29. package/dist/runtime/components/Integrations/WorkflowTriggerView.d.vue.ts +8 -0
  30. package/dist/runtime/components/Integrations/WorkflowTriggerView.vue +82 -0
  31. package/dist/runtime/components/Integrations/WorkflowTriggerView.vue.d.ts +8 -0
  32. package/dist/runtime/components/Integrations/WorkflowsTable.d.vue.ts +6 -0
  33. package/dist/runtime/components/Integrations/WorkflowsTable.vue +268 -0
  34. package/dist/runtime/components/Integrations/WorkflowsTable.vue.d.ts +6 -0
  35. package/dist/runtime/components/Integrations/workflowLayout.d.ts +17 -0
  36. package/dist/runtime/components/Integrations/workflowLayout.js +29 -0
  37. package/dist/runtime/composables/integrationsApi.d.ts +13 -0
  38. package/dist/runtime/composables/integrationsApi.js +55 -0
  39. package/dist/runtime/composables/useCredentialTypes.d.ts +19 -0
  40. package/dist/runtime/composables/useCredentialTypes.js +47 -0
  41. package/dist/runtime/composables/useIntegrationsAudit.d.ts +26 -0
  42. package/dist/runtime/composables/useIntegrationsAudit.js +39 -0
  43. package/dist/runtime/composables/useIntegrationsCredentials.d.ts +43 -0
  44. package/dist/runtime/composables/useIntegrationsCredentials.js +98 -0
  45. package/dist/runtime/composables/useIntegrationsFocus.d.ts +16 -0
  46. package/dist/runtime/composables/useIntegrationsFocus.js +17 -0
  47. package/dist/runtime/composables/useIntegrationsNodes.d.ts +6 -0
  48. package/dist/runtime/composables/useIntegrationsNodes.js +32 -0
  49. package/dist/runtime/composables/useIntegrationsRuns.d.ts +31 -0
  50. package/dist/runtime/composables/useIntegrationsRuns.js +109 -0
  51. package/dist/runtime/composables/useIntegrationsSchedules.d.ts +14 -0
  52. package/dist/runtime/composables/useIntegrationsSchedules.js +32 -0
  53. package/dist/runtime/composables/useIntegrationsSecrets.d.ts +27 -0
  54. package/dist/runtime/composables/useIntegrationsSecrets.js +76 -0
  55. package/dist/runtime/composables/useIntegrationsTemplates.d.ts +19 -0
  56. package/dist/runtime/composables/useIntegrationsTemplates.js +141 -0
  57. package/dist/runtime/composables/useIntegrationsTriggers.d.ts +39 -0
  58. package/dist/runtime/composables/useIntegrationsTriggers.js +39 -0
  59. package/dist/runtime/composables/useIntegrationsWorkflows.d.ts +28 -0
  60. package/dist/runtime/composables/useIntegrationsWorkflows.js +152 -0
  61. package/dist/runtime/data/integrationNodeCatalog.d.ts +41 -0
  62. package/dist/runtime/data/integrationNodeCatalog.js +67 -0
  63. package/dist/runtime/data/integrationRuns.d.ts +7 -0
  64. package/dist/runtime/data/integrationRuns.js +109 -0
  65. package/dist/runtime/data/integrationTemplates.d.ts +11 -0
  66. package/dist/runtime/data/integrationTemplates.js +9 -0
  67. package/dist/runtime/data/integrationWorkflowSamples.d.ts +18 -0
  68. package/dist/runtime/data/integrationWorkflowSamples.js +318 -0
  69. package/dist/runtime/pages/integrations/audit.d.vue.ts +2 -0
  70. package/dist/runtime/pages/integrations/audit.vue +156 -0
  71. package/dist/runtime/pages/integrations/audit.vue.d.ts +2 -0
  72. package/dist/runtime/pages/integrations/credentials/oauth-complete.d.vue.ts +2 -0
  73. package/dist/runtime/pages/integrations/credentials/oauth-complete.vue +28 -0
  74. package/dist/runtime/pages/integrations/credentials/oauth-complete.vue.d.ts +2 -0
  75. package/dist/runtime/pages/integrations/credentials.d.vue.ts +2 -0
  76. package/dist/runtime/pages/integrations/credentials.vue +403 -0
  77. package/dist/runtime/pages/integrations/credentials.vue.d.ts +2 -0
  78. package/dist/runtime/pages/integrations/index.d.vue.ts +2 -0
  79. package/dist/runtime/pages/integrations/index.vue +226 -0
  80. package/dist/runtime/pages/integrations/index.vue.d.ts +2 -0
  81. package/dist/runtime/pages/integrations/runs.d.vue.ts +2 -0
  82. package/dist/runtime/pages/integrations/runs.vue +100 -0
  83. package/dist/runtime/pages/integrations/runs.vue.d.ts +2 -0
  84. package/dist/runtime/pages/integrations/schedules.d.vue.ts +2 -0
  85. package/dist/runtime/pages/integrations/schedules.vue +111 -0
  86. package/dist/runtime/pages/integrations/schedules.vue.d.ts +2 -0
  87. package/dist/runtime/pages/integrations/secrets.d.vue.ts +2 -0
  88. package/dist/runtime/pages/integrations/secrets.vue +248 -0
  89. package/dist/runtime/pages/integrations/secrets.vue.d.ts +2 -0
  90. package/dist/runtime/pages/integrations/workflows/[id].d.vue.ts +2 -0
  91. package/dist/runtime/pages/integrations/workflows/[id].vue +326 -0
  92. package/dist/runtime/pages/integrations/workflows/[id].vue.d.ts +2 -0
  93. package/dist/runtime/pages/integrations/workflows/index.d.vue.ts +2 -0
  94. package/dist/runtime/pages/integrations/workflows/index.vue +31 -0
  95. package/dist/runtime/pages/integrations/workflows/index.vue.d.ts +2 -0
  96. package/dist/runtime/pages/integrations/workflows/new.d.vue.ts +2 -0
  97. package/dist/runtime/pages/integrations/workflows/new.vue +153 -0
  98. package/dist/runtime/pages/integrations/workflows/new.vue.d.ts +2 -0
  99. package/dist/runtime/types/integrations.d.ts +427 -0
  100. package/dist/runtime/types/integrations.js +0 -0
  101. package/dist/runtime/utils/localize.d.ts +9 -0
  102. package/dist/runtime/utils/localize.js +21 -0
  103. package/dist/runtime/utils/statusStyle.d.ts +15 -0
  104. package/dist/runtime/utils/statusStyle.js +78 -0
  105. package/dist/types.d.mts +9 -0
  106. package/package.json +46 -0
@@ -0,0 +1,140 @@
1
+ <script setup>
2
+ import { computed, ref } from "vue";
3
+ import * as Lucide from "lucide-vue-next";
4
+ import { INTEGRATION_NODE_CATALOG, NODE_CATEGORIES, TRIGGER_TEMPLATES } from "../../data/integrationNodeCatalog";
5
+ const { load: loadNodes } = useIntegrationsNodes();
6
+ onMounted(() => {
7
+ void loadNodes();
8
+ });
9
+ const search = ref("");
10
+ function labelOf(value) {
11
+ if (!value) return "";
12
+ return typeof value === "string" ? value : Object.values(value)[0] ?? "";
13
+ }
14
+ function descOf(value) {
15
+ if (!value) return "";
16
+ return typeof value === "string" ? value : value.en ?? Object.values(value)[0] ?? "";
17
+ }
18
+ const grouped = computed(() => {
19
+ const q = search.value.trim().toLowerCase();
20
+ const matchesManifest = (m) => {
21
+ if (!q) return true;
22
+ return labelOf(m.name).toLowerCase().includes(q) || (m.slug ?? "").toLowerCase().includes(q) || descOf(m.description).toLowerCase().includes(q);
23
+ };
24
+ const matchesTrigger = (t) => {
25
+ if (!q) return true;
26
+ return labelOf(t.name).toLowerCase().includes(q) || t.type.includes(q) || t.id.includes(q);
27
+ };
28
+ const knownKeys = new Set(NODE_CATEGORIES.map((c) => String(c.key)));
29
+ const groups = NODE_CATEGORIES.map((cat) => {
30
+ const manifests = INTEGRATION_NODE_CATALOG.filter((m) => m.category === cat.key && matchesManifest(m));
31
+ const triggers = cat.key === "trigger" ? TRIGGER_TEMPLATES.filter(matchesTrigger) : [];
32
+ return { ...cat, manifests, triggers };
33
+ });
34
+ const other = INTEGRATION_NODE_CATALOG.filter((m) => !knownKeys.has(String(m.category ?? "")) && matchesManifest(m));
35
+ if (other.length) {
36
+ groups.push({ key: "other", label: "Nodes", color: "bg-slate-100 text-slate-500", manifests: other, triggers: [] });
37
+ }
38
+ return groups.filter((g) => g.manifests.length || g.triggers.length);
39
+ });
40
+ function iconFor(name) {
41
+ if (!name) return Lucide.Box;
42
+ const cleaned = (name.includes(":") ? name.split(":").pop() : name).split("-").map((s, i) => i === 0 ? s.charAt(0).toUpperCase() + s.slice(1) : s.charAt(0).toUpperCase() + s.slice(1)).join("");
43
+ const fallback = Lucide[cleaned];
44
+ if (fallback) return fallback;
45
+ return Lucide.Box;
46
+ }
47
+ function onManifestDragStart(manifest, ev) {
48
+ if (!ev.dataTransfer) return;
49
+ ev.dataTransfer.setData("application/integration-node", JSON.stringify({
50
+ kind: "manifest",
51
+ slug: manifest.slug,
52
+ version: manifest.version
53
+ }));
54
+ ev.dataTransfer.effectAllowed = "move";
55
+ }
56
+ function onTriggerDragStart(tpl, ev) {
57
+ if (!ev.dataTransfer) return;
58
+ ev.dataTransfer.setData("application/integration-node", JSON.stringify({
59
+ kind: "trigger",
60
+ type: tpl.type
61
+ }));
62
+ ev.dataTransfer.effectAllowed = "move";
63
+ }
64
+ </script>
65
+
66
+ <template>
67
+ <aside class="flex h-full w-60 shrink-0 flex-col border-r border-black/[0.06] bg-white">
68
+ <div class="p-3 border-b border-black/[0.06]">
69
+ <div class="text-mono text-muted-foreground mb-2">
70
+ Add node
71
+ </div>
72
+ <div class="relative">
73
+ <Lucide.Search :size="12" class="absolute left-2 top-1/2 -translate-y-1/2 text-muted-foreground" />
74
+ <input
75
+ v-model="search"
76
+ type="text"
77
+ placeholder="Search…"
78
+ class="h-7 w-full rounded-md border border-black/[0.08] bg-white pl-7 pr-2 text-sm focus:outline-none focus:ring-2 focus:ring-emerald-500/40"
79
+ >
80
+ </div>
81
+ </div>
82
+
83
+ <div class="flex-1 overflow-y-auto p-2 space-y-3">
84
+ <div v-for="cat in grouped" :key="cat.key">
85
+ <div class="px-2 py-1 text-mono text-muted-foreground">
86
+ {{ cat.label }}
87
+ </div>
88
+ <div class="space-y-0.5">
89
+ <!-- Trigger templates (only in the "trigger" category) -->
90
+ <div
91
+ v-for="t in cat.triggers"
92
+ :key="t.id"
93
+ class="group flex items-center gap-2 rounded-md border border-transparent px-2 py-1.5 cursor-grab transition hover:border-black/[0.08] hover:bg-muted/40 active:cursor-grabbing"
94
+ draggable="true"
95
+ :title="labelOf(t.name)"
96
+ @dragstart="onTriggerDragStart(t, $event)"
97
+ >
98
+ <span class="flex size-6 shrink-0 items-center justify-center rounded-md" :class="cat.color">
99
+ <component :is="iconFor(t.icon)" :size="13" />
100
+ </span>
101
+ <div class="min-w-0">
102
+ <div class="text-sm font-medium truncate">
103
+ {{ labelOf(t.name) }}
104
+ </div>
105
+ <div class="text-sm text-muted-foreground truncate">
106
+ {{ t.type }}
107
+ </div>
108
+ </div>
109
+ </div>
110
+
111
+ <!-- Real node manifests -->
112
+ <div
113
+ v-for="m in cat.manifests"
114
+ :key="`${m.slug}@${m.version}`"
115
+ class="group flex items-center gap-2 rounded-md border border-transparent px-2 py-1.5 cursor-grab transition hover:border-black/[0.08] hover:bg-muted/40 active:cursor-grabbing"
116
+ draggable="true"
117
+ :title="labelOf(m.name)"
118
+ @dragstart="onManifestDragStart(m, $event)"
119
+ >
120
+ <span class="flex size-6 shrink-0 items-center justify-center rounded-md" :class="cat.color">
121
+ <component :is="iconFor(m.icon)" :size="13" />
122
+ </span>
123
+ <div class="min-w-0">
124
+ <div class="text-sm font-medium truncate">
125
+ {{ labelOf(m.name) }}
126
+ </div>
127
+ <div class="text-sm text-muted-foreground truncate">
128
+ {{ m.slug }}@{{ m.version }}
129
+ </div>
130
+ </div>
131
+ </div>
132
+ </div>
133
+ </div>
134
+ </div>
135
+
136
+ <div class="border-t border-black/[0.06] px-3 py-2 text-sm text-muted-foreground">
137
+ Drag a node onto the canvas.
138
+ </div>
139
+ </aside>
140
+ </template>
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ export default _default;
@@ -0,0 +1,11 @@
1
+ import type { WorkflowRun } from '../../types/integrations.js';
2
+ type __VLS_Props = {
3
+ open: boolean;
4
+ run: WorkflowRun | null;
5
+ };
6
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
7
+ "update:open": (args_0: boolean) => any;
8
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
9
+ "onUpdate:open"?: ((args_0: boolean) => any) | undefined;
10
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
11
+ export default _default;
@@ -0,0 +1,169 @@
1
+ <script setup>
2
+ import { computed, ref, watch } from "vue";
3
+ import { RefreshCircle as Loader2, ArrowRightUp as OpenIcon } from "#solar-icons";
4
+ import {
5
+ Badge,
6
+ Button,
7
+ Dialog,
8
+ DialogContent,
9
+ DialogDescription,
10
+ DialogHeader,
11
+ DialogTitle
12
+ } from "@revenexx/studio";
13
+ import { statusClass } from "../../utils/statusStyle";
14
+ const props = defineProps({
15
+ open: { type: Boolean, required: true },
16
+ run: { type: [Object, null], required: true }
17
+ });
18
+ const emit = defineEmits(["update:open"]);
19
+ const router = useRouter();
20
+ const { getRun, getHistory, getStackTrace } = useIntegrationsRuns();
21
+ const loading = ref(false);
22
+ const result = ref(null);
23
+ const history = ref([]);
24
+ const historySource = ref(null);
25
+ const stackTrace = ref(null);
26
+ const loadError = ref(null);
27
+ function fmt(iso) {
28
+ if (!iso) return "\u2014";
29
+ try {
30
+ return new Date(iso).toLocaleString();
31
+ } catch {
32
+ return iso;
33
+ }
34
+ }
35
+ function fmtDuration(ms) {
36
+ if (ms == null) return "\u2014";
37
+ if (ms < 1e3) return `${ms}ms`;
38
+ if (ms < 6e4) return `${(ms / 1e3).toFixed(2)}s`;
39
+ return `${(ms / 6e4).toFixed(1)}m`;
40
+ }
41
+ const hasResult = computed(() => result.value != null && Object.keys(result.value).length > 0);
42
+ async function load() {
43
+ const run = props.run;
44
+ if (!run) return;
45
+ loading.value = true;
46
+ loadError.value = null;
47
+ result.value = null;
48
+ history.value = [];
49
+ stackTrace.value = null;
50
+ try {
51
+ const [runRes, histRes] = await Promise.allSettled([
52
+ getRun(run.workflowId, run.id),
53
+ getHistory(run.workflowId, run.id, { page_size: 50 })
54
+ ]);
55
+ if (runRes.status === "fulfilled") {
56
+ result.value = runRes.value?.result ?? null;
57
+ }
58
+ if (histRes.status === "fulfilled") {
59
+ history.value = histRes.value?.data ?? [];
60
+ historySource.value = histRes.value?.source ?? null;
61
+ }
62
+ if (run.status === "running" || run.status === "failed") {
63
+ try {
64
+ stackTrace.value = await getStackTrace(run.workflowId, run.id);
65
+ } catch {
66
+ stackTrace.value = null;
67
+ }
68
+ }
69
+ } catch (e) {
70
+ loadError.value = e?.message ?? "Could not load run details.";
71
+ } finally {
72
+ loading.value = false;
73
+ }
74
+ }
75
+ watch(() => [props.open, props.run?.id], () => {
76
+ if (props.open && props.run) void load();
77
+ }, { immediate: true });
78
+ function openWorkflow() {
79
+ if (props.run) router.push(`/integrations/workflows/${props.run.workflowId}`);
80
+ }
81
+ function eventLabel(ev) {
82
+ return String(ev.event_type ?? ev.eventType ?? ev.type ?? "event");
83
+ }
84
+ </script>
85
+
86
+ <template>
87
+ <Dialog :open="open" @update:open="(v) => emit('update:open', v)">
88
+ <DialogContent class="sm:max-w-2xl">
89
+ <DialogHeader>
90
+ <DialogTitle class="flex items-center gap-2">
91
+ <span class="truncate">{{ run?.workflowName ?? "Run" }}</span>
92
+ <Badge v-if="run" variant="outline" :class="['text-sm border', statusClass(run.status)]">
93
+ {{ run.status }}
94
+ </Badge>
95
+ </DialogTitle>
96
+ <DialogDescription class="font-mono text-sm">
97
+ Run {{ run?.id }}
98
+ </DialogDescription>
99
+ </DialogHeader>
100
+
101
+ <div v-if="run" class="space-y-4 max-h-[32rem] overflow-y-auto pr-1">
102
+ <!-- Facts -->
103
+ <div class="grid grid-cols-2 gap-x-6 gap-y-1 text-sm">
104
+ <div class="flex justify-between"><span class="text-muted-foreground">Trigger</span><span>{{ run.triggerType }}</span></div>
105
+ <div class="flex justify-between"><span class="text-muted-foreground">Duration</span><span class="tabular-nums">{{ fmtDuration(run.durationMs) }}</span></div>
106
+ <div class="flex justify-between"><span class="text-muted-foreground">Started</span><span class="tabular-nums">{{ fmt(run.startedAt) }}</span></div>
107
+ <div class="flex justify-between"><span class="text-muted-foreground">Finished</span><span class="tabular-nums">{{ fmt(run.finishedAt) }}</span></div>
108
+ </div>
109
+
110
+ <div v-if="run.errorMessage" class="rounded-md border border-rose-500/20 bg-rose-500/5 px-3 py-2 text-sm text-rose-700">
111
+ {{ run.errorMessage }}
112
+ </div>
113
+
114
+ <div v-if="loading" class="flex items-center gap-2 text-sm text-muted-foreground">
115
+ <Loader2 :size="14" class="animate-spin" /> Loading details…
116
+ </div>
117
+ <div v-else-if="loadError" class="text-sm text-rose-700">
118
+ {{ loadError }}
119
+ </div>
120
+
121
+ <template v-else>
122
+ <!-- Result -->
123
+ <section v-if="hasResult" class="space-y-1">
124
+ <h4 class="text-mono text-muted-foreground">
125
+ Result
126
+ </h4>
127
+ <pre class="rounded-md bg-muted/40 p-3 text-sm overflow-x-auto max-h-56">{{ JSON.stringify(result, null, 2) }}</pre>
128
+ </section>
129
+
130
+ <!-- History -->
131
+ <section v-if="history.length" class="space-y-1">
132
+ <h4 class="text-mono text-muted-foreground">
133
+ History <span v-if="historySource">· {{ historySource }}</span>
134
+ </h4>
135
+ <ol class="space-y-1">
136
+ <li
137
+ v-for="(ev, i) in history"
138
+ :key="i"
139
+ class="flex items-center gap-2 rounded-md border border-black/[0.05] bg-white px-2 py-1 text-sm"
140
+ >
141
+ <span class="tabular-nums text-muted-foreground w-8 shrink-0">{{ ev.event_id ?? i + 1 }}</span>
142
+ <span class="font-mono truncate">{{ eventLabel(ev) }}</span>
143
+ </li>
144
+ </ol>
145
+ </section>
146
+
147
+ <!-- Stack trace -->
148
+ <section v-if="stackTrace" class="space-y-1">
149
+ <h4 class="text-mono text-muted-foreground">
150
+ Stack trace
151
+ </h4>
152
+ <pre class="rounded-md bg-slate-900 text-slate-100 p-3 text-sm overflow-x-auto max-h-56">{{ stackTrace }}</pre>
153
+ </section>
154
+
155
+ <p v-if="!hasResult && !history.length && !stackTrace" class="text-sm text-muted-foreground">
156
+ No execution detail available for this run yet.
157
+ </p>
158
+ </template>
159
+ </div>
160
+
161
+ <div class="flex justify-end pt-2">
162
+ <Button variant="outline" size="sm" @click="openWorkflow">
163
+ <OpenIcon :size="14" class="mr-1" />
164
+ Open workflow
165
+ </Button>
166
+ </div>
167
+ </DialogContent>
168
+ </Dialog>
169
+ </template>
@@ -0,0 +1,11 @@
1
+ import type { WorkflowRun } from '../../types/integrations.js';
2
+ type __VLS_Props = {
3
+ open: boolean;
4
+ run: WorkflowRun | null;
5
+ };
6
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
7
+ "update:open": (args_0: boolean) => any;
8
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
9
+ "onUpdate:open"?: ((args_0: boolean) => any) | undefined;
10
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
11
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ export default _default;
@@ -0,0 +1,32 @@
1
+ <script setup>
2
+ import { Pulse as Activity, ClockCircle as Clock, Home, Key as KeyRound, ShieldCheck, ShieldKeyhole as Credentials, Programming as Workflow } from "#solar-icons";
3
+ const { workflows } = useIntegrationsWorkflows();
4
+ const { runningCount } = useIntegrationsRuns();
5
+ const { activeCount: schedulesActive } = useIntegrationsSchedules();
6
+ const { total: credentialsTotal } = useIntegrationsCredentials();
7
+ const { total: secretsTotal } = useIntegrationsSecrets();
8
+ const sections = computed(() => [
9
+ {
10
+ key: "pinned",
11
+ items: [
12
+ { label: "Dashboard", to: "/integrations", icon: Home, exact: true }
13
+ ]
14
+ },
15
+ {
16
+ key: "integrations",
17
+ label: "Integrations",
18
+ items: [
19
+ { label: "Workflows", to: "/integrations/workflows", icon: Workflow, badge: workflows.value.length || null },
20
+ { label: "Runs", to: "/integrations/runs", icon: Activity, badge: runningCount.value || null },
21
+ { label: "Schedules", to: "/integrations/schedules", icon: Clock, badge: schedulesActive.value || null },
22
+ { label: "Credentials", to: "/integrations/credentials", icon: Credentials, badge: credentialsTotal.value || null },
23
+ { label: "Secrets", to: "/integrations/secrets", icon: KeyRound, badge: secretsTotal.value || null },
24
+ { label: "Audit Log", to: "/integrations/audit", icon: ShieldCheck }
25
+ ]
26
+ }
27
+ ]);
28
+ </script>
29
+
30
+ <template>
31
+ <SidebarNav title="Integration Studio" :icon="Workflow" :sections="sections" minimal />
32
+ </template>
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ export default _default;
@@ -0,0 +1,23 @@
1
+ import { type EdgeProps } from '@vue-flow/core';
2
+ /**
3
+ * Enterprise-style smoothstep edge:
4
+ *
5
+ * - rounded right-angle routing (`getSmoothStepPath`)
6
+ * - arrow-head pointing into the target
7
+ * - color encodes the *source port kind* — branch outputs (`true`/`false`,
8
+ * switch cases) get a soft color, error outputs get rose, defaults stay
9
+ * slate
10
+ * - optional center label (used by the canvas to print branch names)
11
+ *
12
+ * The canvas creates these via `edgeTypes.flow = WorkflowEdgeView`. Edge
13
+ * data is passed through Vue Flow's `data` prop verbatim.
14
+ */
15
+ type EdgeKind = 'default' | 'success' | 'error' | 'branch-true' | 'branch-false' | 'branch';
16
+ interface Data {
17
+ kind: EdgeKind;
18
+ /** Optional human label shown mid-edge (e.g. "true", "cases:paid"). */
19
+ label?: string;
20
+ }
21
+ type __VLS_Props = EdgeProps<Data>;
22
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
23
+ export default _default;
@@ -0,0 +1,86 @@
1
+ <script setup>
2
+ import { computed } from "vue";
3
+ import {
4
+ BaseEdge,
5
+ EdgeLabelRenderer,
6
+ getSmoothStepPath
7
+ } from "@vue-flow/core";
8
+ const props = defineProps({
9
+ id: { type: String, required: true },
10
+ sourceNode: { type: Object, required: true },
11
+ targetNode: { type: Object, required: true },
12
+ source: { type: String, required: true },
13
+ target: { type: String, required: true },
14
+ type: { type: null, required: true },
15
+ label: { type: [String, Object, Function], required: false },
16
+ style: { type: Object, required: false },
17
+ selected: { type: Boolean, required: false },
18
+ sourcePosition: { type: String, required: true },
19
+ targetPosition: { type: String, required: true },
20
+ sourceHandleId: { type: String, required: false },
21
+ targetHandleId: { type: String, required: false },
22
+ animated: { type: Boolean, required: false },
23
+ updatable: { type: Boolean, required: false },
24
+ markerStart: { type: String, required: true },
25
+ markerEnd: { type: String, required: true },
26
+ curvature: { type: Number, required: false },
27
+ interactionWidth: { type: Number, required: false },
28
+ data: { type: Object, required: true },
29
+ events: { type: void 0, required: true },
30
+ labelStyle: { type: Object, required: false },
31
+ labelShowBg: { type: Boolean, required: false },
32
+ labelBgStyle: { type: Object, required: false },
33
+ labelBgPadding: { type: Array, required: false },
34
+ labelBgBorderRadius: { type: Number, required: false },
35
+ sourceX: { type: Number, required: true },
36
+ sourceY: { type: Number, required: true },
37
+ targetX: { type: Number, required: true },
38
+ targetY: { type: Number, required: true }
39
+ });
40
+ const path = computed(() => getSmoothStepPath({
41
+ sourceX: props.sourceX,
42
+ sourceY: props.sourceY,
43
+ sourcePosition: props.sourcePosition,
44
+ targetX: props.targetX,
45
+ targetY: props.targetY,
46
+ targetPosition: props.targetPosition,
47
+ borderRadius: 12
48
+ }));
49
+ const palette = {
50
+ default: { stroke: "#94a3b8", label: "#475569", bg: "#f1f5f9" },
51
+ success: { stroke: "#10b981", label: "#047857", bg: "#ecfdf5" },
52
+ error: { stroke: "#f43f5e", label: "#be123c", bg: "#fff1f2" },
53
+ "branch-true": { stroke: "#10b981", label: "#047857", bg: "#ecfdf5" },
54
+ "branch-false": { stroke: "#f59e0b", label: "#b45309", bg: "#fffbeb" },
55
+ branch: { stroke: "#8b5cf6", label: "#6d28d9", bg: "#f5f3ff" }
56
+ };
57
+ const color = computed(() => palette[props.data?.kind ?? "default"] ?? palette.default);
58
+ const isSelected = computed(() => props.selected);
59
+ </script>
60
+
61
+ <template>
62
+ <BaseEdge
63
+ :id="props.id"
64
+ :path="path[0]"
65
+ :marker-end="props.markerEnd"
66
+ :style="{
67
+ stroke: color.stroke,
68
+ strokeWidth: isSelected ? 2.5 : 1.75,
69
+ transition: 'stroke-width 120ms ease-out'
70
+ }"
71
+ />
72
+
73
+ <EdgeLabelRenderer v-if="props.data?.label">
74
+ <div
75
+ class="absolute pointer-events-none select-none rounded-md border px-1.5 py-0.5 text-mono shadow-sm"
76
+ :style="{
77
+ transform: `translate(-50%, -50%) translate(${path[1]}px, ${path[2]}px)`,
78
+ color: color.label,
79
+ background: color.bg,
80
+ borderColor: color.stroke + '55'
81
+ }"
82
+ >
83
+ {{ props.data.label }}
84
+ </div>
85
+ </EdgeLabelRenderer>
86
+ </template>
@@ -0,0 +1,23 @@
1
+ import { type EdgeProps } from '@vue-flow/core';
2
+ /**
3
+ * Enterprise-style smoothstep edge:
4
+ *
5
+ * - rounded right-angle routing (`getSmoothStepPath`)
6
+ * - arrow-head pointing into the target
7
+ * - color encodes the *source port kind* — branch outputs (`true`/`false`,
8
+ * switch cases) get a soft color, error outputs get rose, defaults stay
9
+ * slate
10
+ * - optional center label (used by the canvas to print branch names)
11
+ *
12
+ * The canvas creates these via `edgeTypes.flow = WorkflowEdgeView`. Edge
13
+ * data is passed through Vue Flow's `data` prop verbatim.
14
+ */
15
+ type EdgeKind = 'default' | 'success' | 'error' | 'branch-true' | 'branch-false' | 'branch';
16
+ interface Data {
17
+ kind: EdgeKind;
18
+ /** Optional human label shown mid-edge (e.g. "true", "cases:paid"). */
19
+ label?: string;
20
+ }
21
+ type __VLS_Props = EdgeProps<Data>;
22
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
23
+ export default _default;
@@ -0,0 +1,14 @@
1
+ import '@vue-flow/core/dist/style.css';
2
+ import '@vue-flow/core/dist/theme-default.css';
3
+ import '@vue-flow/controls/dist/style.css';
4
+ import '@vue-flow/minimap/dist/style.css';
5
+ import type { Workflow, WorkflowBlob } from '../../types/integrations.js';
6
+ type __VLS_Props = {
7
+ workflow: Workflow;
8
+ };
9
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
10
+ change: (blob: WorkflowBlob) => any;
11
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
12
+ onChange?: ((blob: WorkflowBlob) => any) | undefined;
13
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
14
+ export default _default;