@oomol-lab/open-flow 0.1.0-beta.51 → 0.1.0-beta.53

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 (45) hide show
  1. package/dist/browser/{createResourceDialog-BDtXpRSt.js → createResourceDialog-BsaBMf7_.js} +2 -1
  2. package/dist/browser/flow-authoring.js +46 -3
  3. package/dist/browser/flow-change.d.ts +6 -1
  4. package/dist/browser/flow-change.js +46 -3
  5. package/dist/browser/{flowChanges-BWSXSnMX.js → flowChanges-CcscgZsW.js} +3492 -1939
  6. package/dist/browser/{flowWorkspace-DBaq2Eks.js → flowWorkspace-CoT_ewLX.js} +904 -330
  7. package/dist/browser/{workbenchSelect-C9kwcUmN.js → icons-0s-Q_3lp.js} +48 -32
  8. package/dist/browser/licenses.md +204 -0
  9. package/dist/browser/preview.css +282 -179
  10. package/dist/browser/preview.js +4311 -2200
  11. package/dist/browser/theme.css +2 -0
  12. package/dist/browser/ui-hostNavigationActions.d.ts +13 -0
  13. package/dist/browser/ui-hostTooltip.d.ts +8 -0
  14. package/dist/browser/ui-logo.d.ts +5 -0
  15. package/dist/browser/ui.css +82 -8
  16. package/dist/browser/ui.d.ts +3 -0
  17. package/dist/browser/ui.js +172 -8
  18. package/dist/browser/workbench-contract.d.ts +4 -11
  19. package/dist/browser/workbench.css +346 -200
  20. package/dist/browser/workbench.d.ts +1 -1
  21. package/dist/browser/workbench.js +1056 -367
  22. package/dist/browser/workbenchSelect-BqUPacsr.js +31 -0
  23. package/dist/common/authoringExamples.d.ts +4 -3
  24. package/dist/common/connector-proxy.d.ts +32 -0
  25. package/dist/common/control-api-conformance.js +54 -3
  26. package/dist/common/control-api.d.ts +6 -0
  27. package/dist/common/control-api.js +58 -4
  28. package/dist/common/control-requests.d.ts +4 -0
  29. package/dist/common/control-requests.js +1299 -68
  30. package/dist/common/feishu-subscriptions.d.ts +1 -5
  31. package/dist/common/flow-connectionUsage.d.ts +1 -0
  32. package/dist/common/flow-encoding.js +34 -0
  33. package/dist/common/flow-semantics.js +675 -252
  34. package/dist/common/integration-trigger.js +23 -0
  35. package/dist/common/mcp.js +54 -3
  36. package/dist/common/openapi.d.ts +53 -0
  37. package/dist/common/openapi.js +10390 -0
  38. package/dist/common/poll-trigger.js +23 -0
  39. package/dist/common/provider-triggers.d.ts +1 -1
  40. package/dist/common/provider-triggers.js +166 -16204
  41. package/dist/common/run-events.js +1 -0
  42. package/dist/common/scheduler.d.ts +1 -1
  43. package/dist/common/scheduler.js +31 -1
  44. package/dist/common/webhook-trigger.js +23 -0
  45. package/package.json +5 -1
@@ -1,7 +1,7 @@
1
- import { $t as EmptyTitle, An as connection, At as flowDependencies, Ct as resetInputValues, Dt as setTriggerConnection, En as isJsonObject, Et as setInputSources, F as deriveAddNodeOptions, Fn as record, Ft as PopoverContent, G as resourceValue, Gt as InputGroup, H as Resource, In as string, Jt as Empty, K as designerGraph, Kt as InputGroupAddon, L as feishuResourceKind, Ln as providerIconAppearance, Mn as inputValue, Mt as followWorkbenchLink, Nn as invalidResponse, Nt as Switch, Ot as updateTriggerConfig, P as addNodeIntent, Pn as jsonValue, Pt as Popover, Qt as EmptyMedia, R as supportsFeishuChatFilter, Rn as ApiError, Rt as PopoverTitle, St as repairNodeNames, Tn as triggerOutputDefinitions, Tt as setConnectorConnection, V as scopedValue, Vn as IconThemeContext, W as resourceData, X as providerIcon, Xt as EmptyDescription, Yt as EmptyContent, Zt as EmptyHeader, _ as updateTaskAdditionalInputs, _n as WorkbenchClient, _t as setComment, a as deleteSelection, at as Latest, b as updateWebhook, bt as setNodePositions, c as setInputVariable, d as updateNodeIcon, dt as actionWithConnections, en as EventSourcesPage, f as updateNodeName, ft as connectionCatalog, g as updateTask, gn as errorNotice, gt as restoreCanvasPresentation, h as updateSubflow, ht as removeComments, i as createResource, it as revisionView, jn as connectorActionMetadata, jt as IdTooltip, kt as updateTriggerSchedule, l as updateCondition, m as updateResolution, mt as commentIds, o as nameCreatedNodes, ot as deriveInspectorDiagnostics, p as updateNodeSettings, pt as canvasPresentationChange, qt as InputGroupInput, r as applyFlowChanges, rn as createI18n, s as setInputValue, st as diagnosticItems, t as addNode, tt as RunStore, u as updateNodeDescription, v as updateTaskPorts, vn as randomId, vt as setFlowViewport, wn as sampleErrorOutputs, wt as setCodeActions, xn as decodeTriggerCatalog, xt as targetPresentation, y as updateValue, yn as allConnectorConnectionsQuery, yt as setNodeContentHidden, z as combineSources, zn as controlErrorCode, zt as PopoverTrigger } from "./flowChanges-BWSXSnMX.js";
1
+ import { $t as InputGroup, At as flowDependencies, Bn as inputValue, Bt as followWorkbenchLink, Ct as resetInputValues, Dn as allConnectorConnectionsQuery, Dt as setTriggerConnection, En as randomId, Et as setInputSources, F as deriveAddNodeOptions, G as resourceValue, Gn as providerIconAppearance, H as CacheResource, Hn as jsonValue, Ht as Popover, K as designerGraph, Kn as ApiError, Kt as PopoverTitle, L as feishuResourceKind, Mn as sampleErrorOutputs, Nn as triggerOutputDefinitions, Ot as updateTriggerConfig, P as addNodeIntent, Pn as isJsonObject, R as supportsFeishuChatFilter, Rn as connection, St as repairNodeNames, Tn as WorkbenchClient, Tt as setConnectorConnection, Un as record, Ut as PopoverContent, V as scopedValue, Vn as invalidResponse, Vt as Switch, W as resourceData, Wn as string, X as providerIcon, Yn as IconThemeContext, _ as updateTaskAdditionalInputs, _t as setComment, a as deleteSelection, an as EmptyHeader, at as Latest, b as updateWebhook, bt as setNodePositions, c as setInputVariable, cn as EventSourcesPage, d as updateNodeIcon, dn as createI18n, dt as actionWithConnections, en as InputGroupAddon, f as updateNodeName, ft as connectionCatalog, g as updateTask, gt as restoreCanvasPresentation, h as updateSubflow, ht as removeComments, i as createResource, in as EmptyDescription, it as revisionView, kn as decodeTriggerCatalog, kt as updateTriggerSchedule, l as updateCondition, m as updateResolution, mt as commentIds, nn as Empty, o as nameCreatedNodes, on as EmptyMedia, ot as deriveInspectorDiagnostics, p as updateNodeSettings, pt as canvasPresentationChange, qn as controlErrorCode, qt as PopoverTrigger, r as applyFlowChanges, rn as EmptyContent, s as setInputValue, sn as EmptyTitle, st as diagnosticItems, t as addNode, tn as InputGroupInput, tt as RunStore, u as updateNodeDescription, v as updateTaskPorts, vt as setFlowViewport, wn as errorNotice, wt as setCodeActions, xt as targetPresentation, y as updateValue, yt as setNodeContentHidden, z as combineSources, zn as connectorActionMetadata, zt as IdTooltip } from "./flowChanges-CcscgZsW.js";
2
2
  import { a as derive, i as compute, l as val } from "./dist-bO8nvHFH.js";
3
3
  import { a as useVal, i as useTranslate, r as useLang, t as I18nProvider } from "./main-BPABKzwN.js";
4
- import { D as FlowChangeError, E as FieldLabel, Fr as Button, L as mapConditionSources, Lr as cn, Mn as Input, N as portsByHandle, O as applyFlowChanges$1, P as resourceNameIssue, R as nodeInputMappings, S as Field, T as FieldGroup, a as DialogContent, c as DialogHeader, d as Tooltip, f as TooltipContent, i as DialogClose, l as DialogTitle, m as TooltipTrigger, n as Icon, o as DialogDescription, q as dequal$1, r as Dialog, s as DialogFooter, t as WorkbenchSelect, w as FieldError, x as Spinner } from "./workbenchSelect-C9kwcUmN.js";
4
+ import { C as FieldError, D as applyFlowChanges$1, E as FlowChangeError, I as mapConditionSources, Ir as cn, K as dequal$1, L as nodeInputMappings, N as resourceNameIssue, Pr as Button, T as FieldLabel, a as DialogDescription, b as Spinner, c as DialogTitle, d as TooltipContent, i as DialogContent, jn as Input, n as Dialog, o as DialogFooter, p as TooltipTrigger, r as DialogClose, s as DialogHeader, t as Icon, u as Tooltip, w as FieldGroup, x as Field } from "./icons-0s-Q_3lp.js";
5
5
  import { a as toPlainObject } from "./dist-BDBTOgS5.js";
6
6
  import { c as isUiLanguage, d as uiLanguages, l as resolveUiLanguage, u as uiLanguageNames } from "./value-DL_poNiC.js";
7
7
  import { Suspense, lazy, useEffect, useRef, useState } from "react";
@@ -196,34 +196,11 @@ function Skeleton({ className, ...props }) {
196
196
  }
197
197
  //#endregion
198
198
  //#region src/workbench/browser/runtime/shell/resourceBrowser.tsx
199
- var CreateResourceDialog = lazy(() => import("./createResourceDialog-BDtXpRSt.js"));
200
- var languageOptions = uiLanguages.map((language) => ({
201
- label: uiLanguageNames[language],
202
- value: language
203
- }));
199
+ var CreateResourceDialog = lazy(() => import("./createResourceDialog-BsaBMf7_.js"));
204
200
  var flowIdTooltipAlignOffset = 44;
205
201
  var renamePopoverAlignOffset = -12;
206
202
  var renamePopoverVerticalShift = 8;
207
203
  var rowControlSelector = "a, button, input, select, textarea, [data-slot=\"tooltip-trigger\"]";
208
- function LanguageSelect({ language, onLanguageChange }) {
209
- const t = useTranslate();
210
- const [portalRoot, setPortalRoot] = useState(null);
211
- if (onLanguageChange == null) return null;
212
- return /* @__PURE__ */ jsxs("div", {
213
- className: "resource-language",
214
- ref: setPortalRoot,
215
- children: [/* @__PURE__ */ jsx("span", {
216
- className: "sr-only",
217
- children: t("language.label")
218
- }), /* @__PURE__ */ jsx(WorkbenchSelect, {
219
- ariaLabel: t("language.label"),
220
- onValueChange: (value) => onLanguageChange(value),
221
- options: languageOptions,
222
- portalRoot,
223
- value: language
224
- })]
225
- });
226
- }
227
204
  function compactFlowId(flowId) {
228
205
  return flowId.length <= 20 ? flowId : `${flowId.slice(0, 10)}…${flowId.slice(-6)}`;
229
206
  }
@@ -504,12 +481,19 @@ function FlowItem({ badge, busy, flow, href, onSelect, store }) {
504
481
  "aria-hidden": "true",
505
482
  className: cn("status-dot", publicationTone)
506
483
  }),
507
- t(publicationStatus),
508
- flow.live != null && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
509
- "aria-hidden": "true",
510
- className: "resource-status-separator",
511
- children: "·"
512
- }), /* @__PURE__ */ jsx("span", { children: t(flow.live.enabled ? "resource.enabled" : "resource.disabled") })] })
484
+ /* @__PURE__ */ jsx("span", { children: t(publicationStatus) }),
485
+ flow.live != null && /* @__PURE__ */ jsxs("span", {
486
+ className: "resource-enabled-status",
487
+ "aria-busy": pending == "enabled",
488
+ children: [/* @__PURE__ */ jsx("span", { children: t(flow.live.enabled ? "resource.enabled" : "resource.disabled") }), /* @__PURE__ */ jsx(Switch, {
489
+ "aria-label": t("resource.enableFlow", { name: flow.name }),
490
+ checked: flow.live.enabled,
491
+ disabled: flow.status != "active" || busy != null || pending != null,
492
+ onCheckedChange: (enabled) => void update(enabled),
493
+ size: "sm",
494
+ title: t("resource.enabledHint")
495
+ })]
496
+ })
513
497
  ]
