@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.
Files changed (188) hide show
  1. package/README.md +31 -0
  2. package/dist/module.d.mts +2 -2
  3. package/dist/module.json +1 -1
  4. package/dist/runtime/components/Integrations/CredentialCreateDialog.d.vue.ts +13 -0
  5. package/dist/runtime/components/Integrations/CredentialCreateDialog.vue +279 -0
  6. package/dist/runtime/components/Integrations/CredentialCreateDialog.vue.d.ts +13 -0
  7. package/dist/runtime/components/Integrations/CredentialDetailDialog.d.vue.ts +20 -0
  8. package/dist/runtime/components/Integrations/CredentialDetailDialog.vue +342 -0
  9. package/dist/runtime/components/Integrations/CredentialDetailDialog.vue.d.ts +20 -0
  10. package/dist/runtime/components/Integrations/CredentialLogo.d.vue.ts +14 -0
  11. package/dist/runtime/components/Integrations/CredentialLogo.vue +37 -0
  12. package/dist/runtime/components/Integrations/CredentialLogo.vue.d.ts +14 -0
  13. package/dist/runtime/components/Integrations/CredentialRevenexxSource.d.vue.ts +12 -0
  14. package/dist/runtime/components/Integrations/CredentialRevenexxSource.vue +364 -0
  15. package/dist/runtime/components/Integrations/CredentialRevenexxSource.vue.d.ts +12 -0
  16. package/dist/runtime/components/Integrations/CredentialTypePicker.d.vue.ts +15 -0
  17. package/dist/runtime/components/Integrations/CredentialTypePicker.vue +71 -0
  18. package/dist/runtime/components/Integrations/CredentialTypePicker.vue.d.ts +15 -0
  19. package/dist/runtime/components/Integrations/DeadLettersPanel.d.vue.ts +5 -0
  20. package/dist/runtime/components/Integrations/DeadLettersPanel.vue +151 -0
  21. package/dist/runtime/components/Integrations/DeadLettersPanel.vue.d.ts +5 -0
  22. package/dist/runtime/components/Integrations/EditorTip.d.vue.ts +17 -0
  23. package/dist/runtime/components/Integrations/EditorTip.vue +46 -0
  24. package/dist/runtime/components/Integrations/EditorTip.vue.d.ts +17 -0
  25. package/dist/runtime/components/Integrations/EventTypeCombobox.d.vue.ts +9 -0
  26. package/dist/runtime/components/Integrations/EventTypeCombobox.vue +64 -0
  27. package/dist/runtime/components/Integrations/EventTypeCombobox.vue.d.ts +9 -0
  28. package/dist/runtime/components/Integrations/ExpressionInput.d.vue.ts +19 -0
  29. package/dist/runtime/components/Integrations/ExpressionInput.vue +236 -0
  30. package/dist/runtime/components/Integrations/ExpressionInput.vue.d.ts +19 -0
  31. package/dist/runtime/components/Integrations/GroupFrameView.d.vue.ts +28 -0
  32. package/dist/runtime/components/Integrations/GroupFrameView.vue +222 -0
  33. package/dist/runtime/components/Integrations/GroupFrameView.vue.d.ts +28 -0
  34. package/dist/runtime/components/Integrations/NodeConfigDynamicField.d.vue.ts +14 -0
  35. package/dist/runtime/components/Integrations/NodeConfigDynamicField.vue +184 -0
  36. package/dist/runtime/components/Integrations/NodeConfigDynamicField.vue.d.ts +14 -0
  37. package/dist/runtime/components/Integrations/NodeConfigDynamicSchema.d.vue.ts +16 -0
  38. package/dist/runtime/components/Integrations/NodeConfigDynamicSchema.vue +102 -0
  39. package/dist/runtime/components/Integrations/NodeConfigDynamicSchema.vue.d.ts +16 -0
  40. package/dist/runtime/components/Integrations/NodeConfigField.d.vue.ts +23 -0
  41. package/dist/runtime/components/Integrations/NodeConfigField.vue +587 -0
  42. package/dist/runtime/components/Integrations/NodeConfigField.vue.d.ts +23 -0
  43. package/dist/runtime/components/Integrations/NodeDynamicOutputsResolver.d.vue.ts +14 -0
  44. package/dist/runtime/components/Integrations/NodeDynamicOutputsResolver.vue +80 -0
  45. package/dist/runtime/components/Integrations/NodeDynamicOutputsResolver.vue.d.ts +14 -0
  46. package/dist/runtime/components/Integrations/NodeInspector.d.vue.ts +22 -3
  47. package/dist/runtime/components/Integrations/NodeInspector.vue +1074 -294
  48. package/dist/runtime/components/Integrations/NodeInspector.vue.d.ts +22 -3
  49. package/dist/runtime/components/Integrations/NodeLogo.d.vue.ts +9 -0
  50. package/dist/runtime/components/Integrations/NodeLogo.vue +38 -0
  51. package/dist/runtime/components/Integrations/NodeLogo.vue.d.ts +9 -0
  52. package/dist/runtime/components/Integrations/NodePalette.d.vue.ts +22 -1
  53. package/dist/runtime/components/Integrations/NodePalette.vue +411 -90
  54. package/dist/runtime/components/Integrations/NodePalette.vue.d.ts +22 -1
  55. package/dist/runtime/components/Integrations/QueryBuilder.d.vue.ts +9 -0
  56. package/dist/runtime/components/Integrations/QueryBuilder.vue +239 -0
  57. package/dist/runtime/components/Integrations/QueryBuilder.vue.d.ts +9 -0
  58. package/dist/runtime/components/Integrations/{RunDetailDialog.d.vue.ts → RunActionsMenu.d.vue.ts} +3 -4
  59. package/dist/runtime/components/Integrations/RunActionsMenu.vue +86 -0
  60. package/dist/runtime/components/Integrations/{RunDetailDialog.vue.d.ts → RunActionsMenu.vue.d.ts} +3 -4
  61. package/dist/runtime/components/Integrations/RunDetailPanel.d.vue.ts +14 -0
  62. package/dist/runtime/components/Integrations/RunDetailPanel.vue +777 -0
  63. package/dist/runtime/components/Integrations/RunDetailPanel.vue.d.ts +14 -0
  64. package/dist/runtime/components/Integrations/RunPayloadInput.d.vue.ts +13 -0
  65. package/dist/runtime/components/Integrations/RunPayloadInput.vue +175 -0
  66. package/dist/runtime/components/Integrations/RunPayloadInput.vue.d.ts +13 -0
  67. package/dist/runtime/components/Integrations/RunResponseModal.d.vue.ts +27 -0
  68. package/dist/runtime/components/Integrations/RunResponseModal.vue +84 -0
  69. package/dist/runtime/components/Integrations/RunResponseModal.vue.d.ts +27 -0
  70. package/dist/runtime/components/Integrations/RunsTable.d.vue.ts +21 -0
  71. package/dist/runtime/components/Integrations/RunsTable.vue +114 -0
  72. package/dist/runtime/components/Integrations/RunsTable.vue.d.ts +21 -0
  73. package/dist/runtime/components/Integrations/SftpAccountImportDialog.d.vue.ts +11 -0
  74. package/dist/runtime/components/Integrations/SftpAccountImportDialog.vue +91 -0
  75. package/dist/runtime/components/Integrations/SftpAccountImportDialog.vue.d.ts +11 -0
  76. package/dist/runtime/components/Integrations/StickyNoteView.d.vue.ts +28 -0
  77. package/dist/runtime/components/Integrations/StickyNoteView.vue +208 -0
  78. package/dist/runtime/components/Integrations/StickyNoteView.vue.d.ts +28 -0
  79. package/dist/runtime/components/Integrations/TemplateFlowPreview.d.vue.ts +29 -0
  80. package/dist/runtime/components/Integrations/TemplateFlowPreview.vue +201 -0
  81. package/dist/runtime/components/Integrations/TemplateFlowPreview.vue.d.ts +29 -0
  82. package/dist/runtime/components/Integrations/WorkflowContextMenu.d.vue.ts +32 -0
  83. package/dist/runtime/components/Integrations/WorkflowContextMenu.vue +138 -0
  84. package/dist/runtime/components/Integrations/WorkflowContextMenu.vue.d.ts +32 -0
  85. package/dist/runtime/components/Integrations/WorkflowCreateDialog.d.vue.ts +9 -0
  86. package/dist/runtime/components/Integrations/WorkflowCreateDialog.vue +322 -0
  87. package/dist/runtime/components/Integrations/WorkflowCreateDialog.vue.d.ts +9 -0
  88. package/dist/runtime/components/Integrations/WorkflowDuplicateDialog.d.vue.ts +18 -0
  89. package/dist/runtime/components/Integrations/WorkflowDuplicateDialog.vue +63 -0
  90. package/dist/runtime/components/Integrations/WorkflowDuplicateDialog.vue.d.ts +18 -0
  91. package/dist/runtime/components/Integrations/WorkflowEdgeView.d.vue.ts +12 -1
  92. package/dist/runtime/components/Integrations/WorkflowEdgeView.vue +68 -6
  93. package/dist/runtime/components/Integrations/WorkflowEdgeView.vue.d.ts +12 -1
  94. package/dist/runtime/components/Integrations/WorkflowEditor.d.vue.ts +8 -1
  95. package/dist/runtime/components/Integrations/WorkflowEditor.vue +1424 -144
  96. package/dist/runtime/components/Integrations/WorkflowEditor.vue.d.ts +8 -1
  97. package/dist/runtime/components/Integrations/WorkflowHistoryPanel.d.vue.ts +12 -0
  98. package/dist/runtime/components/Integrations/WorkflowHistoryPanel.vue +417 -0
  99. package/dist/runtime/components/Integrations/WorkflowHistoryPanel.vue.d.ts +12 -0
  100. package/dist/runtime/components/Integrations/WorkflowIconPicker.d.vue.ts +10 -0
  101. package/dist/runtime/components/Integrations/WorkflowIconPicker.vue +89 -0
  102. package/dist/runtime/components/Integrations/WorkflowIconPicker.vue.d.ts +10 -0
  103. package/dist/runtime/components/Integrations/WorkflowIconView.d.vue.ts +10 -0
  104. package/dist/runtime/components/Integrations/WorkflowIconView.vue +35 -0
  105. package/dist/runtime/components/Integrations/WorkflowIconView.vue.d.ts +10 -0
  106. package/dist/runtime/components/Integrations/WorkflowNodeView.d.vue.ts +5 -1
  107. package/dist/runtime/components/Integrations/WorkflowNodeView.vue +114 -84
  108. package/dist/runtime/components/Integrations/WorkflowNodeView.vue.d.ts +5 -1
  109. package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.d.vue.ts +12 -0
  110. package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.vue +654 -0
  111. package/dist/runtime/components/Integrations/WorkflowRunReplayPanel.vue.d.ts +12 -0
  112. package/dist/runtime/components/Integrations/WorkflowSettingsDialog.d.vue.ts +36 -0
  113. package/dist/runtime/components/Integrations/WorkflowSettingsDialog.vue +136 -0
  114. package/dist/runtime/components/Integrations/WorkflowSettingsDialog.vue.d.ts +36 -0
  115. package/dist/runtime/components/Integrations/WorkflowTagsInput.d.vue.ts +14 -0
  116. package/dist/runtime/components/Integrations/WorkflowTagsInput.vue +63 -0
  117. package/dist/runtime/components/Integrations/WorkflowTagsInput.vue.d.ts +14 -0
  118. package/dist/runtime/components/Integrations/WorkflowTriggerView.vue +35 -15
  119. package/dist/runtime/components/Integrations/WorkflowVariablesDialog.d.vue.ts +13 -0
  120. package/dist/runtime/components/Integrations/WorkflowVariablesDialog.vue +265 -0
  121. package/dist/runtime/components/Integrations/WorkflowVariablesDialog.vue.d.ts +13 -0
  122. package/dist/runtime/components/Integrations/WorkflowsTable.d.vue.ts +4 -1
  123. package/dist/runtime/components/Integrations/WorkflowsTable.vue +122 -39
  124. package/dist/runtime/components/Integrations/WorkflowsTable.vue.d.ts +4 -1
  125. package/dist/runtime/components/Integrations/workflowLayout.d.ts +5 -0
  126. package/dist/runtime/components/Integrations/workflowLayout.js +5 -3
  127. package/dist/runtime/composables/integrationsApi.d.ts +6 -7
  128. package/dist/runtime/composables/integrationsApi.js +6 -12
  129. package/dist/runtime/composables/useCanvasShortcuts.d.ts +37 -0
  130. package/dist/runtime/composables/useCanvasShortcuts.js +62 -0
  131. package/dist/runtime/composables/useCredentialTypes.js +2 -1
  132. package/dist/runtime/composables/useIntegrationsAudit.js +2 -1
  133. package/dist/runtime/composables/useIntegrationsCredentials.js +2 -1
  134. package/dist/runtime/composables/useIntegrationsDeadLetters.d.ts +22 -0
  135. package/dist/runtime/composables/useIntegrationsDeadLetters.js +50 -0
  136. package/dist/runtime/composables/useIntegrationsNodes.d.ts +4 -0
  137. package/dist/runtime/composables/useIntegrationsNodes.js +8 -4
  138. package/dist/runtime/composables/useIntegrationsRevisions.d.ts +40 -0
  139. package/dist/runtime/composables/useIntegrationsRevisions.js +52 -0
  140. package/dist/runtime/composables/useIntegrationsRuns.d.ts +21 -1
  141. package/dist/runtime/composables/useIntegrationsRuns.js +94 -5
  142. package/dist/runtime/composables/useIntegrationsSecrets.js +2 -1
  143. package/dist/runtime/composables/useIntegrationsTemplates.d.ts +1 -0
  144. package/dist/runtime/composables/useIntegrationsTemplates.js +34 -5
  145. package/dist/runtime/composables/useIntegrationsTriggers.js +2 -1
  146. package/dist/runtime/composables/useIntegrationsWorkflows.d.ts +1 -0
  147. package/dist/runtime/composables/useIntegrationsWorkflows.js +59 -2
  148. package/dist/runtime/composables/useMiniMapLayout.d.ts +34 -0
  149. package/dist/runtime/composables/useMiniMapLayout.js +119 -0
  150. package/dist/runtime/composables/useNodeConfigResolve.d.ts +43 -0
  151. package/dist/runtime/composables/useNodeConfigResolve.js +124 -0
  152. package/dist/runtime/composables/useNodeDrag.d.ts +22 -0
  153. package/dist/runtime/composables/useNodeDrag.js +10 -0
  154. package/dist/runtime/composables/usePaletteLayout.d.ts +41 -0
  155. package/dist/runtime/composables/usePaletteLayout.js +113 -0
  156. package/dist/runtime/data/expressionEditor.d.ts +22 -0
  157. package/dist/runtime/data/expressionEditor.js +40 -0
  158. package/dist/runtime/data/integrationNodeCatalog.js +8 -8
  159. package/dist/runtime/data/nodeInputData.d.ts +37 -0
  160. package/dist/runtime/data/nodeInputData.js +62 -0
  161. package/dist/runtime/data/nodeRunData.d.ts +56 -0
  162. package/dist/runtime/data/nodeRunData.js +91 -0
  163. package/dist/runtime/data/payloadForm.d.ts +44 -0
  164. package/dist/runtime/data/payloadForm.js +126 -0
  165. package/dist/runtime/data/workflowIconCatalog.d.ts +34 -0
  166. package/dist/runtime/data/workflowIconCatalog.js +116 -0
  167. package/dist/runtime/pages/integrations/audit.vue +25 -35
  168. package/dist/runtime/pages/integrations/credentials.vue +117 -122
  169. package/dist/runtime/pages/integrations/index.vue +133 -36
  170. package/dist/runtime/pages/integrations/runs.vue +125 -75
  171. package/dist/runtime/pages/integrations/schedules.vue +5 -16
  172. package/dist/runtime/pages/integrations/secrets.vue +1 -3
  173. package/dist/runtime/pages/integrations/workflows/[id].vue +599 -194
  174. package/dist/runtime/pages/integrations/workflows/index.vue +10 -8
  175. package/dist/runtime/types/integrations.d.ts +190 -4
  176. package/dist/runtime/utils/apiError.d.ts +17 -0
  177. package/dist/runtime/utils/apiError.js +8 -0
  178. package/dist/runtime/utils/credentialState.d.ts +28 -0
  179. package/dist/runtime/utils/credentialState.js +29 -0
  180. package/dist/runtime/utils/localize.d.ts +3 -1
  181. package/dist/runtime/utils/localize.js +1 -2
  182. package/dist/runtime/utils/statusStyle.d.ts +6 -0
  183. package/dist/runtime/utils/statusStyle.js +15 -0
  184. package/package.json +20 -3
  185. package/dist/runtime/components/Integrations/RunDetailDialog.vue +0 -169
  186. package/dist/runtime/pages/integrations/workflows/new.d.vue.ts +0 -2
  187. package/dist/runtime/pages/integrations/workflows/new.vue +0 -153
  188. package/dist/runtime/pages/integrations/workflows/new.vue.d.ts +0 -2
