@revenexx/studio-integrations 2.3.0 → 2.5.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 +36 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +30 -2
- package/dist/runtime/components/Integrations/CredentialDetailDialog.vue +50 -14
- package/dist/runtime/components/Integrations/CredentialRevenexxSource.vue +27 -18
- package/dist/runtime/components/Integrations/ExpressionInput.vue +7 -4
- package/dist/runtime/components/Integrations/NodeInspector.vue +6 -2
- package/dist/runtime/components/Integrations/NodePalette.vue +5 -4
- package/dist/runtime/components/Integrations/NodeRetireDialog.d.vue.ts +19 -0
- package/dist/runtime/components/Integrations/NodeRetireDialog.vue +131 -0
- package/dist/runtime/components/Integrations/NodeRetireDialog.vue.d.ts +19 -0
- package/dist/runtime/components/Integrations/NodeVersionsPanel.d.vue.ts +5 -0
- package/dist/runtime/components/Integrations/NodeVersionsPanel.vue +134 -0
- package/dist/runtime/components/Integrations/NodeVersionsPanel.vue.d.ts +5 -0
- package/dist/runtime/components/Integrations/TemplateFlowPreview.vue +3 -2
- package/dist/runtime/components/Integrations/WorkflowContextMenu.d.vue.ts +2 -0
- package/dist/runtime/components/Integrations/WorkflowContextMenu.vue +3 -2
- package/dist/runtime/components/Integrations/WorkflowContextMenu.vue.d.ts +2 -0
- package/dist/runtime/components/Integrations/WorkflowCreateDialog.vue +4 -3
- package/dist/runtime/components/Integrations/WorkflowEditor.d.vue.ts +6 -3
- package/dist/runtime/components/Integrations/WorkflowEditor.vue +7 -27
- package/dist/runtime/components/Integrations/WorkflowEditor.vue.d.ts +6 -3
- package/dist/runtime/components/Integrations/WorkflowTriggerView.vue +5 -4
- package/dist/runtime/composables/useIntegrationsCredentials.d.ts +6 -1
- package/dist/runtime/composables/useIntegrationsCredentials.js +6 -3
- package/dist/runtime/composables/useIntegrationsNodes.js +3 -0
- package/dist/runtime/composables/useNodeRetirement.d.ts +48 -0
- package/dist/runtime/composables/useNodeRetirement.js +31 -0
- package/dist/runtime/data/integrationNodeCatalog.d.ts +10 -1
- package/dist/runtime/data/integrationNodeCatalog.js +8 -5
- package/dist/runtime/data/triggerGlyphs.d.ts +8 -3
- package/dist/runtime/data/triggerGlyphs.js +2 -2
- package/dist/runtime/i18n/messages/de.json +30 -1
- package/dist/runtime/i18n/messages/en.json +30 -1
- package/dist/runtime/pages/integrations/workflows/[id].vue +29 -12
- package/dist/runtime/types/integrations.d.ts +7 -0
- package/dist/runtime/utils/cockpitSources.d.ts +10 -3
- package/dist/runtime/utils/credentialEdit.d.ts +16 -0
- package/dist/runtime/utils/credentialEdit.js +7 -0
- package/package.json +1 -1
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"integration.canvas.contextMenu.item.paste": "Einfügen",
|
|
54
54
|
"integration.canvas.contextMenu.item.rename": "Umbenennen",
|
|
55
55
|
"integration.canvas.contextMenu.item.runWorkflow": "Workflow ausführen",
|
|
56
|
+
"integration.canvas.contextMenu.item.saveAndRunWorkflow": "Speichern & Workflow ausführen",
|
|
56
57
|
"integration.canvas.contextMenu.item.selectAll": "Alle auswählen",
|
|
57
58
|
"integration.canvas.contextMenu.item.tidyUp": "Aufräumen",
|
|
58
59
|
"integration.canvas.edge.action.delete": "Verbindung löschen",
|
|
@@ -169,9 +170,11 @@
|
|
|
169
170
|
"integration.credentials.detail.field.typeSlug": "Typ-Slug",
|
|
170
171
|
"integration.credentials.detail.field.updated": "Aktualisiert",
|
|
171
172
|
"integration.credentials.detail.field.version": "Version",
|
|
173
|
+
"integration.credentials.detail.state.testedAt": "· geprüft {time}",
|
|
172
174
|
"integration.credentials.detail.state.untestedHint": "Testen Sie die Verbindung, um zu prüfen, ob diese Zugangsdaten tatsächlich funktionieren.",
|
|
173
175
|
"integration.credentials.detail.tab.credentials": "Zugangsdaten",
|
|
174
176
|
"integration.credentials.detail.tab.details": "Details",
|
|
177
|
+
"integration.credentials.detail.test.editNotSupported": "Der Dienst kann nur gespeicherte Werte testen, diese Werte wurden also nicht geprüft. Speichern Sie sie, um sie zu testen.",
|
|
175
178
|
"integration.credentials.error.delete": "Zugangsdaten konnten nicht gelöscht werden.",
|
|
176
179
|
"integration.credentials.error.loadFailed": "Zugangsdaten konnten nicht geladen werden.",
|
|
177
180
|
"integration.credentials.error.loadTypes": "Zugangsdatentypen konnten nicht geladen werden.",
|
|
@@ -219,6 +222,7 @@
|
|
|
219
222
|
"integration.credentials.revenexxSource.error.createSmtp": "Die Mail-Zugangsdaten konnten nicht erstellt werden.",
|
|
220
223
|
"integration.credentials.revenexxSource.error.loadResources": "revenexx-Ressourcen konnten nicht geladen werden.",
|
|
221
224
|
"integration.credentials.revenexxSource.error.mailCredentialGone": "Diese Mail-Zugangsdaten sind nicht mehr vorhanden.",
|
|
225
|
+
"integration.credentials.revenexxSource.error.mailCredentialNoSecret": "Diese Mail-Zugangsdaten haben keinen Key, deshalb wurde nichts übernommen. Wählen Sie andere aus oder prüfen Sie diese unter Mail.",
|
|
222
226
|
"integration.credentials.revenexxSource.error.mailCredentialNotReturned": "Die Mail-Zugangsdaten wurden nicht zurückgegeben — bitte aus der Liste wählen, sobald sie erscheinen.",
|
|
223
227
|
"integration.credentials.revenexxSource.error.noTenant": "Kein Mandant ausgewählt.",
|
|
224
228
|
"integration.credentials.revenexxSource.error.provisioningFailed": "Bereitstellung fehlgeschlagen.",
|
|
@@ -439,6 +443,7 @@
|
|
|
439
443
|
"integration.editor.run.error.syncFailed": "Synchroner Run fehlgeschlagen",
|
|
440
444
|
"integration.editor.run.error.syncTimeout": "Synchroner Run: Zeitüberschreitung",
|
|
441
445
|
"integration.editor.run.loading": "Run wird geladen…",
|
|
446
|
+
"integration.editor.run.saveAndRun": "Speichern & Run",
|
|
442
447
|
"integration.editor.run.waitingForBuild": "Warten auf Build…",
|
|
443
448
|
"integration.editor.runPayload.action.latestEvent": "Letztes reales Event",
|
|
444
449
|
"integration.editor.runPayload.action.latestEvent.title": "Letztes empfangenes Event dieses Topics einfügen",
|
|
@@ -1348,5 +1353,29 @@
|
|
|
1348
1353
|
"integration.workflows.variables.row.aria": "Variable {key}",
|
|
1349
1354
|
"integration.workflows.variables.state.empty": "Noch keine Variablen — fügen Sie die erste unten hinzu.",
|
|
1350
1355
|
"integration.workflows.variables.toast.copied": "Ausdruck kopiert",
|
|
1351
|
-
"integration.workflows.variables.toast.copyFailed": "Kopieren fehlgeschlagen"
|
|
1356
|
+
"integration.workflows.variables.toast.copyFailed": "Kopieren fehlgeschlagen",
|
|
1357
|
+
"integration.nodeVersions.retire.dialog.title": "Diese Version ausmustern?",
|
|
1358
|
+
"integration.nodeVersions.retire.dialog.description": "wird nicht mehr angeboten: Niemand kann sie mehr in einen Workflow einfügen. Workflows, die sie schon nutzen, laufen weiter.",
|
|
1359
|
+
"integration.nodeVersions.retire.confirm.label": "Zum Fortfahren {version} eintippen",
|
|
1360
|
+
"integration.nodeVersions.retire.confirm.aria": "Auszumusternde Version, ausgeschrieben",
|
|
1361
|
+
"integration.nodeVersions.retire.reason.label": "Grund (optional)",
|
|
1362
|
+
"integration.nodeVersions.retire.reason.placeholder": "z. B. der Anbieter hat API v1 abgeschaltet",
|
|
1363
|
+
"integration.nodeVersions.retire.usage.none": "Kein Workflow und kein Template nutzt diese Version.",
|
|
1364
|
+
"integration.nodeVersions.retire.usage.counts": "Genutzt von {workflows} Workflow(s), davon {active} aktiv, in {tenants} Mandant(en), und von {templates} Template(s).",
|
|
1365
|
+
"integration.nodeVersions.retire.usage.keepWorking": "Sie laufen unverändert weiter. Die Version wird nur nicht mehr angeboten und kann keinem Workflow neu hinzugefügt werden.",
|
|
1366
|
+
"integration.nodeVersions.retire.action.check": "Nutzung prüfen",
|
|
1367
|
+
"integration.nodeVersions.retire.action.retire": "Version ausmustern",
|
|
1368
|
+
"integration.nodeVersions.retire.error.generic": "Die Version konnte nicht ausgemustert werden.",
|
|
1369
|
+
"integration.nodeVersions.restore.error.generic": "Die Version konnte nicht wiederhergestellt werden.",
|
|
1370
|
+
"integration.nodeVersions.error.load": "Die Node-Versionen konnten nicht geladen werden.",
|
|
1371
|
+
"integration.nodeVersions.empty.noPackage": "Diese Integration hat noch kein Node-Paket veröffentlicht.",
|
|
1372
|
+
"integration.nodeVersions.empty.noNodes": "Dieses Paket registriert keine Nodes.",
|
|
1373
|
+
"integration.nodeVersions.loading": "Node-Versionen werden geladen…",
|
|
1374
|
+
"integration.nodeVersions.column.version": "Version",
|
|
1375
|
+
"integration.nodeVersions.column.state": "Status",
|
|
1376
|
+
"integration.nodeVersions.badge.retired": "Ausgemustert",
|
|
1377
|
+
"integration.nodeVersions.badge.offered": "Angeboten",
|
|
1378
|
+
"integration.nodeVersions.badge.notBuilt": "Nicht gebaut",
|
|
1379
|
+
"integration.nodeVersions.action.retire": "Ausmustern",
|
|
1380
|
+
"integration.nodeVersions.action.restore": "Wiederherstellen"
|
|
1352
1381
|
}
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"integration.canvas.contextMenu.item.paste": "Paste",
|
|
54
54
|
"integration.canvas.contextMenu.item.rename": "Rename",
|
|
55
55
|
"integration.canvas.contextMenu.item.runWorkflow": "Run workflow",
|
|
56
|
+
"integration.canvas.contextMenu.item.saveAndRunWorkflow": "Save & run workflow",
|
|
56
57
|
"integration.canvas.contextMenu.item.selectAll": "Select all",
|
|
57
58
|
"integration.canvas.contextMenu.item.tidyUp": "Tidy up",
|
|
58
59
|
"integration.canvas.edge.action.delete": "Delete this connection",
|
|
@@ -169,9 +170,11 @@
|
|
|
169
170
|
"integration.credentials.detail.field.typeSlug": "Type slug",
|
|
170
171
|
"integration.credentials.detail.field.updated": "Updated",
|
|
171
172
|
"integration.credentials.detail.field.version": "Version",
|
|
173
|
+
"integration.credentials.detail.state.testedAt": "· verified {time}",
|
|
172
174
|
"integration.credentials.detail.state.untestedHint": "Run a test to verify these credentials actually connect.",
|
|
173
175
|
"integration.credentials.detail.tab.credentials": "Credentials",
|
|
174
176
|
"integration.credentials.detail.tab.details": "Details",
|
|
177
|
+
"integration.credentials.detail.test.editNotSupported": "The service can test only what is saved, so these values were not tried. Save them to test them.",
|
|
175
178
|
"integration.credentials.error.delete": "Could not delete credential.",
|
|
176
179
|
"integration.credentials.error.loadFailed": "Could not load credentials.",
|
|
177
180
|
"integration.credentials.error.loadTypes": "Could not load credential types.",
|
|
@@ -219,6 +222,7 @@
|
|
|
219
222
|
"integration.credentials.revenexxSource.error.createSmtp": "Could not create the mail credential.",
|
|
220
223
|
"integration.credentials.revenexxSource.error.loadResources": "Could not load revenexx resources.",
|
|
221
224
|
"integration.credentials.revenexxSource.error.mailCredentialGone": "That mail credential is no longer there.",
|
|
225
|
+
"integration.credentials.revenexxSource.error.mailCredentialNoSecret": "That mail credential has no key, so nothing was copied. Pick another one, or check this one in Mail.",
|
|
222
226
|
"integration.credentials.revenexxSource.error.mailCredentialNotReturned": "The mail credential was not returned — pick it from the list once it appears.",
|
|
223
227
|
"integration.credentials.revenexxSource.error.noTenant": "No tenant selected.",
|
|
224
228
|
"integration.credentials.revenexxSource.error.provisioningFailed": "Provisioning failed.",
|
|
@@ -439,6 +443,7 @@
|
|
|
439
443
|
"integration.editor.run.error.syncFailed": "Sync run failed",
|
|
440
444
|
"integration.editor.run.error.syncTimeout": "Sync run timed out",
|
|
441
445
|
"integration.editor.run.loading": "Loading run…",
|
|
446
|
+
"integration.editor.run.saveAndRun": "Save & run",
|
|
442
447
|
"integration.editor.run.waitingForBuild": "Waiting for build…",
|
|
443
448
|
"integration.editor.runPayload.action.latestEvent": "Latest real event",
|
|
444
449
|
"integration.editor.runPayload.action.latestEvent.title": "Insert the latest received event of this topic",
|
|
@@ -1348,5 +1353,29 @@
|
|
|
1348
1353
|
"integration.workflows.variables.row.aria": "Variable {key}",
|
|
1349
1354
|
"integration.workflows.variables.state.empty": "No variables yet — add the first one below.",
|
|
1350
1355
|
"integration.workflows.variables.toast.copied": "Expression copied",
|
|
1351
|
-
"integration.workflows.variables.toast.copyFailed": "Could not copy"
|
|
1356
|
+
"integration.workflows.variables.toast.copyFailed": "Could not copy",
|
|
1357
|
+
"integration.nodeVersions.retire.dialog.title": "Retire this version?",
|
|
1358
|
+
"integration.nodeVersions.retire.dialog.description": "stops being offered: nobody can add it to a workflow any more. Workflows that already use it keep working.",
|
|
1359
|
+
"integration.nodeVersions.retire.confirm.label": "Type {version} to continue",
|
|
1360
|
+
"integration.nodeVersions.retire.confirm.aria": "Version to retire, typed out",
|
|
1361
|
+
"integration.nodeVersions.retire.reason.label": "Reason (optional)",
|
|
1362
|
+
"integration.nodeVersions.retire.reason.placeholder": "e.g. the vendor switched off API v1",
|
|
1363
|
+
"integration.nodeVersions.retire.usage.none": "No workflow and no template uses this version.",
|
|
1364
|
+
"integration.nodeVersions.retire.usage.counts": "Used by {workflows} workflow(s), {active} of them active, in {tenants} tenant(s), and by {templates} template(s).",
|
|
1365
|
+
"integration.nodeVersions.retire.usage.keepWorking": "They keep working as they are. The version is only no longer offered, and cannot be added to a workflow again.",
|
|
1366
|
+
"integration.nodeVersions.retire.action.check": "Check usage",
|
|
1367
|
+
"integration.nodeVersions.retire.action.retire": "Retire version",
|
|
1368
|
+
"integration.nodeVersions.retire.error.generic": "The version could not be retired.",
|
|
1369
|
+
"integration.nodeVersions.restore.error.generic": "The version could not be restored.",
|
|
1370
|
+
"integration.nodeVersions.error.load": "The node versions could not be loaded.",
|
|
1371
|
+
"integration.nodeVersions.empty.noPackage": "This integration has not published a node package yet.",
|
|
1372
|
+
"integration.nodeVersions.empty.noNodes": "This package registers no nodes.",
|
|
1373
|
+
"integration.nodeVersions.loading": "Loading node versions…",
|
|
1374
|
+
"integration.nodeVersions.column.version": "Version",
|
|
1375
|
+
"integration.nodeVersions.column.state": "State",
|
|
1376
|
+
"integration.nodeVersions.badge.retired": "Retired",
|
|
1377
|
+
"integration.nodeVersions.badge.offered": "Offered",
|
|
1378
|
+
"integration.nodeVersions.badge.notBuilt": "Not built",
|
|
1379
|
+
"integration.nodeVersions.action.retire": "Retire",
|
|
1380
|
+
"integration.nodeVersions.action.restore": "Restore"
|
|
1352
1381
|
}
|
|
@@ -400,7 +400,11 @@ async function run(mode) {
|
|
|
400
400
|
}
|
|
401
401
|
const payloadDriven = computed(() => payloadFieldsFromBlob(shownBlob.value ?? { nodes: [] }).length > 0);
|
|
402
402
|
async function runFromEditor() {
|
|
403
|
-
if (!workflow.value) return;
|
|
403
|
+
if (!workflow.value || saving.value) return;
|
|
404
|
+
if (isDirty.value) {
|
|
405
|
+
await save();
|
|
406
|
+
if (isDirty.value) return;
|
|
407
|
+
}
|
|
404
408
|
if (payloadDriven.value || workflow.value.execution_mode === "caller_decides") {
|
|
405
409
|
runPayloadOpen.value = true;
|
|
406
410
|
return;
|
|
@@ -817,14 +821,12 @@ async function confirmDeactivate() {
|
|
|
817
821
|
<WorkflowIconView :icon="shownIcon" :size="16" />
|
|
818
822
|
</span>
|
|
819
823
|
<span class="truncate" :title="shownName">{{ shownName }}</span>
|
|
820
|
-
<!-- The
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
<Badge variant="outline" class="ml-1.5 shrink-0 border text-xs font-medium uppercase text-muted-foreground" :title="t('integration.editor.header.executionMode.title', { mode: modeLabel(workflow.execution_mode) })">
|
|
827
|
-
{{ modeLabel(workflow.execution_mode) }}
|
|
824
|
+
<!-- The DRAFTED mode, like the name beside it: Run over a draft saves
|
|
825
|
+
it first (PO-567), so this is the mode the next run goes out in. The
|
|
826
|
+
saved one would read ASYNC over a button about to fire a sync run;
|
|
827
|
+
the unsaved marker says the platform does not have it yet. -->
|
|
828
|
+
<Badge variant="outline" class="ml-1.5 shrink-0 border text-xs font-medium uppercase text-muted-foreground" :title="t('integration.editor.header.executionMode.title', { mode: modeLabel(draftedMode) })">
|
|
829
|
+
{{ modeLabel(draftedMode) }}
|
|
828
830
|
</Badge>
|
|
829
831
|
</template>
|
|
830
832
|
</span>
|
|
@@ -927,8 +929,23 @@ async function confirmDeactivate() {
|
|
|
927
929
|
<Save v-else :size="12" />
|
|
928
930
|
{{ saving ? t("integration.editor.action.save.saving") : t("integration.editor.action.save.label") }}
|
|
929
931
|
</Button>
|
|
932
|
+
<!-- Run stands beside Save because a run goes to the workflow the
|
|
933
|
+
platform holds, not to the draft on the canvas: with the two at
|
|
934
|
+
opposite ends of the screen, a changed value was run as the old one
|
|
935
|
+
and nothing said so. While there is a draft the press saves it first,
|
|
936
|
+
and the name says that it will (PO-567). -->
|
|
937
|
+
<Button
|
|
938
|
+
class="h-7 bg-emerald-600 text-sm text-white hover:bg-emerald-700"
|
|
939
|
+
:disabled="saving || running || syncLoading || waitingForBuild"
|
|
940
|
+
:title="waitingForBuild ? t('integration.editor.tool.run.tooltipWaiting') : t('integration.editor.tool.run.tooltip')"
|
|
941
|
+
@click="runFromEditor"
|
|
942
|
+
>
|
|
943
|
+
<Loader2 v-if="running || syncLoading || waitingForBuild" :size="12" class="animate-spin" />
|
|
944
|
+
<Play v-else :size="12" />
|
|
945
|
+
{{ waitingForBuild ? t("integration.editor.run.waitingForBuild") : isDirty ? t("integration.editor.run.saveAndRun") : t("integration.editor.run.button") }}
|
|
946
|
+
</Button>
|
|
930
947
|
<!-- Activation is a standing state, not a transport control. The play
|
|
931
|
-
symbol belongs to Run,
|
|
948
|
+
symbol belongs to Run, the button just before this one,
|
|
932
949
|
where pressing it makes one thing happen now; arming a workflow's
|
|
933
950
|
triggers looks like nothing happening at all. So this states the
|
|
934
951
|
state in the words the workflows list uses — Active, Paused — and
|
|
@@ -1064,8 +1081,8 @@ async function confirmDeactivate() {
|
|
|
1064
1081
|
ref="editorRef"
|
|
1065
1082
|
:workflow="workflow"
|
|
1066
1083
|
:draft="draft?.blob ?? null"
|
|
1067
|
-
:run-busy="running || syncLoading || waitingForBuild"
|
|
1068
|
-
:run-
|
|
1084
|
+
:run-busy="saving || running || syncLoading || waitingForBuild"
|
|
1085
|
+
:run-saves="isDirty"
|
|
1069
1086
|
:overlay-open="settingsOpen || duplicateOpen || importOpen || !!exporter?.open || deleteOpen || syncOpen || runPayloadOpen || deactivationOpen || leaveOpen"
|
|
1070
1087
|
@change="onChange"
|
|
1071
1088
|
@run="runFromEditor"
|
|
@@ -425,6 +425,13 @@ export interface NodeManifest {
|
|
|
425
425
|
* does not make every node disappear.
|
|
426
426
|
*/
|
|
427
427
|
__hasBundle?: boolean;
|
|
428
|
+
/**
|
|
429
|
+
* Whether the publisher retired this version (editor-side enrichment from
|
|
430
|
+
* `GET /nodes`; not manifest data, PO-549). A retired version still draws and
|
|
431
|
+
* runs for the workflows already on it, but is offered nowhere new, and the
|
|
432
|
+
* platform refuses a save that newly uses it.
|
|
433
|
+
*/
|
|
434
|
+
__retired?: boolean;
|
|
428
435
|
}
|
|
429
436
|
export interface SecretRecord {
|
|
430
437
|
key: string;
|
|
@@ -205,14 +205,21 @@ export interface CockpitSftpAccount {
|
|
|
205
205
|
/**
|
|
206
206
|
* The members of the cockpit's `MailCredential` this module reads.
|
|
207
207
|
*
|
|
208
|
-
* The SMTP pair is optional on the wire
|
|
209
|
-
*
|
|
210
|
-
*
|
|
208
|
+
* The SMTP pair is optional on the wire, and the mail engine leaves it out: its
|
|
209
|
+
* `show` and create answers carry the name and the key. So the login is read the
|
|
210
|
+
* way the cockpit's Mail tab reads it — `smtp_username` or else the name, and
|
|
211
|
+
* `smtp_password` or else the key — and a credential with neither secret copies
|
|
212
|
+
* nothing rather than an empty password (PO-602).
|
|
211
213
|
*/
|
|
212
214
|
export interface CockpitMailCredential {
|
|
213
215
|
uuid: string;
|
|
214
216
|
name: string;
|
|
215
217
|
type?: string;
|
|
218
|
+
/**
|
|
219
|
+
* The credential's secret. The mail engine authenticates SMTP by it alone, and
|
|
220
|
+
* where `smtp_password` is absent it is the password (PO-602).
|
|
221
|
+
*/
|
|
222
|
+
key?: string;
|
|
216
223
|
smtp_username?: string;
|
|
217
224
|
smtp_password?: string;
|
|
218
225
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { CredentialTypeField } from '../types/integrations.js';
|
|
2
|
+
/**
|
|
3
|
+
* Whether the values an edit would send differ from what the credential holds, as
|
|
4
|
+
* far as the studio can see it (PO-535).
|
|
5
|
+
*
|
|
6
|
+
* `payload` is what a save would send: every non-secret field, and only the secrets
|
|
7
|
+
* that were typed — a blank secret means "keep the stored one" and is never sent.
|
|
8
|
+
* So a secret in the payload is a change by definition, since the stored one is never
|
|
9
|
+
* shown; a non-secret is a change when it reads differently from `public_config`.
|
|
10
|
+
*
|
|
11
|
+
* The platform judges this again on the merged values before it records a test, so
|
|
12
|
+
* this only decides whether to ask for a test of the edit at all — which takes the
|
|
13
|
+
* right to change the credential, where a test of the stored one takes only the
|
|
14
|
+
* right to read it.
|
|
15
|
+
*/
|
|
16
|
+
export declare function credentialEditDiffers(fields: CredentialTypeField[], payload: Record<string, unknown>, publicConfig: Record<string, unknown>): boolean;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export function credentialEditDiffers(fields, payload, publicConfig) {
|
|
2
|
+
const secret = new Set(fields.filter((f) => f.type === "secret").map((f) => f.key));
|
|
3
|
+
return Object.entries(payload).some(([key, value]) => secret.has(key) || readsAs(value) !== readsAs(publicConfig[key]));
|
|
4
|
+
}
|
|
5
|
+
function readsAs(value) {
|
|
6
|
+
return value === void 0 || value === null ? "" : String(value);
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revenexx/studio-integrations",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.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
6
|
"repository": {
|