514
498
  })
515
499
  ]
@@ -519,14 +503,6 @@ function FlowItem({ badge, busy, flow, href, onSelect, store }) {
519
503
  "aria-busy": pending != null,
520
504
  onClick: openFromRow,
521
505
  children: [
522
- flow.live != null && /* @__PURE__ */ jsx(Switch, {
523
- "aria-label": t("resource.enableFlow", { name: flow.name }),
524
- checked: flow.live.enabled,
525
- disabled: flow.status != "active" || busy != null || pending != null,
526
- onCheckedChange: (enabled) => void update(enabled),
527
- size: "sm",
528
- title: t("resource.enabledHint")
529
- }),
530
506
  flow.status == "active" && /* @__PURE__ */ jsx(Button, {
531
507
  onClick: () => onSelect(flow),
532
508
  size: "sm",
@@ -619,7 +595,7 @@ function FlowSkeleton() {
619
595
  })]
620
596
  });
621
597
  }
622
- function FlowBrowser({ catalogWidth, createFlowDisabled, createFlowField, flowBadges, hrefForFlow, language, onCreateFlow, onLanguageChange, onSelectFlow, store }) {
598
+ function FlowBrowser({ catalogWidth, createFlowDisabled, createFlowField, flowBadges, hrefForFlow, onCreateFlow, onSelectFlow, store }) {
623
599
  const t = useTranslate();
624
600
  const busy = useVal(store.workspace.$.busy);
625
601
  const loadFailed = useVal(store.workspace.$.flowLoadFailed);
@@ -666,107 +642,105 @@ function FlowBrowser({ catalogWidth, createFlowDisabled, createFlowField, flowBa
666
642
  }), !loading && /* @__PURE__ */ jsx("span", { children: t("resource.flowCount", { count: total ?? flows.length }) })]
667
643
  }), /* @__PURE__ */ jsxs("div", {
668
644
  className: "resource-list-actions",
669
- children: [
670
- /* @__PURE__ */ jsx(LanguageSelect, {
671
- language,
672
- onLanguageChange
673
- }),
674
- /* @__PURE__ */ jsxs(InputGroup, {
675
- className: "w-full sm:w-56",
676
- children: [/* @__PURE__ */ jsx(InputGroupAddon, { children: /* @__PURE__ */ jsx(Icon, {
677
- name: "search",
678
- size: 17
679
- }) }), /* @__PURE__ */ jsx(InputGroupInput, {
680
- autoComplete: "off",
681
- "aria-label": t("resource.searchByName"),
682
- name: "flow-search",
683
- onChange: (event) => setFilter(event.target.value),
684
- placeholder: t("resource.searchByName"),
685
- value: filter
686
- })]
687
- }),
688
- /* @__PURE__ */ jsxs(Button, {
689
- className: "pr-3",
690
- disabled: busy != null,
691
- onClick: () => setCreating(true),
692
- children: [/* @__PURE__ */ jsx(Icon, {
693
- "data-icon": "inline-start",
694
- name: "plus"
695
- }), t("resource.newFlow")]
696
- })
697
- ]
698
- })]
699
- }),
700
- /* @__PURE__ */ jsxs("div", {
701
- "aria-hidden": "true",
702
- className: "resource-list-columns-shell",
703
- children: [/* @__PURE__ */ jsxs("div", {
704
- className: "resource-list-columns flow-columns",
705
- children: [
706
- /* @__PURE__ */ jsx("span", { children: t("resource.name") }),
707
- /* @__PURE__ */ jsx("span", {
708
- className: "resource-flow-id-heading",
709
- children: t("resource.flowId")
710
- }),
711
- /* @__PURE__ */ jsx("span", {
712
- className: "resource-updated-heading",
713
- children: t("resource.updated")
714
- }),
715
- /* @__PURE__ */ jsx("span", { children: t("resource.status") })
716
- ]
717
- }), /* @__PURE__ */ jsx("span", {
718
- className: "resource-actions-heading",
719
- children: t("resource.actions")
720
- })]
721
- }),
722
- /* @__PURE__ */ jsx("div", {
723
- className: "resource-list",
724
- children: loading ? Array.from({ length: 5 }, (_, index) => /* @__PURE__ */ jsx(FlowSkeleton, {}, index)) : loadFailed ? /* @__PURE__ */ jsxs(Empty, {
725
- className: "min-h-64",
726
- role: "alert",
727
- children: [/* @__PURE__ */ jsxs(EmptyHeader, { children: [
728
- /* @__PURE__ */ jsx(EmptyMedia, {
729
- variant: "icon",
730
- children: /* @__PURE__ */ jsx(Icon, {
731
- name: "alert",
732
- size: 20
733
- })
734
- }),
735
- /* @__PURE__ */ jsx(EmptyTitle, { children: t("resource.flowsLoadFailed") }),
736
- /* @__PURE__ */ jsx(EmptyDescription, { children: t("resource.flowsLoadFailedDescription") })
737
- ] }), /* @__PURE__ */ jsx(EmptyContent, { children: /* @__PURE__ */ jsx(Button, {
738
- onClick: () => void store.retryFlows(),
739
- variant: "outline",
740
- children: t("empty.retry")
741
- }) })]
742
- }) : visible.length == 0 ? /* @__PURE__ */ jsxs(Empty, {
743
- className: "min-h-64",
744
- children: [/* @__PURE__ */ jsxs(EmptyHeader, { children: [
745
- /* @__PURE__ */ jsx(EmptyMedia, {
746
- variant: "icon",
747
- children: /* @__PURE__ */ jsx(Icon, {
748
- name: "flow",
749
- size: 20
750
- })
751
- }),
752
- /* @__PURE__ */ jsx(EmptyTitle, { children: t(normalized.length == 0 ? "resource.noFlows" : "resource.noMatchingFlows") }),
753
- /* @__PURE__ */ jsx(EmptyDescription, { children: t(normalized.length == 0 ? "resource.noFlowsDescription" : "resource.noMatchingDescription") })
754
- ] }), normalized.length == 0 && /* @__PURE__ */ jsx(EmptyContent, { children: /* @__PURE__ */ jsxs(Button, {
645
+ children: [/* @__PURE__ */ jsxs(InputGroup, {
646
+ className: "w-full sm:w-56",
647
+ children: [/* @__PURE__ */ jsx(InputGroupAddon, { children: /* @__PURE__ */ jsx(Icon, {
648
+ name: "search",
649
+ size: 17
650
+ }) }), /* @__PURE__ */ jsx(InputGroupInput, {
651
+ autoComplete: "off",
652
+ "aria-label": t("resource.searchByName"),
653
+ name: "flow-search",
654
+ onChange: (event) => setFilter(event.target.value),
655
+ placeholder: t("resource.searchByName"),
656
+ value: filter
657
+ })]
658
+ }), /* @__PURE__ */ jsxs(Button, {
659
+ className: "pr-3",
660
+ disabled: busy != null,
755
661
  onClick: () => setCreating(true),
756
- variant: "outline",
757
662
  children: [/* @__PURE__ */ jsx(Icon, {
758
663
  "data-icon": "inline-start",
759
664
  name: "plus"
760
665
  }), t("resource.newFlow")]
761
- }) })]
762
- }) : visible.map((flow) => /* @__PURE__ */ jsx(FlowItem, {
763
- badge: flowBadges?.[flow.flowId],
764
- busy,
765
- flow,
766
- href: hrefForFlow(flow),
767
- onSelect: onSelectFlow,
768
- store
769
- }, flow.flowId))
666
+ })]
667
+ })]
668
+ }),
669
+ /* @__PURE__ */ jsx("div", {
670
+ className: "resource-table-scroll",
671
+ children: /* @__PURE__ */ jsxs("div", {
672
+ className: "resource-table",
673
+ children: [/* @__PURE__ */ jsxs("div", {
674
+ "aria-hidden": "true",
675
+ className: "resource-list-columns-shell",
676
+ children: [/* @__PURE__ */ jsxs("div", {
677
+ className: "resource-list-columns flow-columns",
678
+ children: [
679
+ /* @__PURE__ */ jsx("span", { children: t("resource.name") }),
680
+ /* @__PURE__ */ jsx("span", {
681
+ className: "resource-flow-id-heading",
682
+ children: t("resource.flowId")
683
+ }),
684
+ /* @__PURE__ */ jsx("span", {
685
+ className: "resource-updated-heading",
686
+ children: t("resource.updated")
687
+ }),
688
+ /* @__PURE__ */ jsx("span", { children: t("resource.status") })
689
+ ]
690
+ }), /* @__PURE__ */ jsx("span", {
691
+ className: "resource-actions-heading",
692
+ children: t("resource.actions")
693
+ })]
694
+ }), /* @__PURE__ */ jsx("div", {
695
+ className: "resource-list",
696
+ children: loading ? Array.from({ length: 5 }, (_, index) => /* @__PURE__ */ jsx(FlowSkeleton, {}, index)) : loadFailed ? /* @__PURE__ */ jsxs(Empty, {
697
+ className: "min-h-64",
698
+ role: "alert",
699
+ children: [/* @__PURE__ */ jsxs(EmptyHeader, { children: [
700
+ /* @__PURE__ */ jsx(EmptyMedia, {
701
+ variant: "icon",
702
+ children: /* @__PURE__ */ jsx(Icon, {
703
+ name: "alert",
704
+ size: 20
705
+ })
706
+ }),
707
+ /* @__PURE__ */ jsx(EmptyTitle, { children: t("resource.flowsLoadFailed") }),
708
+ /* @__PURE__ */ jsx(EmptyDescription, { children: t("resource.flowsLoadFailedDescription") })
709
+ ] }), /* @__PURE__ */ jsx(EmptyContent, { children: /* @__PURE__ */ jsx(Button, {
710
+ onClick: () => void store.retryFlows(),
711
+ variant: "outline",
712
+ children: t("empty.retry")
713
+ }) })]
714
+ }) : visible.length == 0 ? /* @__PURE__ */ jsxs(Empty, {
715
+ className: "min-h-64",
716
+ children: [/* @__PURE__ */ jsxs(EmptyHeader, { children: [
717
+ /* @__PURE__ */ jsx(EmptyMedia, {
718
+ variant: "icon",
719
+ children: /* @__PURE__ */ jsx(Icon, {
720
+ name: "flow",
721
+ size: 20
722
+ })
723
+ }),
724
+ /* @__PURE__ */ jsx(EmptyTitle, { children: t(normalized.length == 0 ? "resource.noFlows" : "resource.noMatchingFlows") }),
725
+ /* @__PURE__ */ jsx(EmptyDescription, { children: t(normalized.length == 0 ? "resource.noFlowsDescription" : "resource.noMatchingDescription") })
726
+ ] }), normalized.length == 0 && /* @__PURE__ */ jsx(EmptyContent, { children: /* @__PURE__ */ jsxs(Button, {
727
+ onClick: () => setCreating(true),
728
+ variant: "outline",
729
+ children: [/* @__PURE__ */ jsx(Icon, {
730
+ "data-icon": "inline-start",
731
+ name: "plus"
732
+ }), t("resource.newFlow")]
733
+ }) })]
734
+ }) : visible.map((flow) => /* @__PURE__ */ jsx(FlowItem, {
735
+ badge: flowBadges?.[flow.flowId],
736
+ busy,
737
+ flow,
738
+ href: hrefForFlow(flow),
739
+ onSelect: onSelectFlow,
740
+ store
741
+ }, flow.flowId))
742
+ })]
743
+ })
770
744
  }),
