@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.
- package/README.md +51 -0
- package/dist/module.d.mts +6 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +45 -0
- package/dist/runtime/components/Integrations/Layout.d.vue.ts +12 -0
- package/dist/runtime/components/Integrations/Layout.vue +20 -0
- package/dist/runtime/components/Integrations/Layout.vue.d.ts +12 -0
- package/dist/runtime/components/Integrations/NodeInspector.d.vue.ts +16 -0
- package/dist/runtime/components/Integrations/NodeInspector.vue +450 -0
- package/dist/runtime/components/Integrations/NodeInspector.vue.d.ts +16 -0
- package/dist/runtime/components/Integrations/NodePalette.d.vue.ts +2 -0
- package/dist/runtime/components/Integrations/NodePalette.vue +140 -0
- package/dist/runtime/components/Integrations/NodePalette.vue.d.ts +2 -0
- package/dist/runtime/components/Integrations/RunDetailDialog.d.vue.ts +11 -0
- package/dist/runtime/components/Integrations/RunDetailDialog.vue +169 -0
- package/dist/runtime/components/Integrations/RunDetailDialog.vue.d.ts +11 -0
- package/dist/runtime/components/Integrations/Sidebar.d.vue.ts +2 -0
- package/dist/runtime/components/Integrations/Sidebar.vue +32 -0
- package/dist/runtime/components/Integrations/Sidebar.vue.d.ts +2 -0
- package/dist/runtime/components/Integrations/WorkflowEdgeView.d.vue.ts +23 -0
- package/dist/runtime/components/Integrations/WorkflowEdgeView.vue +86 -0
- package/dist/runtime/components/Integrations/WorkflowEdgeView.vue.d.ts +23 -0
- package/dist/runtime/components/Integrations/WorkflowEditor.d.vue.ts +14 -0
- package/dist/runtime/components/Integrations/WorkflowEditor.vue +419 -0
- package/dist/runtime/components/Integrations/WorkflowEditor.vue.d.ts +14 -0
- package/dist/runtime/components/Integrations/WorkflowNodeView.d.vue.ts +11 -0
- package/dist/runtime/components/Integrations/WorkflowNodeView.vue +200 -0
- package/dist/runtime/components/Integrations/WorkflowNodeView.vue.d.ts +11 -0
- package/dist/runtime/components/Integrations/WorkflowTriggerView.d.vue.ts +8 -0
- package/dist/runtime/components/Integrations/WorkflowTriggerView.vue +82 -0
- package/dist/runtime/components/Integrations/WorkflowTriggerView.vue.d.ts +8 -0
- package/dist/runtime/components/Integrations/WorkflowsTable.d.vue.ts +6 -0
- package/dist/runtime/components/Integrations/WorkflowsTable.vue +268 -0
- package/dist/runtime/components/Integrations/WorkflowsTable.vue.d.ts +6 -0
- package/dist/runtime/components/Integrations/workflowLayout.d.ts +17 -0
- package/dist/runtime/components/Integrations/workflowLayout.js +29 -0
- package/dist/runtime/composables/integrationsApi.d.ts +13 -0
- package/dist/runtime/composables/integrationsApi.js +55 -0
- package/dist/runtime/composables/useCredentialTypes.d.ts +19 -0
- package/dist/runtime/composables/useCredentialTypes.js +47 -0
- package/dist/runtime/composables/useIntegrationsAudit.d.ts +26 -0
- package/dist/runtime/composables/useIntegrationsAudit.js +39 -0
- package/dist/runtime/composables/useIntegrationsCredentials.d.ts +43 -0
- package/dist/runtime/composables/useIntegrationsCredentials.js +98 -0
- package/dist/runtime/composables/useIntegrationsFocus.d.ts +16 -0
- package/dist/runtime/composables/useIntegrationsFocus.js +17 -0
- package/dist/runtime/composables/useIntegrationsNodes.d.ts +6 -0
- package/dist/runtime/composables/useIntegrationsNodes.js +32 -0
- package/dist/runtime/composables/useIntegrationsRuns.d.ts +31 -0
- package/dist/runtime/composables/useIntegrationsRuns.js +109 -0
- package/dist/runtime/composables/useIntegrationsSchedules.d.ts +14 -0
- package/dist/runtime/composables/useIntegrationsSchedules.js +32 -0
- package/dist/runtime/composables/useIntegrationsSecrets.d.ts +27 -0
- package/dist/runtime/composables/useIntegrationsSecrets.js +76 -0
- package/dist/runtime/composables/useIntegrationsTemplates.d.ts +19 -0
- package/dist/runtime/composables/useIntegrationsTemplates.js +141 -0
- package/dist/runtime/composables/useIntegrationsTriggers.d.ts +39 -0
- package/dist/runtime/composables/useIntegrationsTriggers.js +39 -0
- package/dist/runtime/composables/useIntegrationsWorkflows.d.ts +28 -0
- package/dist/runtime/composables/useIntegrationsWorkflows.js +152 -0
- package/dist/runtime/data/integrationNodeCatalog.d.ts +41 -0
- package/dist/runtime/data/integrationNodeCatalog.js +67 -0
- package/dist/runtime/data/integrationRuns.d.ts +7 -0
- package/dist/runtime/data/integrationRuns.js +109 -0
- package/dist/runtime/data/integrationTemplates.d.ts +11 -0
- package/dist/runtime/data/integrationTemplates.js +9 -0
- package/dist/runtime/data/integrationWorkflowSamples.d.ts +18 -0
- package/dist/runtime/data/integrationWorkflowSamples.js +318 -0
- package/dist/runtime/pages/integrations/audit.d.vue.ts +2 -0
- package/dist/runtime/pages/integrations/audit.vue +156 -0
- package/dist/runtime/pages/integrations/audit.vue.d.ts +2 -0
- package/dist/runtime/pages/integrations/credentials/oauth-complete.d.vue.ts +2 -0
- package/dist/runtime/pages/integrations/credentials/oauth-complete.vue +28 -0
- package/dist/runtime/pages/integrations/credentials/oauth-complete.vue.d.ts +2 -0
- package/dist/runtime/pages/integrations/credentials.d.vue.ts +2 -0
- package/dist/runtime/pages/integrations/credentials.vue +403 -0
- package/dist/runtime/pages/integrations/credentials.vue.d.ts +2 -0
- package/dist/runtime/pages/integrations/index.d.vue.ts +2 -0
- package/dist/runtime/pages/integrations/index.vue +226 -0
- package/dist/runtime/pages/integrations/index.vue.d.ts +2 -0
- package/dist/runtime/pages/integrations/runs.d.vue.ts +2 -0
- package/dist/runtime/pages/integrations/runs.vue +100 -0
- package/dist/runtime/pages/integrations/runs.vue.d.ts +2 -0
- package/dist/runtime/pages/integrations/schedules.d.vue.ts +2 -0
- package/dist/runtime/pages/integrations/schedules.vue +111 -0
- package/dist/runtime/pages/integrations/schedules.vue.d.ts +2 -0
- package/dist/runtime/pages/integrations/secrets.d.vue.ts +2 -0
- package/dist/runtime/pages/integrations/secrets.vue +248 -0
- package/dist/runtime/pages/integrations/secrets.vue.d.ts +2 -0
- package/dist/runtime/pages/integrations/workflows/[id].d.vue.ts +2 -0
- package/dist/runtime/pages/integrations/workflows/[id].vue +326 -0
- package/dist/runtime/pages/integrations/workflows/[id].vue.d.ts +2 -0
- package/dist/runtime/pages/integrations/workflows/index.d.vue.ts +2 -0
- package/dist/runtime/pages/integrations/workflows/index.vue +31 -0
- package/dist/runtime/pages/integrations/workflows/index.vue.d.ts +2 -0
- package/dist/runtime/pages/integrations/workflows/new.d.vue.ts +2 -0
- package/dist/runtime/pages/integrations/workflows/new.vue +153 -0
- package/dist/runtime/pages/integrations/workflows/new.vue.d.ts +2 -0
- package/dist/runtime/types/integrations.d.ts +427 -0
- package/dist/runtime/types/integrations.js +0 -0
- package/dist/runtime/utils/localize.d.ts +9 -0
- package/dist/runtime/utils/localize.js +21 -0
- package/dist/runtime/utils/statusStyle.d.ts +15 -0
- package/dist/runtime/utils/statusStyle.js +78 -0
- package/dist/types.d.mts +9 -0
- package/package.json +46 -0
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type contracts for the Integration Studio surface.
|
|
3
|
+
*
|
|
4
|
+
* These mirror the integrations Laravel service (see `playground/integrations`)
|
|
5
|
+
* and its Scribe-published API. The wire format is the JSON `blob` of a
|
|
6
|
+
* workflow whose shape is defined by the `v0-draft` schema. We type a
|
|
7
|
+
* subset that the mockup needs — the editor only reads/writes the blob,
|
|
8
|
+
* never invents fields outside it.
|
|
9
|
+
*/
|
|
10
|
+
export type LocalizedString = string | Record<string, string>;
|
|
11
|
+
export type WorkflowVariableType = 'string' | 'number' | 'boolean' | 'object' | 'array';
|
|
12
|
+
export interface WorkflowVariable {
|
|
13
|
+
type: WorkflowVariableType;
|
|
14
|
+
default?: unknown;
|
|
15
|
+
description?: LocalizedString;
|
|
16
|
+
required?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export type TriggerType = 'manual' | 'schedule' | 'webhook' | 'event';
|
|
19
|
+
export interface WorkflowTrigger {
|
|
20
|
+
id: string;
|
|
21
|
+
type: TriggerType;
|
|
22
|
+
name?: LocalizedString;
|
|
23
|
+
/** Whether the trigger is active (API field). */
|
|
24
|
+
active?: boolean;
|
|
25
|
+
config: {
|
|
26
|
+
cron?: string;
|
|
27
|
+
timezone?: string;
|
|
28
|
+
path?: string;
|
|
29
|
+
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
30
|
+
secretRef?: string;
|
|
31
|
+
event_type?: string;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export type RetryStrategy = 'linear' | 'exponential';
|
|
35
|
+
export interface WorkflowNodeRetry {
|
|
36
|
+
maxAttempts: number;
|
|
37
|
+
backoffSeconds?: number;
|
|
38
|
+
strategy?: RetryStrategy;
|
|
39
|
+
}
|
|
40
|
+
export interface WorkflowNodePosition {
|
|
41
|
+
x: number;
|
|
42
|
+
y: number;
|
|
43
|
+
}
|
|
44
|
+
export interface WorkflowNode {
|
|
45
|
+
id: string;
|
|
46
|
+
/** kebab-case slug pointing at a Node manifest in the registry. */
|
|
47
|
+
nodeSlug: string;
|
|
48
|
+
/** semver pin for the chosen manifest version. */
|
|
49
|
+
nodeVersion: string;
|
|
50
|
+
name?: LocalizedString;
|
|
51
|
+
/** Free-form key→value config, validated against the node manifest. */
|
|
52
|
+
config: Record<string, unknown>;
|
|
53
|
+
position?: WorkflowNodePosition;
|
|
54
|
+
retry?: WorkflowNodeRetry;
|
|
55
|
+
}
|
|
56
|
+
export interface WorkflowEdge {
|
|
57
|
+
id: string;
|
|
58
|
+
from: {
|
|
59
|
+
nodeId: string;
|
|
60
|
+
output: string;
|
|
61
|
+
};
|
|
62
|
+
to: {
|
|
63
|
+
nodeId: string;
|
|
64
|
+
input?: string;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export interface WorkflowBlob {
|
|
68
|
+
nodeManifestVersion: string;
|
|
69
|
+
name: LocalizedString;
|
|
70
|
+
description?: LocalizedString;
|
|
71
|
+
variables?: Record<string, WorkflowVariable>;
|
|
72
|
+
triggers: WorkflowTrigger[];
|
|
73
|
+
nodes: WorkflowNode[];
|
|
74
|
+
edges: WorkflowEdge[];
|
|
75
|
+
/** Canvas positions for triggers, keyed by trigger handle (BlobDef). */
|
|
76
|
+
triggerPositions?: Record<string, {
|
|
77
|
+
x: number;
|
|
78
|
+
y: number;
|
|
79
|
+
}>;
|
|
80
|
+
}
|
|
81
|
+
export type WorkflowExecutionMode = 'async_only' | 'sync_only' | 'caller_decides';
|
|
82
|
+
export interface Workflow {
|
|
83
|
+
id: number;
|
|
84
|
+
name: string;
|
|
85
|
+
description: string | null;
|
|
86
|
+
blob_definition_version: 'v0-draft';
|
|
87
|
+
blob: WorkflowBlob;
|
|
88
|
+
active: boolean;
|
|
89
|
+
revision: number;
|
|
90
|
+
execution_mode?: WorkflowExecutionMode;
|
|
91
|
+
created_at: string;
|
|
92
|
+
updated_at: string;
|
|
93
|
+
}
|
|
94
|
+
export type NodeCategory = 'trigger' | 'action' | 'transform' | 'control' | 'io';
|
|
95
|
+
export type NodeDataType = 'any' | 'object' | 'array' | 'string' | 'number' | 'boolean';
|
|
96
|
+
export type OutputKind = 'default' | 'branch' | 'error';
|
|
97
|
+
export interface NodeManifestInput {
|
|
98
|
+
dataType: NodeDataType;
|
|
99
|
+
required?: boolean;
|
|
100
|
+
description?: LocalizedString;
|
|
101
|
+
}
|
|
102
|
+
export interface NodeManifestOutput {
|
|
103
|
+
name?: string;
|
|
104
|
+
label?: LocalizedString;
|
|
105
|
+
kind: OutputKind;
|
|
106
|
+
dataType: NodeDataType;
|
|
107
|
+
description?: LocalizedString;
|
|
108
|
+
sourceFromConfig?: string;
|
|
109
|
+
fallback?: {
|
|
110
|
+
name: string;
|
|
111
|
+
label?: LocalizedString;
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
export type ConfigFieldType = 'string' | 'number' | 'boolean' | 'select' | 'multiselect' | 'object' | 'array' | 'expression' | 'secret-ref' | 'credentials-ref';
|
|
115
|
+
export interface ConfigFieldOption {
|
|
116
|
+
value: string | number | boolean;
|
|
117
|
+
label: LocalizedString;
|
|
118
|
+
}
|
|
119
|
+
export interface ConfigField {
|
|
120
|
+
key: string;
|
|
121
|
+
label: LocalizedString;
|
|
122
|
+
description?: LocalizedString;
|
|
123
|
+
type: ConfigFieldType;
|
|
124
|
+
required?: boolean;
|
|
125
|
+
default?: unknown;
|
|
126
|
+
placeholder?: LocalizedString;
|
|
127
|
+
expressionAllowed?: boolean;
|
|
128
|
+
options?: ConfigFieldOption[];
|
|
129
|
+
/** sub-fields when type === 'object' (one level deep) */
|
|
130
|
+
properties?: ConfigField[];
|
|
131
|
+
/** item type when type === 'array' */
|
|
132
|
+
items?: ConfigField;
|
|
133
|
+
/** credential type slug the field binds to when type === 'credentials-ref' (e.g. 'revenexx:business-central'). */
|
|
134
|
+
credentialType?: string;
|
|
135
|
+
validation?: {
|
|
136
|
+
pattern?: string;
|
|
137
|
+
min?: number;
|
|
138
|
+
max?: number;
|
|
139
|
+
minLength?: number;
|
|
140
|
+
maxLength?: number;
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
export interface NodeManifest {
|
|
144
|
+
slug: string;
|
|
145
|
+
version: string;
|
|
146
|
+
category: NodeCategory;
|
|
147
|
+
name: LocalizedString;
|
|
148
|
+
description?: LocalizedString;
|
|
149
|
+
/** lucide-vue-next icon name OR mdi:icon-id. */
|
|
150
|
+
icon?: string;
|
|
151
|
+
input: NodeManifestInput;
|
|
152
|
+
outputs: NodeManifestOutput[];
|
|
153
|
+
config?: ConfigField[];
|
|
154
|
+
}
|
|
155
|
+
export interface SecretRecord {
|
|
156
|
+
key: string;
|
|
157
|
+
created_at: string;
|
|
158
|
+
updated_at: string;
|
|
159
|
+
}
|
|
160
|
+
/** How a credential type resolves to runtime access data. */
|
|
161
|
+
export type AuthKind = 'static' | 'api-key' | 'basic' | 'oauth2-client-credentials' | 'oauth2-authcode';
|
|
162
|
+
/** A single configurable field of a credential type (from its descriptor). */
|
|
163
|
+
export interface CredentialTypeField {
|
|
164
|
+
key: string;
|
|
165
|
+
type: 'string' | 'number' | 'boolean' | 'select' | 'secret';
|
|
166
|
+
label: LocalizedString;
|
|
167
|
+
required?: boolean;
|
|
168
|
+
options?: Array<{
|
|
169
|
+
label: string;
|
|
170
|
+
value: string | number | boolean;
|
|
171
|
+
}>;
|
|
172
|
+
validation?: {
|
|
173
|
+
pattern?: string;
|
|
174
|
+
min?: number;
|
|
175
|
+
max?: number;
|
|
176
|
+
minLength?: number;
|
|
177
|
+
maxLength?: number;
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/** A globally-registered credential type — drives the dynamic credential form. */
|
|
181
|
+
export interface CredentialType {
|
|
182
|
+
slug: string;
|
|
183
|
+
version: string;
|
|
184
|
+
name: LocalizedString;
|
|
185
|
+
description?: LocalizedString;
|
|
186
|
+
icon?: string;
|
|
187
|
+
auth_kind: AuthKind;
|
|
188
|
+
fields: CredentialTypeField[];
|
|
189
|
+
}
|
|
190
|
+
export type CredentialStatus = 'active' | 'needs_reauth';
|
|
191
|
+
/** A tenant's credential instance (secret fields never returned). */
|
|
192
|
+
export interface Credential {
|
|
193
|
+
id: string;
|
|
194
|
+
credential_type_slug: string;
|
|
195
|
+
name: string;
|
|
196
|
+
status: CredentialStatus;
|
|
197
|
+
/** non-secret field values only (whitelisted types). */
|
|
198
|
+
public_config?: Record<string, unknown>;
|
|
199
|
+
created_at: string;
|
|
200
|
+
updated_at: string;
|
|
201
|
+
}
|
|
202
|
+
export type ConnectionStatus = 'connected' | 'misconfigured' | 'unverified' | 'failing';
|
|
203
|
+
export interface ConnectionTemplate {
|
|
204
|
+
/** kebab-case slug (e.g. 'shopify'). */
|
|
205
|
+
vendor: string;
|
|
206
|
+
name: string;
|
|
207
|
+
description: string;
|
|
208
|
+
icon: string;
|
|
209
|
+
category: 'erp' | 'pim' | 'crm' | 'shop' | 'mail' | 'analytics' | 'other';
|
|
210
|
+
/** secrets the connection needs; UI nudges the user to set them. */
|
|
211
|
+
requiredSecrets: Array<{
|
|
212
|
+
key: string;
|
|
213
|
+
label: string;
|
|
214
|
+
sensitive?: boolean;
|
|
215
|
+
}>;
|
|
216
|
+
}
|
|
217
|
+
export interface Connection {
|
|
218
|
+
id: string;
|
|
219
|
+
vendor: string;
|
|
220
|
+
name: string;
|
|
221
|
+
status: ConnectionStatus;
|
|
222
|
+
lastVerifiedAt: string | null;
|
|
223
|
+
/** keys this connection composes from the secrets store. */
|
|
224
|
+
secretRefs: string[];
|
|
225
|
+
config: Record<string, unknown>;
|
|
226
|
+
createdAt: string;
|
|
227
|
+
updatedAt: string;
|
|
228
|
+
}
|
|
229
|
+
export interface WebhookEntry {
|
|
230
|
+
/** opaque id — combines workflow id and trigger id. */
|
|
231
|
+
id: string;
|
|
232
|
+
workflowId: number;
|
|
233
|
+
workflowName: string;
|
|
234
|
+
triggerId: string;
|
|
235
|
+
path: string;
|
|
236
|
+
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
237
|
+
secretRef?: string;
|
|
238
|
+
active: boolean;
|
|
239
|
+
lastFiredAt: string | null;
|
|
240
|
+
callCount24h: number;
|
|
241
|
+
}
|
|
242
|
+
export interface ScheduleEntry {
|
|
243
|
+
id: string;
|
|
244
|
+
workflowId: number;
|
|
245
|
+
workflowName: string;
|
|
246
|
+
triggerId: string;
|
|
247
|
+
cron: string;
|
|
248
|
+
timezone: string;
|
|
249
|
+
active: boolean;
|
|
250
|
+
nextRunAt: string | null;
|
|
251
|
+
lastRunAt: string | null;
|
|
252
|
+
}
|
|
253
|
+
export type TemplateCategory = 'sync' | 'notification' | 'enrichment' | 'fulfilment' | 'reporting' | 'finance';
|
|
254
|
+
export interface WorkflowTemplate {
|
|
255
|
+
/** kebab-case stable id. */
|
|
256
|
+
slug: string;
|
|
257
|
+
name: string;
|
|
258
|
+
description: string;
|
|
259
|
+
category: TemplateCategory;
|
|
260
|
+
industries: Array<'mechanical-engineering' | 'chemicals' | 'wholesale' | 'manufacturing' | 'retail' | 'any'>;
|
|
261
|
+
/** Vendor slugs this template wires together (used to compute prerequisites). */
|
|
262
|
+
vendors: string[];
|
|
263
|
+
/** Required secret keys; UI shows which are missing. */
|
|
264
|
+
requiredSecrets: string[];
|
|
265
|
+
/** Difficulty hint for the editor. */
|
|
266
|
+
level: 'beginner' | 'intermediate' | 'advanced';
|
|
267
|
+
/** Steps in the template — surfaced as a preview without rendering the canvas. */
|
|
268
|
+
outline: string[];
|
|
269
|
+
/** Number of node instances in the canonical blob. */
|
|
270
|
+
nodeCount: number;
|
|
271
|
+
/** Number of installs across the platform (used for "popular" ranking). */
|
|
272
|
+
installs: number;
|
|
273
|
+
/** Author identity. */
|
|
274
|
+
publisher: {
|
|
275
|
+
name: string;
|
|
276
|
+
kind: 'revenexx' | 'partner' | 'community';
|
|
277
|
+
};
|
|
278
|
+
/** Updated date for "last refreshed" labels. */
|
|
279
|
+
updatedAt: string;
|
|
280
|
+
/** The blob the editor receives when the user clicks "Use template". */
|
|
281
|
+
blob: WorkflowBlob;
|
|
282
|
+
/** Set when the entry came from the live registry (`GET /v1/templates`). */
|
|
283
|
+
fromApi?: boolean;
|
|
284
|
+
}
|
|
285
|
+
/** A credential type a template's workflow references (GET /templates/{slug}/requirements). */
|
|
286
|
+
export interface TemplateCredentialRequirement {
|
|
287
|
+
slug: string;
|
|
288
|
+
registered: boolean;
|
|
289
|
+
existingInstances: number;
|
|
290
|
+
usedBy: {
|
|
291
|
+
nodeId: string;
|
|
292
|
+
configKey: string;
|
|
293
|
+
}[];
|
|
294
|
+
version?: string;
|
|
295
|
+
name?: string;
|
|
296
|
+
authKind?: string;
|
|
297
|
+
fields?: unknown[];
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* A secret key a template references, cross-referenced against the tenant.
|
|
301
|
+
* `key` is null when the template author left it for the installing user to
|
|
302
|
+
* choose; `exists` is whether the tenant already stores that key.
|
|
303
|
+
*/
|
|
304
|
+
export interface TemplateSecretRequirement {
|
|
305
|
+
key: string | null;
|
|
306
|
+
exists: boolean;
|
|
307
|
+
usedBy?: Array<{
|
|
308
|
+
nodeId?: string;
|
|
309
|
+
configKey?: string;
|
|
310
|
+
source?: string;
|
|
311
|
+
handle?: string | null;
|
|
312
|
+
}>;
|
|
313
|
+
}
|
|
314
|
+
/** Install prerequisites for a template, scoped to the current tenant. */
|
|
315
|
+
export interface TemplateRequirements {
|
|
316
|
+
credentialTypes: TemplateCredentialRequirement[];
|
|
317
|
+
secrets: TemplateSecretRequirement[];
|
|
318
|
+
}
|
|
319
|
+
export type RunStatus = 'running' | 'succeeded' | 'failed' | 'cancelled' | 'queued';
|
|
320
|
+
export interface WorkflowRunNodeStep {
|
|
321
|
+
nodeId: string;
|
|
322
|
+
status: 'succeeded' | 'failed' | 'skipped' | 'pending';
|
|
323
|
+
startedAt: string;
|
|
324
|
+
finishedAt: string | null;
|
|
325
|
+
attempt: number;
|
|
326
|
+
durationMs: number | null;
|
|
327
|
+
}
|
|
328
|
+
export interface WorkflowRun {
|
|
329
|
+
id: string;
|
|
330
|
+
workflowId: number;
|
|
331
|
+
workflowName: string;
|
|
332
|
+
status: RunStatus;
|
|
333
|
+
triggerId: string;
|
|
334
|
+
triggerType: TriggerType;
|
|
335
|
+
startedAt: string;
|
|
336
|
+
finishedAt: string | null;
|
|
337
|
+
durationMs: number | null;
|
|
338
|
+
steps: WorkflowRunNodeStep[];
|
|
339
|
+
errorMessage?: string;
|
|
340
|
+
}
|
|
341
|
+
/** A webhook delivery outcome, shared by events and attempts. */
|
|
342
|
+
export type DeliveryStatus = 'success' | 'failed' | 'pending';
|
|
343
|
+
/**
|
|
344
|
+
* An event that arrived in Outpost for this tenant (GET /events). Outpost
|
|
345
|
+
* fans it out to every destination subscribed to its topic.
|
|
346
|
+
*/
|
|
347
|
+
export interface OutpostEvent {
|
|
348
|
+
id: string;
|
|
349
|
+
/** Topic the event was published on, e.g. "order.created". */
|
|
350
|
+
topic: string;
|
|
351
|
+
/** ISO timestamp the event was received. */
|
|
352
|
+
time: string;
|
|
353
|
+
/** Whether delivery may be retried (eligible_for_retry). */
|
|
354
|
+
eligibleForRetry: boolean;
|
|
355
|
+
/** Freeform event payload. */
|
|
356
|
+
data: Record<string, unknown>;
|
|
357
|
+
/** Header-style metadata forwarded to webhooks. */
|
|
358
|
+
metadata: Record<string, string>;
|
|
359
|
+
/**
|
|
360
|
+
* Rolled-up delivery state. Outpost's event object does not carry one;
|
|
361
|
+
* set only when the UI derives it (e.g. from deliveries).
|
|
362
|
+
*/
|
|
363
|
+
status?: DeliveryStatus;
|
|
364
|
+
/** How many destinations this event matched (matched_destination_ids). */
|
|
365
|
+
destinationCount: number;
|
|
366
|
+
}
|
|
367
|
+
/** Per-destination delivery of one event (GET /events/{id}, attempts). */
|
|
368
|
+
export interface OutpostEventDelivery {
|
|
369
|
+
destinationId: string;
|
|
370
|
+
destinationName: string;
|
|
371
|
+
status: DeliveryStatus;
|
|
372
|
+
attempts: number;
|
|
373
|
+
lastAttemptAt: string | null;
|
|
374
|
+
responseStatus: number | null;
|
|
375
|
+
}
|
|
376
|
+
/** Outpost destination type (GET /destination-types). v1: webhooks. */
|
|
377
|
+
export type OutboundDestinationType = 'webhook';
|
|
378
|
+
/**
|
|
379
|
+
* A webhook destination the tenant registered (GET/POST
|
|
380
|
+
* /tenants/{id}/destinations). "Event X on a subscribed topic → this webhook."
|
|
381
|
+
*/
|
|
382
|
+
export interface OutboundDestination {
|
|
383
|
+
id: string;
|
|
384
|
+
type: OutboundDestinationType;
|
|
385
|
+
/** Human label. */
|
|
386
|
+
name: string;
|
|
387
|
+
/** Topics this destination subscribes to; "*" means all. */
|
|
388
|
+
topics: string[];
|
|
389
|
+
/** Provider config — for webhooks, the target URL (+ optional secret ref). */
|
|
390
|
+
config: {
|
|
391
|
+
url: string;
|
|
392
|
+
secretRef?: string | null;
|
|
393
|
+
};
|
|
394
|
+
/** disabled_at === null means enabled. */
|
|
395
|
+
disabledAt: string | null;
|
|
396
|
+
createdAt: string;
|
|
397
|
+
/**
|
|
398
|
+
* Rolling delivery health — not on the Outpost destination object; present
|
|
399
|
+
* only when derived from metrics/attempts. UI shows "—" when absent.
|
|
400
|
+
*/
|
|
401
|
+
successRate24h?: number;
|
|
402
|
+
lastDeliveryAt?: string | null;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* A single delivery attempt to a destination
|
|
406
|
+
* (GET /tenants/{id}/destinations/{id}/attempts). This is the
|
|
407
|
+
* "Event X → Webhook Y" log row.
|
|
408
|
+
*/
|
|
409
|
+
export interface OutboundDeliveryAttempt {
|
|
410
|
+
id: string;
|
|
411
|
+
destinationId: string;
|
|
412
|
+
eventId: string;
|
|
413
|
+
/** Topic of the delivered event; present when Outpost inlines the event. */
|
|
414
|
+
topic?: string;
|
|
415
|
+
status: DeliveryStatus;
|
|
416
|
+
/** HTTP status (Outpost `code`) returned by the destination, if it responded. */
|
|
417
|
+
responseStatus: number | null;
|
|
418
|
+
/** Outpost `attempt_number`. */
|
|
419
|
+
attempt: number;
|
|
420
|
+
time: string;
|
|
421
|
+
/** Not provided by Outpost's attempt object today. */
|
|
422
|
+
durationMs?: number | null;
|
|
423
|
+
}
|
|
424
|
+
/** A topic available to subscribe to (GET /topics). */
|
|
425
|
+
export interface OutboundTopic {
|
|
426
|
+
name: string;
|
|
427
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a multilingual value from the Integrations API. The API returns
|
|
3
|
+
* names and descriptions either as a plain string or as an already-parsed
|
|
4
|
+
* object `{de:"…", en:"…"}` (the HTTP client does JSON decoding automatically).
|
|
5
|
+
* JSON-encoded strings like `'{"de":"…","en":"…"}'` are also handled.
|
|
6
|
+
*
|
|
7
|
+
* Priority: 1) current browser locale language, 2) "en", 3) first key found.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveLocalized(value: unknown): string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function resolveLocalized(value) {
|
|
2
|
+
if (value === null || value === void 0) return "";
|
|
3
|
+
if (typeof value === "object" && !Array.isArray(value)) {
|
|
4
|
+
const map = value;
|
|
5
|
+
const keys = Object.keys(map);
|
|
6
|
+
if (!keys.length) return "";
|
|
7
|
+
const lang = typeof navigator !== "undefined" ? navigator.language?.split("-")[0]?.toLowerCase() ?? "en" : "en";
|
|
8
|
+
const picked = map[lang] ?? map["en"] ?? map[keys[0]];
|
|
9
|
+
return typeof picked === "string" ? picked : "";
|
|
10
|
+
}
|
|
11
|
+
if (typeof value !== "string") return String(value);
|
|
12
|
+
const trimmed = value.trim();
|
|
13
|
+
if (!trimmed.startsWith("{")) return trimmed;
|
|
14
|
+
try {
|
|
15
|
+
const parsed = JSON.parse(trimmed);
|
|
16
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return trimmed;
|
|
17
|
+
return resolveLocalized(parsed);
|
|
18
|
+
} catch {
|
|
19
|
+
return trimmed;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One source of truth for status → colour across the cockpit.
|
|
3
|
+
*
|
|
4
|
+
* Studios used to each carry their own `statusClass` map with slightly
|
|
5
|
+
* different palettes. Map a domain status string to a semantic tone, and
|
|
6
|
+
* a tone to the Badge/pill classes, so "succeeded", "active", "paid" and
|
|
7
|
+
* "published" all read as the same green everywhere.
|
|
8
|
+
*/
|
|
9
|
+
export type StatusTone = 'success' | 'running' | 'warning' | 'error' | 'info' | 'neutral';
|
|
10
|
+
/** Resolve a status string to its semantic tone (neutral when unknown). */
|
|
11
|
+
export declare function statusTone(status: string | null | undefined): StatusTone;
|
|
12
|
+
/** Badge/pill classes for a status string (use with `variant="outline"`). */
|
|
13
|
+
export declare function statusClass(status: string | null | undefined): string;
|
|
14
|
+
/** Tone classes directly (when you already have a tone). */
|
|
15
|
+
export declare function toneClass(tone: StatusTone): string;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
const TONE_CLASS = {
|
|
2
|
+
success: "bg-emerald-500/15 text-emerald-700 border-emerald-500/20",
|
|
3
|
+
running: "bg-sky-500/15 text-sky-700 border-sky-500/20",
|
|
4
|
+
warning: "bg-amber-500/15 text-amber-700 border-amber-500/20",
|
|
5
|
+
error: "bg-rose-500/15 text-rose-700 border-rose-500/20",
|
|
6
|
+
info: "bg-violet-500/15 text-violet-700 border-violet-500/20",
|
|
7
|
+
neutral: "bg-slate-500/15 text-slate-700 border-slate-500/20"
|
|
8
|
+
};
|
|
9
|
+
const STATUS_TONE = {
|
|
10
|
+
// success
|
|
11
|
+
succeeded: "success",
|
|
12
|
+
success: "success",
|
|
13
|
+
active: "success",
|
|
14
|
+
enabled: "success",
|
|
15
|
+
published: "success",
|
|
16
|
+
completed: "success",
|
|
17
|
+
complete: "success",
|
|
18
|
+
paid: "success",
|
|
19
|
+
connected: "success",
|
|
20
|
+
delivered: "success",
|
|
21
|
+
healthy: "success",
|
|
22
|
+
live: "success",
|
|
23
|
+
ok: "success",
|
|
24
|
+
done: "success",
|
|
25
|
+
approved: "success",
|
|
26
|
+
sent: "success",
|
|
27
|
+
// running / in progress
|
|
28
|
+
running: "running",
|
|
29
|
+
processing: "running",
|
|
30
|
+
provisioning: "running",
|
|
31
|
+
pending: "running",
|
|
32
|
+
syncing: "running",
|
|
33
|
+
sending: "running",
|
|
34
|
+
in_progress: "running",
|
|
35
|
+
started: "running",
|
|
36
|
+
// warning / awaiting
|
|
37
|
+
queued: "warning",
|
|
38
|
+
draft: "warning",
|
|
39
|
+
paused: "warning",
|
|
40
|
+
warning: "warning",
|
|
41
|
+
past_due: "warning",
|
|
42
|
+
retrying: "warning",
|
|
43
|
+
scheduled: "warning",
|
|
44
|
+
waiting: "warning",
|
|
45
|
+
partial: "warning",
|
|
46
|
+
// error
|
|
47
|
+
failed: "error",
|
|
48
|
+
failure: "error",
|
|
49
|
+
error: "error",
|
|
50
|
+
rejected: "error",
|
|
51
|
+
bounced: "error",
|
|
52
|
+
disconnected: "error",
|
|
53
|
+
expired: "error",
|
|
54
|
+
overdue: "error",
|
|
55
|
+
dead: "error",
|
|
56
|
+
unpaid: "error",
|
|
57
|
+
// neutral
|
|
58
|
+
cancelled: "neutral",
|
|
59
|
+
canceled: "neutral",
|
|
60
|
+
inactive: "neutral",
|
|
61
|
+
disabled: "neutral",
|
|
62
|
+
unknown: "neutral",
|
|
63
|
+
archived: "neutral",
|
|
64
|
+
uninstalled: "neutral",
|
|
65
|
+
none: "neutral",
|
|
66
|
+
skipped: "neutral"
|
|
67
|
+
};
|
|
68
|
+
export function statusTone(status) {
|
|
69
|
+
if (!status) return "neutral";
|
|
70
|
+
const key = String(status).toLowerCase().replace(/[\s-]+/g, "_");
|
|
71
|
+
return STATUS_TONE[key] ?? "neutral";
|
|
72
|
+
}
|
|
73
|
+
export function statusClass(status) {
|
|
74
|
+
return TONE_CLASS[statusTone(status)];
|
|
75
|
+
}
|
|
76
|
+
export function toneClass(tone) {
|
|
77
|
+
return TONE_CLASS[tone];
|
|
78
|
+
}
|
package/dist/types.d.mts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NuxtModule } from '@nuxt/schema'
|
|
2
|
+
|
|
3
|
+
import type { default as Module } from './module.mjs'
|
|
4
|
+
|
|
5
|
+
export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
|
|
6
|
+
|
|
7
|
+
export { default } from './module.mjs'
|
|
8
|
+
|
|
9
|
+
export * from '../dist/runtime/types/integrations.js'
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@revenexx/studio-integrations",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Integration Studio (core: workflows, node editor, runs, schedules, credentials, secrets, audit) as a standalone, publishable Nuxt module.",
|
|
6
|
+
"main": "./dist/module.mjs",
|
|
7
|
+
"types": "./dist/types.d.mts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/types.d.mts",
|
|
11
|
+
"import": "./dist/module.mjs"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"registry": "https://registry.npmjs.org/",
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@nuxt/kit": "^4.0.0"
|
|
23
|
+
},
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"@dagrejs/dagre": "^3.0.0",
|
|
26
|
+
"@revenexx/studio": "*",
|
|
27
|
+
"@vue-flow/background": "^1.3.2",
|
|
28
|
+
"@vue-flow/controls": "^1.1.3",
|
|
29
|
+
"@vue-flow/core": "^1.48.2",
|
|
30
|
+
"@vue-flow/minimap": "^1.5.4",
|
|
31
|
+
"lucide-vue-next": "^1.0.0",
|
|
32
|
+
"nuxt": "^4.0.0",
|
|
33
|
+
"vue": "^3.5.0",
|
|
34
|
+
"@revenexx/studio-shared": "0.1.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@nuxt/module-builder": "^1.0.2",
|
|
38
|
+
"@nuxt/kit": "^4.0.0",
|
|
39
|
+
"nuxt": "^4.2.2",
|
|
40
|
+
"vue": "^3.5.26",
|
|
41
|
+
"vue-tsc": "^2.2.0"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "nuxt-module-build build"
|
|
45
|
+
}
|
|
46
|
+
}
|