package/README.md CHANGED
@@ -49,3 +49,34 @@ Adjust the relative paths to reach `node_modules` from your CSS file.
49
49
  `@revenexx/studio`, `@revenexx/studio-shared`, `nuxt` ^4, `vue` ^3.5,
50
50
  `@vue-flow/*` + `@dagrejs/dagre` (workflow editor), `lucide-vue-next`; register
51
51
  `@solar-icons/nuxt` in the host.
52
+
53
+ ## Develop
54
+
55
+ This repo is the source of truth for the module (it used to live in the
56
+ cockpit monorepo under `packages/studio-integrations`).
57
+
58
+ ```bash
59
+ pnpm install # runs the module `prepare` (nuxt-module-build)
60
+ pnpm test # vitest
61
+ pnpm build # dist/
62
+ ```
63
+
64
+ Hosts to develop against:
65
+
66
+ * **Playground** (`playground/`, in this repo): thin standalone Nuxt host that
67
+ loads the module from `src/` — see `playground/README.md` for the full
68
+ runbook against a local integrations service
69
+ (`docker compose -f playground/docker-compose.dev.yml up`).
70
+ * **Cockpit** (`../revenexx-cockpit`): its dev server loads this module from
71
+ the sibling checkout's `src/module.ts` automatically (dev-from-source, see
72
+ the cockpit's `nuxt.config.ts`). Edit `src/**` here, the cockpit HMRs.
73
+ * **Integrations service** (`../integrations`): the `studio-ui` dev host
74
+ consumes a packed tarball — `studio-ui/scripts/pack-vendor.sh` builds and
75
+ packs this repo into `studio-ui/vendor/`.
76
+
77
+ ## Release
78
+
79
+ Bump `version` in `package.json` and push to `main` — CI
80
+ (`.github/workflows/publish.yml`) publishes any version that isn't on npm
81
+ yet, via npm Trusted Publishing (the trusted publisher on npmjs is bound to
82
+ this repo + workflow file).
package/dist/module.d.mts CHANGED
@@ -1,6 +1,6 @@
1
- import * as nuxt_schema from 'nuxt/schema';
1
+ import * as _nuxt_schema from '@nuxt/schema';
2
2
  export * from '../dist/runtime/types/integrations.js';