771
745
  nextCursor != null && /* @__PURE__ */ jsx("div", {
772
746
  className: "resource-list-footer",
@@ -1506,93 +1480,35 @@ var PublicationStore = class {
1506
1480
  //#endregion
1507
1481
  //#region src/workbench/browser/runtime/runs/runRequestStore.ts
1508
1482
  var initialState$5 = { starting: false };
1509
- function inputPorts$1(node) {
1510
- switch (node.kind) {
1511
- case "condition": return {};
1512
- case "subflow": return portsByHandle(node.definition?.inputs ?? []);
1513
- case "task": return portsByHandle(node.definition?.inputs ?? []);
1514
- case "value": return {};
1515
- case "approval":
1516
- case "wait": return portsByHandle(node.node.inputDefinitions);
1517
- }
1518
- }
1519
- function nodeTitle(node) {
1520
- if (node.node.name != null) return node.node.name;
1521
- if (node.kind == "task" || node.kind == "subflow") return node.definition?.name ?? node.id;
1522
- return node.id;
1523
- }
1524
- function inputSpecs(draft, triggerId) {
1525
- const revision = revisionView(draft);
1526
- const graph = revision.graph({ kind: "flow" });
1527
- if (graph == null) return [];
1528
- const reachable = /* @__PURE__ */ new Set([triggerId]);
1529
- const pending = [triggerId];
1530
- while (pending.length > 0) {
1531
- const source = pending.pop();
1532
- for (const edge of graph.edges) {
1533
- if (edge.source != source || reachable.has(edge.target)) continue;
1534
- reachable.add(edge.target);
1535
- pending.push(edge.target);
1536
- }
1537
- }
1538
- return Object.entries(graph.nodes).filter(([id]) => reachable.has(id)).toSorted(([left], [right]) => left.localeCompare(right)).flatMap(([nodeId, node]) => {
1539
- const resolved = revision.resolveNode(nodeId, node);
1540
- if (resolved.kind == "trigger") {
1541
- if (resolved.trigger.kind == "manual" || resolved.trigger.kind == "cron") return [];
1542
- return [{
1543
- definitions: triggerOutputDefinitions(resolved.trigger),
1544
- samples: resolved.trigger.kind == "error" ? sampleErrorOutputs : void 0,
1545
- nodeId,
1546
- title: resolved.trigger.name
1547
- }];
1548
- }
1549
- const definitions = Object.entries(inputPorts$1(resolved)).filter(([handle, port]) => resolved.node.inputs[handle] == null && !Object.hasOwn(port, "value")).toSorted(([left], [right]) => left.localeCompare(right)).map(([handle, port]) => Object.assign({
1550
- handle,
1551
- jsonSchema: port.jsonSchema,
1552
- nullable: port.nullable
1553
- }, port.description == null ? {} : { description: port.description }));
1554
- return definitions.length == 0 ? [] : [{
1555
- definitions,
1556
- samples: void 0,
1557
- nodeId,
1558
- title: nodeTitle(resolved)
1559
- }];
1560
- });
1483
+ function inputSpec(draft, triggerId) {
1484
+ const trigger = revisionView(draft).graph({ kind: "flow" })?.nodes[triggerId];
1485
+ if (trigger == null || "inputs" in trigger || trigger.kind == "manual" || trigger.kind == "cron") return void 0;
1486
+ const definitions = triggerOutputDefinitions(trigger);
1487
+ return definitions.length === 0 ? void 0 : {
1488
+ definitions,
1489
+ samples: trigger.kind == "error" ? sampleErrorOutputs : void 0
1490
+ };
1561
1491
  }
1562
- function inputSignature(specs) {
1563
- return JSON.stringify(specs.map((group) => [group.nodeId, group.definitions.map((definition) => [
1492
+ function inputSignature(spec) {
1493
+ return JSON.stringify(spec?.definitions.map((definition) => [
1564
1494
  definition.handle,
1565
1495
  definition.jsonSchema,
1566
1496
  definition.nullable
1567
- ])]));
1497
+ ]) ?? []);
1568
1498
  }
1569
- async function inputGroups(specs, language, values) {
1499
+ async function inputEditor(spec, language, values) {
1500
+ if (spec == null) return void 0;
1570
1501
  const { FlowRunInputEditorStore } = await import("./flowRunInputEditorStore-Dsxyfwae.js").then((n) => n.t);
1571
- return specs.map((group) => {
1572
- const editor = new FlowRunInputEditorStore(group.definitions, language);
1573
- const initial = values?.[group.nodeId] ?? group.samples;
1574
- if (initial != null) editor.replaceValues(initial);
1575
- return {
1576
- editor,
1577
- nodeId: group.nodeId,
1578
- title: group.title
1579
- };
1580
- });
1581
- }
1582
- function groupValues(groups) {
1583
- return Object.fromEntries(groups.map((group) => [group.nodeId, group.editor.values()]));
1502
+ const editor = new FlowRunInputEditorStore(spec.definitions, language);
1503
+ const initial = values ?? spec.samples;
1504
+ if (initial != null) editor.replaceValues(initial);
1505
+ return editor;
1584
1506
  }
1585
1507
  function testOutputs(revision, triggerId) {
1586
1508
  const node = revisionView(revision).graph({ kind: "flow" })?.nodes[triggerId];
1587
1509
  if (node?.kind == "error") return sampleErrorOutputs;
1588
1510
  return node?.kind === "cron" ? { scheduledAt: (/* @__PURE__ */ new Date()).toISOString() } : {};
1589
1511
  }
1590
- function runValues(groups, triggerId, revision) {
1591
- return {
1592
- inputs: Object.fromEntries(groups.filter((group) => group.nodeId != triggerId).map((group) => [group.nodeId, group.editor.values()])),
1593
- outputs: groups.find((group) => group.nodeId == triggerId)?.editor.values() ?? testOutputs(revision, triggerId)
1594
- };
1595
- }
1596
1512
  var RunRequestStore = class {
1597
1513
  #prepareDraft;
1598
1514
  #client;
@@ -1657,10 +1573,10 @@ var RunRequestStore = class {
1657
1573
  }
1658
1574
  }
1659
1575
  inputStatus(flowId, draft, triggerId) {
1660
- const specs = inputSpecs(draft, triggerId);
1661
- if (specs.length == 0) return "none";
1576
+ const spec = inputSpec(draft, triggerId);
1577
+ if (spec == null) return "none";
1662
1578
  const saved = this.#savedInputs.get(this.#inputKey(flowId, triggerId));
1663
- return saved?.valid == true && saved.signature == inputSignature(specs) ? "ready" : "missing";
1579
+ return saved?.valid == true && saved.signature == inputSignature(spec) ? "ready" : "missing";
1664
1580
  }
1665
1581
  async requestLive(flow) {
1666
1582
  const current = this.#requests.begin();
@@ -1695,11 +1611,11 @@ var RunRequestStore = class {
1695
1611
  return false;
1696
1612
  }
1697
1613
  this.#rememberInputs(request);
1698
- const { inputs, outputs } = runValues(request.groups, request.triggerId, request.revision);
1614
+ const outputs = request.editor?.values() ?? testOutputs(request.revision, request.triggerId);
1699
1615
  const started = await this.#start(request.source, request.flow, request.revisionId, {
1700
1616
  nodeId: request.triggerId,
1701
1617
  outputs
1702
- }, inputs, request.publicationId);
1618
+ }, request.publicationId);
1703
1619
  if (started && this.#state.value.inputRequest === request) this.dismissInputs();
1704
1620
  return started;
1705
1621
  }
@@ -1710,18 +1626,18 @@ var RunRequestStore = class {
1710
1626
  this.#rememberInputs(request);
1711
1627
  this.#set({ starting: true });
1712
1628
  try {
1713
- const specs = inputSpecs(request.revision, triggerId);
1629
+ const spec = inputSpec(request.revision, triggerId);
1714
1630
  const saved = this.#savedInputs.get(this.#inputKey(request.flow.flowId, triggerId));
1715
- const groups = await inputGroups(specs, this.#i18n.lang$, saved?.values);
1631
+ const editor = await inputEditor(spec, this.#i18n.lang$, saved?.values);
1716
1632
  if (!current() || this.#state.value.inputRequest !== request) {
1717
- for (const group of groups) group.editor.dispose();
1633
+ editor?.dispose();
1718
1634
  return;
1719
1635
  }
1720
- const valid = compute((get) => groups.every((group) => get(group.editor.valid$)));
1636
+ const valid = compute((get) => editor == null || get(editor.valid$));
1721
1637
  this.#set({ inputRequest: {
1722
1638
  ...request,
1723
1639
  attempted: false,
1724
- groups,
1640
+ editor,
1725
1641
  triggerId,
1726
1642
  valid
1727
1643
  } });
@@ -1763,32 +1679,32 @@ var RunRequestStore = class {
1763
1679
  });
1764
1680
  return "unavailable";
1765
1681
  }
1766
- const specs = only == null ? [] : inputSpecs(revision, only.nodeId);
1767
- const signature = inputSignature(specs);
1682
+ const spec = only == null ? void 0 : inputSpec(revision, only.nodeId);
1683
+ const signature = inputSignature(spec);
1768
1684
  const saved = only == null ? void 0 : this.#savedInputs.get(this.#inputKey(flow.flowId, only.nodeId));
1769
- const groups = only == null ? [] : await inputGroups(specs, this.#i18n.lang$, saved?.values);
1685
+ const editor = await inputEditor(spec, this.#i18n.lang$, saved?.values);
1770
1686
  if (!current()) {
1771
- for (const group of groups) group.editor.dispose();
1687
+ editor?.dispose();
1772
1688
  return "unavailable";
1773
1689
  }
1774
- if (!edit && only != null && groups.length == 0) return await this.#start(source, flow, revisionId, {
1690
+ if (!edit && only != null && editor == null) return await this.#start(source, flow, revisionId, {
1775
1691
  nodeId: only.nodeId,
1776
1692
  outputs: testOutputs(revision, only.nodeId)
1777
- }, {}, publicationId) ? "started" : "unavailable";
1778
- if (!edit && only != null && saved?.valid == true && saved.signature == signature && groups.every((group) => group.editor.valid$.value)) {
1779
- const values = runValues(groups, only.nodeId, revision);
1780
- for (const group of groups) group.editor.dispose();
1693
+ }, publicationId) ? "started" : "unavailable";
1694
+ if (!edit && only != null && saved?.valid == true && saved.signature == signature && editor != null && editor.valid$.value) {
1695
+ const outputs = editor.values();
1696
+ editor?.dispose();
1781
1697
  return await this.#start(source, flow, revisionId, {
1782
1698
  nodeId: only.nodeId,
1783
- outputs: values.outputs
1784
- }, values.inputs, publicationId) ? "started" : "unavailable";
1699
+ outputs
1700
+ }, publicationId) ? "started" : "unavailable";
1785
1701
  }
1786
- const valid = compute((get) => only != null && groups.every((group) => get(group.editor.valid$)));
1702
+ const valid = compute((get) => only != null && (editor == null || get(editor.valid$)));
1787
1703
  this.#set({
1788
1704
  inputRequest: {
1789
1705
  attempted: false,
1790
1706
  flow,
1791
- groups,
1707
+ editor,
1792
1708
  revision,
1793
1709
  triggers,
1794
1710
  triggerId: only?.nodeId,
@@ -1802,7 +1718,7 @@ var RunRequestStore = class {
1802
1718
  });
1803
1719
  return "input";
1804
1720
  }
1805
- async #start(source, flow, revisionId, trigger, inputs = {}, publicationId) {
1721
+ async #start(source, flow, revisionId, trigger, publicationId) {
1806
1722
  if (source == "live" && publicationId == null) return false;
1807
1723
  const alive = this.#lifetime.capture();
1808
1724
  const current = this.#runs.prepareStart();
@@ -1821,7 +1737,6 @@ var RunRequestStore = class {
1821
1737
  revisionId
1822
1738
  } : { publicationId };
1823
1739
  const signature = JSON.stringify({
1824
- inputs,
1825
1740
  trigger,
1826
1741
  source,
1827
1742
  ...target
@@ -1833,11 +1748,11 @@ var RunRequestStore = class {
1833
1748
  this.#attempt = attempt;
1834
1749
  const run = source == "draft" ? await this.#client.createDraftRun(flow.flowId, revisionId, {
1835
1750
  idempotencyKey: attempt.key,
1836
- inputs,
1751
+ inputs: {},
1837
1752
  trigger
1838
1753
  }) : await this.#client.createLiveRun(publicationId, {
1839
1754
  idempotencyKey: attempt.key,
1840
- inputs,
1755
+ inputs: {},
1841
1756
  trigger
1842
1757
  });
1843
1758
  if (!alive() || !current()) return false;
