@oomol-lab/open-flow 0.1.0-beta.62 → 0.1.0-beta.63
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/dist/browser/{createResourceDialog-DZgJsr3e.js → createResourceDialog-BAJXbzNH.js} +20 -7
- package/dist/browser/flow-authoring.js +8 -7
- package/dist/browser/flow-change-schema.d.ts +1 -0
- package/dist/browser/flow-change.d.ts +1 -0
- package/dist/browser/flow-change.js +8 -7
- package/dist/browser/{flowChanges-CzYIVevI.js → flowChanges-DpZOQuJE.js} +784 -443
- package/dist/browser/{flowRunInputEditorStore-Dsxyfwae.js → flowRunInputEditorStore-B2Rw4VsT.js} +1 -1
- package/dist/browser/{flowWorkspace-BgZaFKZm.js → flowWorkspace-B7a5NNA_.js} +41 -29
- package/dist/browser/{icons-CajfDpy_.js → icons-Db2Jb2iX.js} +30 -10
- package/dist/browser/preview.css +5 -6
- package/dist/browser/preview.js +437 -402
- package/dist/browser/{typeScriptSession-fXPMFGjW.js → typeScriptSession-D0bjYDeg.js} +1 -1
- package/dist/browser/ui.css +4 -5
- package/dist/browser/ui.js +2 -2
- package/dist/browser/{value-DL_poNiC.js → value-BADHeZ9I.js} +12 -1
- package/dist/browser/workbench-contract.d.ts +10 -0
- package/dist/browser/workbench.css +5 -6
- package/dist/browser/workbench.d.ts +5 -3
- package/dist/browser/workbench.js +198 -171
- package/dist/browser/{workbenchSelect-H9wzEFkH.js → workbenchSelect-C-jf6NIM.js} +1 -1
- package/dist/command/index.js +40 -39
- package/dist/common/authoringSchema.d.ts +1 -0
- package/dist/common/connector-action.d.ts +1 -0
- package/dist/common/connector-action.js +15 -12
- package/dist/common/control-api-conformance.js +107 -8
- package/dist/common/control-api.d.ts +8 -0
- package/dist/common/control-api.js +47 -8
- package/dist/common/control-requests.d.ts +6 -0
- package/dist/common/control-requests.js +41 -18
- package/dist/common/decision.js +8 -7
- package/dist/common/flow-connectionUsage.d.ts +1 -0
- package/dist/common/flow-encoding.d.ts +1 -0
- package/dist/common/flow-encoding.js +202 -10
- package/dist/common/flow-semantics.js +64 -46
- package/dist/common/flow-workflowFile.d.ts +23 -0
- package/dist/common/integration-trigger.js +8 -7
- package/dist/common/localization.d.ts +1 -0
- package/dist/common/localization.js +12 -1
- package/dist/common/mcp.d.ts +61 -0
- package/dist/common/mcp.js +92 -9
- package/dist/common/openapi.js +8 -7
- package/dist/common/poll-trigger.js +8 -7
- package/dist/common/runtime-contract.js +1 -1
- package/dist/common/scheduler.d.ts +22 -2
- package/dist/common/scheduler.js +354 -83
- package/dist/common/trigger-config.d.ts +2 -0
- package/dist/common/webhook-trigger.js +8 -7
- package/dist/index.d.ts +2 -2
- package/package.json +1 -1
- package/skills/open-flow/SKILL.md +1 -1
- package/skills/open-flow/references/flow-authoring.md +20 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import type { WorkflowFile } from '../common/flow-workflowFile.js';
|
|
1
2
|
export { EventSourcesPage } from './event-sources.js';
|
|
2
3
|
import type { FormEvent, ReactElement } from 'react';
|
|
3
|
-
import type { ConnectionHref, WorkbenchHost, WorkbenchLanguage, WorkbenchLocation, WorkbenchNavigationOptions, WorkbenchPreferences, WorkbenchTheme } from './workbench-contract.js';
|
|
4
|
+
import type { ConnectionHref, OpenFlowWorkbenchHandle, WorkbenchHost, WorkbenchLanguage, WorkbenchLocation, WorkbenchNavigationOptions, WorkbenchPreferences, WorkbenchTheme } from './workbench-contract.js';
|
|
4
5
|
export declare function OpenFlowSessionGate({ action, description, error, onSubmit, onTokenChange, pending, title, token, tokenLabel, }: {
|
|
5
6
|
readonly action?: string | undefined;
|
|
6
7
|
readonly description: string;
|
|
@@ -13,11 +14,12 @@ export declare function OpenFlowSessionGate({ action, description, error, onSubm
|
|
|
13
14
|
readonly tokenLabel?: string | undefined;
|
|
14
15
|
}): ReactElement;
|
|
15
16
|
export type { WorkbenchActor } from './workbench-contract.js';
|
|
16
|
-
export type { FlowCatalogEvent, FlowChangeEvent, WorkbenchHost, WorkbenchLanguage, WorkbenchLocation, WorkbenchNavigationOptions, WorkbenchNotification, WorkbenchPreferences, WorkbenchTheme, WorkbenchView, } from './workbench-contract.js';
|
|
17
|
+
export type { OpenFlowWorkbenchHandle, WorkbenchImportInput, FlowCatalogEvent, FlowChangeEvent, WorkbenchHost, WorkbenchLanguage, WorkbenchLocation, WorkbenchNavigationOptions, WorkbenchNotification, WorkbenchPreferences, WorkbenchTheme, WorkbenchView, } from './workbench-contract.js';
|
|
17
18
|
export { isUiLanguage as isWorkbenchLanguage, resolveUiLanguage as resolveWorkbenchLanguage, uiLanguageNames as workbenchLanguageNames, uiLanguages as workbenchLanguages, } from '../common/localization.js';
|
|
18
19
|
export interface OpenFlowWorkbenchProps {
|
|
19
20
|
/** Embedded catalogs fill a host-owned page without adding width limits or page padding. */
|
|
20
21
|
readonly catalogWidth?: 'default' | 'full' | 'embedded' | undefined;
|
|
22
|
+
readonly importFlow?: ((file: WorkflowFile, name: string, idempotencyKey: string) => Promise<string>) | undefined;
|
|
21
23
|
readonly createFlow?: ((name: string) => Promise<string>) | undefined;
|
|
22
24
|
readonly createFlowDisabled?: boolean | undefined;
|
|
23
25
|
readonly createFlowField?: {
|
|
@@ -62,4 +64,4 @@ export interface OpenFlowWorkbenchProps {
|
|
|
62
64
|
readonly theme: WorkbenchTheme;
|
|
63
65
|
readonly variables?: boolean;
|
|
64
66
|
}
|
|
65
|
-
export declare
|
|
67
|
+
export declare const OpenFlowWorkbench: import("react").ForwardRefExoticComponent<OpenFlowWorkbenchProps & import("react").RefAttributes<OpenFlowWorkbenchHandle>>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { $
|
|
1
|
+
import { $n as connection, $t as DropdownMenu, At as WorkflowExportMenuItem, B as CacheResource, Ct as resetInputValues, Dt as setTriggerConnection, En as EventSourcesPage, Et as setInputSources, F as feishuResourceKind, G as designerGraph, Gn as allConnectorConnectionsQuery, Gt as InputGroupAddon, H as resourceData, Hn as errorNotice, I as supportsFeishuChatFilter, Jt as EmptyContent, Kt as InputGroupInput, L as combineSources, M as addNodeIntent, Mt as followWorkbenchLink, N as deriveAddNodeOptions, Nt as Popover, Ot as updateTriggerConfig, Pt as PopoverContent, Qn as isJsonObject, Qt as EmptyTitle, Rt as PopoverTitle, Sr as controlErrorCode, St as repairNodeNames, Tn as Badge, Tr as IconThemeContext, Tt as setConnectorConnection, U as resourceValue, Un as WorkbenchClient, W as connectorActionPorts, Wn as randomId, Wt as InputGroup, Xn as sampleErrorOutputs, Xt as EmptyHeader, Y as providerIcon, Yt as EmptyDescription, Zn as triggerOutputDefinitions, Zt as EmptyMedia, _ as updateValue, _r as invalidResponse, _t as restoreCanvasPresentation, a as nameCreatedNodes, at as Latest, br as string, bt as setNodeContentHidden, c as updateCondition, d as updateNodeName, dn as DropdownMenuTrigger, dt as actionWithConnections, er as connectorActionMetadata, et as RunStore, f as updateNodeSettings, ft as connectionCatalog, g as updateTaskPorts, gr as inputValue, gt as removeComments, h as updateTaskAdditionalInputs, ht as flowPresentation, i as deleteSelection, ir as workflowNameFromFile, it as flowResourceReferences, jt as IdTooltip, kn as createI18n, kt as updateTriggerSchedule, l as updateNodeDescription, m as updateTask, mt as commentIds, nr as parseWorkflowFile, o as setInputValue, ot as deriveInspectorDiagnostics, p as updateResolution, pt as canvasPresentationChange, qn as decodeTriggerCatalog, qt as Empty, r as applyFlowChanges, rn as DropdownMenuItem, rr as workflowFileName, rt as revisionView, s as setInputVariable, sn as DropdownMenuSeparator, sr as providerIconAppearance, st as diagnosticItems, t as addNode, tn as DropdownMenuContent, tr as encodeWorkflowFile, u as updateNodeIcon, v as updateWebhook, vr as jsonValue, vt as setComment, wt as setCodeActions, xr as ApiError, xt as setNodePositions, yr as record, yt as setFlowViewport, z as scopedValue } from "./flowChanges-DpZOQuJE.js";
|
|
2
2
|
import { a as derive, i as compute, l as val } from "./dist-bO8nvHFH.js";
|
|
3
|
-
import {
|
|
4
|
-
import { B as
|
|
5
|
-
import { c as
|
|
6
|
-
import { Suspense, lazy, useEffect, useRef, useState } from "react";
|
|
3
|
+
import { c as useLang, l as useTranslate, o as I18nProvider, u as useVal } from "./dist-BFmpkX4P.js";
|
|
4
|
+
import { B as FlowChangeError, Ci as cn, E as FieldLabel, Q as nodeInputMappings, S as Field, T as FieldGroup, V as applyFlowChanges$1, Z as mapConditionSources, a as DialogDescription, at as dequal$1, c as DialogTitle, d as TooltipContent, i as DialogContent, lr as Input, n as Dialog, o as DialogFooter, p as TooltipTrigger, q as resourceNameIssue, r as DialogClose, s as DialogHeader, t as Icon, u as Tooltip, w as FieldError, x as Spinner, xi as Button } from "./icons-Db2Jb2iX.js";
|
|
5
|
+
import { c as importedWorkflowName, d as uiLanguageNames, f as uiLanguages, l as isUiLanguage, u as resolveUiLanguage } from "./value-BADHeZ9I.js";
|
|
6
|
+
import { Suspense, forwardRef, lazy, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from "react";
|
|
7
7
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
import * as Cause from "effect/Cause";
|
|
9
9
|
import * as Effect from "effect/Effect";
|
|
@@ -95,11 +95,17 @@ var NavigationStore = class {
|
|
|
95
95
|
this.#syncing = false;
|
|
96
96
|
this.#write(view, false, { runSource });
|
|
97
97
|
}
|
|
98
|
+
async importFlow(file, name, key, importer) {
|
|
99
|
+
return await this.#openNewFlow(() => this.#store.importFlow(file, name, key, importer));
|
|
100
|
+
}
|
|
98
101
|
async createFlow(name, create) {
|
|
102
|
+
return await this.#openNewFlow(() => this.#store.createFlow(name, create));
|
|
103
|
+
}
|
|
104
|
+
async #openNewFlow(create) {
|
|
99
105
|
const change = ++this.#change;
|
|
100
106
|
this.#syncing = true;
|
|
101
107
|
try {
|
|
102
|
-
const created = await
|
|
108
|
+
const created = await create();
|
|
103
109
|
if (created && change == this.#change) this.#write("design", false);
|
|
104
110
|
return created;
|
|
105
111
|
} finally {
|
|
@@ -184,7 +190,7 @@ function Skeleton({ className, ...props }) {
|
|
|
184
190
|
}
|
|
185
191
|
//#endregion
|
|
186
192
|
//#region src/workbench/browser/runtime/shell/resourceBrowser.tsx
|
|
187
|
-
var CreateResourceDialog = lazy(() => import("./createResourceDialog-
|
|
193
|
+
var CreateResourceDialog = lazy(() => import("./createResourceDialog-BAJXbzNH.js"));
|
|
188
194
|
var flowIdTooltipAlignOffset = 44;
|
|
189
195
|
var renamePopoverAlignOffset = -12;
|
|
190
196
|
var renamePopoverVerticalShift = 8;
|
|
@@ -531,6 +537,10 @@ function FlowItem({ showTeam, badge, busy, flow, href, onSelect, store }) {
|
|
|
531
537
|
}), t(flow.live.enabled ? "resource.stop" : "resource.start")]
|
|
532
538
|
}),
|
|
533
539
|
/* @__PURE__ */ jsx(DropdownMenuSeparator, { className: "mx-2 bg-border/50" }),
|
|
540
|
+
/* @__PURE__ */ jsx(WorkflowExportMenuItem, {
|
|
541
|
+
disabled: flow.status != "active" || busy != null,
|
|
542
|
+
onClick: () => void store.workspace.exportFlow(flow.flowId)
|
|
543
|
+
}),
|
|
534
544
|
/* @__PURE__ */ jsxs(DropdownMenuItem, {
|
|
535
545
|
disabled: flow.status != "active",
|
|
536
546
|
onClick: () => onSelect(flow, "publications"),
|
|
@@ -622,7 +632,7 @@ function FlowSkeleton({ showTeam }) {
|
|
|
622
632
|
})]
|
|
623
633
|
});
|
|
624
634
|
}
|
|
625
|
-
function FlowBrowser({ catalogWidth, createFlowDisabled, createFlowField, flowBadges, hrefForFlow, initializing = false, onCreateFlow, onSelectFlow, store }) {
|
|
635
|
+
var FlowBrowser = forwardRef(function FlowBrowser({ catalogWidth, createFlowDisabled, createFlowField, flowBadges, hrefForFlow, initializing = false, onCreateFlow, onImportFlow, onSelectFlow, store, language }, ref) {
|
|
626
636
|
const t = useTranslate();
|
|
627
637
|
const busy = useVal(store.workspace.$.busy);
|
|
628
638
|
const loadFailed = useVal(store.workspace.$.flowLoadFailed);
|
|
@@ -634,17 +644,54 @@ function FlowBrowser({ catalogWidth, createFlowDisabled, createFlowField, flowBa
|
|
|
634
644
|
const refreshing = useVal(store.workspace.$.flowRefreshing);
|
|
635
645
|
const flows = useVal(store.workspace.$.flows);
|
|
636
646
|
const total = useVal(store.workspace.$.flowTotal);
|
|
637
|
-
const [
|
|
647
|
+
const [creation$] = useState(() => val(void 0));
|
|
648
|
+
const creation = useVal(creation$);
|
|
649
|
+
const [importError, setImportError] = useState(false);
|
|
650
|
+
const fileInput = useRef(null);
|
|
638
651
|
const [filter, setFilter] = useState("");
|
|
639
652
|
const [name, setName] = useState("");
|
|
640
653
|
const showTeam = flows.some((flow) => (flowBadges?.[flow.flowId]?.trim().length ?? 0) > 0);
|
|
641
654
|
const normalized = filter.trim().toLocaleLowerCase();
|
|
642
655
|
const visible = flows.filter((flow) => flow.name.toLocaleLowerCase().includes(normalized));
|
|
656
|
+
const command = useRef();
|
|
657
|
+
useImperativeHandle(ref, () => ({ openImport: (input) => command.current?.(input) ?? "unavailable" }), []);
|
|
658
|
+
useLayoutEffect(() => {
|
|
659
|
+
command.current = openImport;
|
|
660
|
+
return () => {
|
|
661
|
+
command.current = void 0;
|
|
662
|
+
};
|
|
663
|
+
});
|
|
664
|
+
function openImport(input) {
|
|
665
|
+
if (initializing || store.workspace.$.busy.value != null || creation$.value != null || onImportFlow == null) return "unavailable";
|
|
666
|
+
setImportError(false);
|
|
667
|
+
let file;
|
|
668
|
+
try {
|
|
669
|
+
file = parseWorkflowFile(input.text);
|
|
670
|
+
} catch {
|
|
671
|
+
setImportError(true);
|
|
672
|
+
return "invalid-file";
|
|
673
|
+
}
|
|
674
|
+
setName(file.name ?? (input.fileName == null ? importedWorkflowName(language) : workflowNameFromFile(input.fileName)));
|
|
675
|
+
creation$.set({
|
|
676
|
+
kind: "import",
|
|
677
|
+
file,
|
|
678
|
+
key: randomId(),
|
|
679
|
+
...input.sourceUrl == null ? {} : { sourceUrl: input.sourceUrl }
|
|
680
|
+
});
|
|
681
|
+
return "opened";
|
|
682
|
+
}
|
|
683
|
+
function openCreate() {
|
|
684
|
+
if (creation$.value != null) return;
|
|
685
|
+
setName("");
|
|
686
|
+
creation$.set({ kind: "create" });
|
|
687
|
+
}
|
|
643
688
|
async function create(event) {
|
|
644
689
|
event.preventDefault();
|
|
690
|
+
const request = creation$.value;
|
|
645
691
|
const nextName = name.trim();
|
|
646
|
-
if (
|
|
647
|
-
|
|
692
|
+
if (request == null || resourceNameIssue(nextName) != null) return;
|
|
693
|
+
if (!(request.kind == "create" ? await onCreateFlow(nextName) : await onImportFlow?.(request.file, nextName, request.key)) || command.current == null || creation$.value !== request) return;
|
|
694
|
+
creation$.set(void 0);
|
|
648
695
|
setName("");
|
|
649
696
|
}
|
|
650
697
|
return /* @__PURE__ */ jsx("main", {
|
|
@@ -675,30 +722,61 @@ function FlowBrowser({ catalogWidth, createFlowDisabled, createFlowField, flowBa
|
|
|
675
722
|
}), !loading && /* @__PURE__ */ jsx("span", { children: t("resource.flowCount", { count: total ?? flows.length }) })]
|
|
676
723
|
}), /* @__PURE__ */ jsxs("div", {
|
|
677
724
|
className: "resource-list-actions",
|
|
678
|
-
children: [
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
725
|
+
children: [
|
|
726
|
+
/* @__PURE__ */ jsxs(InputGroup, {
|
|
727
|
+
className: "w-full sm:w-56",
|
|
728
|
+
children: [/* @__PURE__ */ jsx(InputGroupAddon, { children: /* @__PURE__ */ jsx(Icon, {
|
|
729
|
+
name: "search",
|
|
730
|
+
size: 17
|
|
731
|
+
}) }), /* @__PURE__ */ jsx(InputGroupInput, {
|
|
732
|
+
autoComplete: "off",
|
|
733
|
+
"aria-label": t("resource.searchByName"),
|
|
734
|
+
name: "flow-search",
|
|
735
|
+
onChange: (event) => setFilter(event.target.value),
|
|
736
|
+
placeholder: t("resource.searchByName"),
|
|
737
|
+
value: filter
|
|
738
|
+
})]
|
|
739
|
+
}),
|
|
740
|
+
onImportFlow != null && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Input, {
|
|
741
|
+
ref: fileInput,
|
|
742
|
+
className: "hidden",
|
|
743
|
+
type: "file",
|
|
744
|
+
accept: ".openflow.json,.json,application/json",
|
|
745
|
+
"aria-label": t("resource.importFlow"),
|
|
746
|
+
onChange: (event) => {
|
|
747
|
+
const file = event.target.files?.[0];
|
|
748
|
+
event.target.value = "";
|
|
749
|
+
if (file == null) return;
|
|
750
|
+
setImportError(false);
|
|
751
|
+
file.text().then((text) => {
|
|
752
|
+
command.current?.({
|
|
753
|
+
text,
|
|
754
|
+
fileName: file.name
|
|
755
|
+
});
|
|
756
|
+
}).catch(() => setImportError(true));
|
|
757
|
+
}
|
|
758
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
759
|
+
variant: "outline",
|
|
760
|
+
disabled: initializing || busy != null || createFlowDisabled,
|
|
761
|
+
onClick: () => fileInput.current?.click(),
|
|
762
|
+
children: t("resource.importFlow")
|
|
763
|
+
})] }),
|
|
764
|
+
/* @__PURE__ */ jsxs(Button, {
|
|
765
|
+
className: "pr-3",
|
|
766
|
+
disabled: initializing || busy != null,
|
|
767
|
+
onClick: openCreate,
|
|
768
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
769
|
+
"data-icon": "inline-start",
|
|
770
|
+
name: "plus"
|
|
771
|
+
}), t("resource.newFlow")]
|
|
772
|
+
})
|
|
773
|
+
]
|
|
700
774
|
})]
|
|
701
775
|
}),
|
|
776
|
+
importError && /* @__PURE__ */ jsx("p", {
|
|
777
|
+
role: "alert",
|
|
778
|
+
children: t("resource.importInvalid")
|
|
779
|
+
}),
|
|
702
780
|
/* @__PURE__ */ jsx("div", {
|
|
703
781
|
className: "resource-table-scroll",
|
|
704
782
|
children: /* @__PURE__ */ jsxs("div", {
|
|
@@ -762,7 +840,7 @@ function FlowBrowser({ catalogWidth, createFlowDisabled, createFlowField, flowBa
|
|
|
762
840
|
/* @__PURE__ */ jsx(EmptyTitle, { children: t(normalized.length == 0 ? "resource.noFlows" : "resource.noMatchingFlows") }),
|
|
763
841
|
/* @__PURE__ */ jsx(EmptyDescription, { children: t(normalized.length == 0 ? "resource.noFlowsDescription" : "resource.noMatchingDescription") })
|
|
764
842
|
] }), normalized.length == 0 && /* @__PURE__ */ jsx(EmptyContent, { children: /* @__PURE__ */ jsxs(Button, {
|
|
765
|
-
onClick:
|
|
843
|
+
onClick: openCreate,
|
|
766
844
|
variant: "outline",
|
|
767
845
|
children: [/* @__PURE__ */ jsx(Icon, {
|
|
768
846
|
"data-icon": "inline-start",
|
|
@@ -792,7 +870,7 @@ function FlowBrowser({ catalogWidth, createFlowDisabled, createFlowField, flowBa
|
|
|
792
870
|
})
|
|
793
871
|
]
|
|
794
872
|
}),
|
|
795
|
-
|
|
873
|
+
creation != null && /* @__PURE__ */ jsx(Suspense, {
|
|
796
874
|
fallback: null,
|
|
797
875
|
children: /* @__PURE__ */ jsx(CreateResourceDialog, {
|
|
798
876
|
disabled: createFlowDisabled,
|
|
@@ -802,16 +880,23 @@ function FlowBrowser({ catalogWidth, createFlowDisabled, createFlowField, flowBa
|
|
|
802
880
|
label: t("resource.flowName"),
|
|
803
881
|
name,
|
|
804
882
|
onNameChange: setName,
|
|
805
|
-
onOpenChange:
|
|
883
|
+
onOpenChange: (open) => {
|
|
884
|
+
if (!open) {
|
|
885
|
+
creation$.set(void 0);
|
|
886
|
+
setName("");
|
|
887
|
+
}
|
|
888
|
+
},
|
|
806
889
|
onSubmit: (event) => void create(event),
|
|
807
890
|
pending: busy == "flow",
|
|
808
|
-
|
|
891
|
+
sourceUrl: creation.kind == "import" ? creation.sourceUrl : void 0,
|
|
892
|
+
submitLabel: creation.kind == "import" ? t("resource.importFlow") : void 0,
|
|
893
|
+
title: t(creation.kind == "create" ? "resource.newFlow" : "resource.importFlow")
|
|
809
894
|
})
|
|
810
895
|
})
|
|
811
896
|
]
|
|
812
897
|
})
|
|
813
898
|
});
|
|
814
|
-
}
|
|
899
|
+
});
|
|
815
900
|
//#endregion
|
|
816
901
|
//#region ../../node_modules/.bun/dequal@2.0.3/node_modules/dequal/dist/index.mjs
|
|
817
902
|
var has = Object.prototype.hasOwnProperty;
|
|
@@ -1542,7 +1627,7 @@ function inputSignature(spec) {
|
|
|
1542
1627
|
}
|
|
1543
1628
|
async function inputEditor(spec, language, values) {
|
|
1544
1629
|
if (spec == null) return void 0;
|
|
1545
|
-
const { FlowRunInputEditorStore } = await import("./flowRunInputEditorStore-
|
|
1630
|
+
const { FlowRunInputEditorStore } = await import("./flowRunInputEditorStore-B2Rw4VsT.js").then((n) => n.t);
|
|
1546
1631
|
const editor = new FlowRunInputEditorStore(spec.definitions, language);
|
|
1547
1632
|
const initial = values ?? spec.samples;
|
|
1548
1633
|
if (initial != null) editor.replaceValues(initial);
|
|
@@ -2506,116 +2591,6 @@ function getConnectionsCache(options) {
|
|
|
2506
2591
|
return getSingleton(singletonKey(oomolNamespaces.connections, options, [query.ownerId], options.sessionId), () => createConnectionsCacheInternal(options, validated));
|
|
2507
2592
|
}
|
|
2508
2593
|
//#endregion
|
|
2509
|
-
//#region src/connector/common/actionSchema.ts
|
|
2510
|
-
function connectorActionPorts(inputSchema, outputSchema) {
|
|
2511
|
-
const inputs = inputPorts(inputSchema);
|
|
2512
|
-
return {
|
|
2513
|
-
inputs,
|
|
2514
|
-
initialInputs: inputs.flatMap((input) => input.value === void 0 ? [] : [{
|
|
2515
|
-
handle: input.handle,
|
|
2516
|
-
value: input.value
|
|
2517
|
-
}]),
|
|
2518
|
-
outputs: outputPorts(outputSchema)
|
|
2519
|
-
};
|
|
2520
|
-
}
|
|
2521
|
-
function inputPorts(schema) {
|
|
2522
|
-
const root = toPlainObject(schema);
|
|
2523
|
-
if (root == null || root.type != "object" && root.properties == null) throw new Error("Connector action inputSchema must be an object schema.");
|
|
2524
|
-
const properties = toPlainObject(root.properties);
|
|
2525
|
-
if (properties == null) return [];
|
|
2526
|
-
const required = stringSet(root.required);
|
|
2527
|
-
return Object.entries(properties).map(([handle, propertySchema]) => {
|
|
2528
|
-
const nullable = !required.has(handle) || schemaAllowsNull(propertySchema, root);
|
|
2529
|
-
return {
|
|
2530
|
-
description: schemaDescription(root, propertySchema),
|
|
2531
|
-
handle,
|
|
2532
|
-
json_schema: propertySchemaWithDefinitions(root, propertySchema),
|
|
2533
|
-
nullable,
|
|
2534
|
-
value: schemaDefault(root, propertySchema, nullable)
|
|
2535
|
-
};
|
|
2536
|
-
});
|
|
2537
|
-
}
|
|
2538
|
-
function outputPorts(schema) {
|
|
2539
|
-
const root = toPlainObject(schema);
|
|
2540
|
-
const properties = toPlainObject(root?.properties);
|
|
2541
|
-
if (root != null && (root.type == "object" || properties != null)) {
|
|
2542
|
-
if (properties == null) return [];
|
|
2543
|
-
const required = stringSet(root.required);
|
|
2544
|
-
return Object.entries(properties).map(([handle, propertySchema]) => ({
|
|
2545
|
-
description: schemaDescription(root, propertySchema),
|
|
2546
|
-
handle,
|
|
2547
|
-
json_schema: propertySchemaWithDefinitions(root, propertySchema),
|
|
2548
|
-
nullable: !required.has(handle) || schemaAllowsNull(propertySchema, root)
|
|
2549
|
-
}));
|
|
2550
|
-
} else return [{
|
|
2551
|
-
description: schemaDescription(root, schema),
|
|
2552
|
-
handle: "output",
|
|
2553
|
-
json_schema: schema,
|
|
2554
|
-
nullable: schemaAllowsNull(schema)
|
|
2555
|
-
}];
|
|
2556
|
-
}
|
|
2557
|
-
function propertySchemaWithDefinitions(root, schema) {
|
|
2558
|
-
const property = toPlainObject(schema);
|
|
2559
|
-
if (property == null) return schema;
|
|
2560
|
-
const result = Object.assign({}, property);
|
|
2561
|
-
if (result.$defs == null && root.$defs != null) result.$defs = root.$defs;
|
|
2562
|
-
if (result.definitions == null && root.definitions != null) result.definitions = root.definitions;
|
|
2563
|
-
return result;
|
|
2564
|
-
}
|
|
2565
|
-
function schemaDescription(root, schema) {
|
|
2566
|
-
for (const object of referencedSchemas(root, schema)) if (typeof object.description == "string") return object.description;
|
|
2567
|
-
}
|
|
2568
|
-
function schemaDefault(root, schema, nullable) {
|
|
2569
|
-
for (const object of referencedSchemas(root, schema)) if (Object.hasOwn(object, "default")) return object.default;
|
|
2570
|
-
return nullable ? null : void 0;
|
|
2571
|
-
}
|
|
2572
|
-
function stringSet(value) {
|
|
2573
|
-
if (!Array.isArray(value)) return /* @__PURE__ */ new Set();
|
|
2574
|
-
return new Set(value.filter((item) => typeof item == "string"));
|
|
2575
|
-
}
|
|
2576
|
-
function schemaAllowsNull(schema, root = schema, references = /* @__PURE__ */ new Set()) {
|
|
2577
|
-
const object = toPlainObject(schema);
|
|
2578
|
-
if (object == null) return false;
|
|
2579
|
-
if (Object.hasOwn(object, "type")) return object.type == "null" || Array.isArray(object.type) && object.type.includes("null");
|
|
2580
|
-
if (Object.hasOwn(object, "enum")) return Array.isArray(object.enum) && object.enum.includes(null);
|
|
2581
|
-
for (const key of ["anyOf", "oneOf"]) if (Object.hasOwn(object, key)) return Array.isArray(object[key]) && object[key].some((item) => schemaAllowsNull(item, root, references));
|
|
2582
|
-
const reference = typeof object.$ref == "string" ? object.$ref : void 0;
|
|
2583
|
-
if (reference == null || references.has(reference)) return false;
|
|
2584
|
-
const target = resolveLocalReference(root, reference);
|
|
2585
|
-
if (target === void 0) return false;
|
|
2586
|
-
const nextReferences = new Set(references);
|
|
2587
|
-
nextReferences.add(reference);
|
|
2588
|
-
return schemaAllowsNull(target, root, nextReferences);
|
|
2589
|
-
}
|
|
2590
|
-
function referencedSchemas(root, schema) {
|
|
2591
|
-
const result = [];
|
|
2592
|
-
const references = /* @__PURE__ */ new Set();
|
|
2593
|
-
let current = schema;
|
|
2594
|
-
while (true) {
|
|
2595
|
-
const object = toPlainObject(current);
|
|
2596
|
-
if (object == null) return result;
|
|
2597
|
-
result.push(object);
|
|
2598
|
-
const reference = typeof object.$ref == "string" ? object.$ref : void 0;
|
|
2599
|
-
if (reference == null || references.has(reference)) return result;
|
|
2600
|
-
const target = resolveLocalReference(root, reference);
|
|
2601
|
-
if (target === void 0) return result;
|
|
2602
|
-
references.add(reference);
|
|
2603
|
-
current = target;
|
|
2604
|
-
}
|
|
2605
|
-
}
|
|
2606
|
-
function resolveLocalReference(root, reference) {
|
|
2607
|
-
if (reference == "#") return root;
|
|
2608
|
-
if (!reference.startsWith("#/")) return void 0;
|
|
2609
|
-
let current = root;
|
|
2610
|
-
for (const encodedToken of reference.slice(2).split("/")) {
|
|
2611
|
-
const object = toPlainObject(current);
|
|
2612
|
-
const token = encodedToken.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
2613
|
-
if (object == null || !Object.hasOwn(object, token)) return void 0;
|
|
2614
|
-
current = object[token];
|
|
2615
|
-
}
|
|
2616
|
-
return current;
|
|
2617
|
-
}
|
|
2618
|
-
//#endregion
|
|
2619
2594
|
//#region src/workbench/browser/runtime/stores/proxyCatalog.ts
|
|
2620
2595
|
/** Validate the fields we consume without discarding upstream representation fields. */
|
|
2621
2596
|
function proxyResponse(value, validate) {
|
|
@@ -4903,12 +4878,6 @@ var FlowCatalog = class {
|
|
|
4903
4878
|
this.#pending.delete(flow.flowId);
|
|
4904
4879
|
}
|
|
4905
4880
|
}
|
|
4906
|
-
async create(name) {
|
|
4907
|
-
const flow = await this.#client.createFlow(name);
|
|
4908
|
-
if (this.#disposed) return;
|
|
4909
|
-
this.insert(flow);
|
|
4910
|
-
return flow;
|
|
4911
|
-
}
|
|
4912
4881
|
include(flow) {
|
|
4913
4882
|
const index = this.#state.value.flows.findIndex((candidate) => candidate.flowId == flow.flowId);
|
|
4914
4883
|
if (index < 0) {
|
|
@@ -5092,6 +5061,7 @@ var PresentationChanges = class {
|
|
|
5092
5061
|
#changes = Promise.resolve();
|
|
5093
5062
|
#committed;
|
|
5094
5063
|
#disposed = false;
|
|
5064
|
+
#failed = false;
|
|
5095
5065
|
#pending = [];
|
|
5096
5066
|
constructor(client, setNotice, setPresentation, i18n) {
|
|
5097
5067
|
this.#client = client;
|
|
@@ -5100,6 +5070,7 @@ var PresentationChanges = class {
|
|
|
5100
5070
|
this.#i18n = i18n;
|
|
5101
5071
|
}
|
|
5102
5072
|
reset(presentation) {
|
|
5073
|
+
this.#failed = false;
|
|
5103
5074
|
this.#committed = presentation;
|
|
5104
5075
|
this.#pending = [];
|
|
5105
5076
|
}
|
|
@@ -5107,8 +5078,16 @@ var PresentationChanges = class {
|
|
|
5107
5078
|
this.#disposed = true;
|
|
5108
5079
|
this.#pending = [];
|
|
5109
5080
|
}
|
|
5081
|
+
async flush() {
|
|
5082
|
+
await this.settled();
|
|
5083
|
+
return !this.#failed && !this.#disposed;
|
|
5084
|
+
}
|
|
5110
5085
|
async settled() {
|
|
5111
|
-
|
|
5086
|
+
let pending;
|
|
5087
|
+
do {
|
|
5088
|
+
pending = this.#changes;
|
|
5089
|
+
await pending;
|
|
5090
|
+
} while (pending !== this.#changes);
|
|
5112
5091
|
}
|
|
5113
5092
|
async change(flowId, presentation, current, update) {
|
|
5114
5093
|
if (this.#disposed || this.#committed == null) return false;
|
|
@@ -5141,6 +5120,7 @@ var PresentationChanges = class {
|
|
|
5141
5120
|
success = true;
|
|
5142
5121
|
} catch (error) {
|
|
5143
5122
|
if (this.#disposed || !current()) return;
|
|
5123
|
+
this.#failed = true;
|
|
5144
5124
|
if (error instanceof ApiError && error.code == "flow.presentation-conflict") try {
|
|
5145
5125
|
const latest = await this.#client.getPresentation(flowId);
|
|
5146
5126
|
if (this.#disposed || !current()) return;
|
|
@@ -5555,14 +5535,49 @@ var WorkspaceStore = class {
|
|
|
5555
5535
|
});
|
|
5556
5536
|
return true;
|
|
5557
5537
|
}
|
|
5558
|
-
async
|
|
5538
|
+
async exportFlow(flowId) {
|
|
5539
|
+
const current = this.#draftSession.capture();
|
|
5540
|
+
const selected = this.#model.value.flowId == flowId;
|
|
5541
|
+
if (selected && (!await this.saveDraft() || !await this.#presentationChanges.flush() || !current())) {
|
|
5542
|
+
this.#setNotice({
|
|
5543
|
+
kind: "error",
|
|
5544
|
+
message: this.#i18n.t("notice.exportSaveFailed")
|
|
5545
|
+
});
|
|
5546
|
+
return;
|
|
5547
|
+
}
|
|
5548
|
+
this.#set({ busy: "flow" });
|
|
5549
|
+
try {
|
|
5550
|
+
const file = await this.#client.exportFlow(flowId);
|
|
5551
|
+
if (this.#disposed || selected && !current()) return;
|
|
5552
|
+
const url = URL.createObjectURL(new Blob([encodeWorkflowFile(file)], { type: "application/json;charset=utf-8" }));
|
|
5553
|
+
const link = document.createElement("a");
|
|
5554
|
+
link.href = url;
|
|
5555
|
+
link.download = workflowFileName(file.name ?? "workflow");
|
|
5556
|
+
link.click();
|
|
5557
|
+
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
5558
|
+
} catch (error) {
|
|
5559
|
+
if (!this.#disposed) this.#setNotice(errorNotice(error, this.#i18n.t));
|
|
5560
|
+
} finally {
|
|
5561
|
+
this.#set({ busy: void 0 });
|
|
5562
|
+
}
|
|
5563
|
+
}
|
|
5564
|
+
createFlow(name, create) {
|
|
5565
|
+
return this.#createFlow(async () => create == null ? this.#client.createFlow(name) : this.#client.getFlow(await create(name)));
|
|
5566
|
+
}
|
|
5567
|
+
importFlow(file, name, key, importer) {
|
|
5568
|
+
return this.#createFlow(async () => importer == null ? this.#client.importFlow(file, {
|
|
5569
|
+
name,
|
|
5570
|
+
idempotencyKey: key
|
|
5571
|
+
}) : this.#client.getFlow(await importer(file, name, key)));
|
|
5572
|
+
}
|
|
5573
|
+
async #createFlow(create) {
|
|
5559
5574
|
if (!await this.saveModuleEditor()) return;
|
|
5560
5575
|
this.#set({ busy: "flow" });
|
|
5561
5576
|
try {
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
this.#flows.insert(
|
|
5565
|
-
return
|
|
5577
|
+
const created = await create();
|
|
5578
|
+
if (this.#disposed) return;
|
|
5579
|
+
this.#flows.insert(created);
|
|
5580
|
+
return created;
|
|
5566
5581
|
} catch (error) {
|
|
5567
5582
|
if (!this.#disposed) this.#setNotice(errorNotice(error, this.#i18n.t));
|
|
5568
5583
|
} finally {
|
|
@@ -6607,13 +6622,18 @@ var WorkbenchStore = class {
|
|
|
6607
6622
|
this.#openingCreatedFlow = false;
|
|
6608
6623
|
}
|
|
6609
6624
|
}
|
|
6625
|
+
async importFlow(file, name, key, importer) {
|
|
6626
|
+
return await this.#openNewFlow(await this.workspace.importFlow(file, name, key, importer), "notice.flowImported");
|
|
6627
|
+
}
|
|
6610
6628
|
async createFlow(name, create) {
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
|
|
6629
|
+
return await this.#openNewFlow(await this.workspace.createFlow(name, create), "notice.created");
|
|
6630
|
+
}
|
|
6631
|
+
async #openNewFlow(created, notice) {
|
|
6632
|
+
if (this.#disposed || created == null) return false;
|
|
6633
|
+
await this.selectFlow(created.flowId);
|
|
6614
6634
|
if (!this.#disposed) this.#notice.set({
|
|
6615
6635
|
kind: "success",
|
|
6616
|
-
message: this.#i18n.t(
|
|
6636
|
+
message: this.#i18n.t(notice, { name: created.name })
|
|
6617
6637
|
});
|
|
6618
6638
|
return true;
|
|
6619
6639
|
}
|
|
@@ -6793,7 +6813,7 @@ var WorkbenchStore = class {
|
|
|
6793
6813
|
};
|
|
6794
6814
|
//#endregion
|
|
6795
6815
|
//#region src/workbench/browser/runtime/openFlowWorkbench.tsx
|
|
6796
|
-
var FlowWorkspace = lazy(() => import("./flowWorkspace-
|
|
6816
|
+
var FlowWorkspace = lazy(() => import("./flowWorkspace-B7a5NNA_.js"));
|
|
6797
6817
|
function OpenFlowSessionGate({ action, description, error, onSubmit, onTokenChange, pending = false, title, token, tokenLabel }) {
|
|
6798
6818
|
const hasToken = token != null && tokenLabel != null && onTokenChange != null;
|
|
6799
6819
|
const tokenValue = token ?? "";
|
|
@@ -6899,11 +6919,12 @@ function FlowNameBridge({ store, onChange }) {
|
|
|
6899
6919
|
useEffect(() => () => onChange(void 0), [onChange]);
|
|
6900
6920
|
return null;
|
|
6901
6921
|
}
|
|
6902
|
-
function Workbench({ catalogWidth, createFlow, createFlowDisabled, createFlowField, flowBadges, connectionHref, hrefFor, initializing, language, navigation, onConfigureConnector, onManageConnectorAccess, onLanguageChange, store, theme }) {
|
|
6922
|
+
function Workbench({ importRef, catalogWidth, createFlow, importFlow, createFlowDisabled, createFlowField, flowBadges, connectionHref, hrefFor, initializing, language, navigation, onConfigureConnector, onManageConnectorAccess, onLanguageChange, store, theme }) {
|
|
6903
6923
|
const flowId = useVal(store.workspace.$.flowId);
|
|
6904
6924
|
return /* @__PURE__ */ jsx("div", {
|
|
6905
6925
|
className: "app-shell",
|
|
6906
6926
|
children: flowId == null ? /* @__PURE__ */ jsx(FlowBrowser, {
|
|
6927
|
+
ref: importRef,
|
|
6907
6928
|
catalogWidth,
|
|
6908
6929
|
createFlowDisabled,
|
|
6909
6930
|
createFlowField,
|
|
@@ -6915,6 +6936,7 @@ function Workbench({ catalogWidth, createFlow, createFlowDisabled, createFlowFie
|
|
|
6915
6936
|
initializing,
|
|
6916
6937
|
language,
|
|
6917
6938
|
onCreateFlow: (name) => navigation.createFlow(name, createFlow),
|
|
6939
|
+
onImportFlow: (file, name, key) => navigation.importFlow(file, name, key, importFlow),
|
|
6918
6940
|
onLanguageChange,
|
|
6919
6941
|
onSelectFlow: (flow, view) => void navigation.selectFlow(flow, view),
|
|
6920
6942
|
store
|
|
@@ -6935,7 +6957,9 @@ function Workbench({ catalogWidth, createFlow, createFlowDisabled, createFlowFie
|
|
|
6935
6957
|
})
|
|
6936
6958
|
});
|
|
6937
6959
|
}
|
|
6938
|
-
function Session({ catalogWidth, createFlow, createFlowDisabled, createFlowField, flowBadges, connectionHref, host, hrefFor, language, location, onConfigureConnector, onManageConnectorAccess, onLanguageChange, onNavigate, onFlowNameChange, preferences, sessionKey, theme, variables = true }) {
|
|
6960
|
+
var Session = forwardRef(function Session({ catalogWidth, createFlow, importFlow, createFlowDisabled, createFlowField, flowBadges, connectionHref, host, hrefFor, language, location, onConfigureConnector, onManageConnectorAccess, onLanguageChange, onNavigate, onFlowNameChange, preferences, sessionKey, theme, variables = true }, ref) {
|
|
6961
|
+
const importRef = useRef(null);
|
|
6962
|
+
useImperativeHandle(ref, () => ({ openImport: (input) => importRef.current?.openImport(input) ?? "unavailable" }), []);
|
|
6939
6963
|
const navigate = useRef(onNavigate);
|
|
6940
6964
|
navigate.current = onNavigate;
|
|
6941
6965
|
const [{ i18n, navigation, store }] = useState(() => {
|
|
@@ -6999,8 +7023,10 @@ function Session({ catalogWidth, createFlow, createFlowDisabled, createFlowField
|
|
|
6999
7023
|
onChange: onFlowNameChange
|
|
7000
7024
|
}),
|
|
7001
7025
|
started || location.flowId == null ? /* @__PURE__ */ jsx(Workbench, {
|
|
7026
|
+
importRef: location.flowId == null ? importRef : void 0,
|
|
7002
7027
|
catalogWidth,
|
|
7003
7028
|
createFlow,
|
|
7029
|
+
importFlow,
|
|
7004
7030
|
createFlowDisabled,
|
|
7005
7031
|
createFlowField,
|
|
7006
7032
|
flowBadges,
|
|
@@ -7022,12 +7048,13 @@ function Session({ catalogWidth, createFlow, createFlowDisabled, createFlowField
|
|
|
7022
7048
|
})
|
|
7023
7049
|
})
|
|
7024
7050
|
});
|
|
7025
|
-
}
|
|
7026
|
-
function OpenFlowWorkbench({ sessionKey, ...props }) {
|
|
7051
|
+
});
|
|
7052
|
+
var OpenFlowWorkbench = forwardRef(function OpenFlowWorkbench({ sessionKey, ...props }, ref) {
|
|
7027
7053
|
return /* @__PURE__ */ jsx(Session, {
|
|
7054
|
+
ref,
|
|
7028
7055
|
sessionKey,
|
|
7029
7056
|
...props
|
|
7030
7057
|
}, `${sessionKey}:${props.host.connectorOwnerId ?? ""}`);
|
|
7031
|
-
}
|
|
7058
|
+
});
|
|
7032
7059
|
//#endregion
|
|
7033
7060
|
export { EventSourcesPage, OpenFlowSessionGate, OpenFlowWorkbench, isUiLanguage as isWorkbenchLanguage, resolveUiLanguage as resolveWorkbenchLanguage, uiLanguageNames as workbenchLanguageNames, uiLanguages as workbenchLanguages };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { At as SelectValue, Ci as cn, Ct as Select, Dt as SelectItem, Et as SelectGroup, Tt as SelectContent, kt as SelectTrigger } from "./icons-Db2Jb2iX.js";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
//#region src/workbench/browser/runtime/shell/workbenchSelect.tsx
|
|
4
4
|
function WorkbenchSelect({ ariaLabel, className, disabled = false, id, onValueChange, options, portalRoot, size, value, variant }) {
|