@revenexx/studio-integrations 0.1.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/dist/module.d.mts +2 -2
- package/dist/module.json +1 -1
- package/dist/runtime/components/Integrations/CredentialCreateDialog.d.vue.ts +13 -0
- package/dist/runtime/components/Integrations/CredentialCreateDialog.vue +279 -0
- package/dist/runtime/components/Integrations/CredentialCreateDialog.vue.d.ts +13 -0
- package/dist/runtime/components/Integrations/CredentialDetailDialog.d.vue.ts +20 -0
- package/dist/runtime/components/Integrations/CredentialDetailDialog.vue +342 -0
- package/dist/runtime/components/Integrations/CredentialDetailDialog.vue.d.ts +20 -0
- package/dist/runtime/components/Integrations/CredentialLogo.d.vue.ts +14 -0
- package/dist/runtime/components/Integrations/CredentialLogo.vue +37 -0
- package/dist/runtime/components/Integrations/CredentialLogo.vue.d.ts +14 -0
- package/dist/runtime/components/Integrations/CredentialRevenexxSource.d.vue.ts +12 -0
- package/dist/runtime/components/Integrations/CredentialRevenexxSource.vue +364 -0
- package/dist/runtime/components/Integrations/CredentialRevenexxSource.vue.d.ts +12 -0
- package/dist/runtime/components/Integrations/CredentialTypePicker.d.vue.ts +15 -0
- package/dist/runtime/components/Integrations/CredentialTypePicker.vue +71 -0
- package/dist/runtime/components/Integrations/CredentialTypePicker.vue.d.ts +15 -0
- package/dist/runtime/components/Integrations/DeadLettersPanel.d.vue.ts +5 -0
- package/dist/runtime/components/Integrations/DeadLettersPanel.vue +151 -0
- package/dist/runtime/components/Integrations/DeadLettersPanel.vue.d.ts +5 -0
- package/dist/runtime/components/Integrations/EditorTip.d.vue.ts +17 -0
- package/dist/runtime/components/Integrations/EditorTip.vue +46 -0
- package/dist/runtime/components/Integrations/EditorTip.vue.d.ts +17 -0
- package/dist/runtime/components/Integrations/EventTypeCombobox.d.vue.ts +9 -0
- package/dist/runtime/components/Integrations/EventTypeCombobox.vue +64 -0
- package/dist/runtime/components/Integrations/EventTypeCombobox.vue.d.ts +9 -0
- package/dist/runtime/components/Integrations/ExpressionInput.d.vue.ts +19 -0
- package/dist/runtime/components/Integrations/ExpressionInput.vue +236 -0
- package/dist/runtime/components/Integrations/ExpressionInput.vue.d.ts +19 -0
- package/dist/runtime/components/Integrations/GroupFrameView.d.vue.ts +28 -0
- package/dist/runtime/components/Integrations/GroupFrameView.vue +222 -0
- package/dist/runtime/components/Integrations/GroupFrameView.vue.d.ts +28 -0
- package/dist/runtime/components/Integrations/NodeConfigDynamicField.d.vue.ts +14 -0
- package/dist/runtime/components/Integrations/NodeConfigDynamicField.vue +184 -0
- package/dist/runtime/components/Integrations/NodeConfigDynamicField.vue.d.ts +14 -0
- package/dist/runtime/components/Integrations/NodeConfigDynamicSchema.d.vue.ts +16 -0
- package/dist/runtime/components/Integrations/NodeConfigDynamicSchema.vue +102 -0
- package/dist/runtime/components/Integrations/NodeConfigDynamicSchema.vue.d.ts +16 -0
- package/dist/runtime/components/Integrations/NodeConfigField.d.vue.ts +23 -0
- package/dist/runtime/components/Integrations/NodeConfigField.vue +587 -0
- package/dist/runtime/components/Integrations/NodeConfigField.vue.d.ts +23 -0
- package/dist/runtime/components/Integrations/NodeDynamicOutputsResolver.d.vue.ts +14 -0
- package/dist/runtime/components/Integrations/NodeDynamicOutputsResolver.vue +80 -0
- package/dist/runtime/components/Integrations/NodeDynamicOutputsResolver.vue.d.ts +14 -0
- package/dist/runtime/components/Integrations/NodeInspector.d.vue.ts +22 -3
- package/dist/runtime/components/Integrations/NodeInspector.vue +1074 -294
- package/dist/runtime/components/Integrations/NodeInspector.vue.d.ts +22 -3
- package/dist/runtime/components/Integrations/NodeLogo.d.vue.ts +9 -0
- package/dist/runtime/components/Integrations/NodeLogo.vue +38 -0
- package/dist/runtime/components/Integrations/NodeLogo.vue.d.ts +9 -0
- package/dist/runtime/components/Integrations/NodePalette.d.vue.ts +22 -1
- package/dist/runtime/components/Integrations/NodePalette.vue +411 -90
- package/dist/runtime/components/Integrations/NodePalette.vue.d.ts +22 -1
- package/dist/runtime/components/Integrations/QueryBuilder.d.vue.ts +9 -0
- package/dist/runtime/components/Integrations/QueryBuilder.vue +239 -0
- package/dist/runtime/components/Integrations/QueryBuilder.vue.d.ts +9 -0
- package/dist/runtime/components/Integrations/{RunDetailDialog.d.vue.ts → RunActionsMenu.d.vue.ts} +3 -4
- package/dist/runtime/components/Integrations/RunActionsMenu.vue +86 -0
- package/dist/runtime/components/Integrations/{RunDetailDialog.vue.d.ts → RunActionsMenu.vue.d.ts} +3 -4
- package/dist/runtime/components/Integrations/RunDetailPanel.d.vue.ts +14 -0
- package/dist/runtime/components/Integrations/RunDetailPanel.vue +777 -0
- package/dist/runtime/components/Integrations/RunDetailPanel.vue.d.ts +14 -0
- package/dist/runtime/components/Integrations/RunPayloadInput.d.vue.ts +13 -0
- package/dist/runtime/components/Integrations/RunPayloadInput.vue +175 -0
- package/dist/runtime/components/Integrations/RunPayloadInput.vue.d.ts +13 -0
- package/dist/runtime/components/Integrations/RunResponseModal.d.vue.ts +27 -0
- package/dist/runtime/components/Integrations/RunResponseModal.vue +84 -0
- package/dist/runtime/components/Integrations/RunResponseModal.vue.d.ts +27 -0
- package/dist/runtime/components/Integrations/RunsTable.d.vue.ts +21 -0
- package/dist/runtime/components/Integrations/RunsTable.vue +114 -0
- package/dist/runtime/components/Integrations/RunsTable.vue.d.ts +21 -0
- package/dist/runtime/components/Integrations/SftpAccountImportDialog.d.vue.ts +11 -0
- package/dist/runtime/components/Integrations/SftpAccountImportDialog.vue +91 -0
- package/dist/runtime/components/Integrations/SftpAccountImportDialog.vue.d.ts +11 -0
- package/dist/runtime/components/Integrations/StickyNoteView.d.vue.ts +28 -0
- package/dist/runtime/components/Integrations/StickyNoteView.vue +208 -0
- package/dist/runtime/components/Integrations/StickyNoteView.vue.d.ts +28 -0
- package/dist/runtime/components/Integrations/TemplateFlowPreview.d.vue.ts +29 -0
- package/dist/runtime/components/Integrations/TemplateFlowPreview.vue +201 -0
- package/dist/runtime/components/Integrations/TemplateFlowPreview.vue.d.ts +29 -0
- package/dist/runtime/components/Integrations/WorkflowContextMenu.d.vue.ts +32 -0
- package/dist/runtime/components/Integrations/WorkflowContextMenu.vue +138 -0
- package/dist/runtime/components/Integrations/WorkflowContextMenu.vue.d.ts +32 -0
- package/dist/runtime/components/Integrations/WorkflowCreateDialog.d.vue.ts +9 -0
- package/dist/runtime/components/Integrations/WorkflowCreateDialog.vue +322 -0
- package/dist/runtime/components/Integrations/WorkflowCreateDialog.vue.d.ts +9 -0
- package/dist/runtime/components/Integrations/WorkflowDuplicateDialog.d.vue.ts +18 -0
- package/dist/runtime/components/Integrations/WorkflowDuplicateDialog.vue +63 -0
- package/dist/runtime/components/Integrations/WorkflowDuplicateDialog.vue.d.ts +18 -0
- package/dist/runtime/components/Integrations/WorkflowEdgeView.d.vue.ts +12 -1
- package/dist/runtime/components/Integrations/WorkflowEdgeView.vue +68 -6
- package/dist/runtime/components/Integrations/WorkflowEdgeView.vue.d.ts +12 -1
- package/dist/runtime/components/Integrations/WorkflowEditor.d.vue.ts +8 -1
- package/dist/runtime/components/Integrations/WorkflowEditor.vue +1424 -144
- package/dist/runtime/components/Integrations/WorkflowEditor.vue.d.ts +8 -1
- package/dist/runtime/components/Integrations/WorkflowHistoryPanel.d.vue.ts +12 -0
- package/dist/runtime/components/Integrations/WorkflowHistoryPanel.vue +417 -0
- package/dist/runtime/components/Integrations/WorkflowHistoryPanel.vue.d.ts +12 -0
- package/dist/runtime/components/Integrations/WorkflowIconPicker.d.vue.ts +10 -0
- package/dist/runtime/components/Integrations/WorkflowIconPicker.vue +89 -0
- package/dist/runtime/components/Integrations/WorkflowIconPicker.vue.d.ts +10 -0
- package/dist/runtime/components/Integrations/WorkflowIconView.d.vue.ts +10 -0
- package/dist/runtime/components/Integrations/WorkflowIconView.vue +35 -0
- package/dist/runtime/components/Integrations/WorkflowIconView.vue.d.ts +10 -0
- package/dist/runtime/components/Integrations/WorkflowNodeView.d.vue.ts +5 -1
- package/dist/runtime/components/Integrations/WorkflowNodeView.vue +114 -84
- package/dist/runtime/components/Integrations/WorkflowNodeView.vue.d.ts +5 -1
- package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.d.vue.ts +12 -0
- package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.vue +654 -0
- package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.vue.d.ts +12 -0
- package/dist/runtime/components/Integrations/WorkflowSettingsDialog.d.vue.ts +36 -0
- package/dist/runtime/components/Integrations/WorkflowSettingsDialog.vue +136 -0
- package/dist/runtime/components/Integrations/WorkflowSettingsDialog.vue.d.ts +36 -0
- package/dist/runtime/components/Integrations/WorkflowTagsInput.d.vue.ts +14 -0
- package/dist/runtime/components/Integrations/WorkflowTagsInput.vue +63 -0
- package/dist/runtime/components/Integrations/WorkflowTagsInput.vue.d.ts +14 -0
- package/dist/runtime/components/Integrations/WorkflowTriggerView.vue +35 -15
- package/dist/runtime/components/Integrations/WorkflowVariablesDialog.d.vue.ts +13 -0
- package/dist/runtime/components/Integrations/WorkflowVariablesDialog.vue +265 -0
- package/dist/runtime/components/Integrations/WorkflowVariablesDialog.vue.d.ts +13 -0
- package/dist/runtime/components/Integrations/WorkflowsTable.d.vue.ts +4 -1
- package/dist/runtime/components/Integrations/WorkflowsTable.vue +122 -39
- package/dist/runtime/components/Integrations/WorkflowsTable.vue.d.ts +4 -1
- package/dist/runtime/components/Integrations/workflowLayout.d.ts +5 -0
- package/dist/runtime/components/Integrations/workflowLayout.js +5 -3
- package/dist/runtime/composables/integrationsApi.d.ts +6 -7
- package/dist/runtime/composables/integrationsApi.js +6 -12
- package/dist/runtime/composables/useCanvasShortcuts.d.ts +37 -0
- package/dist/runtime/composables/useCanvasShortcuts.js +62 -0
- package/dist/runtime/composables/useCredentialTypes.js +2 -1
- package/dist/runtime/composables/useIntegrationsAudit.js +2 -1
- package/dist/runtime/composables/useIntegrationsCredentials.js +2 -1
- package/dist/runtime/composables/useIntegrationsDeadLetters.d.ts +22 -0
- package/dist/runtime/composables/useIntegrationsDeadLetters.js +50 -0
- package/dist/runtime/composables/useIntegrationsNodes.d.ts +4 -0
- package/dist/runtime/composables/useIntegrationsNodes.js +8 -4
- package/dist/runtime/composables/useIntegrationsRevisions.d.ts +40 -0
- package/dist/runtime/composables/useIntegrationsRevisions.js +52 -0
- package/dist/runtime/composables/useIntegrationsRuns.d.ts +21 -1
- package/dist/runtime/composables/useIntegrationsRuns.js +94 -5
- package/dist/runtime/composables/useIntegrationsSecrets.js +2 -1
- package/dist/runtime/composables/useIntegrationsTemplates.d.ts +1 -0
- package/dist/runtime/composables/useIntegrationsTemplates.js +34 -5
- package/dist/runtime/composables/useIntegrationsTriggers.js +2 -1
- package/dist/runtime/composables/useIntegrationsWorkflows.d.ts +1 -0
- package/dist/runtime/composables/useIntegrationsWorkflows.js +59 -2
- package/dist/runtime/composables/useMiniMapLayout.d.ts +34 -0
- package/dist/runtime/composables/useMiniMapLayout.js +119 -0
- package/dist/runtime/composables/useNodeConfigResolve.d.ts +43 -0
- package/dist/runtime/composables/useNodeConfigResolve.js +124 -0
- package/dist/runtime/composables/useNodeDrag.d.ts +22 -0
- package/dist/runtime/composables/useNodeDrag.js +10 -0
- package/dist/runtime/composables/usePaletteLayout.d.ts +41 -0
- package/dist/runtime/composables/usePaletteLayout.js +113 -0
- package/dist/runtime/data/expressionEditor.d.ts +22 -0
- package/dist/runtime/data/expressionEditor.js +40 -0
- package/dist/runtime/data/integrationNodeCatalog.js +8 -8
- package/dist/runtime/data/nodeInputData.d.ts +37 -0
- package/dist/runtime/data/nodeInputData.js +62 -0
- package/dist/runtime/data/nodeRunData.d.ts +56 -0
- package/dist/runtime/data/nodeRunData.js +91 -0
- package/dist/runtime/data/payloadForm.d.ts +44 -0
- package/dist/runtime/data/payloadForm.js +126 -0
- package/dist/runtime/data/workflowIconCatalog.d.ts +34 -0
- package/dist/runtime/data/workflowIconCatalog.js +116 -0
- package/dist/runtime/pages/integrations/audit.vue +25 -35
- package/dist/runtime/pages/integrations/credentials.vue +117 -122
- package/dist/runtime/pages/integrations/index.vue +133 -36
- package/dist/runtime/pages/integrations/runs.vue +125 -75
- package/dist/runtime/pages/integrations/schedules.vue +5 -16
- package/dist/runtime/pages/integrations/secrets.vue +1 -3
- package/dist/runtime/pages/integrations/workflows/[id].vue +599 -194
- package/dist/runtime/pages/integrations/workflows/index.vue +10 -8
- package/dist/runtime/types/integrations.d.ts +190 -4
- package/dist/runtime/utils/apiError.d.ts +17 -0
- package/dist/runtime/utils/apiError.js +8 -0
- package/dist/runtime/utils/credentialState.d.ts +28 -0
- package/dist/runtime/utils/credentialState.js +29 -0
- package/dist/runtime/utils/localize.d.ts +3 -1
- package/dist/runtime/utils/localize.js +1 -2
- package/dist/runtime/utils/statusStyle.d.ts +6 -0
- package/dist/runtime/utils/statusStyle.js +15 -0
- package/package.json +20 -3
- package/dist/runtime/components/Integrations/RunDetailDialog.vue +0 -169
- package/dist/runtime/pages/integrations/workflows/new.d.vue.ts +0 -2
- package/dist/runtime/pages/integrations/workflows/new.vue +0 -153
- package/dist/runtime/pages/integrations/workflows/new.vue.d.ts +0 -2
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
import { AddCircle as Plus } from "#solar-icons";
|
|
3
3
|
import { Button } from "@revenexx/studio";
|
|
4
4
|
import WorkflowsTable from "../../../components/Integrations/WorkflowsTable.vue";
|
|
5
|
+
import WorkflowCreateDialog from "../../../components/Integrations/WorkflowCreateDialog.vue";
|
|
5
6
|
useHead({ title: "Workflows \xB7 Revenexx Cockpit" });
|
|
6
|
-
const { workflows, load } = useIntegrationsWorkflows();
|
|
7
|
+
const { workflows, loading, load } = useIntegrationsWorkflows();
|
|
7
8
|
onMounted(() => {
|
|
8
9
|
void load();
|
|
9
10
|
});
|
|
11
|
+
const createOpen = ref(false);
|
|
10
12
|
</script>
|
|
11
13
|
|
|
12
14
|
<template>
|
|
@@ -15,17 +17,17 @@ onMounted(() => {
|
|
|
15
17
|
title="Workflows"
|
|
16
18
|
>
|
|
17
19
|
<template #actions>
|
|
18
|
-
<
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
</Button>
|
|
23
|
-
</NuxtLink>
|
|
20
|
+
<Button class="h-7 text-sm" @click="createOpen = true">
|
|
21
|
+
<Plus :size="14" />
|
|
22
|
+
New workflow
|
|
23
|
+
</Button>
|
|
24
24
|
</template>
|
|
25
25
|
</PageHeader>
|
|
26
26
|
|
|
27
27
|
<div class="p-4">
|
|
28
|
-
<WorkflowsTable :workflows="workflows" />
|
|
28
|
+
<WorkflowsTable :workflows="workflows" :loading="loading" />
|
|
29
29
|
</div>
|
|
30
|
+
|
|
31
|
+
<WorkflowCreateDialog v-model:open="createOpen" />
|
|
30
32
|
</IntegrationsLayout>
|
|
31
33
|
</template>
|
|
@@ -37,6 +37,12 @@ export interface WorkflowNodeRetry {
|
|
|
37
37
|
backoffSeconds?: number;
|
|
38
38
|
strategy?: RetryStrategy;
|
|
39
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* What the engine does when a node still fails after its retries: `fail`
|
|
42
|
+
* (default) fails the run; `route` records the failure as the node's `error`
|
|
43
|
+
* output so a wired error edge handles it. Stop and Error always fails.
|
|
44
|
+
*/
|
|
45
|
+
export type WorkflowNodeOnError = 'route' | 'fail';
|
|
40
46
|
export interface WorkflowNodePosition {
|
|
41
47
|
x: number;
|
|
42
48
|
y: number;
|
|
@@ -48,10 +54,19 @@ export interface WorkflowNode {
|
|
|
48
54
|
/** semver pin for the chosen manifest version. */
|
|
49
55
|
nodeVersion: string;
|
|
50
56
|
name?: LocalizedString;
|
|
57
|
+
/** Optional editor-only note/comment on this node instance (blob `nodes[].notes`). */
|
|
58
|
+
notes?: string;
|
|
51
59
|
/** Free-form key→value config, validated against the node manifest. */
|
|
52
60
|
config: Record<string, unknown>;
|
|
53
61
|
position?: WorkflowNodePosition;
|
|
54
62
|
retry?: WorkflowNodeRetry;
|
|
63
|
+
onError?: WorkflowNodeOnError;
|
|
64
|
+
/**
|
|
65
|
+
* Per-node execution timeout in seconds (engine start-to-close, 1..7200).
|
|
66
|
+
* Absent = engine default (10 minutes). For long-running orchestration
|
|
67
|
+
* nodes, e.g. waiting on a bulk import job.
|
|
68
|
+
*/
|
|
69
|
+
timeoutSeconds?: number;
|
|
55
70
|
}
|
|
56
71
|
export interface WorkflowEdge {
|
|
57
72
|
id: string;
|
|
@@ -64,6 +79,49 @@ export interface WorkflowEdge {
|
|
|
64
79
|
input?: string;
|
|
65
80
|
};
|
|
66
81
|
}
|
|
82
|
+
/** Editor-only node group: a canvas frame owning member nodes (blob `groups[]`). */
|
|
83
|
+
export interface WorkflowGroup {
|
|
84
|
+
id: string;
|
|
85
|
+
label: LocalizedString;
|
|
86
|
+
/** Member node/trigger handles. */
|
|
87
|
+
nodeIds: string[];
|
|
88
|
+
/** Palette index 0..6 (shares the sticky palette). */
|
|
89
|
+
color?: number;
|
|
90
|
+
/** Collapsed groups render as one compact card; members hide. */
|
|
91
|
+
collapsed?: boolean;
|
|
92
|
+
/** Manually resized frame; absent = derived from the members' bounding box. */
|
|
93
|
+
rect?: {
|
|
94
|
+
x: number;
|
|
95
|
+
y: number;
|
|
96
|
+
width: number;
|
|
97
|
+
height: number;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/** Editor-only sticky note on the canvas (engine-irrelevant; blob `stickies[]`). */
|
|
101
|
+
export interface WorkflowSticky {
|
|
102
|
+
id: string;
|
|
103
|
+
/** Note text; markdown-lite (`#`/`##`/`###` headings, `**bold**`), line breaks kept. */
|
|
104
|
+
content: string;
|
|
105
|
+
position: {
|
|
106
|
+
x: number;
|
|
107
|
+
y: number;
|
|
108
|
+
};
|
|
109
|
+
/** Absent → the editor's 240x160 default. */
|
|
110
|
+
size?: {
|
|
111
|
+
width: number;
|
|
112
|
+
height: number;
|
|
113
|
+
};
|
|
114
|
+
/** Palette index 0..6 (0 = amber default). */
|
|
115
|
+
color?: number;
|
|
116
|
+
}
|
|
117
|
+
/** Editor-only workflow icon (BlobDef `icon`): a curated solar icon name or a node-package image URL. */
|
|
118
|
+
export interface WorkflowIcon {
|
|
119
|
+
kind: 'solar' | 'image';
|
|
120
|
+
/** Icon-library name (kind=solar). */
|
|
121
|
+
name?: string;
|
|
122
|
+
/** Image URL, e.g. a node-package logo (kind=image). */
|
|
123
|
+
src?: string;
|
|
124
|
+
}
|
|
67
125
|
export interface WorkflowBlob {
|
|
68
126
|
nodeManifestVersion: string;
|
|
69
127
|
name: LocalizedString;
|
|
@@ -77,8 +135,22 @@ export interface WorkflowBlob {
|
|
|
77
135
|
x: number;
|
|
78
136
|
y: number;
|
|
79
137
|
}>;
|
|
138
|
+
/** Canvas sticky notes (engine-irrelevant annotations, BlobDef `stickies`). */
|
|
139
|
+
stickies?: WorkflowSticky[];
|
|
140
|
+
/** Canvas node groups (engine-irrelevant frames, BlobDef `groups`). */
|
|
141
|
+
groups?: WorkflowGroup[];
|
|
142
|
+
/** Organisational tags for grouping/filtering (engine-irrelevant, BlobDef `tags`). */
|
|
143
|
+
tags?: string[];
|
|
144
|
+
/** Workflow icon shown in lists and headers (engine-irrelevant, BlobDef `icon`). */
|
|
145
|
+
icon?: WorkflowIcon;
|
|
80
146
|
}
|
|
81
147
|
export type WorkflowExecutionMode = 'async_only' | 'sync_only' | 'caller_decides';
|
|
148
|
+
/**
|
|
149
|
+
* Build state of a workflow's executable bundle (backend `build_status`). Source
|
|
150
|
+
* of truth for runnability — the worker pool only runs a workflow once its
|
|
151
|
+
* bundle is `ready`; the API rejects runs with 409 in any other state.
|
|
152
|
+
*/
|
|
153
|
+
export type WorkflowBuildStatus = 'pending' | 'building' | 'ready' | 'failed';
|
|
82
154
|
export interface Workflow {
|
|
83
155
|
id: number;
|
|
84
156
|
name: string;
|
|
@@ -88,6 +160,10 @@ export interface Workflow {
|
|
|
88
160
|
active: boolean;
|
|
89
161
|
revision: number;
|
|
90
162
|
execution_mode?: WorkflowExecutionMode;
|
|
163
|
+
/** Bundle build state; `null` on legacy rows the builder never touched. */
|
|
164
|
+
buildStatus: WorkflowBuildStatus | null;
|
|
165
|
+
/** Human-readable build failure reason, present when `buildStatus === 'failed'`. */
|
|
166
|
+
buildError: string | null;
|
|
91
167
|
created_at: string;
|
|
92
168
|
updated_at: string;
|
|
93
169
|
}
|
|
@@ -106,12 +182,18 @@ export interface NodeManifestOutput {
|
|
|
106
182
|
dataType: NodeDataType;
|
|
107
183
|
description?: LocalizedString;
|
|
108
184
|
sourceFromConfig?: string;
|
|
185
|
+
/** When true, the node's outputs for this manifest are resolved dynamically
|
|
186
|
+
* via config:resolve with target 'outputs' (later phase; harmless now). */
|
|
187
|
+
resolveOutputs?: boolean;
|
|
109
188
|
fallback?: {
|
|
110
189
|
name: string;
|
|
111
190
|
label?: LocalizedString;
|
|
112
191
|
};
|
|
192
|
+
/** Declared field names of this output's payload, when the manifest
|
|
193
|
+
* publishes them. Author-time schema only, never live run data. */
|
|
194
|
+
fields?: string[] | Record<string, unknown>;
|
|
113
195
|
}
|
|
114
|
-
export type ConfigFieldType = 'string' | 'number' | 'boolean' | 'select' | 'multiselect' | 'object' | 'array' | 'expression' | 'secret-ref' | 'credentials-ref';
|
|
196
|
+
export type ConfigFieldType = 'string' | 'number' | 'boolean' | 'select' | 'multiselect' | 'object' | 'array' | 'expression' | 'secret-ref' | 'credentials-ref' | 'dynamic-schema';
|
|
115
197
|
export interface ConfigFieldOption {
|
|
116
198
|
value: string | number | boolean;
|
|
117
199
|
label: LocalizedString;
|
|
@@ -126,12 +208,20 @@ export interface ConfigField {
|
|
|
126
208
|
placeholder?: LocalizedString;
|
|
127
209
|
expressionAllowed?: boolean;
|
|
128
210
|
options?: ConfigFieldOption[];
|
|
211
|
+
/** When true, this field's `options` are resolved at author-time via
|
|
212
|
+
* config:resolve with target === this field's `key` (see useNodeConfigResolve). */
|
|
213
|
+
dynamic?: boolean;
|
|
129
214
|
/** sub-fields when type === 'object' (one level deep) */
|
|
130
215
|
properties?: ConfigField[];
|
|
131
216
|
/** item type when type === 'array' */
|
|
132
217
|
items?: ConfigField;
|
|
133
|
-
/** credential type slug the field binds to when type === 'credentials-ref'
|
|
134
|
-
|
|
218
|
+
/** credential type slug(s) the field binds to when type === 'credentials-ref'
|
|
219
|
+
* (e.g. 'revenexx:business-central'). An array lets a node accept more than
|
|
220
|
+
* one credential type; the picker merges the tenant's credentials across all. */
|
|
221
|
+
credentialType?: string | string[];
|
|
222
|
+
/** keys of other config fields this field's options/schema depend on. The
|
|
223
|
+
* driving `select` fields also form the node's canvas subtitle. */
|
|
224
|
+
dependsOn?: string[];
|
|
135
225
|
validation?: {
|
|
136
226
|
pattern?: string;
|
|
137
227
|
min?: number;
|
|
@@ -140,6 +230,20 @@ export interface ConfigField {
|
|
|
140
230
|
maxLength?: number;
|
|
141
231
|
};
|
|
142
232
|
}
|
|
233
|
+
export interface ResolveOption {
|
|
234
|
+
value: string | number | boolean;
|
|
235
|
+
label?: LocalizedString;
|
|
236
|
+
}
|
|
237
|
+
export interface NodeConfigResolveResult {
|
|
238
|
+
options?: ResolveOption[];
|
|
239
|
+
fields?: ConfigField[];
|
|
240
|
+
outputs?: NodeManifestOutput[];
|
|
241
|
+
}
|
|
242
|
+
export type ResolveErrorKind = 'building' | 'runtime' | 'forbidden' | 'notfound' | 'generic';
|
|
243
|
+
export interface NodeConfigResolveError {
|
|
244
|
+
kind: ResolveErrorKind;
|
|
245
|
+
message: string;
|
|
246
|
+
}
|
|
143
247
|
export interface NodeManifest {
|
|
144
248
|
slug: string;
|
|
145
249
|
version: string;
|
|
@@ -148,9 +252,27 @@ export interface NodeManifest {
|
|
|
148
252
|
description?: LocalizedString;
|
|
149
253
|
/** lucide-vue-next icon name OR mdi:icon-id. */
|
|
150
254
|
icon?: string;
|
|
255
|
+
/**
|
|
256
|
+
* Curated palette group path (e.g. ["Business Central", "Sales Orders"]).
|
|
257
|
+
* Optional manifest field; when absent the palette derives a path from the
|
|
258
|
+
* source package + slug heuristics.
|
|
259
|
+
*/
|
|
260
|
+
groups?: LocalizedString[];
|
|
261
|
+
/** Brand images (category `logo` drives palette/canvas rendering); src is a signed URL. */
|
|
262
|
+
images?: Array<{
|
|
263
|
+
src: string;
|
|
264
|
+
alt?: LocalizedString;
|
|
265
|
+
title?: LocalizedString;
|
|
266
|
+
category?: string;
|
|
267
|
+
}>;
|
|
151
268
|
input: NodeManifestInput;
|
|
152
269
|
outputs: NodeManifestOutput[];
|
|
153
270
|
config?: ConfigField[];
|
|
271
|
+
/** Source package (editor-side enrichment from GET /nodes; not manifest data). */
|
|
272
|
+
__package?: {
|
|
273
|
+
name: string;
|
|
274
|
+
label: string | null;
|
|
275
|
+
};
|
|
154
276
|
}
|
|
155
277
|
export interface SecretRecord {
|
|
156
278
|
key: string;
|
|
@@ -178,12 +300,21 @@ export interface CredentialTypeField {
|
|
|
178
300
|
};
|
|
179
301
|
}
|
|
180
302
|
/** A globally-registered credential type — drives the dynamic credential form. */
|
|
303
|
+
/** A brand/logo image shipped with a credential type. `src` is a short-lived
|
|
304
|
+
* signed URL minted by the credential-types API (ManifestImageUrlSigner). */
|
|
305
|
+
export interface CredentialTypeImage {
|
|
306
|
+
src: string;
|
|
307
|
+
alt?: LocalizedString;
|
|
308
|
+
category?: 'logo' | 'icon' | 'banner' | 'screenshot' | 'other' | string;
|
|
309
|
+
}
|
|
181
310
|
export interface CredentialType {
|
|
182
311
|
slug: string;
|
|
183
312
|
version: string;
|
|
184
313
|
name: LocalizedString;
|
|
185
314
|
description?: LocalizedString;
|
|
186
315
|
icon?: string;
|
|
316
|
+
/** Signed logo/brand image URLs from the API (prefer `category: 'logo'`). */
|
|
317
|
+
images?: CredentialTypeImage[];
|
|
187
318
|
auth_kind: AuthKind;
|
|
188
319
|
fields: CredentialTypeField[];
|
|
189
320
|
}
|
|
@@ -196,6 +327,10 @@ export interface Credential {
|
|
|
196
327
|
status: CredentialStatus;
|
|
197
328
|
/** non-secret field values only (whitelisted types). */
|
|
198
329
|
public_config?: Record<string, unknown>;
|
|
330
|
+
/** Outcome of the last connection test (persisted by the API). Null when never tested. */
|
|
331
|
+
last_test_at?: string | null;
|
|
332
|
+
last_test_ok?: boolean | null;
|
|
333
|
+
last_test_message?: string | null;
|
|
199
334
|
created_at: string;
|
|
200
335
|
updated_at: string;
|
|
201
336
|
}
|
|
@@ -250,12 +385,30 @@ export interface ScheduleEntry {
|
|
|
250
385
|
nextRunAt: string | null;
|
|
251
386
|
lastRunAt: string | null;
|
|
252
387
|
}
|
|
253
|
-
export type TemplateCategory = 'sync' | 'notification' | 'enrichment' | 'fulfilment' | 'reporting' | 'finance';
|
|
388
|
+
export type TemplateCategory = 'sync' | 'notification' | 'enrichment' | 'fulfilment' | 'reporting' | 'finance' | 'commerce' | 'sales';
|
|
254
389
|
export interface WorkflowTemplate {
|
|
255
390
|
/** kebab-case stable id. */
|
|
256
391
|
slug: string;
|
|
257
392
|
name: string;
|
|
393
|
+
/** Plain one-liner for cards and pickers (shortDescription, or a de-markdowned excerpt). */
|
|
258
394
|
description: string;
|
|
395
|
+
/** The full registry description as Markdown; rendered on the detail page. */
|
|
396
|
+
descriptionMd: string;
|
|
397
|
+
/** Trigger types from the catalogue listing (schedule/webhook/manual/event). */
|
|
398
|
+
triggerTypes: TriggerType[];
|
|
399
|
+
/** Registry images (banner/screenshot categories, signed URLs). */
|
|
400
|
+
images: Array<{
|
|
401
|
+
src: string;
|
|
402
|
+
category?: string;
|
|
403
|
+
alt?: unknown;
|
|
404
|
+
}>;
|
|
405
|
+
/** True once the heavy definition blob has been merged via fetchDetail. */
|
|
406
|
+
detailLoaded?: boolean;
|
|
407
|
+
/** Source node package this template ships with (e.g. Business Central). */
|
|
408
|
+
package?: {
|
|
409
|
+
name: string;
|
|
410
|
+
label: string | null;
|
|
411
|
+
} | null;
|
|
259
412
|
category: TemplateCategory;
|
|
260
413
|
industries: Array<'mechanical-engineering' | 'chemicals' | 'wholesale' | 'manufacturing' | 'retail' | 'any'>;
|
|
261
414
|
/** Vendor slugs this template wires together (used to compute prerequisites). */
|
|
@@ -325,11 +478,42 @@ export interface WorkflowRunNodeStep {
|
|
|
325
478
|
attempt: number;
|
|
326
479
|
durationMs: number | null;
|
|
327
480
|
}
|
|
481
|
+
export interface RunStepRow {
|
|
482
|
+
node_id: string;
|
|
483
|
+
node_slug: string;
|
|
484
|
+
activity_type: string;
|
|
485
|
+
status: string;
|
|
486
|
+
attempt: number;
|
|
487
|
+
scheduled_event_id: number | null;
|
|
488
|
+
duration_ms: number | null;
|
|
489
|
+
branch?: string | null;
|
|
490
|
+
error?: string | null;
|
|
491
|
+
input?: unknown;
|
|
492
|
+
output?: unknown;
|
|
493
|
+
/** Resolved node config for this step (present with include_payloads). */
|
|
494
|
+
config?: unknown;
|
|
495
|
+
scheduled_at?: string | null;
|
|
496
|
+
started_at?: string | null;
|
|
497
|
+
completed_at?: string | null;
|
|
498
|
+
}
|
|
499
|
+
export interface DeadLetterRow {
|
|
500
|
+
id: number;
|
|
501
|
+
workflow_id: number;
|
|
502
|
+
trigger_id: string | null;
|
|
503
|
+
source: string | null;
|
|
504
|
+
trigger_handle: string | null;
|
|
505
|
+
reason: string | null;
|
|
506
|
+
status: 'pending' | 'replayed' | 'discarded' | string;
|
|
507
|
+
created_at: string | null;
|
|
508
|
+
updated_at: string | null;
|
|
509
|
+
}
|
|
328
510
|
export interface WorkflowRun {
|
|
329
511
|
id: string;
|
|
330
512
|
workflowId: number;
|
|
331
513
|
workflowName: string;
|
|
332
514
|
status: RunStatus;
|
|
515
|
+
/** Temporal run id for this execution; null when the row predates Temporal. */
|
|
516
|
+
temporalRunId?: string | null;
|
|
333
517
|
triggerId: string;
|
|
334
518
|
triggerType: TriggerType;
|
|
335
519
|
startedAt: string;
|
|
@@ -348,6 +532,8 @@ export interface OutpostEvent {
|
|
|
348
532
|
id: string;
|
|
349
533
|
/** Topic the event was published on, e.g. "order.created". */
|
|
350
534
|
topic: string;
|
|
535
|
+
/** Tenant slug from the envelope (empty when the source omits it). */
|
|
536
|
+
tenantId?: string;
|
|
351
537
|
/** ISO timestamp the event was received. */
|
|
352
538
|
time: string;
|
|
353
539
|
/** Whether delivery may be retried (eligible_for_retry). */
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error thrown by the Integrations API client.
|
|
3
|
+
*
|
|
4
|
+
* It lives here rather than next to `useIntegrationsApi` on purpose: the
|
|
5
|
+
* module auto-imports everything the `composables/` directory exports, and a
|
|
6
|
+
* class exported from there gets registered as an auto-import too. Consumed
|
|
7
|
+
* from the built `dist/` (any host that installs the package from npm) the
|
|
8
|
+
* auto-import resolver then injects the identifier back into the very file
|
|
9
|
+
* that declares it — "Identifier 'IntegrationsApiError' has already been
|
|
10
|
+
* declared" at runtime. Keeping non-composable exports out of that directory
|
|
11
|
+
* avoids the whole class of problem; callers import it explicitly.
|
|
12
|
+
*/
|
|
13
|
+
export declare class IntegrationsApiError extends Error {
|
|
14
|
+
status: number;
|
|
15
|
+
body: unknown;
|
|
16
|
+
constructor(status: number, body: unknown, message: string);
|
|
17
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Credential } from '../types/integrations.js';
|
|
2
|
+
/**
|
|
3
|
+
* The honest, operator-facing state of a credential — derived from the
|
|
4
|
+
* persisted connection-test result, NOT from `status` (which only tracks the
|
|
5
|
+
* OAuth refresh lifecycle and defaults to `active` on create, so it can't say
|
|
6
|
+
* whether the access data actually works).
|
|
7
|
+
*
|
|
8
|
+
* needs_reauth → an OAuth refresh failed; reconnect required
|
|
9
|
+
* connected → the last connection test passed
|
|
10
|
+
* failed → the last connection test failed (see `message`)
|
|
11
|
+
* untested → never tested — deliberately distinct from a passing test
|
|
12
|
+
*/
|
|
13
|
+
export type CredentialConnState = 'connected' | 'failed' | 'needs_reauth' | 'untested';
|
|
14
|
+
export interface CredentialStateInfo {
|
|
15
|
+
key: CredentialConnState;
|
|
16
|
+
label: string;
|
|
17
|
+
/** Badge/pill classes for this state. */
|
|
18
|
+
toneClass: string;
|
|
19
|
+
/** Failure detail, when the state is `failed`. */
|
|
20
|
+
message?: string | null;
|
|
21
|
+
/** When the underlying result was recorded (ISO). */
|
|
22
|
+
at?: string | null;
|
|
23
|
+
}
|
|
24
|
+
type TestableCredential = Pick<Credential, 'status' | 'last_test_ok' | 'last_test_at' | 'last_test_message'>;
|
|
25
|
+
export declare function credentialState(c: TestableCredential): CredentialStateInfo;
|
|
26
|
+
/** "just now" / "3m ago" / "2h ago" / "5d ago" / a date. Empty for no timestamp. */
|
|
27
|
+
export declare function relativeTime(iso?: string | null): string;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const TONE = {
|
|
2
|
+
connected: "bg-emerald-500/10 border-emerald-500/20 text-emerald-700",
|
|
3
|
+
failed: "bg-rose-500/10 border-rose-500/20 text-rose-700",
|
|
4
|
+
needs_reauth: "bg-amber-500/10 border-amber-500/20 text-amber-700",
|
|
5
|
+
untested: "bg-slate-500/10 border-slate-500/20 text-slate-600"
|
|
6
|
+
};
|
|
7
|
+
export function credentialState(c) {
|
|
8
|
+
if (c.status === "needs_reauth") {
|
|
9
|
+
return { key: "needs_reauth", label: "Needs reconnect", toneClass: TONE.needs_reauth, at: c.last_test_at };
|
|
10
|
+
}
|
|
11
|
+
if (c.last_test_ok === true) {
|
|
12
|
+
return { key: "connected", label: "Connected", toneClass: TONE.connected, at: c.last_test_at };
|
|
13
|
+
}
|
|
14
|
+
if (c.last_test_ok === false) {
|
|
15
|
+
return { key: "failed", label: "Failed", toneClass: TONE.failed, message: c.last_test_message, at: c.last_test_at };
|
|
16
|
+
}
|
|
17
|
+
return { key: "untested", label: "Not Connected", toneClass: TONE.untested };
|
|
18
|
+
}
|
|
19
|
+
export function relativeTime(iso) {
|
|
20
|
+
if (!iso) return "";
|
|
21
|
+
const t = new Date(iso).getTime();
|
|
22
|
+
if (Number.isNaN(t)) return "";
|
|
23
|
+
const ms = Date.now() - t;
|
|
24
|
+
if (ms < 6e4) return "just now";
|
|
25
|
+
if (ms < 36e5) return `${Math.floor(ms / 6e4)}m ago`;
|
|
26
|
+
if (ms < 864e5) return `${Math.floor(ms / 36e5)}h ago`;
|
|
27
|
+
if (ms < 30 * 864e5) return `${Math.floor(ms / 864e5)}d ago`;
|
|
28
|
+
return new Date(iso).toLocaleDateString();
|
|
29
|
+
}
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* object `{de:"…", en:"…"}` (the HTTP client does JSON decoding automatically).
|
|
5
5
|
* JSON-encoded strings like `'{"de":"…","en":"…"}'` are also handled.
|
|
6
6
|
*
|
|
7
|
-
* Priority: 1)
|
|
7
|
+
* Priority: 1) "en", 2) first key found. English is the cockpit default —
|
|
8
|
+
* there is no working language switcher yet; browser-locale preference
|
|
9
|
+
* returns together with the switcher.
|
|
8
10
|
*/
|
|
9
11
|
export declare function resolveLocalized(value: unknown): string;
|
|
@@ -4,8 +4,7 @@ export function resolveLocalized(value) {
|
|
|
4
4
|
const map = value;
|
|
5
5
|
const keys = Object.keys(map);
|
|
6
6
|
if (!keys.length) return "";
|
|
7
|
-
const
|
|
8
|
-
const picked = map[lang] ?? map["en"] ?? map[keys[0]];
|
|
7
|
+
const picked = map["en"] ?? map[keys[0]];
|
|
9
8
|
return typeof picked === "string" ? picked : "";
|
|
10
9
|
}
|
|
11
10
|
if (typeof value !== "string") return String(value);
|
|
@@ -13,3 +13,9 @@ export declare function statusTone(status: string | null | undefined): StatusTon
|
|
|
13
13
|
export declare function statusClass(status: string | null | undefined): string;
|
|
14
14
|
/** Tone classes directly (when you already have a tone). */
|
|
15
15
|
export declare function toneClass(tone: StatusTone): string;
|
|
16
|
+
/**
|
|
17
|
+
* Raw API/Temporal run vocabulary → the cockpit's run-status labels, so a run
|
|
18
|
+
* never reads "completed" in one surface and "succeeded" in another. Unknown
|
|
19
|
+
* statuses pass through lowercased.
|
|
20
|
+
*/
|
|
21
|
+
export declare function runStatusLabel(status: string | null | undefined): string;
|
|
@@ -76,3 +76,18 @@ export function statusClass(status) {
|
|
|
76
76
|
export function toneClass(tone) {
|
|
77
77
|
return TONE_CLASS[tone];
|
|
78
78
|
}
|
|
79
|
+
export function runStatusLabel(status) {
|
|
80
|
+
if (!status) return "";
|
|
81
|
+
const s = String(status).toLowerCase().replace(/[\s-]+/g, "_");
|
|
82
|
+
switch (s) {
|
|
83
|
+
case "completed":
|
|
84
|
+
return "succeeded";
|
|
85
|
+
case "pending":
|
|
86
|
+
return "queued";
|
|
87
|
+
case "terminated":
|
|
88
|
+
case "timed_out":
|
|
89
|
+
return "failed";
|
|
90
|
+
default:
|
|
91
|
+
return s;
|
|
92
|
+
}
|
|
93
|
+
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revenexx/studio-integrations",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Integration Studio (core: workflows, node editor, runs, schedules, credentials, secrets, audit) as a standalone, publishable Nuxt module.",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/revenexx/studio-integrations.git"
|
|
9
|
+
},
|
|
6
10
|
"main": "./dist/module.mjs",
|
|
7
11
|
"types": "./dist/types.d.mts",
|
|
8
12
|
"exports": {
|
|
@@ -25,24 +29,37 @@
|
|
|
25
29
|
"peerDependencies": {
|
|
26
30
|
"@dagrejs/dagre": "^3.0.0",
|
|
27
31
|
"@revenexx/studio": "*",
|
|
32
|
+
"@revenexx/studio-shared": "^0.1.2",
|
|
33
|
+
"@solar-icons/nuxt": "^1.2.0",
|
|
34
|
+
"@tiptap/core": "^3.28.0",
|
|
35
|
+
"@tiptap/extension-document": "^3.28.0",
|
|
36
|
+
"@tiptap/extension-history": "^3.28.0",
|
|
37
|
+
"@tiptap/extension-paragraph": "^3.28.0",
|
|
38
|
+
"@tiptap/extension-text": "^3.28.0",
|
|
39
|
+
"@tiptap/pm": "^3.28.0",
|
|
40
|
+
"@tiptap/vue-3": "^3.28.0",
|
|
28
41
|
"@vue-flow/background": "^1.3.2",
|
|
29
42
|
"@vue-flow/controls": "^1.1.3",
|
|
30
43
|
"@vue-flow/core": "^1.48.2",
|
|
31
44
|
"@vue-flow/minimap": "^1.5.4",
|
|
45
|
+
"@vue-flow/node-toolbar": "^1.1.1",
|
|
32
46
|
"lucide-vue-next": "^1.0.0",
|
|
33
47
|
"nuxt": "^4.0.0",
|
|
34
48
|
"vue": "^3.5.0",
|
|
35
|
-
"
|
|
49
|
+
"vue-sonner": "^2.0.0"
|
|
36
50
|
},
|
|
37
51
|
"devDependencies": {
|
|
38
52
|
"@nuxt/module-builder": "^1.0.2",
|
|
39
53
|
"@nuxt/kit": "^4.0.0",
|
|
54
|
+
"@nuxt/schema": "^4.0.0",
|
|
40
55
|
"nuxt": "^4.2.2",
|
|
56
|
+
"vitest": "^3.2.0",
|
|
41
57
|
"vue": "^3.5.26",
|
|
42
58
|
"vue-tsc": "^2.2.0"
|
|
43
59
|
},
|
|
44
60
|
"license": "SEE LICENSE IN LICENSE",
|
|
45
61
|
"scripts": {
|
|
46
|
-
"build": "nuxt-module-build build"
|
|
62
|
+
"build": "nuxt-module-build build",
|
|
63
|
+
"test": "vitest run"
|
|
47
64
|
}
|
|
48
65
|
}
|