@@ -1856,17 +1771,17 @@ var RunRequestStore = class {
1856
1771
  #disposeInputRequest(request = this.#state.value.inputRequest) {
1857
1772
  if (request == null) return;
1858
1773
  request.valid.dispose();
1859
- for (const group of request.groups) group.editor.dispose();
1774
+ request.editor?.dispose();
1860
1775
  }
1861
1776
  #inputKey(flowId, triggerId) {
1862
1777
  return `${flowId}\u0000${triggerId}`;
1863
1778
  }
1864
1779
  #rememberInputs(request) {
1865
- if (request?.triggerId == null || request.groups.length == 0) return;
1780
+ if (request?.triggerId == null || request.editor == null) return;
1866
1781
  this.#savedInputs.set(this.#inputKey(request.flow.flowId, request.triggerId), {
1867
- signature: inputSignature(inputSpecs(request.revision, request.triggerId)),
1782
+ signature: inputSignature(inputSpec(request.revision, request.triggerId)),
1868
1783
  valid: request.valid.value,
1869
- values: groupValues(request.groups)
1784
+ values: request.editor.values()
1870
1785
  });
1871
1786
  }
1872
1787
  #set(patch) {
@@ -1961,48 +1876,591 @@ function createStore(dbName, storeName) {
1961
1876
  };
1962
1877
  return (txMode, callback) => getDB().then((db) => callback(db.transaction(storeName, txMode).objectStore(storeName)));
1963
1878
  }
