@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
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { whenIdle } from "./whenIdle.js";
|
|
2
|
+
export function createLoadGate(state) {
|
|
3
|
+
const { loading, loaded, started, finished } = state;
|
|
4
|
+
return {
|
|
5
|
+
async claim(force = false) {
|
|
6
|
+
const askedAt = started.value;
|
|
7
|
+
while (loading.value) {
|
|
8
|
+
await whenIdle(loading);
|
|
9
|
+
if (!force) return false;
|
|
10
|
+
if (finished.value > askedAt) return false;
|
|
11
|
+
}
|
|
12
|
+
if (loaded?.value && !force) return false;
|
|
13
|
+
started.value++;
|
|
14
|
+
loading.value = true;
|
|
15
|
+
return true;
|
|
16
|
+
},
|
|
17
|
+
release() {
|
|
18
|
+
loading.value = false;
|
|
19
|
+
finished.value++;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -1,11 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tell the studio which language to render in. **This is the host's job**, and
|
|
3
|
+
* it is the whole contract: the module is published, so it must not go looking
|
|
4
|
+
* for the cockpit's storage keys or import the cockpit's i18n. A host with a
|
|
5
|
+
* language switcher calls this whenever the choice changes; a host with a fixed
|
|
6
|
+
* language sets `studioIntegrations.locale` in its Nuxt config instead and
|
|
7
|
+
* never calls this at all.
|
|
8
|
+
*
|
|
9
|
+
* A BCP-47 tag (`de`, `en`, `de-CH`). Empty or absent means English.
|
|
10
|
+
*/
|
|
11
|
+
export declare function setStudioLocale(locale: string | null | undefined): void;
|
|
12
|
+
/** The language the studio is currently rendering in. Reactive when read in an effect. */
|
|
13
|
+
export declare function studioLocale(): string;
|
|
1
14
|
/**
|
|
2
15
|
* Resolve a multilingual value from the Integrations API. The API returns
|
|
3
16
|
* names and descriptions either as a plain string or as an already-parsed
|
|
4
17
|
* object `{de:"…", en:"…"}` (the HTTP client does JSON decoding automatically).
|
|
5
18
|
* JSON-encoded strings like `'{"de":"…","en":"…"}'` are also handled.
|
|
6
19
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
20
|
+
* The language is the studio's ({@link setStudioLocale}) unless the caller
|
|
21
|
+
* names one. English is the fallback, and the map's own first entry the
|
|
22
|
+
* fallback after that.
|
|
23
|
+
*
|
|
24
|
+
* **This is the studio's only resolver, and that is the point.** The same three
|
|
25
|
+
* lines used to sit in seventeen components under six names (`labelText`, `loc`,
|
|
26
|
+
* `locText`, `localLabel`, `title`, `descriptionText`), all agreeing with this
|
|
27
|
+
* function by coincidence. A language switcher wired into this one place would
|
|
28
|
+
* have translated a fraction of the surface with nothing going red — so PO-229
|
|
29
|
+
* collapsed them here before building one. Anything that renders a name, a
|
|
30
|
+
* label, a description or a placeholder from the API calls this; nothing
|
|
31
|
+
* re-derives the rule.
|
|
32
|
+
*
|
|
33
|
+
* Two of the seventeen were named for their call site rather than for the rule
|
|
34
|
+
* (`WorkflowTriggerView`'s `title`, `WorkflowVariablesDialog`'s
|
|
35
|
+
* `descriptionText`), so no grep for the rule's shape found them. Both resolve
|
|
36
|
+
* text a person typed and went to `resolveDisplayName` below, not here.
|
|
37
|
+
*/
|
|
38
|
+
export declare function resolveLocalized(value: unknown, locale?: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* The same resolution, for a value that may be **text a person wrote** — a
|
|
41
|
+
* node's own name, a group frame's label.
|
|
42
|
+
*
|
|
43
|
+
* `resolveLocalized` normalises: it trims, and it reads a leading `{` as JSON.
|
|
44
|
+
* That is right for a manifest string and wrong for a user's own, and it has
|
|
45
|
+
* already cost once (PO-204): run through the trimming resolver, the node-name
|
|
46
|
+
* field ate the space the user had just typed, so "Fetch open orders" came back
|
|
47
|
+
* as "Fetchopenorders". A name like `{"a":"b"}` would render as `b`.
|
|
48
|
+
*
|
|
49
|
+
* So a string is passed through untouched and only the localised-object form is
|
|
50
|
+
* resolved. Use this wherever the value can be something a person typed; use
|
|
51
|
+
* `resolveLocalized` for anything that can only have come from a manifest.
|
|
10
52
|
*/
|
|
11
|
-
export declare function
|
|
53
|
+
export declare function resolveDisplayName(value: string | Record<string, string> | undefined | null, locale?: string): string;
|
|
@@ -1,11 +1,34 @@
|
|
|
1
|
-
|
|
1
|
+
import { shallowRef } from "vue";
|
|
2
|
+
const uiLocale = shallowRef("en");
|
|
3
|
+
export function setStudioLocale(locale) {
|
|
4
|
+
const next = typeof locale === "string" ? locale.trim() : "";
|
|
5
|
+
uiLocale.value = next || "en";
|
|
6
|
+
}
|
|
7
|
+
export function studioLocale() {
|
|
8
|
+
return uiLocale.value;
|
|
9
|
+
}
|
|
10
|
+
function pickLanguage(map, locale) {
|
|
11
|
+
const keys = Object.keys(map);
|
|
12
|
+
if (!keys.length) return "";
|
|
13
|
+
const wanted = locale.toLowerCase();
|
|
14
|
+
const base = wanted.split("-")[0];
|
|
15
|
+
const candidates = [
|
|
16
|
+
keys.find((k) => k.toLowerCase() === wanted),
|
|
17
|
+
keys.find((k) => k.toLowerCase().split("-")[0] === base),
|
|
18
|
+
keys.find((k) => k.toLowerCase().split("-")[0] === "en"),
|
|
19
|
+
keys[0]
|
|
20
|
+
];
|
|
21
|
+
for (const key of candidates) {
|
|
22
|
+
if (key === void 0) continue;
|
|
23
|
+
const picked = map[key];
|
|
24
|
+
if (typeof picked === "string") return picked;
|
|
25
|
+
}
|
|
26
|
+
return "";
|
|
27
|
+
}
|
|
28
|
+
export function resolveLocalized(value, locale = uiLocale.value) {
|
|
2
29
|
if (value === null || value === void 0) return "";
|
|
3
30
|
if (typeof value === "object" && !Array.isArray(value)) {
|
|
4
|
-
|
|
5
|
-
const keys = Object.keys(map);
|
|
6
|
-
if (!keys.length) return "";
|
|
7
|
-
const picked = map["en"] ?? map[keys[0]];
|
|
8
|
-
return typeof picked === "string" ? picked : "";
|
|
31
|
+
return pickLanguage(value, locale);
|
|
9
32
|
}
|
|
10
33
|
if (typeof value !== "string") return String(value);
|
|
11
34
|
const trimmed = value.trim();
|
|
@@ -13,8 +36,12 @@ export function resolveLocalized(value) {
|
|
|
13
36
|
try {
|
|
14
37
|
const parsed = JSON.parse(trimmed);
|
|
15
38
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return trimmed;
|
|
16
|
-
return resolveLocalized(parsed);
|
|
39
|
+
return resolveLocalized(parsed, locale);
|
|
17
40
|
} catch {
|
|
18
41
|
return trimmed;
|
|
19
42
|
}
|
|
20
43
|
}
|
|
44
|
+
export function resolveDisplayName(value, locale = uiLocale.value) {
|
|
45
|
+
if (typeof value === "string") return value;
|
|
46
|
+
return resolveLocalized(value, locale);
|
|
47
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A proxy rather than a hand-written object, so the whole library stays reachable:
|
|
3
|
+
* `toast.dismiss`, `toast.promise`, `toast.custom` and whatever it gains next are
|
|
4
|
+
* forwarded and guarded on access. Listing the methods by hand would have turned the
|
|
5
|
+
* first call to an unlisted one into "undefined is not a function" — a second defect
|
|
6
|
+
* of the same shape as the one this file exists for.
|
|
7
|
+
*/
|
|
8
|
+
export declare const toast: ((message: string | (() => string | import("vue").Component) | import("vue").Component, data?: import("vue-sonner").ExternalToast) => string | number) & {
|
|
9
|
+
success: (message: string | (() => string | import("vue").Component) | import("vue").Component, data?: import("vue-sonner").ExternalToast) => string | number;
|
|
10
|
+
info: (message: string | (() => string | import("vue").Component) | import("vue").Component, data?: import("vue-sonner").ExternalToast) => string | number;
|
|
11
|
+
warning: (message: string | (() => string | import("vue").Component) | import("vue").Component, data?: import("vue-sonner").ExternalToast) => string | number;
|
|
12
|
+
error: (message: string | (() => string | import("vue").Component) | import("vue").Component, data?: import("vue-sonner").ExternalToast) => string | number;
|
|
13
|
+
custom: (component: import("vue").Component, data?: import("vue-sonner").ExternalToast) => string | number;
|
|
14
|
+
message: (message: string | (() => string | import("vue").Component) | import("vue").Component, data?: import("vue-sonner").ExternalToast) => string | number;
|
|
15
|
+
promise: <ToastData>(promise: Promise<ToastData> | (() => Promise<ToastData>), data?: ({
|
|
16
|
+
action?: (import("vue-sonner").Action | import("vue").Component) | undefined;
|
|
17
|
+
icon?: import("vue").Component | undefined;
|
|
18
|
+
class?: string | undefined;
|
|
19
|
+
id?: number | string | undefined;
|
|
20
|
+
position?: ("top-left" | "top-right" | "bottom-left" | "bottom-right" | "top-center" | "bottom-center") | undefined;
|
|
21
|
+
cancel?: (import("vue-sonner").Action | import("vue").Component) | undefined;
|
|
22
|
+
toasterId?: string | undefined;
|
|
23
|
+
component?: import("vue").Component | undefined;
|
|
24
|
+
componentProps?: any;
|
|
25
|
+
richColors?: boolean | undefined;
|
|
26
|
+
invert?: boolean | undefined;
|
|
27
|
+
closeButton?: boolean | undefined;
|
|
28
|
+
dismissible?: boolean | undefined;
|
|
29
|
+
duration?: number | undefined;
|
|
30
|
+
important?: boolean | undefined;
|
|
31
|
+
onDismiss?: ((toast: import("vue-sonner").ToastT) => void) | undefined;
|
|
32
|
+
onAutoClose?: ((toast: import("vue-sonner").ToastT) => void) | undefined;
|
|
33
|
+
cancelButtonStyle?: import("vue").CSSProperties | undefined;
|
|
34
|
+
actionButtonStyle?: import("vue").CSSProperties | undefined;
|
|
35
|
+
style?: import("vue").CSSProperties | undefined;
|
|
36
|
+
unstyled?: boolean | undefined;
|
|
37
|
+
classes?: import("vue-sonner").ToastClasses | undefined;
|
|
38
|
+
descriptionClass?: string | undefined;
|
|
39
|
+
closeButtonPosition?: ("top-left" | "top-right" | "bottom-left" | "bottom-right") | undefined;
|
|
40
|
+
testId?: string | undefined;
|
|
41
|
+
} & {
|
|
42
|
+
loading?: string | import("vue").Component;
|
|
43
|
+
success?: (string | import("vue").Component | ((data: ToastData) => import("vue").Component | string | Promise<import("vue").Component | string>)) | (import("vue-sonner").PromiseIExtendedResult | ((data: ToastData) => import("vue-sonner").PromiseIExtendedResult | Promise<import("vue-sonner").PromiseIExtendedResult>)) | undefined;
|
|
44
|
+
error?: (string | import("vue").Component | ((data: any) => import("vue").Component | string | Promise<import("vue").Component | string>)) | (import("vue-sonner").PromiseIExtendedResult | ((data: any) => import("vue-sonner").PromiseIExtendedResult | Promise<import("vue-sonner").PromiseIExtendedResult>));
|
|
45
|
+
description?: string | import("vue").Component | ((data: any) => import("vue").Component | string | Promise<import("vue").Component | string>);
|
|
46
|
+
finally?: () => void | Promise<void>;
|
|
47
|
+
}) | undefined) => (string & {
|
|
48
|
+
unwrap: () => Promise<ToastData>;
|
|
49
|
+
}) | (number & {
|
|
50
|
+
unwrap: () => Promise<ToastData>;
|
|
51
|
+
}) | {
|
|
52
|
+
unwrap: () => Promise<ToastData>;
|
|
53
|
+
} | undefined;
|
|
54
|
+
dismiss: (id?: number | string) => string | number | undefined;
|
|
55
|
+
loading: (message: string | (() => string | import("vue").Component) | import("vue").Component, data?: import("vue-sonner").ExternalToast) => string | number;
|
|
56
|
+
} & {
|
|
57
|
+
getHistory: () => (import("vue-sonner").ToastT<import("vue").Component> | import("vue-sonner").ToastToDismiss)[];
|
|
58
|
+
getToasts: () => (import("vue-sonner").ToastT<import("vue").Component> | import("vue-sonner").ToastToDismiss)[];
|
|
59
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { toast as sonner } from "vue-sonner";
|
|
2
|
+
function guarded(kind, fn) {
|
|
3
|
+
return (...args) => {
|
|
4
|
+
try {
|
|
5
|
+
return fn(...args);
|
|
6
|
+
} catch (e) {
|
|
7
|
+
console.warn(`[studio-integrations] notification dropped (${kind}): ${String(args[0])}`, e);
|
|
8
|
+
return void 0;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export const toast = new Proxy(sonner, {
|
|
13
|
+
apply(target, thisArg, args) {
|
|
14
|
+
return guarded("message", (...a) => Reflect.apply(target, thisArg, a))(...args);
|
|
15
|
+
},
|
|
16
|
+
get(target, prop) {
|
|
17
|
+
const value = Reflect.get(target, prop);
|
|
18
|
+
if (typeof value !== "function") return value;
|
|
19
|
+
return guarded(String(prop), (...args) => value.apply(target, args));
|
|
20
|
+
}
|
|
21
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How often a poll is still allowed to fetch once realtime is carrying the same
|
|
3
|
+
* updates.
|
|
4
|
+
*
|
|
5
|
+
* Every run surface polls: the runs list every three seconds, the detail panel
|
|
6
|
+
* every three and its timeline every ten, the replay canvas every four. That is the
|
|
7
|
+
* only thing that made a `running → completed` transition appear at all, and it is
|
|
8
|
+
* expensive — `runs.vue`'s pass fans out one request per workflow and then
|
|
9
|
+
* reconciles up to five active runs, so the list can cost dozens of requests every
|
|
10
|
+
* three seconds while anything is in flight.
|
|
11
|
+
*
|
|
12
|
+
* Talkback replaces the *latency* argument for polling, not the safety argument. So
|
|
13
|
+
* the intervals stay exactly where they are and this decides, per tick, whether the
|
|
14
|
+
* tick may spend a request: at the ordinary cadence while nothing is being reported,
|
|
15
|
+
* and at a slow safety cadence once something is.
|
|
16
|
+
*
|
|
17
|
+
* COUNTING TICKS, NOT READING A CLOCK, and that is deliberate twice over. The tick
|
|
18
|
+
* is the only thing that has actually happened — a wall-clock reading would make
|
|
19
|
+
* this disagree with a `setInterval` the browser throttled in a background tab. And
|
|
20
|
+
* `specs/runs.md` AC-12's test installs Playwright's fake clock and fast-forwards
|
|
21
|
+
* it; a `Date.now()` in here would read the fake time, which is the kind of
|
|
22
|
+
* coupling that makes a test pass for the wrong reason.
|
|
23
|
+
*
|
|
24
|
+
* WHAT `delivering` HAS TO MEAN, and this is the argument the parameter's name is
|
|
25
|
+
* carrying. Being subscribed is no evidence: a channel resolves from the local
|
|
26
|
+
* subscription, so a tenant whose event catalogue never publishes these topics holds
|
|
27
|
+
* open channels that stay silent for the life of the tab — and thinning on that state
|
|
28
|
+
* would make such a tenant ten times slower than before any of this existed, with
|
|
29
|
+
* nothing anywhere saying so. `useIntegrationsRealtime` therefore counts deliveries,
|
|
30
|
+
* and this is only ever thinned once something has really arrived.
|
|
31
|
+
*
|
|
32
|
+
* WHY A SLOW POLL RATHER THAN NONE. What is still unavailable is whether delivery is
|
|
33
|
+
* CONTINUING: a socket that dies quietly after one event keeps reading as delivering,
|
|
34
|
+
* because the per-channel confirmation that would settle it is not passed through the
|
|
35
|
+
* packages between Centrifugo and here. A budget that stopped fetching entirely would
|
|
36
|
+
* then show a stale list for as long as the tab stayed open, with nothing anywhere
|
|
37
|
+
* saying so. Backing off from three seconds to thirty gives up latency we now get
|
|
38
|
+
* from events and keeps the property that mattered: the view converges without the
|
|
39
|
+
* operator doing anything.
|
|
40
|
+
*
|
|
41
|
+
* The caller keeps its own tick-shedding (`!loading.value`) in front of this, so a
|
|
42
|
+
* tick that finds a load still out neither fetches nor spends budget — see
|
|
43
|
+
* `loadGate.ts` for why that flag is trustworthy.
|
|
44
|
+
*/
|
|
45
|
+
export interface PollBudgetOptions {
|
|
46
|
+
/** The caller's own interval, i.e. how much time one `due()` call stands for. */
|
|
47
|
+
intervalMs: number;
|
|
48
|
+
/** The gap between fetches while reports are arriving. */
|
|
49
|
+
liveIntervalMs: number;
|
|
50
|
+
}
|
|
51
|
+
export interface PollBudget {
|
|
52
|
+
/**
|
|
53
|
+
* Whether this tick may fetch. Advances the budget, so call it once per tick and
|
|
54
|
+
* last in the condition — `hasActive && !loading && budget.due(delivering)`.
|
|
55
|
+
*/
|
|
56
|
+
due: (delivering: boolean) => boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Counts a fetch this budget did not authorise: a report's refetch, a manual
|
|
59
|
+
* refresh, a row action, an opening surface's first read. Without it the next due
|
|
60
|
+
* tick would send a second request for a state that was just read.
|
|
61
|
+
*
|
|
62
|
+
* CALL IT IN THE LOADER, not at each call site, wherever the surface has a loader
|
|
63
|
+
* of its own to put it in — `[id].vue`'s `loadRuns`, `RunDetailPanel`'s
|
|
64
|
+
* `loadSummary` and `loadTimelineEvents`, `runs.vue`'s `reload`. A contract that
|
|
65
|
+
* asks every future caller to remember is one that ends up wider than the wiring,
|
|
66
|
+
* which is how this note came to be written.
|
|
67
|
+
*/
|
|
68
|
+
spend: () => void;
|
|
69
|
+
}
|
|
70
|
+
/** The safety cadence every run surface backs off to while reports are arriving. */
|
|
71
|
+
export declare const SAFETY_POLL_MS = 30000;
|
|
72
|
+
export declare function createPollBudget(options: PollBudgetOptions): PollBudget;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const SAFETY_POLL_MS = 3e4;
|
|
2
|
+
export function createPollBudget(options) {
|
|
3
|
+
let elapsed = 0;
|
|
4
|
+
return {
|
|
5
|
+
due(delivering) {
|
|
6
|
+
elapsed += options.intervalMs;
|
|
7
|
+
if (!delivering || elapsed >= options.liveIntervalMs) {
|
|
8
|
+
elapsed = 0;
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
return false;
|
|
12
|
+
},
|
|
13
|
+
spend() {
|
|
14
|
+
elapsed = 0;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which credential types offer the "Use revenexx …" source alternative, and
|
|
3
|
+
* under which kind.
|
|
4
|
+
*
|
|
5
|
+
* This lives apart from the component that renders it because its *parents* need
|
|
6
|
+
* it too: the detail dialog mounts that component only for the types it actually
|
|
7
|
+
* serves, since for every other type it renders nothing anyway.
|
|
8
|
+
*
|
|
9
|
+
* It was once load-bearing for a different reason — the component resolved
|
|
10
|
+
* cockpit-only composables at setup time, so mounting it outside the cockpit
|
|
11
|
+
* threw and took the surrounding form down. That is fixed (PO-222): the component
|
|
12
|
+
* asks whether those sources exist. So this guard is now tidiness rather than
|
|
13
|
+
* protection, which is also why the create dialog never having one stopped
|
|
14
|
+
* mattering.
|
|
15
|
+
*/
|
|
16
|
+
export type RevenexxSourceKind = 'sftp' | 'smtp' | 'api';
|
|
17
|
+
export declare const REVENEXX_SOURCE_KIND_BY_SLUG: Record<string, RevenexxSourceKind>;
|
|
18
|
+
/**
|
|
19
|
+
* Whether this credential type has a managed revenexx counterpart to copy from.
|
|
20
|
+
*
|
|
21
|
+
* Own properties only: `in` would answer yes for everything on the prototype
|
|
22
|
+
* chain, so a type slugged `toString` or `constructor` would pass the guard and
|
|
23
|
+
* then resolve to a function instead of a kind — and this guard is what decides
|
|
24
|
+
* whether the cockpit-coupled component mounts at all.
|
|
25
|
+
*/
|
|
26
|
+
export declare function hasRevenexxSource(slug: string | null | undefined): boolean;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/** A rhythm the picker can build, and `describeRecurrence` can always say. */
|
|
2
|
+
export type Recurrence =
|
|
3
|
+
/** `interval` minutes apart, all day, every day. `1` means every minute. */
|
|
4
|
+
{
|
|
5
|
+
kind: 'minutes';
|
|
6
|
+
interval: number;
|
|
7
|
+
}
|
|
8
|
+
/** Once an hour, at `minute` past. */
|
|
9
|
+
| {
|
|
10
|
+
kind: 'hourly';
|
|
11
|
+
minute: number;
|
|
12
|
+
}
|
|
13
|
+
/** Every `interval` hours (2 or more), at `minute` past. */
|
|
14
|
+
| {
|
|
15
|
+
kind: 'hours';
|
|
16
|
+
interval: number;
|
|
17
|
+
minute: number;
|
|
18
|
+
}
|
|
19
|
+
/** Once a day, at a fixed time. */
|
|
20
|
+
| {
|
|
21
|
+
kind: 'daily';
|
|
22
|
+
hour: number;
|
|
23
|
+
minute: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Several times a day, at the same minute past each of `hours` — two or more —
|
|
27
|
+
* and on `days`, or every day when that is `null`.
|
|
28
|
+
*
|
|
29
|
+
* A list of hours and a run of them are the same rhythm written two ways
|
|
30
|
+
* (`9,10,11` fires exactly when `9-11` does), so both read back into this one
|
|
31
|
+
* form and `toCron` picks the canonical spelling. Times with *different*
|
|
32
|
+
* minutes are not one rhythm and cron cannot express them in one expression:
|
|
33
|
+
* 07:30 and 09:15 is two schedules.
|
|
34
|
+
*/
|
|
35
|
+
| {
|
|
36
|
+
kind: 'times';
|
|
37
|
+
minute: number;
|
|
38
|
+
hours: number[];
|
|
39
|
+
days: number[] | null;
|
|
40
|
+
}
|
|
41
|
+
/** On the given weekdays (0 = Sunday), at a fixed time. Never empty. */
|
|
42
|
+
| {
|
|
43
|
+
kind: 'weekly';
|
|
44
|
+
days: number[];
|
|
45
|
+
hour: number;
|
|
46
|
+
minute: number;
|
|
47
|
+
}
|
|
48
|
+
/** On one day of the month, at a fixed time. */
|
|
49
|
+
| {
|
|
50
|
+
kind: 'monthly';
|
|
51
|
+
day: number;
|
|
52
|
+
hour: number;
|
|
53
|
+
minute: number;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* The zone a schedule without one of its own runs in: the platform's default,
|
|
57
|
+
* which is UTC (`config('app.timezone')`, which nothing overrides).
|
|
58
|
+
*
|
|
59
|
+
* Not the zone the studio *writes*. A schedule set up here carries
|
|
60
|
+
* `Europe/Berlin` from the trigger's own default config, and this is only what a
|
|
61
|
+
* schedule that arrived without a zone actually runs in.
|
|
62
|
+
*/
|
|
63
|
+
export declare const PLATFORM_TIMEZONE = "UTC";
|
|
64
|
+
/**
|
|
65
|
+
* The zone a schedule's numbers are read in — its own where it has one, the
|
|
66
|
+
* platform's default where it does not.
|
|
67
|
+
*
|
|
68
|
+
* One function because two surfaces show it: the trigger settings under the
|
|
69
|
+
* controls, and the Schedules page in its own column. A surface that answered this
|
|
70
|
+
* for itself is how one schedule ends up with two zones, and a zone is half of
|
|
71
|
+
* what a time means.
|
|
72
|
+
*/
|
|
73
|
+
export declare function scheduleTimezone(timezone: unknown): string;
|
|
74
|
+
/**
|
|
75
|
+
* The rhythm an expression describes, or `null` when it is not one of them.
|
|
76
|
+
*
|
|
77
|
+
* @param cron A five-field expression: minute hour day-of-month month day-of-week.
|
|
78
|
+
*/
|
|
79
|
+
export declare function parseCron(cron: string | null | undefined): Recurrence | null;
|
|
80
|
+
/**
|
|
81
|
+
* The five-field expression for a rhythm. Always valid, always five fields, and
|
|
82
|
+
* **never both a day of the month and a weekday** — cron reads that pair as
|
|
83
|
+
* "either", so a picker that produced it would mean something other than what it
|
|
84
|
+
* showed.
|
|
85
|
+
*
|
|
86
|
+
* Three rhythms are written in their canonical form rather than literally, so one
|
|
87
|
+
* rhythm has one expression: an hourly interval of 1 is `hourly`, a weekly
|
|
88
|
+
* schedule on all seven days is `daily`, and every day of the week under `times`
|
|
89
|
+
* is written as an open field. Reading any of them back therefore gives the
|
|
90
|
+
* canonical form, not the one passed in.
|
|
91
|
+
*/
|
|
92
|
+
export declare function toCron(r: Recurrence): string;
|
|
93
|
+
/**
|
|
94
|
+
* A sentence for a rhythm. Total: every `Recurrence` has one, which is what lets
|
|
95
|
+
* a surface show the sentence in place of the expression.
|
|
96
|
+
*/
|
|
97
|
+
export declare function describeRecurrence(r: Recurrence): string;
|
|
98
|
+
/**
|
|
99
|
+
* A sentence for the expression, or `null` when it cannot be said plainly.
|
|
100
|
+
*
|
|
101
|
+
* Nothing at all is the point where it happens. A wrong aid is worse than none,
|
|
102
|
+
* because a schedule that reads "Daily at 03:00" and fires hourly is a fault
|
|
103
|
+
* nobody goes looking for — so the shapes this cannot read produce no sentence,
|
|
104
|
+
* and the surface shows the expression instead.
|
|
105
|
+
*
|
|
106
|
+
* Times are read as written: the expression's own numbers, in the schedule's own
|
|
107
|
+
* timezone. Nothing here converts anything, which is why the timezone is the
|
|
108
|
+
* caller's to show.
|
|
109
|
+
*/
|
|
110
|
+
export declare function describeCron(cron: string | null | undefined): string | null;
|
|
111
|
+
/**
|
|
112
|
+
* How long a rhythm waits between firings, in minutes — the order a "when does
|
|
113
|
+
* this run" column sorts in. An expression that cannot be read sorts last, since
|
|
114
|
+
* the alternative is ordering rows by a string the reader cannot see.
|
|
115
|
+
*/
|
|
116
|
+
export declare function cadenceRank(cron: string | null | undefined): number;
|