3
3
 
4
- declare const _default: nuxt_schema.NuxtModule<nuxt_schema.ModuleOptions, nuxt_schema.ModuleOptions, false>;
4
+ declare const _default: _nuxt_schema.NuxtModule<_nuxt_schema.ModuleOptions, _nuxt_schema.ModuleOptions, false>;
5
5
 
6
6
  export { _default as default };
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@revenexx/studio-integrations",
3
3
  "configKey": "studioIntegrations",
4
- "version": "0.1.4",
4
+ "version": "0.3.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
@@ -0,0 +1,13 @@
1
+ type __VLS_Props = {
2
+ open: boolean;
3
+ /** Credential type slug(s) the field accepts — the dialog is scoped to these. */
4
+ credentialType?: string | string[];
5
+ };
6
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
7
+ "update:open": (args_0: boolean) => any;
8
+ created: (credentialId: string) => any;
9
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
10
+ "onUpdate:open"?: ((args_0: boolean) => any) | undefined;
11
+ onCreated?: ((credentialId: string) => any) | undefined;
12
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
+ export default _default;
@@ -0,0 +1,279 @@
1
+ <script setup>
2
+ import { computed, reactive, ref, watch } from "vue";
3
+ import { RefreshCircle as Loader2, TestTube as TestIcon } from "#solar-icons";
4
+ import {
5
+ Button,
6
+ Dialog,
7
+ DialogContent,
8
+ DialogDescription,
9
+ DialogFooter,
10
+ DialogHeader,
11
+ DialogTitle,
12
+ Input,
13
+ Label,
14
+ Switch,
15
+ Select,
16
+ SelectContent,
17
+ SelectItem,
18
+ SelectTrigger,
19
+ SelectValue
20
+ } from "@revenexx/studio";
21
+ import { toast } from "vue-sonner";
22
+ const props = defineProps({
23
+ open: { type: Boolean, required: true },
24
+ credentialType: { type: [String, Array], required: false }
25
+ });
26
+ const emit = defineEmits(["update:open", "created"]);
27
+ const { create, testInline, load, oauthAuthorizeUrl } = useIntegrationsCredentials();
28
+ const { load: loadTypes, bySlug } = useCredentialTypes();
29
+ function loc(v) {
30
+ if (!v) return "";
31
+ if (typeof v === "string") return v;
32
+ const o = v;
33
+ return o.en ?? o.de ?? Object.values(o)[0] ?? "";
34
+ }
35
+ function authKindLabel(k) {
36
+ switch (k) {
37
+ case "api-key":
38
+ return "API Key";
39
+ case "oauth2-authcode":
40
+ case "oauth2-client-credentials":
41
+ return "OAuth2";
42
+ case "basic-auth":
43
+ return "Basic Auth";
44
+ case "static":
45
+ return "Static";
46
+ case "secret":
47
+ return "Secret";
48
+ default:
49
+ return k ?? "";
50
+ }
51
+ }
52
+ const allowedSlugs = computed(() => {
53
+ const t = props.credentialType;
54
+ if (!t) return [];
55
+ return (Array.isArray(t) ? t : [t]).map((s) => s.trim()).filter(Boolean);
56
+ });
57
+ const allowedTypes = computed(() => allowedSlugs.value.map((s) => bySlug(s)).filter((x) => !!x));
58
+ const pickedType = ref(null);
59
+ const form = reactive({ name: "", config: {} });
60
+ const sourceActive = ref(false);
61
+ const saving = ref(false);
62
+ const testing = ref(false);
63
+ const testResult = ref(null);
64
+ function fieldsOf(t) {
65
+ return t?.fields ?? [];
66
+ }
67
+ function isOAuthAuthcode(t) {
68
+ return t?.auth_kind === "oauth2-authcode";
69
+ }
70
+ watch(() => props.open, async (o) => {
71
+ if (!o) return;
72
+ testResult.value = null;
73
+ sourceActive.value = false;
74
+ form.config = {};
75
+ await loadTypes();
76
+ if (allowedTypes.value.length === 1) {
77
+ pickedType.value = allowedTypes.value[0];
78
+ form.name = loc(pickedType.value.name);
79
+ } else {
80
+ pickedType.value = null;
81
+ form.name = "";
82
+ }
83
+ }, { immediate: true });
84
+ function pickType(t) {
85
+ pickedType.value = t;
86
+ form.config = {};
87
+ testResult.value = null;
88
+ sourceActive.value = false;
89
+ if (!form.name) form.name = loc(t.name);
90
+ }
91
+ function buildConfigPayload() {
92
+ const out = {};
93
+ for (const f of fieldsOf(pickedType.value)) {
94
+ const v = form.config[f.key];
95
+ if (v !== void 0 && v !== "") out[f.key] = v;
96
+ }
97
+ return out;
98
+ }
99
+ async function runTest() {
100
+ if (!pickedType.value) return;
101
+ testing.value = true;
102
+ testResult.value = null;
103
+ try {
104
+ testResult.value = await testInline(pickedType.value.slug, buildConfigPayload());
105
+ } finally {
106
+ testing.value = false;
107
+ }
108
+ }
109
+ function connect(id) {
110
+ return oauthAuthorizeUrl(id).then((authorizeUrl) => {
111
+ const popup = window.open(authorizeUrl, "oauth-connect", "width=600,height=720");
112
+ const onMessage = (ev) => {
113
+ if (ev.data?.type === "integrations-oauth-complete") {
114
+ window.removeEventListener("message", onMessage);
115
+ void load(true);
116
+ }
117
+ };
118
+ window.addEventListener("message", onMessage);
119
+ const poll = window.setInterval(() => {
120
+ if (popup?.closed) {
121
+ window.clearInterval(poll);
122
+ window.removeEventListener("message", onMessage);
123
+ void load(true);
124
+ }
125
+ }, 1e3);
126
+ });
127
+ }
128
+ async function submit() {
129
+ if (!pickedType.value || !form.name.trim()) return;
130
+ saving.value = true;
131
+ try {
132
+ const created = await create({
133
+ credential_type_slug: pickedType.value.slug,
134
+ name: form.name.trim(),
135
+ config: buildConfigPayload()
136
+ });
137
+ await load(true);
138
+ toast.success("Credential created");
139
+ if (isOAuthAuthcode(pickedType.value)) {
140
+ void connect(created.id);
141
+ }
142
+ emit("created", created.id);
143
+ emit("update:open", false);
144
+ } catch (e) {
145
+ toast.error(e?.message ?? "Could not create credential.");
146
+ } finally {
147
+ saving.value = false;
148
+ }
149
+ }
150
+ </script>
151
+
152
+ <template>
153
+ <Dialog :open="open" @update:open="(v) => emit('update:open', v)">
154
+ <DialogContent class="sm:max-w-lg">
155
+ <DialogHeader>
156
+ <DialogTitle>New credential</DialogTitle>
157
+ <DialogDescription class="text-sm">
158
+ Create a credential for this node without leaving the editor.
159
+ </DialogDescription>
160
+ </DialogHeader>
161
+
162
+ <!-- Choose the type when the field accepts more than one -->
163
+ <div v-if="!pickedType" class="space-y-2 py-1">
164
+ <p v-if="!allowedTypes.length" class="text-sm text-muted-foreground">
165
+ No credential type available for this field.
166
+ </p>
167
+ <button
168
+ v-for="t in allowedTypes"
169
+ :key="t.slug"
170
+ type="button"
171
+ class="flex w-full items-center gap-2 rounded-lg border border-black/[0.08] p-3 text-left transition hover:border-black/20 hover:bg-muted/30"
172
+ @click="pickType(t)"
173
+ >
174
+ <IntegrationsCredentialLogo :type="t" :size="18" />
175
+ <div class="min-w-0 truncate text-sm">
176
+ <span class="font-semibold">{{ loc(t.name) }}</span>
177
+ <span class="ml-1.5 text-muted-foreground">({{ authKindLabel(t.auth_kind) }})</span>
178
+ </div>
179
+ </button>
180
+ </div>
181
+
182
+ <!-- Dynamic form -->
183
+ <div v-else class="space-y-3 py-1 max-h-[26rem] overflow-y-auto pr-1">
184
+ <div class="flex items-center gap-2">
185
+ <IntegrationsCredentialLogo :type="pickedType" :size="18" />
186
+ <div class="text-sm font-medium">{{ loc(pickedType.name) }}</div>
187
+ <button
188
+ v-if="allowedTypes.length > 1"
189
+ type="button"
190
+ class="ml-auto text-sm text-muted-foreground hover:text-foreground"
191
+ @click="pickedType = null"
192
+ >
193
+ Change type
194
+ </button>
195
+ </div>
196
+
197
+ <div class="space-y-1.5">
198
+ <Label for="cred-name">Name</Label>
199
+ <Input id="cred-name" v-model="form.name" class="bg-white" placeholder="e.g. Production key" />
200
+ </div>
201
+
202
+ <!-- "Use revenexx …" source picker (SFTP / Mail / API key) -->
203
+ <IntegrationsCredentialRevenexxSource
204
+ :type="pickedType"
205
+ @update:active="(v) => sourceActive = v"
206
+ @apply="(c) => Object.assign(form.config, c)"
207
+ />
208
+
209
+ <div v-for="f in fieldsOf(pickedType)" v-show="!sourceActive" :key="f.key" class="space-y-1.5">
210
+ <Label>{{ loc(f.label) }}{{ f.required ? " *" : "" }}</Label>
211
+ <Input
212
+ v-if="f.type === 'secret'"
213
+ :model-value="form.config[f.key] ?? ''"
214
+ type="password"
215
+ autocomplete="new-password"
216
+ class="bg-white"
217
+ @update:model-value="(v) => form.config[f.key] = v"
218
+ />
219
+ <Input
220
+ v-else-if="f.type === 'number'"
221
+ type="number"
222
+ :model-value="form.config[f.key] ?? ''"
223
+ class="bg-white"
224
+ @update:model-value="(v) => form.config[f.key] = v === '' ? void 0 : Number(v)"
225
+ />
226
+ <div v-else-if="f.type === 'boolean'" class="flex items-center gap-2 pt-1">
227
+ <Switch :model-value="Boolean(form.config[f.key])" @update:model-value="(v) => form.config[f.key] = v" />
228
+ </div>
229
+ <Select
230
+ v-else-if="f.type === 'select'"
231
+ :model-value="form.config[f.key] ?? ''"
232
+ @update:model-value="(v) => form.config[f.key] = v"
233
+ >
234
+ <SelectTrigger class="bg-white">
235
+ <SelectValue placeholder="Pick one" />
236
+ </SelectTrigger>
237
+ <SelectContent>
238
+ <SelectItem v-for="opt in f.options ?? []" :key="String(opt.value)" :value="String(opt.value)">
239
+ {{ loc(opt.label) }}
240
+ </SelectItem>
241
+ </SelectContent>
242
+ </Select>
243
+ <Input
244
+ v-else
245
+ :model-value="form.config[f.key] ?? ''"
246
+ class="bg-white"
247
+ @update:model-value="(v) => form.config[f.key] = v"
248
+ />
249
+ </div>
250
+
251
+ <p v-if="isOAuthAuthcode(pickedType)" class="text-sm text-muted-foreground">
252
+ After saving, a window opens to connect with the provider.
253
+ </p>
254
+
255
+ <div
256
+ v-if="testResult"
257
+ class="rounded-md px-3 py-2 text-sm"
258
+ :class="testResult.ok ? 'bg-emerald-500/10 text-emerald-700' : 'bg-rose-500/10 text-rose-700'"
259
+ >
260
+ {{ testResult.ok ? "Connection ok." : testResult.error ?? "Connection failed." }}
261
+ </div>
262
+ </div>
263
+
264
+ <DialogFooter v-if="pickedType">
265
+ <div class="flex items-center gap-2">
266
+ <Button variant="outline" :disabled="saving || testing" @click="runTest">
267
+ <Loader2 v-if="testing" :size="14" class="mr-1 animate-spin" />
268
+ <TestIcon v-else :size="14" class="mr-1" />
269
+ Connect
270
+ </Button>
271
+ <Button :disabled="saving || !form.name.trim()" @click="submit">
272
+ <Loader2 v-if="saving" :size="14" class="mr-1 animate-spin" />
273
+ Save
274
+ </Button>
275
+ </div>
276
+ </DialogFooter>
277
+ </DialogContent>
278
+ </Dialog>
279
+ </template>
@@ -0,0 +1,13 @@
1
+ type __VLS_Props = {
2
+ open: boolean;
3
+ /** Credential type slug(s) the field accepts — the dialog is scoped to these. */
4
+ credentialType?: string | string[];
5
+ };
6
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
7
+ "update:open": (args_0: boolean) => any;
8
+ created: (credentialId: string) => any;
9
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
10
+ "onUpdate:open"?: ((args_0: boolean) => any) | undefined;
11
+ onCreated?: ((credentialId: string) => any) | undefined;
12
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
+ export default _default;
@@ -0,0 +1,20 @@
1
+ import type { Credential, CredentialType } from '../../types/integrations.js';
2
+ /**
3
+ * Credential detail / edit view — a single scrolling page (no tabs): the
4
+ * connection state up top, the editable fields, then read-only metadata.
5
+ * Self-contained — owns update / delete / test / OAuth reconnect against the
6
+ * Integrations service via the shared composable.
7
+ */
8
+ type __VLS_Props = {
9
+ open: boolean;
10
+ credential: Credential | null;
11
+ type: CredentialType | null;
12
+ };
13
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
14
+ "update:open": (args_0: boolean) => any;
15
+ changed: () => any;
16
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
17
+ "onUpdate:open"?: ((args_0: boolean) => any) | undefined;
18
+ onChanged?: (() => any) | undefined;
19
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
20
+ export default _default;