1964
- var defaultGetStoreFunc;
1965
- function defaultGetStore() {
1966
- if (!defaultGetStoreFunc) defaultGetStoreFunc = createStore("keyval-store", "keyval");
1967
- return defaultGetStoreFunc;
1968
- }
1969
- /**
1970
- * Get a value by its key.
1971
- *
1972
- * @param key
1973
- * @param customStore Method to get a custom store. Use with caution (see the docs).
1974
- */
1975
- function get(key, customStore = defaultGetStore()) {
1976
- return customStore("readonly", (store) => promisifyRequest(store.get(key)));
1879
+ //#endregion
1880
+ //#region ../../node_modules/.bun/@oomol-lab+resource-cache@0.1.4/node_modules/@oomol-lab/resource-cache/dist/src-bwD0r9NQ.mjs
1881
+ function abortError() {
1882
+ return new DOMException("Cache operation aborted", "AbortError");
1977
1883
  }
1978
- /**
1979
- * Set a value with a key.
1980
- *
1981
- * @param key
1982
- * @param value
1983
- * @param customStore Method to get a custom store. Use with caution (see the docs).
1984
- */
1985
- function set(key, value, customStore = defaultGetStore()) {
1986
- return customStore("readwrite", (store) => {
1987
- store.put(value, key);
1988
- return promisifyRequest(store.transaction);
1884
+ function wait(promise, lifetime, caller) {
1885
+ const signals = caller ? [lifetime, caller] : [lifetime];
1886
+ return new Promise((resolve, reject) => {
1887
+ const cleanup = () => {
1888
+ for (const signal of signals) signal.removeEventListener("abort", abort);
1889
+ };
1890
+ const abort = () => {
1891
+ cleanup();
1892
+ reject(abortError());
1893
+ };
1894
+ for (const signal of signals) signal.addEventListener("abort", abort, { once: true });
1895
+ promise.then((value) => {
1896
+ cleanup();
1897
+ resolve(value);
1898
+ }, (error) => {
1899
+ cleanup();
1900
+ reject(error);
1901
+ });
1989
1902
  });
1990
1903
  }
1904
+ /** @internal */
1905
+ function validateOptions(options) {
1906
+ if (typeof options.namespace !== "string" || !options.namespace.trim()) throw new TypeError("namespace must be nonempty");
1907
+ if (!Number.isSafeInteger(options.schemaVersion) || options.schemaVersion <= 0) throw new TypeError("schemaVersion must be a positive safe integer");
1908
+ if (!Number.isFinite(options.maxAge) || options.maxAge < 0) throw new TypeError("maxAge must be finite and nonnegative");
1909
+ for (const name of [
1910
+ "key",
1911
+ "decode",
1912
+ "load"
1913
+ ]) if (typeof options[name] !== "function") throw new TypeError(`${name} must be a function`);
1914
+ }
1915
+ /** @internal */
1916
+ function createCache(options, backend, session) {
1917
+ const states = /* @__PURE__ */ new Map();
1918
+ let disposed = false;
1919
+ let scopeBlocked = false;
1920
+ let disposal;
1921
+ let io = Promise.resolve();
1922
+ function storage(action) {
1923
+ const result = io.then(action);
1924
+ io = result.catch(() => {});
1925
+ return result;
1926
+ }
1927
+ function checkOpen() {
1928
+ if (disposed) throw new Error("Cache is disposed");
1929
+ }
1930
+ function identity(query) {
1931
+ checkOpen();
1932
+ const key = options.key(query);
1933
+ if (typeof key !== "string") throw new TypeError("key must return a string");
1934
+ return key;
1935
+ }
1936
+ function stateFor(key) {
1937
+ let state = states.get(key);
1938
+ if (!state) {
1939
+ state = {
1940
+ controller: new AbortController(),
1941
+ blocked: scopeBlocked
1942
+ };
1943
+ states.set(key, state);
1944
+ }
1945
+ return state;
1946
+ }
1947
+ function checkState(state) {
1948
+ if (state.controller.signal.aborted) throw abortError();
1949
+ }
1950
+ function fresh(entry) {
1951
+ const now = Date.now();
1952
+ return !entry.invalidated && entry.validatedAt <= now && now - entry.validatedAt < options.maxAge;
1953
+ }
1954
+ function restore(value, previous) {
1955
+ return {
1956
+ ...value.meta,
1957
+ data: value.body ? options.decode(value.body.data) : previous.data
1958
+ };
1959
+ }
1960
+ async function read(key, state) {
1961
+ if (state.entry && fresh(state.entry)) return state.entry;
1962
+ const entry = await storage(async () => {
1963
+ checkState(state);
1964
+ if (state.blocked) return state.entry;
1965
+ try {
1966
+ const value = await backend.read(key, state.entry?.version);
1967
+ return value ? restore(value, state.entry) : state.entry;
1968
+ } catch {
1969
+ return state.entry;
1970
+ }
1971
+ });
1972
+ checkState(state);
1973
+ state.entry = entry;
1974
+ return entry;
1975
+ }
1976
+ function schedule(key, query, state, force) {
1977
+ const job = {
1978
+ started: false,
1979
+ force
1980
+ };
1981
+ job.promise = (async () => {
1982
+ const previous = await read(key, state);
1983
+ checkState(state);
1984
+ if (!job.force && previous && fresh(previous)) return previous.data;
1985
+ job.started = true;
1986
+ const result = await options.load(query, {
1987
+ etag: previous?.etag ?? null,
1988
+ signal: state.controller.signal
1989
+ });
1990
+ checkState(state);
1991
+ let entry;
1992
+ if (result.modified) entry = {
1993
+ data: result.data,
1994
+ etag: result.etag,
1995
+ version: crypto.getRandomValues(/* @__PURE__ */ new Uint32Array(4)).join("-"),
1996
+ validatedAt: Date.now(),
1997
+ invalidated: false
1998
+ };
1999
+ else {
2000
+ if (!previous) throw new Error("Load protocol error: unmodified response without cached data");
2001
+ entry = {
2002
+ ...previous,
2003
+ etag: result.etag === void 0 ? previous.etag : result.etag,
2004
+ validatedAt: Date.now(),
2005
+ invalidated: false
2006
+ };
2007
+ }
2008
+ await storage(async () => {
2009
+ checkState(state);
2010
+ try {
2011
+ if (await backend.write(key, entry, result.modified)) state.blocked = false;
2012
+ } catch {
2013
+ state.blocked = true;
2014
+ }
2015
+ checkState(state);
2016
+ state.entry = entry;
2017
+ });
2018
+ checkState(state);
2019
+ return entry.data;
2020
+ })();
2021
+ state.job = job;
2022
+ const release = () => {
2023
+ state.job = void 0;
2024
+ };
2025
+ job.promise.then(release, release);
2026
+ return job;
2027
+ }
2028
+ function refresh(key, query, state, force) {
2029
+ const active = state.job;
2030
+ if (!active) return schedule(key, query, state, force).promise;
2031
+ if (!force) return active.promise;
2032
+ if (!active.started) {
2033
+ active.force = true;
2034
+ return active.promise;
2035
+ }
2036
+ if (!state.queued) {
2037
+ const start = () => {
2038
+ checkState(state);
2039
+ state.queued = void 0;
2040
+ return schedule(key, query, state, true).promise;
2041
+ };
2042
+ state.queued = active.promise.then(start, start);
2043
+ }
2044
+ return state.queued;
2045
+ }
2046
+ function reset(key, keep) {
2047
+ const old = states.get(key);
2048
+ const state = {
2049
+ controller: new AbortController(),
2050
+ blocked: true
2051
+ };
2052
+ if (keep && old?.entry) state.entry = {
2053
+ ...old.entry,
2054
+ invalidated: true
2055
+ };
2056
+ states.set(key, state);
2057
+ return {
2058
+ state,
2059
+ cancel: () => old?.controller.abort()
2060
+ };
2061
+ }
2062
+ function resetAll() {
2063
+ const old = [...states.values()];
2064
+ states.clear();
2065
+ const barrier = {};
2066
+ scopeBlocked = barrier;
2067
+ return {
2068
+ barrier,
2069
+ cancel() {
2070
+ for (const state of old) state.controller.abort();
2071
+ }
2072
+ };
2073
+ }
2074
+ return {
2075
+ async get(query, getOptions = {}) {
2076
+ const key = identity(query);
2077
+ if (getOptions.signal?.aborted) throw abortError();
2078
+ const state = stateFor(key);
2079
+ if (!getOptions.revalidate && state.entry && fresh(state.entry)) return state.entry.data;
2080
+ return wait(refresh(key, query, state, getOptions.revalidate === true), state.controller.signal, getOptions.signal);
2081
+ },
2082
+ async peek(query) {
2083
+ const key = identity(query);
2084
+ const state = stateFor(key);
2085
+ const entry = await wait(read(key, state), state.controller.signal);
2086
+ return entry ? {
2087
+ data: entry.data,
2088
+ etag: entry.etag,
2089
+ validatedAt: entry.validatedAt,
2090
+ fresh: fresh(entry)
2091
+ } : void 0;
2092
+ },
2093
+ async invalidate(query) {
2094
+ const key = identity(query);
2095
+ const canRestore = !(states.get(key)?.blocked ?? scopeBlocked);
2096
+ const { state, cancel } = reset(key, true);
2097
+ const cleanup = storage(async () => {
2098
+ const value = await backend.invalidate(key);
2099
+ if (canRestore) state.blocked = false;
2100
+ if (canRestore && !state.controller.signal.aborted && !state.entry && value) try {
2101
+ state.entry = restore(value);
2102
+ } catch {}
2103
+ });
2104
+ cancel();
2105
+ await cleanup;
2106
+ },
2107
+ async remove(query) {
2108
+ const key = identity(query);
2109
+ const { state, cancel } = reset(key, false);
2110
+ const cleanup = storage(async () => {
2111
+ await backend.remove(key);
2112
+ state.blocked = false;
2113
+ });
2114
+ cancel();
2115
+ await cleanup;
2116
+ },
2117
+ async clear() {
2118
+ checkOpen();
2119
+ const { barrier, cancel } = resetAll();
2120
+ const cleanup = storage(async () => {
2121
+ await backend.clear(false);
2122
+ if (scopeBlocked === barrier) scopeBlocked = false;
2123
+ for (const state of states.values()) if (state.blocked === barrier) state.blocked = false;
2124
+ });
2125
+ cancel();
2126
+ await cleanup;
2127
+ },
2128
+ dispose() {
2129
+ if (!disposal) {
2130
+ disposed = true;
2131
+ const { cancel } = resetAll();
2132
+ disposal = storage(async () => {
2133
+ if (session) await backend.clear(true);
2134
+ });
2135
+ disposal = disposal.catch((error) => {
2136
+ disposal = void 0;
2137
+ throw error;
2138
+ });
2139
+ cancel();
2140
+ }
2141
+ return disposal;
2142
+ }
2143
+ };
2144
+ }
2145
+ function object(value) {
2146
+ return typeof value === "object" && value !== null;
2147
+ }
2148
+ function metadata(value) {
2149
+ if (!object(value) || typeof value.version !== "string" || !value.version || !(value.etag === null || typeof value.etag === "string") || typeof value.invalidated !== "boolean") return void 0;
2150
+ const validTime = typeof value.validatedAt === "number" && Number.isFinite(value.validatedAt) && value.validatedAt >= 0;
2151
+ return {
2152
+ version: value.version,
2153
+ etag: value.etag,
2154
+ validatedAt: validTime ? value.validatedAt : 0,
2155
+ invalidated: !validTime || value.invalidated === true
2156
+ };
2157
+ }
2158
+ function stored(meta, body) {
2159
+ if (!object(body) || body.version !== meta.version || !Object.hasOwn(body, "data")) return void 0;
2160
+ return {
2161
+ meta,
2162
+ body: { data: body.data }
2163
+ };
2164
+ }
2165
+ var storagePrefix = "@oomol-lab/resource-cache:";
2166
+ /** Delimit identity fields without ambiguous string concatenation. @internal */
2167
+ function scope(namespace) {
2168
+ return storagePrefix + JSON.stringify(namespace);
2169
+ }
2170
+ /** @internal */
2171
+ function sessionScope(namespace, sessionId) {
2172
+ return storagePrefix + JSON.stringify([namespace, sessionId]);
2173
+ }
2174
+ /** @internal */
2175
+ function persistentStorage(namespace, schemaVersion) {
2176
+ const useStore = createStore("@oomol-lab/resource-cache", "records");
2177
+ const prefix = `${scope(namespace)}:${schemaVersion}:`;
2178
+ const identity = (key, part) => prefix + JSON.stringify([key, part]);
2179
+ function transaction(mode, work) {
2180
+ return useStore(mode, (store) => new Promise((resolve, reject) => {
2181
+ const tx = store.transaction;
2182
+ let value;
2183
+ let failure;
2184
+ tx.oncomplete = () => resolve(value);
2185
+ tx.onabort = () => reject(failure ?? tx.error);
2186
+ const guard = (fn) => {
2187
+ try {
2188
+ fn();
2189
+ } catch (error) {
2190
+ failure = error;
2191
+ tx.abort();
2192
+ }
2193
+ };
2194
+ const read = (request, fn) => {
2195
+ request.onsuccess = () => guard(() => fn(request.result));
2196
+ };
2197
+ guard(() => work(store, read, (result) => {
2198
+ value = result;
2199
+ }));
2200
+ }));
2201
+ }
2202
+ return {
2203
+ read(key, version) {
2204
+ return transaction("readonly", (store, read, result) => {
2205
+ read(store.get(identity(key, "meta")), (raw) => {
2206
+ const meta = metadata(raw);
2207
+ if (!meta) return;
2208
+ if (meta.version === version) {
2209
+ result({ meta });
2210
+ return;
2211
+ }
2212
+ read(store.get(identity(key, "body")), (body) => result(stored(meta, body)));
2213
+ });
2214
+ });
2215
+ },
2216
+ write(key, entry, modified) {
2217
+ return transaction("readwrite", (store, read, result) => {
2218
+ const { data, ...meta } = entry;
2219
+ if (modified) {
2220
+ store.put(meta, identity(key, "meta"));
2221
+ store.put({
2222
+ version: meta.version,
2223
+ data
2224
+ }, identity(key, "body"));
2225
+ result(true);
2226
+ } else read(store.get(identity(key, "meta")), (raw) => {
2227
+ const matches = metadata(raw)?.version === meta.version;
2228
+ if (matches) store.put(meta, identity(key, "meta"));
2229
+ result(matches);
2230
+ });
2231
+ });
2232
+ },
2233
+ invalidate(key) {
2234
+ return transaction("readwrite", (store, read, result) => {
2235
+ read(store.get(identity(key, "meta")), (raw) => {
2236
+ const meta = metadata(raw);
2237
+ if (!meta) return;
2238
+ meta.invalidated = true;
2239
+ store.put(meta, identity(key, "meta"));
2240
+ read(store.get(identity(key, "body")), (body) => result(stored(meta, body)));
2241
+ });
2242
+ });
2243
+ },
2244
+ remove(key) {
2245
+ return transaction("readwrite", (store) => {
2246
+ store.delete(identity(key, "meta"));
2247
+ store.delete(identity(key, "body"));
2248
+ });
2249
+ },
2250
+ clear() {
2251
+ return transaction("readwrite", (store, read) => {
2252
+ read(store.getAllKeys(), (keys) => {
2253
+ for (const key of keys) if (typeof key === "string" && key.startsWith(prefix)) store.delete(key);
2254
+ });
2255
+ });
2256
+ }
2257
+ };
2258
+ }
2259
+ /** @internal */
2260
+ function sessionStorageBackend(namespace, schemaVersion, sessionId) {
2261
+ const base = `${sessionScope(namespace, sessionId)}:`;
2262
+ const prefix = `${base}${schemaVersion}:`;
2263
+ const identity = (key) => prefix + JSON.stringify(key);
2264
+ const record = (key) => {
2265
+ const text = globalThis.sessionStorage.getItem(identity(key));
2266
+ if (text === null) return void 0;
2267
+ const raw = JSON.parse(text);
2268
+ const meta = metadata(raw);
2269
+ return meta ? stored(meta, raw) : void 0;
2270
+ };
2271
+ return {
2272
+ async read(key, version) {
2273
+ const value = record(key);
2274
+ if (value && value.meta.version === version) return { meta: value.meta };
2275
+ return value;
2276
+ },
2277
+ async write(key, entry, modified) {
2278
+ if (modified) {
2279
+ globalThis.sessionStorage.setItem(identity(key), JSON.stringify(entry));
2280
+ return true;
2281
+ } else {
2282
+ const value = record(key);
2283
+ if (value?.meta.version === entry.version) {
2284
+ const { data: _data, ...meta } = entry;
2285
+ globalThis.sessionStorage.setItem(identity(key), JSON.stringify({
2286
+ ...meta,
2287
+ data: value.body.data
2288
+ }));
2289
+ return true;
2290
+ }
2291
+ return false;
2292
+ }
2293
+ },
2294
+ async invalidate(key) {
2295
+ const value = record(key);
2296
+ if (value) {
2297
+ value.meta.invalidated = true;
2298
+ globalThis.sessionStorage.setItem(identity(key), JSON.stringify({
2299
+ ...value.meta,
2300
+ ...value.body
2301
+ }));
2302
+ }
2303
+ return value;
2304
+ },
2305
+ async remove(key) {
2306
+ globalThis.sessionStorage.removeItem(identity(key));
2307
+ },
2308
+ async clear(allVersions) {
2309
+ const storage = globalThis.sessionStorage;
2310
+ const matches = [];
2311
+ for (let i = 0; i < storage.length; i++) {
2312
+ const key = storage.key(i);
2313
+ if (key.startsWith(allVersions ? base : prefix)) matches.push(key);
2314
+ }
2315
+ for (const key of matches) storage.removeItem(key);
2316
+ }
2317
+ };
2318
+ }
2319
+ /** Create an IndexedDB cache. Storage failures preserve successful network results. */
2320
+ function createPersistentCache(options) {
2321
+ validateOptions(options);
2322
+ return createCache({ ...options }, persistentStorage(options.namespace, options.schemaVersion), false);
2323
+ }
2324
+ /** Create a login-scoped sessionStorage cache. Data must survive JSON serialization and decoding. */
2325
+ function createSessionCache(options) {
2326
+ validateOptions(options);
2327
+ if (typeof options.sessionId !== "string" || !options.sessionId.trim()) throw new TypeError("sessionId must be nonempty");
2328
+ return createCache({ ...options }, sessionStorageBackend(options.namespace, options.schemaVersion, options.sessionId), true);
2329
+ }
1991
2330
  //#endregion
1992
- //#region src/workbench/browser/runtime/stores/catalogStorage.ts
1993
- var responses = createStore("open-flow-cache", "responses");
1994
- var indexedStorage = {
1995
- get: (key) => get(key, responses),
1996
- set: (key, value) => set(key, value, responses)
2331
+ //#region ../../node_modules/.bun/@oomol-lab+resource-cache@0.1.4/node_modules/@oomol-lab/resource-cache/dist/oomol.mjs
2332
+ /** Namespaces reserved for the OOMOL response factories. */
2333
+ var oomolNamespaces = {
2334
+ providers: "oomol:providers",
2335
+ actions: "oomol:actions",
2336
+ appCatalog: "oomol:app-catalog",
2337
+ connections: "oomol:connections"
1997
2338
  };
1998
- function catalogPersistence(options, kind, query) {
1999
- if (options == null) return void 0;
2000
- const storage = options.storage ?? indexedStorage;
2339
+ /** Join identity fields without nesting JSON in the storage key. */
2340
+ function readableKey(...parts) {
2341
+ return parts.map((part) => encodeURIComponent(String(part)).replaceAll("%3A", ":")).join("/");
2342
+ }
2343
+ var singletonRegistrySymbol = Symbol.for("oomol-lab.resource-cache.oomol-singletons");
2344
+ var singletonCaches = Reflect.get(globalThis, singletonRegistrySymbol) ?? (() => {
2345
+ const registry = /* @__PURE__ */ new Map();
2346
+ Reflect.set(globalThis, singletonRegistrySymbol, registry);
2347
+ return registry;
2348
+ })();
2349
+ function createOomolCache(resource, options, query) {
2350
+ const environment = validateOomolOptions(options);
2351
+ const { load } = options;
2352
+ const key = readableKey(query.locale);
2353
+ return createPersistentCache({
2354
+ namespace: readableKey(resource, environment),
2355
+ schemaVersion: options.schemaVersion,
2356
+ maxAge: options.maxAge,
2357
+ key: () => key,
2358
+ decode: options.decode,
2359
+ load: (_query, validation) => load({ ...query }, validation)
2360
+ });
2361
+ }
2362
+ function createConnectionsCacheInternal(options, validated) {
2363
+ const { environment, ownerId } = validated;
2364
+ const { load } = options;
2365
+ const key = readableKey(ownerId);
2366
+ return createSessionCache({
2367
+ namespace: readableKey(oomolNamespaces.connections, environment),
2368
+ schemaVersion: options.schemaVersion,
2369
+ maxAge: options.maxAge,
2370
+ sessionId: options.sessionId,
2371
+ key: () => key,
2372
+ decode: options.decode,
2373
+ load: (_query, validation) => load({ ownerId }, validation)
2374
+ });
2375
+ }
2376
+ function validateOomolOptions(options) {
2377
+ const environment = normalizeEnvironment(options.environment);
2378
+ if (typeof options.locale !== "string" || !options.locale.trim()) throw new TypeError("locale must be nonempty");
2379
+ if (typeof options.load !== "function") throw new TypeError("load must be a function");
2380
+ return environment;
2381
+ }
2382
+ function normalizeEnvironment(value) {
2383
+ const environment = value === void 0 ? "production" : value;
2384
+ if (typeof environment !== "string" || !environment.trim()) throw new TypeError("environment must be nonempty");
2385
+ return environment;
2386
+ }
2387
+ function normalizeOwnerId(value) {
2388
+ if (typeof value !== "string" || !value.trim()) throw new TypeError("ownerId must be nonempty");
2389
+ return value;
2390
+ }
2391
+ function validateConnectionsOptions(options) {
2392
+ const environment = normalizeEnvironment(options.environment);
2393
+ if (typeof options.sessionId !== "string" || !options.sessionId.trim()) throw new TypeError("sessionId must be nonempty");
2394
+ const ownerId = normalizeOwnerId(options.ownerId);
2395
+ if (typeof options.load !== "function") throw new TypeError("load must be a function");
2001
2396
  return {
2002
- key: `${kind}:v1:${query}`,
2003
- storage
2397
+ environment,
2398
+ ownerId
2004
2399
  };
2005
2400
  }
2401
+ /** Create an IndexedDB cache for the account-independent GET /v1/providers response, keyed by environment and locale. */
2402
+ function createProvidersCacheInternal(options) {
2403
+ return createOomolCache(oomolNamespaces.providers, options, { locale: options.locale });
2404
+ }
2405
+ /** Create an IndexedDB cache for account-independent GET /v1/actions?service=…, keyed by environment, locale and service. */
2406
+ function createActionsCacheInternal(options) {
2407
+ const environment = validateOomolOptions(options);
2408
+ const { locale, load } = options;
2409
+ return createPersistentCache({
2410
+ namespace: readableKey(oomolNamespaces.actions, environment),
2411
+ schemaVersion: options.schemaVersion,
2412
+ maxAge: options.maxAge,
2413
+ key: (service) => {
2414
+ if (typeof service !== "string" || !service.trim()) throw new TypeError("service must be nonempty");
2415
+ return readableKey(locale, service);
2416
+ },
2417
+ decode: options.decode,
2418
+ load: (service, validation) => load({
2419
+ locale,
2420
+ service
2421
+ }, validation)
2422
+ });
2423
+ }
2424
+ function singletonKey(resource, options, query, sessionId) {
2425
+ const environment = normalizeEnvironment(options.environment);
2426
+ return sessionId === void 0 ? readableKey(resource, environment, options.schemaVersion, ...query) : readableKey(resource, environment, options.schemaVersion, sessionId, ...query);
2427
+ }
2428
+ function getSingleton(key, create) {
2429
+ const existing = singletonCaches.get(key);
2430
+ if (existing) return existing;
2431
+ const cache = create();
2432
+ let disposal;
2433
+ const singleton = {
2434
+ ...cache,
2435
+ dispose() {
2436
+ if (!disposal) disposal = cache.dispose().then(() => {
2437
+ singletonCaches.delete(key);
2438
+ }, (error) => {
2439
+ disposal = void 0;
2440
+ throw error;
2441
+ });
2442
+ return disposal;
2443
+ }
2444
+ };
2445
+ singletonCaches.set(key, singleton);
2446
+ return singleton;
2447
+ }
2448
+ /** Return the shared Providers cache for one environment, locale and schema version. */
2449
+ function getProvidersCache(options) {
2450
+ const query = { locale: options.locale };
2451
+ return getSingleton(singletonKey(oomolNamespaces.providers, options, [query.locale]), () => createProvidersCacheInternal(options));
2452
+ }
2453
+ /** Return the shared Actions cache for one environment, locale and schema version. */
2454
+ function getActionsCache(options) {
2455
+ const query = { locale: options.locale };
2456
+ return getSingleton(singletonKey(oomolNamespaces.actions, options, [query.locale]), () => createActionsCacheInternal(options));
2457
+ }
2458
+ /** Return the shared sessionStorage cache for one login session and owner scope. */
2459
+ function getConnectionsCache(options) {
2460
+ const validated = validateConnectionsOptions(options);
2461
+ const query = { ownerId: validated.ownerId };
2462
+ return getSingleton(singletonKey(oomolNamespaces.connections, options, [query.ownerId], options.sessionId), () => createConnectionsCacheInternal(options, validated));
2463
+ }
2006
2464
  //#endregion
2007
2465
  //#region src/connector/common/actionSchema.ts
2008
2466
  function connectorActionPorts(inputSchema, outputSchema) {
@@ -2176,46 +2634,178 @@ function action(source, providers) {
2176
2634
  }
2177
2635
  //#endregion
2178
2636
  //#region src/workbench/browser/runtime/stores/catalogStores.ts
2179
- function actionsResponse(value) {
2637
+ var catalogMaxAge = {
2638
+ providers: 3e5,
2639
+ actions: 3e4,
2640
+ connections: 3e4
2641
+ };
2642
+ var identity = (...parts) => JSON.stringify(parts);
2643
+ function proxyCatalogPath(kind, flowId, locale, service) {
2644
+ return `/v1/connector/proxy/${kind}?${new URLSearchParams({
2645
+ ...flowId == null ? {} : { flowId },
2646
+ ...service == null ? {} : { service },
2647
+ locale
2648
+ })}`;
2649
+ }
2650
+ function mapCache(cache, toValue, toSnapshot, query) {
2651
+ return {
2652
+ get: async (value, options) => toValue(await cache.get(query(value), options)),
2653
+ peek: async (value) => {
2654
+ const snapshot = await cache.peek(query(value));
2655
+ return snapshot == null ? void 0 : {
2656
+ ...snapshot,
2657
+ data: toSnapshot(snapshot.data)
2658
+ };
2659
+ },
2660
+ invalidate: (value) => cache.invalidate(query(value)),
2661
+ remove: (value) => cache.remove(query(value)),
2662
+ clear: () => cache.clear(),
2663
+ dispose: () => cache.dispose()
2664
+ };
2665
+ }
2666
+ function providerCacheValue(value) {
2667
+ return proxyResponse(value);
2668
+ }
2669
+ function actionCacheValue(value) {
2670
+ return proxyResponse(value);
2671
+ }
2672
+ function connectionsCacheValue(value) {
2180
2673
  const source = record(value);
2181
- if (source.version != 1 || !Array.isArray(source.actions)) return invalidResponse();
2182
- return source.actions.map(connectorActionMetadata);
2674
+ if (source.success === true && Array.isArray(source.data)) return source;
2675
+ if (source.version == 1 && Array.isArray(source.connections)) return {
2676
+ success: true,
2677
+ message: "",
2678
+ data: source.connections,
2679
+ meta: { summary: {
2680
+ providerCount: 0,
2681
+ connectableProviderCount: 0,
2682
+ connectedProviderCount: 0,
2683
+ activeConnectedProviderCount: 0,
2684
+ connectedAppCount: source.connections.length,
2685
+ activeConnectedAppCount: source.connections.length,
2686
+ filteredAppCount: source.connections.length
2687
+ } }
2688
+ };
2689
+ return invalidResponse();
2183
2690
  }
2184
- var identity = (...parts) => JSON.stringify(parts);
2185
- /** Each entry owns one complete upstream response, never a merged entity catalog. */
2691
+ function connectionsAsProxy(value) {
2692
+ return value.data.map(connection);
2693
+ }
2694
+ /** Shared cache construction for one Workbench session. */
2695
+ var CacheFactory = class {
2696
+ #caches = /* @__PURE__ */ new Set();
2697
+ #entries = /* @__PURE__ */ new Map();
2698
+ #disposed = false;
2699
+ constructor(scope) {
2700
+ this.scope = scope;
2701
+ }
2702
+ cache(key, create, owned = true) {
2703
+ let entry = this.#entries.get(key);
2704
+ if (entry == null) {
2705
+ entry = create().then((cache) => {
2706
+ if (owned) {
2707
+ if (this.#disposed) cache.dispose();
2708
+ else this.#caches.add(cache);
2709
+ }
2710
+ return cache;
2711
+ });
2712
+ this.#entries.set(key, entry);
2713
+ }
2714
+ return entry;
2715
+ }
2716
+ async dispose() {
2717
+ this.#disposed = true;
2718
+ await Promise.all([...this.#caches].map((cache) => cache.dispose()));
2719
+ this.#caches.clear();
2720
+ this.#entries.clear();
2721
+ }
2722
+ get environment() {
2723
+ return this.scope.environment ?? "production";
2724
+ }
2725
+ get sessionId() {
2726
+ return this.scope.sessionId;
2727
+ }
2728
+ get connectorOwnerId() {
2729
+ return this.scope.connectorOwnerId;
2730
+ }
2731
+ };
2732
+ /** Each entry owns one complete upstream response; views are derived below. */
2186
2733
  var ProxyStore = class {
2187
- constructor(client, kind, options) {
2734
+ #factory;
2735
+ constructor(client, kind, scope) {
2188
2736
  this.client = client;
2189
2737
  this.kind = kind;
2190
- this.options = options;
2191
2738
  this.entries = /* @__PURE__ */ new Map();
2739
+ this.#factory = new CacheFactory(scope);
2192
2740
  }
2193
- get(flowId, locale, service, force = false) {
2194
- const params = new URLSearchParams({
2195
- ...flowId == null ? {} : { flowId },
2196
- ...service == null ? {} : { service },
2197
- ...locale == null ? {} : { locale }
2198
- });
2199
- const path = `/v1/connector/proxy/${this.kind}${params.size ? `?${params}` : ""}`;
2741
+ get(flowId, locale = "en", service, force = false) {
2742
+ const path = proxyCatalogPath(this.kind, flowId, locale, service);
2200
2743
  let entry = this.entries.get(path);
2201
2744
  if (entry == null) {
2202
- const decode = (value) => proxyResponse(value, this.kind == "providers" ? provider : void 0);
2203
- const cacheParams = new URLSearchParams(params);
2204
- cacheParams.delete("flowId");
2205
- const persistence = catalogPersistence(this.options, this.kind, cacheParams.toString());
2206
- entry = new Resource((etag, signal) => this.client.readProxyCatalog({
2207
- path,
2208
- decode
2209
- }, etag, signal), this.kind == "providers" ? 3e5 : 3e4, persistence == null ? void 0 : {
2210
- ...persistence,
2211
- decode
2212
- });
2745
+ entry = new CacheResource(() => this.#cache(flowId, locale, service, path), void 0, false, catalogMaxAge[this.kind]);
2213
2746
  this.entries.set(path, entry);
2214
2747
  }
2215
2748
  return entry.get(force);
2216
2749
  }
2750
+ async #cache(flowId, locale, service, path) {
2751
+ const ownerId = this.#factory.connectorOwnerId;
2752
+ const key = JSON.stringify([
2753
+ this.kind,
2754
+ flowId ?? null,
2755
+ locale,
2756
+ service ?? null,
2757
+ ownerId ?? null
2758
+ ]);
2759
+ return this.#factory.cache(key, async () => {
2760
+ if (ownerId != null) {
2761
+ if (this.kind == "providers") return mapCache(getProvidersCache({
2762
+ environment: this.#factory.environment,
2763
+ locale,
2764
+ schemaVersion: 1,
2765
+ maxAge: catalogMaxAge.providers,
2766
+ decode: providerCacheValue,
2767
+ load: async (_query, validation) => {
2768
+ return await this.client.readProxyCatalog({
2769
+ path,
2770
+ decode: providerCacheValue
2771
+ }, validation.etag, validation.signal);
2772
+ }
2773
+ }), (value) => value, (value) => value, () => void 0);
2774
+ return mapCache(getActionsCache({
2775
+ environment: this.#factory.environment,
2776
+ locale,
2777
+ schemaVersion: 1,
2778
+ maxAge: catalogMaxAge.actions,
2779
+ decode: actionCacheValue,
2780
+ load: async ({ service: requestedService }, validation) => {
2781
+ return await this.client.readProxyCatalog({
2782
+ path: proxyCatalogPath("actions", flowId, locale, requestedService),
2783
+ decode: actionCacheValue
2784
+ }, validation.etag, validation.signal);
2785
+ }
2786
+ }), (value) => value, (value) => value, () => service ?? "");
2787
+ }
2788
+ return createSessionCache({
2789
+ namespace: JSON.stringify([
2790
+ "open-flow:connector-proxy",
2791
+ this.#factory.environment,
2792
+ this.kind,
2793
+ flowId ?? null
2794
+ ]),
2795
+ schemaVersion: 1,
2796
+ sessionId: this.#factory.sessionId,
2797
+ maxAge: this.kind == "providers" ? catalogMaxAge.providers : catalogMaxAge.actions,
2798
+ key: () => JSON.stringify([locale, service ?? null]),
2799
+ decode: proxyResponse,
2800
+ load: async (_query, validation) => this.client.readProxyCatalog({
2801
+ path,
2802
+ decode: proxyResponse
2803
+ }, validation.etag, validation.signal)
2804
+ });
2805
+ }, ownerId == null);
2806
+ }
2217
2807
  retryFailed() {
2218
- for (const entry of this.entries.values()) if (entry.state.value.error != null) entry.refresh();
2808
+ for (const entry of this.entries.values()) if (entry.state.value.error != null) entry.refresh(true);
2219
2809
  }
2220
2810
  refreshFlow(flowId) {
2221
2811
  for (const [path, entry] of this.entries) if (new URL(path, "https://open-flow.invalid").searchParams.get("flowId") == flowId) entry.refresh(true);
@@ -2223,6 +2813,7 @@ var ProxyStore = class {
2223
2813
  dispose() {
2224
2814
  for (const entry of this.entries.values()) entry.dispose();
2225
2815
  this.entries.clear();
2816
+ this.#factory.dispose();
2226
2817
  }
2227
2818
  };
2228
2819
  var Views = class {
@@ -2273,8 +2864,8 @@ var Views = class {
2273
2864
  };
2274
2865
  var ProviderStore = class {
2275
2866
  #views = new Views();
2276
- constructor(client, options) {
2277
- this.raw = new ProxyStore(client, "providers", options);
2867
+ constructor(client, scope) {
2868
+ this.raw = new ProxyStore(client, "providers", scope);
2278
2869
  }
2279
2870
  get(flowId, locale = "en", force = false) {
2280
2871
  return this.#views.get(identity(flowId, locale), [this.raw.get(flowId, locale, void 0, force)], (response) => response.data.map((item) => provider(item, response.meta?.iconSprite)));
@@ -2291,33 +2882,17 @@ var ProviderStore = class {
2291
2882
  }
2292
2883
  };
2293
2884
  var ConnectionStore = class {
2294
- #storage = {
2295
- get: async (key) => {
2296
- const raw = (this.options?.storage ?? window.sessionStorage).getItem(key);
2297
- return raw == null ? void 0 : JSON.parse(raw);
2298
- },
2299
- set: async (key, value) => {
2300
- (this.options?.storage ?? window.sessionStorage).setItem(key, JSON.stringify(value));
2301
- }
2302
- };
2303
2885
  #entries = /* @__PURE__ */ new Map();
2304
2886
  #views = /* @__PURE__ */ new Map();
2305
- constructor(client, options) {
2887
+ #factory;
2888
+ constructor(client, scope) {
2306
2889
  this.client = client;
2307
- this.options = options;
2890
+ this.#factory = new CacheFactory(scope);
2308
2891
  }
2309
2892
  get(serviceId, flowId, force = false) {
2310
2893
  let entry = this.#entries.get(flowId);
2311
2894
  if (entry == null) {
2312
- const query = allConnectorConnectionsQuery(flowId);
2313
- entry = new Resource((etag, signal) => this.client.readCatalog(query, etag, signal), 3e4, this.options == null ? void 0 : {
2314
- key: `open-flow:connections:v1:${query.path}`,
2315
- storage: this.#storage,
2316
- decode: (value) => {
2317
- if (!Array.isArray(value)) return invalidResponse();
2318
- return value.map(connection);
2319
- }
2320
- });
2895
+ entry = new CacheResource(() => this.#cache(flowId), void 0, false, catalogMaxAge.connections);
2321
2896
  this.#entries.set(flowId, entry);
2322
2897
  }
2323
2898
  const source = entry.get(force);
@@ -2333,8 +2908,54 @@ var ConnectionStore = class {
2333
2908
  }
2334
2909
  return view;
2335
2910
  }
2911
+ async #cache(flowId) {
2912
+ const query = allConnectorConnectionsQuery(flowId);
2913
+ const ownerId = this.#factory.connectorOwnerId;
2914
+ const key = JSON.stringify([
2915
+ "connections",
2916
+ flowId ?? null,
2917
+ ownerId ?? null
2918
+ ]);
2919
+ return this.#factory.cache(key, async () => {
2920
+ if (ownerId != null) return mapCache(getConnectionsCache({
2921
+ environment: this.#factory.environment,
2922
+ sessionId: this.#factory.sessionId,
2923
+ ownerId,
2924
+ schemaVersion: 1,
2925
+ maxAge: catalogMaxAge.connections,
2926
+ decode: connectionsCacheValue,
2927
+ load: async (_query, validation) => {
2928
+ const result = await this.client.readCatalog(query, validation.etag, validation.signal);
2929
+ return result.modified ? {
2930
+ modified: true,
2931
+ data: connectionsCacheValue({
2932
+ version: 1,
2933
+ connections: result.data
2934
+ }),
2935
+ etag: result.etag
2936
+ } : result;
2937
+ }
2938
+ }), connectionsAsProxy, connectionsAsProxy, () => void 0);
2939
+ return createSessionCache({
2940
+ namespace: JSON.stringify([
2941
+ "open-flow:connections",
2942
+ this.#factory.environment,
2943
+ flowId ?? null
2944
+ ]),
2945
+ schemaVersion: 1,
2946
+ sessionId: this.#factory.sessionId,
2947
+ maxAge: catalogMaxAge.connections,
2948
+ key: () => "all",
2949
+ decode: (value) => {
2950
+ if (!Array.isArray(value)) return invalidResponse();
2951
+ return value.map(connection);
2952
+ },
2953
+ load: async (_query, validation) => this.client.readCatalog(query, validation.etag, validation.signal)
2954
+ });
2955
+ }, ownerId == null);
2956
+ }
2336
2957
  retryFailed() {
2337
- for (const entry of this.#entries.values()) if (entry.state.value.error != null) entry.refresh();
2958
+ for (const entry of this.#entries.values()) if (entry.state.value.error != null) entry.refresh(true);
2338
2959
  }
2339
2960
  refreshFlow(flowId) {
2340
2961
  this.#entries.get(flowId)?.refresh(true);
@@ -2344,6 +2965,7 @@ var ConnectionStore = class {
2344
2965
  this.#views.clear();
2345
2966
  for (const entry of this.#entries.values()) entry.dispose();
2346
2967
  this.#entries.clear();
2968
+ this.#factory.dispose();
2347
2969
  }
2348
2970
  };
2349
2971
  var ActionStore = class {
@@ -2352,10 +2974,10 @@ var ActionStore = class {
2352
2974
  #details = /* @__PURE__ */ new Map();
2353
2975
  #searches = /* @__PURE__ */ new Set();
2354
2976
  #searchSessions = /* @__PURE__ */ new WeakMap();
2355
- constructor(client, providers, options) {
2977
+ constructor(client, providers, scope) {
2356
2978
  this.client = client;
2357
2979
  this.providers = providers;
2358
- this.#raw = new ProxyStore(client, "actions", options);
2980
+ this.#raw = new ProxyStore(client, "actions", scope);
2359
2981
  }
2360
2982
  get(serviceId, flowId, locale = "en", force = false) {
2361
2983
  return this.#views.get(identity(flowId, serviceId, locale), [this.#raw.get(flowId, locale, serviceId, force), this.providers.raw.get(flowId, locale)], (actions, providers) => actions.data.flatMap((item) => {
@@ -2399,7 +3021,6 @@ var ActionStore = class {
2399
3021
  q: query.trim(),
2400
3022
  locale
2401
3023
  });
2402
- const key = params.toString();
2403
3024
  let entries = this.#searchSessions.get(signal);
2404
3025
  if (entries == null) {
2405
3026
  entries = /* @__PURE__ */ new Map();
@@ -2414,21 +3035,38 @@ var ActionStore = class {
2414
3035
  this.#searchSessions.delete(signal);
2415
3036
  }, { once: true });
2416
3037
  }
3038
+ const key = params.toString();
2417
3039
  const cached = entries.get(key);
2418
3040
  if (cached != null) {
2419
- cached.refresh();
3041
+ cached.refresh(true);
2420
3042
  return cached;
2421
3043
  }
2422
- const resource = new Resource((_etag, requestSignal) => this.client.readCatalog({
2423
- path: `/v1/connector/action-metadata?${params}`,
2424
- decode: actionsResponse
2425
- }, null, requestSignal), 3e4);
2426
- if (signal.aborted) resource.dispose();
3044
+ const cache = createSessionCache({
3045
+ namespace: JSON.stringify(["open-flow:action-search", crypto.randomUUID()]),
3046
+ schemaVersion: 1,
3047
+ sessionId: "search",
3048
+ maxAge: 0,
3049
+ key: () => "result",
3050
+ decode: (value) => {
3051
+ if (!Array.isArray(value)) return invalidResponse();
3052
+ return value.map(connectorActionMetadata);
3053
+ },
3054
+ load: async (_query, validation) => this.client.readCatalog({
3055
+ path: `/v1/connector/action-metadata?${params}`,
3056
+ decode: (value) => {
3057
+ const source = record(value);
3058
+ if (source.version != 1 || !Array.isArray(source.actions)) return invalidResponse();
3059
+ return source.actions.map(connectorActionMetadata);
3060
+ }
3061
+ }, validation.etag, validation.signal)
3062
+ });
3063
+ const result = new CacheResource(async () => cache, void 0, true, 0);
3064
+ if (signal.aborted) result.dispose();
2427
3065
  else {
2428
- entries.set(key, resource);
2429
- this.#searches.add(resource);
3066
+ entries.set(key, result);
3067
+ this.#searches.add(result);
2430
3068
  }
2431
- return resource;
3069
+ return result;
2432
3070
  }
2433
3071
  retryFailed() {
2434
3072
  this.#raw.retryFailed();
@@ -2446,10 +3084,10 @@ var ActionStore = class {
2446
3084
  }
2447
3085
  };
2448
3086
  var CatalogStores = class {
2449
- constructor(client, options, connections) {
2450
- this.providers = new ProviderStore(client, options);
2451
- this.actions = new ActionStore(client, this.providers, options);
2452
- this.connections = new ConnectionStore(client, connections);
3087
+ constructor(client, scope = { sessionId: crypto.randomUUID() }) {
3088
+ this.providers = new ProviderStore(client, scope);
3089
+ this.actions = new ActionStore(client, this.providers, scope);
3090
+ this.connections = new ConnectionStore(client, scope);
2453
3091
  }
2454
3092
  dispose() {
2455
3093
  this.actions.dispose();
@@ -2625,6 +3263,26 @@ var ConnectorAccessStore = class {
2625
3263
  }
2626
3264
  return false;
2627
3265
  }
3266
+ allowedTriggerCandidates(providerId, triggerId) {
3267
+ return this.#state.value.candidates[providerId]?.candidates.filter((candidate) => candidate.permissions == null || candidate.permissions.allTriggers || candidate.permissions.triggerIds.includes(triggerId));
3268
+ }
3269
+ async filterTriggerConnections(flowId, definition, connections) {
3270
+ if (this.#disposed || flowId != this.#flowId) return [];
3271
+ const access = this.#state.value.access;
3272
+ if (access?.mode == "implicit") return connections;
3273
+ if (access == null) return [];
3274
+ await this.loadCandidates([definition.provider]);
3275
+ if (this.#disposed || flowId != this.#flowId) return [];
3276
+ const candidates = this.allowedTriggerCandidates(definition.provider, definition.key);
3277
+ if (candidates == null) return [];
3278
+ const allowed = new Set(candidates.map((candidate) => candidate.connectionId));
3279
+ const filtered = connections.filter((connection) => allowed.has(connection.connectionId));
3280
+ if (!filtered.some((connection) => connection.status == "active") && connections.some((connection) => connection.status == "active")) this.setNotice({
3281
+ kind: "error",
3282
+ message: this.i18n.t("connectorAccess.noAvailablePermissions")
3283
+ });
3284
+ return filtered;
3285
+ }
2628
3286
  async setService(providerId, selected) {
2629
3287
  const flowId = this.#flowId;
2630
3288
  const access = this.#state.value.access;
@@ -2829,8 +3487,9 @@ var ConnectorStore = class {
2829
3487
  };
2830
3488
  this.provideAddNodeOptionChoices = (optionId, signal) => {
2831
3489
  const service = optionId.slice(19);
2832
- const source = this.data.actions.get(service, void 0, this.#language);
2833
- const providers = this.data.providers.get(void 0, this.#language);
3490
+ const flowId = this.#workspace.$.flowId.value;
3491
+ const source = this.data.actions.get(service, flowId, this.#language);
3492
+ const providers = this.data.providers.get(flowId, this.#language);
2834
3493
  return scopedValue(signal, (get) => {
2835
3494
  const state = get(source);
2836
3495
  const provider = get(providers).data?.find((item) => item.serviceId == service);
@@ -2961,12 +3620,22 @@ var ConnectorStore = class {
2961
3620
  this.#actionIds.set([]);
2962
3621
  this.#services.set([]);
2963
3622
  }
3623
+ retryAction(actionId) {
3624
+ const flowId = this.#workspace.$.flowId.value;
3625
+ if (flowId == null || this.#disposed) return;
3626
+ const actionState = this.data.actions.detail(actionId, flowId, this.#language, true);
3627
+ if (this.data.providers.get(flowId, this.#language).value.error != null) this.data.providers.get(flowId, this.#language, true);
3628
+ if (actionState.value.data?.authenticated !== false) this.data.connections.refreshFlow(flowId);
3629
+ }
2964
3630
  async resolveAction(actionId) {
2965
3631
  const flowId = this.#workspace.$.flowId.value;
2966
3632
  if (flowId == null || this.#disposed) throw new Error("Connector Action cannot be resolved without an active Flow.");
3633
+ const actionState = this.data.actions.detail(actionId, flowId, this.#language);
3634
+ await Promise.resolve();
3635
+ const action = await resourceValue(actionState, void 0, true);
3636
+ const connectionState = action.authenticated ? this.data.connections.get(action.serviceId, flowId) : void 0;
2967
3637
  await Promise.resolve();
2968
- const action = await resourceValue(this.data.actions.detail(actionId, flowId, this.#language), void 0, true);
2969
- const connections = action.authenticated ? await resourceValue(this.data.connections.get(action.serviceId, flowId), void 0, true) : [];
3638
+ const connections = connectionState == null ? [] : await resourceValue(connectionState, void 0, true);
2970
3639
  this.#remember(this.#actionIds, [actionId]);
2971
3640
  if (action.authenticated) this.#remember(this.#services, [action.serviceId]);
2972
3641
  return {
@@ -3143,9 +3812,9 @@ var ConnectorStore = class {
3143
3812
  var TriggerCatalogStore = class {
3144
3813
  #language;
3145
3814
  #entries;
3146
- constructor(client, language, host) {
3815
+ constructor(client, language, environment = "production") {
3147
3816
  this.client = client;
3148
- this.host = host;
3817
+ this.environment = environment;
3149
3818
  this.#entries = /* @__PURE__ */ new Map();
3150
3819
  this.retry = () => {
3151
3820
  this.get(true);
@@ -3161,14 +3830,18 @@ var TriggerCatalogStore = class {
3161
3830
  if (data.locale != locale) throw new Error("Unexpected Trigger catalog language.");
3162
3831
  return data;
3163
3832
  };
3164
- const persistence = catalogPersistence(this.host.catalogCache, "triggers", locale);
3165
- entry = new Resource((etag, signal) => this.client.readCatalog({
3166
- path: `/v1/trigger-keys/catalog?locale=${encodeURIComponent(locale)}`,
3167
- decode
3168
- }, etag, signal), 3e5, persistence == null ? void 0 : {
3169
- ...persistence,
3170
- decode
3833
+ const cache = createPersistentCache({
3834
+ namespace: JSON.stringify(["open-flow:trigger-catalog", this.environment]),
3835
+ schemaVersion: 1,
3836
+ maxAge: 3e5,
3837
+ key: () => locale,
3838
+ decode,
3839
+ load: async (_query, validation) => this.client.readCatalog({
3840
+ path: `/v1/trigger-keys/catalog?locale=${encodeURIComponent(locale)}`,
3841
+ decode
3842
+ }, validation.etag, validation.signal)
3171
3843
  });
3844
+ entry = new CacheResource(async () => cache, void 0, true, 3e5);
3172
3845
  this.#entries.set(locale, entry);
3173
3846
  }
3174
3847
  return entry;
@@ -3247,7 +3920,7 @@ var TriggerStore = class {
3247
3920
  this.#disposed = false;
3248
3921
  this.browseAddNodeOptions = (signal) => this.#options("", signal);
3249
3922
  this.provideAddNodeOptions = (searchTerm, signal) => this.#options(searchTerm, signal);
3250
- this.catalog = new TriggerCatalogStore(client, resolveUiLanguage([i18n.lang]), host);
3923
+ this.catalog = new TriggerCatalogStore(client, resolveUiLanguage([i18n.lang]), host.cacheEnvironment);
3251
3924
  this.#client = client;
3252
3925
  this.#host = host;
3253
3926
  this.#i18n = i18n;
@@ -3262,7 +3935,7 @@ var TriggerStore = class {
3262
3935
  if (trigger.kind != "poll" && trigger.kind != "integration") return { authorizationPending: false };
3263
3936
  const connections = current == null ? void 0 : get(workspace.catalogs.connections.get(current.provider, get(workspace.$.flowId))).data;
3264
3937
  const catalog = connections == null ? void 0 : connectionCatalog(connections);
3265
- const connectionError = current == null ? void 0 : get(workspace.catalogs.connections.get(current.provider, get(workspace.$.flowId))).error;
3938
+ const connectionError = current == null ? void 0 : state.connectionError?.provider == current.provider ? new Error(state.connectionError.message) : get(workspace.catalogs.connections.get(current.provider, get(workspace.$.flowId))).error;
3266
3939
  return {
3267
3940
  activeConnections: catalog?.active,
3268
3941
  authorizationPending: state.authorizationProvider == current?.provider,
@@ -3628,6 +4301,7 @@ function inverseFlowChanges(content, operations) {
3628
4301
  value: operation.before
3629
4302
  });
3630
4303
  break;
4304
+ case "task.openapi.set":
3631
4305
  case "task.agent.set":
3632
4306
  restore.push({
3633
4307
  ...operation,
@@ -4699,10 +5373,11 @@ var WorkspaceStore = class {
4699
5373
  #pendingRepair;
4700
5374
  #stopCatalogWatch;
4701
5375
  #stopFlowWatch;
4702
- constructor(client, setNotice, identity = createAuthoringId, i18n = createI18n(), runChanged = () => {}, catalogs = new CatalogStores(client), flowCreated = () => {}, accessChanged = () => {}) {
5376
+ constructor(client, setNotice, identity = createAuthoringId, i18n = createI18n(), runChanged = () => {}, catalogs = new CatalogStores(client), flowCreated = () => {}, accessChanged = () => {}, filterTriggerConnections) {
4703
5377
  this.catalogs = catalogs;
4704
5378
  this.flowCreated = flowCreated;
4705
5379
  this.accessChanged = accessChanged;
5380
+ this.filterTriggerConnections = filterTriggerConnections;
4706
5381
  this.#draftSession = new Latest();
4707
5382
  this.#history = new CanvasHistory();
4708
5383
  this.history$ = this.#history.state$;
@@ -5022,9 +5697,10 @@ var WorkspaceStore = class {
5022
5697
  if (intent.kind == "provider-trigger" && intent.connectionId == null) {
5023
5698
  try {
5024
5699
  const connections = await resourceValue(this.catalogs.connections.get(intent.definition.provider, draft.flowId));
5700
+ const allowed = this.filterTriggerConnections == null ? connections : await this.filterTriggerConnections(draft.flowId, intent.definition, connections);
5025
5701
  intent = {
5026
5702
  ...intent,
5027
- connectionId: connectionCatalog(connections).preferred?.connectionId
5703
+ connectionId: connectionCatalog(allowed).preferred?.connectionId
5028
5704
  };
5029
5705
  } catch (error) {
5030
5706
  if (!this.#disposed && this.#model.value.draft == draft) this.#setNotice(errorNotice(error, this.#i18n.t));
@@ -5268,6 +5944,9 @@ var WorkspaceStore = class {
5268
5944
  position
5269
5945
  }));
5270
5946
  }
5947
+ loadOpenApiDocument(url, signal) {
5948
+ return this.#client.loadOpenApiDocument(url, signal);
5949
+ }
5271
5950
  async saveTaskSettings(nodeId, settings) {
5272
5951
  const revision = this.$.revision.value;
5273
5952
  const target = this.#model.value.target;
@@ -5817,7 +6496,7 @@ var WorkbenchStore = class {
5817
6496
  #openingCreatedFlow;
5818
6497
  #stopAccessReaction;
5819
6498
  #accessLoading;
5820
- constructor(client, preferences, identity = randomId, i18n = createI18n(), host = blockedExternalPages, variables = true) {
6499
+ constructor(client, preferences, identity = randomId, i18n = createI18n(), host = blockedExternalPages, variables = true, cacheSessionId = crypto.randomUUID()) {
5821
6500
  this.#externalRuns = new Latest();
5822
6501
  this.#notice = val();
5823
6502
  this.#variableNames = val([]);
@@ -5851,9 +6530,16 @@ var WorkbenchStore = class {
5851
6530
  this.workspace = new WorkspaceStore(client, setNotice, createAuthoringId, i18n, (event) => {
5852
6531
  if (event.kind == "run.created") this.#followExternalRun(client, event);
5853
6532
  else this.runs.changed(event.runId);
5854
- }, new CatalogStores(client, host.catalogCache, host.connectionCache), (flowId) => void this.#openCreatedFlow(flowId), (flowId) => {
6533
+ }, new CatalogStores(client, {
6534
+ sessionId: cacheSessionId,
6535
+ environment: host.cacheEnvironment,
6536
+ connectorOwnerId: host.connectorOwnerId
6537
+ }), (flowId) => void this.#openCreatedFlow(flowId), (flowId) => {
5855
6538
  this.connectorAccess.changed(flowId);
5856
6539
  this.workspace.catalogs.refreshFlow(flowId);
6540
+ }, async (flowId, definition, connections) => {
6541
+ await this.#accessLoading;
6542
+ return this.connectorAccess.filterTriggerConnections(flowId, definition, connections);
5857
6543
  });
5858
6544
  this.#stopAccessReaction = this.workspace.$.flowId.reaction((flowId) => {
5859
6545
  this.#accessLoading = this.connectorAccess.load(flowId);
@@ -6229,7 +6915,7 @@ var WorkbenchStore = class {
6229
6915
  };
6230
6916
  //#endregion
6231
6917
  //#region src/workbench/browser/runtime/openFlowWorkbench.tsx
6232
- var FlowWorkspace = lazy(() => import("./flowWorkspace-DBaq2Eks.js"));
6918
+ var FlowWorkspace = lazy(() => import("./flowWorkspace-CoT_ewLX.js"));
6233
6919
  function OpenFlowSessionGate({ action, description, error, onSubmit, onTokenChange, pending = false, title, token, tokenLabel }) {
6234
6920
  const hasToken = token != null && tokenLabel != null && onTokenChange != null;
6235
6921
  const tokenValue = token ?? "";
@@ -6364,17 +7050,17 @@ function Workbench({ catalogWidth, createFlow, createFlowDisabled, createFlowFie
6364
7050
  })
6365
7051
  });
6366
7052
  }
6367
- function Session({ catalogWidth, createFlow, createFlowDisabled, createFlowField, flowBadges, connectionHref, host, hrefFor, language, location, onConfigureConnector, onManageConnectorAccess, onLanguageChange, onNavigate, preferences, theme, variables = true }) {
7053
+ function Session({ catalogWidth, createFlow, createFlowDisabled, createFlowField, flowBadges, connectionHref, host, hrefFor, language, location, onConfigureConnector, onManageConnectorAccess, onLanguageChange, onNavigate, preferences, sessionKey, theme, variables = true }) {
6368
7054
  const navigate = useRef(onNavigate);
6369
7055
  navigate.current = onNavigate;
6370
7056
  const [{ i18n, navigation, store }] = useState(() => {
6371
7057
  const workbenchI18n = createI18n(language);
6372
7058
  const workbenchStore = new WorkbenchStore(new WorkbenchClient((input, init) => host.request(input, init), (flowId, listener) => host.subscribeFlow(flowId, listener), (listener) => host.subscribeFlowCatalog(listener)), preferences, randomId, workbenchI18n, {
6373
7059
  openExternalPage: (resolveUrl) => host.openExternalPage(resolveUrl),
6374
- catalogCache: host.catalogCache,
6375
- connectionCache: host.connectionCache,
7060
+ cacheEnvironment: host.cacheEnvironment,
7061
+ connectorOwnerId: host.connectorOwnerId,
6376
7062
  resolveActor: actorResolver(host, globalThis.location?.origin)
6377
- }, variables);
7063
+ }, variables, sessionKey);
6378
7064
  return {
6379
7065
  i18n: workbenchI18n,
6380
7066
  navigation: new NavigationStore(workbenchStore, location, (nextLocation, options) => navigate.current(nextLocation, options)),
@@ -6445,7 +7131,10 @@ function Session({ catalogWidth, createFlow, createFlowDisabled, createFlowField
6445
7131
  });
6446
7132
  }
6447
7133
  function OpenFlowWorkbench({ sessionKey, ...props }) {
6448
- return /* @__PURE__ */ jsx(Session, { ...props }, sessionKey);
7134
+ return /* @__PURE__ */ jsx(Session, {
7135
+ sessionKey,
7136
+ ...props
7137
+ }, `${sessionKey}:${props.host.connectorOwnerId ?? ""}`);
6449
7138
  }
6450
7139
  //#endregion
6451
7140
  export { EventSourcesPage, OpenFlowSessionGate, OpenFlowWorkbench, isUiLanguage as isWorkbenchLanguage, resolveUiLanguage as resolveWorkbenchLanguage, uiLanguageNames as workbenchLanguageNames, uiLanguages as workbenchLanguages };