@revenexx/studio-integrations 0.5.1 → 0.7.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/CHANGELOG.md +428 -0
- package/README.md +48 -4
- package/dist/module.d.mts +17 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +10 -2
- package/dist/runtime/components/Integrations/CredentialCreateDialog.vue +43 -41
- package/dist/runtime/components/Integrations/CredentialDetailDialog.vue +123 -50
- package/dist/runtime/components/Integrations/CredentialRevenexxSource.vue +108 -71
- package/dist/runtime/components/Integrations/CredentialTypePicker.vue +12 -15
- package/dist/runtime/components/Integrations/DeadLettersPanel.vue +18 -17
- package/dist/runtime/components/Integrations/EventTypeCombobox.d.vue.ts +1 -0
- package/dist/runtime/components/Integrations/EventTypeCombobox.vue +7 -4
- package/dist/runtime/components/Integrations/EventTypeCombobox.vue.d.ts +1 -0
- package/dist/runtime/components/Integrations/ExpressionInput.d.vue.ts +4 -0
- package/dist/runtime/components/Integrations/ExpressionInput.vue +67 -37
- package/dist/runtime/components/Integrations/ExpressionInput.vue.d.ts +4 -0
- package/dist/runtime/components/Integrations/GroupFrameView.vue +30 -20
- package/dist/runtime/components/Integrations/Layout.vue +48 -4
- package/dist/runtime/components/Integrations/NodeConfigDynamicField.vue +23 -23
- package/dist/runtime/components/Integrations/NodeConfigDynamicSchema.vue +11 -13
- package/dist/runtime/components/Integrations/NodeConfigField.d.vue.ts +2 -0
- package/dist/runtime/components/Integrations/NodeConfigField.vue +187 -93
- package/dist/runtime/components/Integrations/NodeConfigField.vue.d.ts +2 -0
- package/dist/runtime/components/Integrations/NodeInspector.d.vue.ts +6 -0
- package/dist/runtime/components/Integrations/NodeInspector.vue +1157 -376
- package/dist/runtime/components/Integrations/NodeInspector.vue.d.ts +6 -0
- package/dist/runtime/components/Integrations/NodeLogo.d.vue.ts +12 -0
- package/dist/runtime/components/Integrations/NodeLogo.vue +2 -30
- package/dist/runtime/components/Integrations/NodeLogo.vue.d.ts +12 -0
- package/dist/runtime/components/Integrations/NodeMark.d.vue.ts +15 -0
- package/dist/runtime/components/Integrations/NodeMark.vue +79 -0
- package/dist/runtime/components/Integrations/NodeMark.vue.d.ts +15 -0
- package/dist/runtime/components/Integrations/NodeOutputSchema.d.vue.ts +21 -0
- package/dist/runtime/components/Integrations/NodeOutputSchema.vue +43 -0
- package/dist/runtime/components/Integrations/NodeOutputSchema.vue.d.ts +21 -0
- package/dist/runtime/components/Integrations/NodePalette.vue +122 -55
- package/dist/runtime/components/Integrations/QueryBuilder.vue +46 -38
- package/dist/runtime/components/Integrations/RunActionsMenu.vue +38 -12
- package/dist/runtime/components/Integrations/RunDetailPanel.vue +114 -62
- package/dist/runtime/components/Integrations/RunPayloadInput.vue +27 -13
- package/dist/runtime/components/Integrations/RunResponseModal.vue +11 -10
- package/dist/runtime/components/Integrations/RunsTable.d.vue.ts +0 -1
- package/dist/runtime/components/Integrations/RunsTable.vue +38 -16
- package/dist/runtime/components/Integrations/RunsTable.vue.d.ts +0 -1
- package/dist/runtime/components/Integrations/SftpAccountImportDialog.vue +8 -7
- package/dist/runtime/components/Integrations/Sidebar.vue +14 -10
- package/dist/runtime/components/Integrations/StickyNoteView.d.vue.ts +14 -4
- package/dist/runtime/components/Integrations/StickyNoteView.vue +38 -23
- package/dist/runtime/components/Integrations/StickyNoteView.vue.d.ts +14 -4
- package/dist/runtime/components/Integrations/TemplateCard.d.vue.ts +18 -0
- package/dist/runtime/components/Integrations/TemplateCard.vue +119 -0
- package/dist/runtime/components/Integrations/TemplateCard.vue.d.ts +18 -0
- package/dist/runtime/components/Integrations/TemplateFlowPreview.d.vue.ts +2 -2
- package/dist/runtime/components/Integrations/TemplateFlowPreview.vue +16 -18
- package/dist/runtime/components/Integrations/TemplateFlowPreview.vue.d.ts +2 -2
- package/dist/runtime/components/Integrations/WorkflowContextMenu.vue +34 -33
- package/dist/runtime/components/Integrations/WorkflowCreateDialog.vue +52 -67
- package/dist/runtime/components/Integrations/WorkflowDuplicateDialog.vue +8 -7
- package/dist/runtime/components/Integrations/WorkflowEdgeView.d.vue.ts +18 -4
- package/dist/runtime/components/Integrations/WorkflowEdgeView.vue +29 -11
- package/dist/runtime/components/Integrations/WorkflowEdgeView.vue.d.ts +18 -4
- package/dist/runtime/components/Integrations/WorkflowEditor.d.vue.ts +20 -1
- package/dist/runtime/components/Integrations/WorkflowEditor.vue +240 -116
- package/dist/runtime/components/Integrations/WorkflowEditor.vue.d.ts +20 -1
- package/dist/runtime/components/Integrations/WorkflowHistoryPanel.vue +28 -43
- package/dist/runtime/components/Integrations/WorkflowIconPicker.d.vue.ts +19 -1
- package/dist/runtime/components/Integrations/WorkflowIconPicker.vue +17 -7
- package/dist/runtime/components/Integrations/WorkflowIconPicker.vue.d.ts +19 -1
- package/dist/runtime/components/Integrations/WorkflowNodeView.d.vue.ts +4 -0
- package/dist/runtime/components/Integrations/WorkflowNodeView.vue +198 -56
- package/dist/runtime/components/Integrations/WorkflowNodeView.vue.d.ts +4 -0
- package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.vue +56 -59
- package/dist/runtime/components/Integrations/WorkflowSettingsDialog.vue +28 -21
- package/dist/runtime/components/Integrations/WorkflowTagsInput.d.vue.ts +1 -0
- package/dist/runtime/components/Integrations/WorkflowTagsInput.vue +15 -9
- package/dist/runtime/components/Integrations/WorkflowTagsInput.vue.d.ts +1 -0
- package/dist/runtime/components/Integrations/WorkflowTriggerView.vue +15 -10
- package/dist/runtime/components/Integrations/WorkflowVariablesDialog.vue +50 -36
- package/dist/runtime/components/Integrations/WorkflowsTable.vue +126 -48
- package/dist/runtime/composables/integrationsApi.js +4 -2
- package/dist/runtime/composables/useCredentialTypes.js +8 -6
- package/dist/runtime/composables/useIntegrationsAudit.js +4 -3
- package/dist/runtime/composables/useIntegrationsCredentials.js +10 -8
- package/dist/runtime/composables/useIntegrationsDeadLetters.js +7 -6
- package/dist/runtime/composables/useIntegrationsFocus.d.ts +12 -0
- package/dist/runtime/composables/useIntegrationsLocale.d.ts +26 -0
- package/dist/runtime/composables/useIntegrationsLocale.js +8 -0
- package/dist/runtime/composables/useIntegrationsNodes.js +7 -5
- package/dist/runtime/composables/useIntegrationsRealtime.d.ts +149 -0
- package/dist/runtime/composables/useIntegrationsRealtime.js +80 -0
- package/dist/runtime/composables/useIntegrationsRevisions.js +9 -7
- package/dist/runtime/composables/useIntegrationsRuns.d.ts +1 -1
- package/dist/runtime/composables/useIntegrationsRuns.js +14 -7
- package/dist/runtime/composables/useIntegrationsSchedules.d.ts +4 -0
- package/dist/runtime/composables/useIntegrationsSchedules.js +10 -3
- package/dist/runtime/composables/useIntegrationsSecrets.js +14 -9
- package/dist/runtime/composables/useIntegrationsT.d.ts +35 -0
- package/dist/runtime/composables/useIntegrationsT.js +9 -0
- package/dist/runtime/composables/useIntegrationsTemplates.d.ts +3 -3
- package/dist/runtime/composables/useIntegrationsTemplates.js +28 -16
- package/dist/runtime/composables/useIntegrationsTriggers.js +10 -8
- package/dist/runtime/composables/useIntegrationsWorkflows.js +13 -7
- package/dist/runtime/composables/useLoadGate.d.ts +17 -0
- package/dist/runtime/composables/useLoadGate.js +8 -0
- package/dist/runtime/composables/useNodeConfigResolve.js +2 -1
- package/dist/runtime/data/branchReorder.d.ts +37 -0
- package/dist/runtime/data/branchReorder.js +71 -0
- package/dist/runtime/data/handleId.d.ts +23 -0
- package/dist/runtime/data/handleId.js +6 -0
- package/dist/runtime/data/integrationNodeCatalog.d.ts +41 -0
- package/dist/runtime/data/integrationNodeCatalog.js +14 -0
- package/dist/runtime/data/integrationTemplates.d.ts +48 -0
- package/dist/runtime/data/integrationTemplates.js +21 -0
- package/dist/runtime/data/integrationWorkflowSamples.js +1 -1
- package/dist/runtime/data/nodeIcons.d.ts +2 -0
- package/dist/runtime/data/nodeIcons.js +73 -0
- package/dist/runtime/data/nodeInputData.d.ts +16 -4
- package/dist/runtime/data/nodeInputData.js +4 -0
- package/dist/runtime/data/payloadForm.d.ts +9 -2
- package/dist/runtime/data/payloadForm.js +29 -4
- package/dist/runtime/data/portTone.d.ts +17 -0
- package/dist/runtime/data/portTone.js +7 -0
- package/dist/runtime/data/webhookAuth.d.ts +18 -0
- package/dist/runtime/data/webhookAuth.js +19 -0
- package/dist/runtime/data/workflowIconCatalog.js +4 -6
- package/dist/runtime/i18n/messages/de.json +1207 -0
- package/dist/runtime/i18n/messages/en.json +1207 -0
- package/dist/runtime/i18n/translate.d.ts +83 -0
- package/dist/runtime/i18n/translate.js +41 -0
- package/dist/runtime/pages/integrations/audit.vue +140 -37
- package/dist/runtime/pages/integrations/credentials/oauth-complete.vue +9 -6
- package/dist/runtime/pages/integrations/credentials.vue +180 -64
- package/dist/runtime/pages/integrations/index.vue +91 -92
- package/dist/runtime/pages/integrations/runs.vue +33 -21
- package/dist/runtime/pages/integrations/schedules.vue +88 -23
- package/dist/runtime/pages/integrations/secrets.vue +57 -35
- package/dist/runtime/pages/integrations/templates/[slug].vue +119 -88
- package/dist/runtime/pages/integrations/templates/index.vue +82 -103
- package/dist/runtime/pages/integrations/workflows/[id].vue +344 -91
- package/dist/runtime/pages/integrations/workflows/index.vue +23 -5
- package/dist/runtime/plugins/locale.d.ts +10 -0
- package/dist/runtime/plugins/locale.js +6 -0
- package/dist/runtime/plugins/realtime.client.d.ts +32 -0
- package/dist/runtime/plugins/realtime.client.js +4 -0
- package/dist/runtime/types/integrations.d.ts +65 -6
- package/dist/runtime/utils/apiError.d.ts +47 -0
- package/dist/runtime/utils/apiError.js +32 -0
- package/dist/runtime/utils/cockpitSources.d.ts +153 -0
- package/dist/runtime/utils/cockpitSources.js +14 -0
- package/dist/runtime/utils/credentialState.d.ts +24 -1
- package/dist/runtime/utils/credentialState.js +26 -11
- package/dist/runtime/utils/loadGate.d.ts +61 -0
- package/dist/runtime/utils/loadGate.js +22 -0
- package/dist/runtime/utils/localize.d.ts +46 -4
- package/dist/runtime/utils/localize.js +34 -7
- package/dist/runtime/utils/notify.d.ts +59 -0
- package/dist/runtime/utils/notify.js +21 -0
- package/dist/runtime/utils/pollBudget.d.ts +72 -0
- package/dist/runtime/utils/pollBudget.js +17 -0
- package/dist/runtime/utils/revenexxCredentialSource.d.ts +26 -0
- package/dist/runtime/utils/revenexxCredentialSource.js +8 -0
- package/dist/runtime/utils/schedule.d.ts +116 -0
- package/dist/runtime/utils/schedule.js +219 -0
- package/dist/runtime/utils/statusStyle.d.ts +26 -2
- package/dist/runtime/utils/statusStyle.js +9 -1
- package/dist/runtime/utils/validationFindings.d.ts +101 -0
- package/dist/runtime/utils/validationFindings.js +54 -0
- package/dist/runtime/utils/whenIdle.d.ts +42 -0
- package/dist/runtime/utils/whenIdle.js +12 -0
- package/dist/types.d.mts +2 -6
- package/package.json +10 -3
|
@@ -3,9 +3,57 @@ import type { WorkflowTemplate } from '../types/integrations.js';
|
|
|
3
3
|
* Category lens config for the Templates catalogue. The templates themselves
|
|
4
4
|
* come live from the Integrations registry (`GET /templates`) — there is no
|
|
5
5
|
* mock catalogue; an empty registry is an empty catalogue.
|
|
6
|
+
*
|
|
7
|
+
* The two categories that templates actually ship with today are `commerce` and
|
|
8
|
+
* `sales`: the eight templates in `@revenexx/integrations-nodes-core` are all
|
|
9
|
+
* `commerce`, the two in the Business Central package `sales`. Neither was named
|
|
10
|
+
* here, so both were shown by the fallback rather than by a label — the studio's
|
|
11
|
+
* one list of categories described none of the catalogue it had. The other six
|
|
12
|
+
* are named on spec and nothing publishes them yet.
|
|
6
13
|
*/
|
|
7
14
|
export declare const TEMPLATE_CATEGORIES: Array<{
|
|
8
15
|
key: WorkflowTemplate['category'];
|
|
9
16
|
label: string;
|
|
10
17
|
color: string;
|
|
11
18
|
}>;
|
|
19
|
+
/**
|
|
20
|
+
* What a template's category is called, wherever the studio shows one.
|
|
21
|
+
*
|
|
22
|
+
* Four surfaces draw a category chip — the gallery, a template's own page, the
|
|
23
|
+
* dashboard's template panel and the start-from-a-template list in the dialog that
|
|
24
|
+
* creates a workflow — and each worked the name out for itself: a lookup with a
|
|
25
|
+
* capitalisation fallback, the raw registry key, and two separate capitalisations.
|
|
26
|
+
* They agreed only by coincidence, because every label in `TEMPLATE_CATEGORIES`
|
|
27
|
+
* above happens to be its key capitalised.
|
|
28
|
+
*
|
|
29
|
+
* That coincidence ends with the first category whose name is not a capitalisation
|
|
30
|
+
* — `crm`, `b2b`, `erp` — and categories arrive with node packages rather than with
|
|
31
|
+
* a release of the studio, so it is a matter of when. Every chip goes through here
|
|
32
|
+
* instead.
|
|
33
|
+
*
|
|
34
|
+
* The fallback is the catalogue's own promise (`specs/templates.md` AC-2): a
|
|
35
|
+
* category the studio has never been taught still gets a chip, named as well as it
|
|
36
|
+
* can be rather than dropped. That guarantee held on the gallery alone before; it
|
|
37
|
+
* now holds on all four.
|
|
38
|
+
*
|
|
39
|
+
* `specs/templates.md` AC-8 splits this in two: the first half — a category the
|
|
40
|
+
* studio *does* have a name for — is the studio's own word, and can follow the
|
|
41
|
+
* reader's language; the second half — the registry's own key, capitalised — never
|
|
42
|
+
* can, because a bare key carries no text to read in any language. Only the first
|
|
43
|
+
* half goes through `useIntegrationsT()`. A message missing from the catalogue
|
|
44
|
+
* (this key not merged into `messages/*.json` yet) falls back to the same English
|
|
45
|
+
* word `TEMPLATE_CATEGORIES` always carried, so the label degrades to "correct but
|
|
46
|
+
* unlocalised" rather than to the raw key.
|
|
47
|
+
*/
|
|
48
|
+
export declare function templateCategoryLabel(key: string): string;
|
|
49
|
+
/**
|
|
50
|
+
* The integration a template ships with, as a card badges it — and as the
|
|
51
|
+
* gallery's search matches it. The core toolbox stays unbadged: every template
|
|
52
|
+
* would carry it, so it would say nothing.
|
|
53
|
+
*
|
|
54
|
+
* It lives here for the same reason `templateCategoryLabel` does. The gallery
|
|
55
|
+
* both shows this label and searches by it, so a copy inside the card component
|
|
56
|
+
* would be a second implementation of a name — the exact duplication PO-243
|
|
57
|
+
* removes.
|
|
58
|
+
*/
|
|
59
|
+
export declare function templatePackageLabel(tpl: Pick<WorkflowTemplate, 'package'>): string | null;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { useIntegrationsT } from "../composables/useIntegrationsT.js";
|
|
1
2
|
export const TEMPLATE_CATEGORIES = [
|
|
2
3
|
// Uniform muted pill — the label carries the meaning, no rainbow needed.
|
|
4
|
+
{ key: "commerce", label: "Commerce", color: "bg-slate-100 text-slate-700" },
|
|
5
|
+
{ key: "sales", label: "Sales", color: "bg-slate-100 text-slate-700" },
|
|
3
6
|
{ key: "sync", label: "Sync", color: "bg-slate-100 text-slate-700" },
|
|
4
7
|
{ key: "notification", label: "Notification", color: "bg-slate-100 text-slate-700" },
|
|
5
8
|
{ key: "fulfilment", label: "Fulfilment", color: "bg-slate-100 text-slate-700" },
|
|
@@ -7,3 +10,21 @@ export const TEMPLATE_CATEGORIES = [
|
|
|
7
10
|
{ key: "finance", label: "Finance", color: "bg-slate-100 text-slate-700" },
|
|
8
11
|
{ key: "reporting", label: "Reporting", color: "bg-slate-100 text-slate-700" }
|
|
9
12
|
];
|
|
13
|
+
export function templateCategoryLabel(key) {
|
|
14
|
+
if (!key) return "";
|
|
15
|
+
const known = TEMPLATE_CATEGORIES.find((c) => c.key === key);
|
|
16
|
+
if (known) {
|
|
17
|
+
const t = useIntegrationsT();
|
|
18
|
+
const messageKey = `integration.templates.category.${known.key}`;
|
|
19
|
+
const translated = t(messageKey);
|
|
20
|
+
return translated === messageKey ? known.label : translated;
|
|
21
|
+
}
|
|
22
|
+
return key.charAt(0).toUpperCase() + key.slice(1);
|
|
23
|
+
}
|
|
24
|
+
export function templatePackageLabel(tpl) {
|
|
25
|
+
const pkg = tpl.package;
|
|
26
|
+
if (!pkg) return null;
|
|
27
|
+
const tail = (pkg.name.split("/").pop() ?? pkg.name).replace(/^integrations-nodes-/, "");
|
|
28
|
+
if (tail === "core") return null;
|
|
29
|
+
return pkg.label ?? tail.split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" ");
|
|
30
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import * as Lucide from "lucide-vue-next";
|
|
2
|
+
const MDI_TO_LUCIDE = {
|
|
3
|
+
"account-group-outline": "Users",
|
|
4
|
+
"account-outline": "User",
|
|
5
|
+
"account-plus-outline": "UserPlus",
|
|
6
|
+
"alert-octagon": "OctagonAlert",
|
|
7
|
+
"api": "Webhook",
|
|
8
|
+
"book-open-outline": "BookOpen",
|
|
9
|
+
"bullseye-arrow": "Target",
|
|
10
|
+
"calendar-check-outline": "CalendarCheck",
|
|
11
|
+
"card-account-details-outline": "IdCard",
|
|
12
|
+
"cart-outline": "ShoppingCart",
|
|
13
|
+
"cart-plus": "ShoppingBasket",
|
|
14
|
+
"circle-outline": "Circle",
|
|
15
|
+
"clock-outline": "Clock",
|
|
16
|
+
"cloud-download": "CloudDownload",
|
|
17
|
+
"cloud-upload": "CloudUpload",
|
|
18
|
+
"cloud-upload-outline": "CloudUpload",
|
|
19
|
+
"code-brackets": "Brackets",
|
|
20
|
+
"code-json": "Braces",
|
|
21
|
+
"code-tags": "Code",
|
|
22
|
+
"compare-horizontal": "ArrowLeftRight",
|
|
23
|
+
"currency-eur": "Euro",
|
|
24
|
+
"database-cog-outline": "Database",
|
|
25
|
+
"database-export-outline": "HardDriveUpload",
|
|
26
|
+
"database-import-outline": "HardDriveDownload",
|
|
27
|
+
"domain": "Building2",
|
|
28
|
+
"email-send": "Send",
|
|
29
|
+
"file-edit-outline": "FilePen",
|
|
30
|
+
"file-export-outline": "FileOutput",
|
|
31
|
+
"file-import-outline": "FileInput",
|
|
32
|
+
"file-move-outline": "FileSymlink",
|
|
33
|
+
"file-plus": "FilePlus",
|
|
34
|
+
"file-question-outline": "FileQuestion",
|
|
35
|
+
"file-remove-outline": "FileX",
|
|
36
|
+
"filter": "Filter",
|
|
37
|
+
"find-replace": "Replace",
|
|
38
|
+
"folder-download-outline": "FolderDown",
|
|
39
|
+
"folder-plus-outline": "FolderPlus",
|
|
40
|
+
"folder-search-outline": "FolderSearch",
|
|
41
|
+
"folder-upload-outline": "FolderUp",
|
|
42
|
+
"folder-zip-outline": "FolderArchive",
|
|
43
|
+
"format-list-bulleted-type": "List",
|
|
44
|
+
"handshake": "Handshake",
|
|
45
|
+
"handshake-outline": "Handshake",
|
|
46
|
+
"link-lock": "Link2",
|
|
47
|
+
"magnify": "Search",
|
|
48
|
+
"office-building-outline": "Building",
|
|
49
|
+
"pencil-box-outline": "SquarePen",
|
|
50
|
+
"pipe": "Workflow",
|
|
51
|
+
"receipt-outline": "Receipt",
|
|
52
|
+
"receipt-text-outline": "ReceiptText",
|
|
53
|
+
"regex": "Regex",
|
|
54
|
+
"repeat": "Repeat",
|
|
55
|
+
"ruler": "Ruler",
|
|
56
|
+
"source-branch": "GitBranch",
|
|
57
|
+
"tag-multiple-outline": "Tags",
|
|
58
|
+
"transfer": "ArrowRightLeft",
|
|
59
|
+
"translate": "Languages",
|
|
60
|
+
"truck-outline": "Truck",
|
|
61
|
+
"web": "Globe",
|
|
62
|
+
"xml": "CodeXml"
|
|
63
|
+
};
|
|
64
|
+
export function nodeIcon(name) {
|
|
65
|
+
if (!name) return Lucide.Box;
|
|
66
|
+
const bare = name.includes(":") ? name.split(":").pop() : name;
|
|
67
|
+
const mapped = MDI_TO_LUCIDE[bare];
|
|
68
|
+
if (mapped && Lucide[mapped]) {
|
|
69
|
+
return Lucide[mapped];
|
|
70
|
+
}
|
|
71
|
+
const pascal = bare.split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
|
|
72
|
+
return Lucide[pascal] || Lucide.Box;
|
|
73
|
+
}
|
|
@@ -27,11 +27,23 @@ export interface PortEntry {
|
|
|
27
27
|
/** Declared payload fields of this port (schema; may be empty). */
|
|
28
28
|
fields: FieldEntry[];
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* A manifest declaring zero output ports describes a TERMINAL node (PO-201):
|
|
32
|
+
* the run ends there, so it gets no output handle and no edge may leave it.
|
|
33
|
+
*
|
|
34
|
+
* The distinction that matters is **declared empty vs. not known**. An absent
|
|
35
|
+
* manifest — a node that is not installed — is not terminal; we simply cannot
|
|
36
|
+
* work out its ports, and it has to stay wirable. Same for a `sourceFromConfig`
|
|
37
|
+
* or `resolveOutputs` set that expands to nothing: unresolved, not terminal.
|
|
38
|
+
* Only an explicit `[]` is the node making a statement about itself.
|
|
39
|
+
*/
|
|
40
|
+
export declare function isTerminalManifest(manifest: NodeManifest | null | undefined): boolean;
|
|
30
41
|
/**
|
|
31
42
|
* The output ports one upstream node exposes, mirroring the canvas port
|
|
32
|
-
* derivation
|
|
33
|
-
* from the node's config values (plus the
|
|
34
|
-
*
|
|
35
|
-
* dynamic outputs, when present, replace
|
|
43
|
+
* derivation in `WorkflowNodeView.vue`. Named ports map straight over,
|
|
44
|
+
* `sourceFromConfig` ports expand from the node's config values (plus the
|
|
45
|
+
* optional fallback), and a node whose ports could not be worked out still
|
|
46
|
+
* gets its `default`. Server-resolved dynamic outputs, when present, replace
|
|
47
|
+
* the manifest's static list.
|
|
36
48
|
*/
|
|
37
49
|
export declare function portsForNode(node: WorkflowNode, manifest: NodeManifest | null, resolvedOutputs?: NodeManifestOutput[]): PortEntry[];
|
|
@@ -44,7 +44,11 @@ function fieldEntries(raw) {
|
|
|
44
44
|
}
|
|
45
45
|
return [];
|
|
46
46
|
}
|
|
47
|
+
export function isTerminalManifest(manifest) {
|
|
48
|
+
return !!manifest && Array.isArray(manifest.outputs) && !manifest.outputs.length;
|
|
49
|
+
}
|
|
47
50
|
export function portsForNode(node, manifest, resolvedOutputs) {
|
|
51
|
+
if (isTerminalManifest(manifest)) return [];
|
|
48
52
|
const list = resolvedOutputs?.length ? resolvedOutputs : manifest?.outputs ?? [];
|
|
49
53
|
const ports = [];
|
|
50
54
|
for (const o of list) {
|
|
@@ -16,8 +16,15 @@ export interface PayloadField {
|
|
|
16
16
|
path: string;
|
|
17
17
|
label: string;
|
|
18
18
|
}
|
|
19
|
-
/**
|
|
20
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Payload form fields: fields DECLARED on a manual trigger come first (the
|
|
21
|
+
* author's explicit contract, e.g. a file field for a manual import), then
|
|
22
|
+
* every `${{ trigger.payload.* }}` reference found in node configs that the
|
|
23
|
+
* declarations don't already cover.
|
|
24
|
+
*/
|
|
25
|
+
export declare function payloadFieldsFromBlob(blob: Pick<WorkflowBlob, 'nodes'> & {
|
|
26
|
+
triggers?: WorkflowBlob['triggers'];
|
|
27
|
+
}): PayloadField[];
|
|
21
28
|
export declare function setPath(target: Record<string, unknown>, path: string, value: unknown): void;
|
|
22
29
|
export declare function getPath(source: Record<string, unknown>, path: string): unknown;
|
|
23
30
|
export interface AttachedFile {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useIntegrationsT } from "../composables/useIntegrationsT.js";
|
|
1
2
|
const PAYLOAD_REF_RE = /\$\{\{\s*trigger\.payload\.([a-zA-Z0-9_.-]+)/g;
|
|
2
3
|
const FILE_KEYS = /* @__PURE__ */ new Set(["data", "filename", "contentType", "size"]);
|
|
3
4
|
function collectRefs(value, out) {
|
|
@@ -14,9 +15,23 @@ function labelFor(path) {
|
|
|
14
15
|
return last.replace(/[_-]/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/^./, (c) => c.toUpperCase());
|
|
15
16
|
}
|
|
16
17
|
export function payloadFieldsFromBlob(blob) {
|
|
18
|
+
const declared = [];
|
|
19
|
+
for (const t of blob.triggers ?? []) {
|
|
20
|
+
if (t.type !== "manual") continue;
|
|
21
|
+
for (const d of t.config?.payloadFields ?? []) {
|
|
22
|
+
const path = d.path?.trim();
|
|
23
|
+
if (!path && d.kind !== "file") continue;
|
|
24
|
+
declared.push({
|
|
25
|
+
kind: d.kind === "file" ? "file" : "text",
|
|
26
|
+
path: path ?? "",
|
|
27
|
+
label: d.label?.trim() || labelFor(path || "file")
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
17
31
|
const refs = /* @__PURE__ */ new Set();
|
|
18
32
|
for (const node of blob.nodes ?? []) collectRefs(node.config, refs);
|
|
19
|
-
if (refs.size === 0) return [];
|
|
33
|
+
if (refs.size === 0 && declared.length === 0) return [];
|
|
34
|
+
const declaredPaths = new Set(declared.map((f) => f.path));
|
|
20
35
|
const byPrefix = /* @__PURE__ */ new Map();
|
|
21
36
|
for (const ref of refs) {
|
|
22
37
|
const idx = ref.lastIndexOf(".");
|
|
@@ -26,10 +41,16 @@ export function payloadFieldsFromBlob(blob) {
|
|
|
26
41
|
byPrefix.get(prefix).add(leaf);
|
|
27
42
|
}
|
|
28
43
|
const fields = [];
|
|
29
|
-
const consumed =
|
|
44
|
+
const consumed = new Set(declaredPaths);
|
|
30
45
|
for (const [prefix, leaves] of byPrefix) {
|
|
31
46
|
if (leaves.has("data")) {
|
|
32
|
-
|
|
47
|
+
if (declaredPaths.has(prefix)) {
|
|
48
|
+
for (const leaf of leaves) {
|
|
49
|
+
if (FILE_KEYS.has(leaf)) consumed.add(prefix === "" ? leaf : `${prefix}.${leaf}`);
|
|
50
|
+
}
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
fields.push({ kind: "file", path: prefix, label: prefix === "" ? useIntegrationsT()("integration.common.label.file") : labelFor(prefix) });
|
|
33
54
|
for (const leaf of leaves) {
|
|
34
55
|
if (FILE_KEYS.has(leaf)) consumed.add(prefix === "" ? leaf : `${prefix}.${leaf}`);
|
|
35
56
|
}
|
|
@@ -37,9 +58,13 @@ export function payloadFieldsFromBlob(blob) {
|
|
|
37
58
|
}
|
|
38
59
|
for (const ref of [...refs].sort()) {
|
|
39
60
|
if (consumed.has(ref)) continue;
|
|
61
|
+
if (declared.some((d) => d.kind === "file" && (d.path === "" ? FILE_KEYS.has(ref) : ref.startsWith(d.path + ".")))) continue;
|
|
40
62
|
fields.push({ kind: "text", path: ref, label: labelFor(ref) });
|
|
41
63
|
}
|
|
42
|
-
return
|
|
64
|
+
return [
|
|
65
|
+
...declared,
|
|
66
|
+
...fields.sort((a, b) => a.kind === b.kind ? a.path.localeCompare(b.path) : a.kind === "file" ? -1 : 1)
|
|
67
|
+
];
|
|
43
68
|
}
|
|
44
69
|
export function setPath(target, path, value) {
|
|
45
70
|
if (path === "") {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { OutputKind } from '../types/integrations.js';
|
|
2
|
+
/**
|
|
3
|
+
* The colour of the dot in front of a port name, wherever a port is listed
|
|
4
|
+
* rather than drawn on the canvas: the Input panel's upstream trees and the
|
|
5
|
+
* node's own output schema.
|
|
6
|
+
*
|
|
7
|
+
* The legend mirrors `portTone` on the canvas node (PO-197): green = a real,
|
|
8
|
+
* active output — the normal continuation, including switch cases, iterator
|
|
9
|
+
* `item` and If/Filter `true`; soft rose = the error output that only runs on
|
|
10
|
+
* failure; neutral slate for `false` and fallbacks. There is no separate branch
|
|
11
|
+
* colour — the labels already say "one of several".
|
|
12
|
+
*
|
|
13
|
+
* It lives here rather than in a component because two lists render it and they
|
|
14
|
+
* must never disagree. They did once: the schema list kept a private copy and
|
|
15
|
+
* silently held the pre-PO-197 palette while the Input panel moved on.
|
|
16
|
+
*/
|
|
17
|
+
export declare function portDotClass(kind: OutputKind, name: string): string;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export function portDotClass(kind, name) {
|
|
2
|
+
if (name === "true") return "bg-emerald-500";
|
|
3
|
+
if (name === "false") return "bg-slate-500";
|
|
4
|
+
if (name === "error" || kind === "error") return "bg-rose-300";
|
|
5
|
+
if (name === "done") return "bg-emerald-500";
|
|
6
|
+
return "bg-emerald-500";
|
|
7
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { WorkflowTrigger } from '../types/integrations.js';
|
|
2
|
+
/**
|
|
3
|
+
* Mapping between the webhook Protection select and the ingress verification
|
|
4
|
+
* profiles stored on the trigger (`authProfile`/`authConfig`). Bearer is the
|
|
5
|
+
* token profile with a fixed Authorization + "Bearer " prefix.
|
|
6
|
+
*
|
|
7
|
+
* An ABSENT authProfile reads as 'token': that is what the exposure defaults
|
|
8
|
+
* to server-side (and what every endpoint provisioned before this feature
|
|
9
|
+
* got), so the select shows the effective behavior. The UI persists the
|
|
10
|
+
* choice explicitly the moment the public toggle is enabled, so anything
|
|
11
|
+
* exposed from here on carries what it shows.
|
|
12
|
+
*/
|
|
13
|
+
export type WebhookAuthChoice = 'none' | 'token' | 'bearer' | 'basic';
|
|
14
|
+
type TriggerConfig = WorkflowTrigger['config'];
|
|
15
|
+
export declare function authChoiceFromConfig(config: TriggerConfig | undefined): WebhookAuthChoice;
|
|
16
|
+
/** The config patch that makes a Protection choice stored state. */
|
|
17
|
+
export declare function configPatchForAuthChoice(choice: WebhookAuthChoice): Partial<TriggerConfig>;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function authChoiceFromConfig(config) {
|
|
2
|
+
if (config?.authProfile === "none") return "none";
|
|
3
|
+
if (config?.authProfile === "basic") return "basic";
|
|
4
|
+
if (config?.authProfile === "token" && config?.authConfig?.prefix === "Bearer ") return "bearer";
|
|
5
|
+
return "token";
|
|
6
|
+
}
|
|
7
|
+
export function configPatchForAuthChoice(choice) {
|
|
8
|
+
switch (choice) {
|
|
9
|
+
case "none":
|
|
10
|
+
return { authProfile: "none", authConfig: void 0 };
|
|
11
|
+
case "bearer":
|
|
12
|
+
return { authProfile: "token", authConfig: { header: "Authorization", prefix: "Bearer " } };
|
|
13
|
+
case "basic":
|
|
14
|
+
return { authProfile: "basic", authConfig: void 0 };
|
|
15
|
+
case "token":
|
|
16
|
+
default:
|
|
17
|
+
return { authProfile: "token", authConfig: void 0 };
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
WalletMoney
|
|
38
38
|
} from "#solar-icons";
|
|
39
39
|
import { INTEGRATION_NODE_CATALOG } from "./integrationNodeCatalog.js";
|
|
40
|
+
import { resolveLocalized } from "../utils/localize.js";
|
|
40
41
|
export const WORKFLOW_SOLAR_ICONS = {
|
|
41
42
|
Programming,
|
|
42
43
|
Bolt,
|
|
@@ -78,10 +79,6 @@ export const WORKFLOW_SOLAR_ICONS = {
|
|
|
78
79
|
export function solarIconFor(name) {
|
|
79
80
|
return (name ? WORKFLOW_SOLAR_ICONS[name] : void 0) ?? Programming;
|
|
80
81
|
}
|
|
81
|
-
function loc(v) {
|
|
82
|
-
if (!v) return "";
|
|
83
|
-
return typeof v === "string" ? v : v.en ?? Object.values(v)[0] ?? "";
|
|
84
|
-
}
|
|
85
82
|
const UUID = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
|
|
86
83
|
const IMAGE_URL_ID_RE = new RegExp(`node-packages/images/(${UUID})`, "i");
|
|
87
84
|
const BARE_UUID_RE = new RegExp(`^${UUID}$`, "i");
|
|
@@ -102,6 +99,7 @@ export function freshImageSrc(stored) {
|
|
|
102
99
|
return null;
|
|
103
100
|
}
|
|
104
101
|
export function nodeLogoOptions() {
|
|
102
|
+
const t = useIntegrationsT();
|
|
105
103
|
const byId = /* @__PURE__ */ new Map();
|
|
106
104
|
for (const m of INTEGRATION_NODE_CATALOG) {
|
|
107
105
|
const imgs = m.images ?? [];
|
|
@@ -109,8 +107,8 @@ export function nodeLogoOptions() {
|
|
|
109
107
|
if (!logo?.src) continue;
|
|
110
108
|
const id = imageIdFromSrc(logo.src) ?? logo.src;
|
|
111
109
|
if (byId.has(id)) continue;
|
|
112
|
-
const label = m.__package?.label || (m.groups?.length ?
|
|
113
|
-
byId.set(id, { label: label || "
|
|
110
|
+
const label = m.__package?.label || (m.groups?.length ? resolveLocalized(m.groups[0]) : "") || resolveLocalized(m.name);
|
|
111
|
+
byId.set(id, { label: label || t("integration.workflows.iconCatalog.label.fallback"), src: logo.src });
|
|
114
112
|
}
|
|
115
113
|
return [...byId.entries()].map(([id, v]) => ({ id, src: v.src, label: v.label })).sort((a, b) => a.label.localeCompare(b.label));
|
|
116
114
|
}
|