@oomol-lab/open-flow 0.1.0-beta.50 → 0.1.0-beta.52
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-CSltk-qY.js → createResourceDialog-BsaBMf7_.js} +2 -1
- package/dist/browser/flow-authoring-node.d.ts +3 -1
- package/dist/browser/flow-authoring.js +82 -3
- package/dist/browser/flow-change-schema.d.ts +1 -1
- package/dist/browser/flow-change.d.ts +15 -2
- package/dist/browser/flow-change.js +81 -3
- package/dist/browser/{flowChanges-DbYrpHnS.js → flowChanges-DtraMpva.js} +3858 -1921
- package/dist/browser/{flowWorkspace-CjwpbVBR.js → flowWorkspace-DLgti4Lk.js} +1353 -513
- package/dist/browser/{workbenchSelect-oVujN2z6.js → icons-0s-Q_3lp.js} +92 -35
- package/dist/browser/licenses.md +204 -0
- package/dist/browser/preview.css +302 -179
- package/dist/browser/preview.js +4829 -2198
- package/dist/browser/theme.css +2 -0
- package/dist/browser/ui-hostNavigationActions.d.ts +13 -0
- package/dist/browser/ui-hostTooltip.d.ts +8 -0
- package/dist/browser/ui-logo.d.ts +5 -0
- package/dist/browser/ui.css +102 -8
- package/dist/browser/ui.d.ts +3 -0
- package/dist/browser/ui.js +176 -11
- package/dist/browser/workbench-contract.d.ts +5 -11
- package/dist/browser/workbench.css +366 -200
- package/dist/browser/workbench.d.ts +1 -1
- package/dist/browser/workbench.js +1154 -379
- package/dist/browser/workbenchSelect-BqUPacsr.js +31 -0
- package/dist/common/authoringExamples.d.ts +4 -2
- package/dist/common/control-api-conformance.js +129 -11
- package/dist/common/control-api.d.ts +38 -5
- package/dist/common/control-api.js +198 -12
- package/dist/common/control-requests.d.ts +4 -0
- package/dist/common/control-requests.js +1320 -67
- package/dist/common/flow-encoding.js +64 -5
- package/dist/common/flow-semantics.js +823 -316
- package/dist/common/integration-trigger.js +39 -1
- package/dist/common/mcp.js +129 -11
- package/dist/common/openapi.d.ts +53 -0
- package/dist/common/openapi.js +10390 -0
- package/dist/common/poll-trigger.js +39 -1
- package/dist/common/provider-triggers.js +39 -1
- package/dist/common/run-events.js +26 -1
- package/dist/common/scheduler.d.ts +4 -1
- package/dist/common/scheduler.js +122 -6
- package/dist/common/trigger-contract.d.ts +2 -0
- package/dist/common/webhook-trigger.js +39 -1
- package/package.json +5 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { $t as
|
|
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-DtraMpva.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 {
|
|
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";
|
|
@@ -68,6 +68,9 @@ var NavigationStore = class {
|
|
|
68
68
|
this.#store = store;
|
|
69
69
|
this.#view.set(location.view);
|
|
70
70
|
}
|
|
71
|
+
get runId() {
|
|
72
|
+
return this.#location.view == "runs" ? this.#location.runId : void 0;
|
|
73
|
+
}
|
|
71
74
|
get runSource() {
|
|
72
75
|
return this.#location.view == "runs" ? this.#location.runSource : void 0;
|
|
73
76
|
}
|
|
@@ -155,15 +158,19 @@ var NavigationStore = class {
|
|
|
155
158
|
#sync;
|
|
156
159
|
#write(view, replace, options = this.#location) {
|
|
157
160
|
const flowId = this.#store.workspace.$.flowId.value;
|
|
158
|
-
const { runSource } = options;
|
|
161
|
+
const { runSource, runId } = options;
|
|
159
162
|
const location = {
|
|
160
163
|
flowId,
|
|
161
164
|
view: flowId == null ? "design" : view,
|
|
162
|
-
...flowId != null && view == "runs" && runSource != null ? { runSource } : {}
|
|
165
|
+
...flowId != null && view == "runs" && runSource != null ? { runSource } : {},
|
|
166
|
+
...flowId != null && view == "runs" && runId != null ? { runId } : {}
|
|
163
167
|
};
|
|
164
168
|
if (this.#ready.value && this.#view.value == "runs" && location.view == "runs") {
|
|
165
169
|
const filter = this.#store.runs.$.filter.value;
|
|
166
|
-
if (filter.source != location.runSource) this.#store.runs.applyFilter({
|
|
170
|
+
if (filter.source != location.runSource || filter.runId != location.runId) this.#store.runs.applyFilter(location.runId != filter.runId ? {
|
|
171
|
+
source: location.runSource,
|
|
172
|
+
runId: location.runId
|
|
173
|
+
} : {
|
|
167
174
|
...filter,
|
|
168
175
|
source: location.runSource
|
|
169
176
|
});
|
|
@@ -176,7 +183,7 @@ var NavigationStore = class {
|
|
|
176
183
|
}
|
|
177
184
|
};
|
|
178
185
|
function sameLocation(left, right) {
|
|
179
|
-
return left.flowId == right.flowId && left.view == right.view && left.runSource == right.runSource;
|
|
186
|
+
return left.flowId == right.flowId && left.view == right.view && left.runSource == right.runSource && left.runId == right.runId;
|
|
180
187
|
}
|
|
181
188
|
//#endregion
|
|
182
189
|
//#region src/ui/browser/skeleton.tsx
|
|
@@ -189,34 +196,11 @@ function Skeleton({ className, ...props }) {
|
|
|
189
196
|
}
|
|
190
197
|
//#endregion
|
|
191
198
|
//#region src/workbench/browser/runtime/shell/resourceBrowser.tsx
|
|
192
|
-
var CreateResourceDialog = lazy(() => import("./createResourceDialog-
|
|
193
|
-
var languageOptions = uiLanguages.map((language) => ({
|
|
194
|
-
label: uiLanguageNames[language],
|
|
195
|
-
value: language
|
|
196
|
-
}));
|
|
199
|
+
var CreateResourceDialog = lazy(() => import("./createResourceDialog-BsaBMf7_.js"));
|
|
197
200
|
var flowIdTooltipAlignOffset = 44;
|
|
198
201
|
var renamePopoverAlignOffset = -12;
|
|
199
202
|
var renamePopoverVerticalShift = 8;
|
|
200
203
|
var rowControlSelector = "a, button, input, select, textarea, [data-slot=\"tooltip-trigger\"]";
|
|
201
|
-
function LanguageSelect({ language, onLanguageChange }) {
|
|
202
|
-
const t = useTranslate();
|
|
203
|
-
const [portalRoot, setPortalRoot] = useState(null);
|
|
204
|
-
if (onLanguageChange == null) return null;
|
|
205
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
206
|
-
className: "resource-language",
|
|
207
|
-
ref: setPortalRoot,
|
|
208
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
209
|
-
className: "sr-only",
|
|
210
|
-
children: t("language.label")
|
|
211
|
-
}), /* @__PURE__ */ jsx(WorkbenchSelect, {
|
|
212
|
-
ariaLabel: t("language.label"),
|
|
213
|
-
onValueChange: (value) => onLanguageChange(value),
|
|
214
|
-
options: languageOptions,
|
|
215
|
-
portalRoot,
|
|
216
|
-
value: language
|
|
217
|
-
})]
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
204
|
function compactFlowId(flowId) {
|
|
221
205
|
return flowId.length <= 20 ? flowId : `${flowId.slice(0, 10)}…${flowId.slice(-6)}`;
|
|
222
206
|
}
|
|
@@ -234,6 +218,56 @@ function formatUpdatedAt(updatedAt, locale) {
|
|
|
234
218
|
function clickedRowControl(event) {
|
|
235
219
|
return event.target instanceof Element && event.target.closest(rowControlSelector) != null;
|
|
236
220
|
}
|
|
221
|
+
function FlowDeletionImpact({ listeners, failed, onRetry }) {
|
|
222
|
+
const t = useTranslate();
|
|
223
|
+
if (failed) return /* @__PURE__ */ jsxs("div", {
|
|
224
|
+
className: "space-y-2",
|
|
225
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
226
|
+
role: "alert",
|
|
227
|
+
className: "text-sm text-destructive",
|
|
228
|
+
children: t("sidebar.listenersFailed")
|
|
229
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
230
|
+
variant: "outline",
|
|
231
|
+
size: "sm",
|
|
232
|
+
onClick: onRetry,
|
|
233
|
+
children: t("errorWorkflow.retry")
|
|
234
|
+
})]
|
|
235
|
+
});
|
|
236
|
+
if (listeners == null) return /* @__PURE__ */ jsx("p", {
|
|
237
|
+
role: "status",
|
|
238
|
+
className: "text-sm text-muted-foreground",
|
|
239
|
+
children: t("sidebar.listenersLoading")
|
|
240
|
+
});
|
|
241
|
+
if (listeners.length == 0) return null;
|
|
242
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
243
|
+
className: "min-w-0 space-y-3 text-sm",
|
|
244
|
+
children: [
|
|
245
|
+
/* @__PURE__ */ jsx("p", { children: t("sidebar.listenersTitle") }),
|
|
246
|
+
/* @__PURE__ */ jsx("ul", {
|
|
247
|
+
className: "m-0 max-h-48 list-none space-y-2 overflow-y-auto p-0",
|
|
248
|
+
children: listeners.map((listener) => /* @__PURE__ */ jsxs("li", {
|
|
249
|
+
className: "break-words",
|
|
250
|
+
children: [
|
|
251
|
+
/* @__PURE__ */ jsx("span", {
|
|
252
|
+
className: "font-medium",
|
|
253
|
+
children: listener.flowName
|
|
254
|
+
}),
|
|
255
|
+
" / ",
|
|
256
|
+
listener.nodeName,
|
|
257
|
+
!listener.enabled && /* @__PURE__ */ jsx("span", {
|
|
258
|
+
className: "ml-2 text-muted-foreground",
|
|
259
|
+
children: t("sidebar.listenerDisabled")
|
|
260
|
+
})
|
|
261
|
+
]
|
|
262
|
+
}, `${listener.flowId}/${listener.nodeId}`))
|
|
263
|
+
}),
|
|
264
|
+
/* @__PURE__ */ jsx("p", {
|
|
265
|
+
className: "text-muted-foreground",
|
|
266
|
+
children: t("sidebar.listenersImpact")
|
|
267
|
+
})
|
|
268
|
+
]
|
|
269
|
+
});
|
|
270
|
+
}
|
|
237
271
|
function FlowItem({ badge, busy, flow, href, onSelect, store }) {
|
|
238
272
|
const [root, setRoot] = useState(null);
|
|
239
273
|
const renameAnchor = useRef(null);
|
|
@@ -244,6 +278,26 @@ function FlowItem({ badge, busy, flow, href, onSelect, store }) {
|
|
|
244
278
|
const t = useTranslate();
|
|
245
279
|
const [mode, setMode] = useState("idle");
|
|
246
280
|
const [name, setName] = useState(flow.name);
|
|
281
|
+
const [listeners, setListeners] = useState();
|
|
282
|
+
const [listenersFailed, setListenersFailed] = useState(false);
|
|
283
|
+
const [listenersRetry, setListenersRetry] = useState(0);
|
|
284
|
+
useEffect(() => {
|
|
285
|
+
if (mode != "delete") return;
|
|
286
|
+
const controller = new AbortController();
|
|
287
|
+
setListeners(void 0);
|
|
288
|
+
setListenersFailed(false);
|
|
289
|
+
store.workspace.getErrorListeners(flow.flowId, controller.signal).then((value) => {
|
|
290
|
+
if (!controller.signal.aborted) setListeners(value);
|
|
291
|
+
}, () => {
|
|
292
|
+
if (!controller.signal.aborted) setListenersFailed(true);
|
|
293
|
+
});
|
|
294
|
+
return () => controller.abort();
|
|
295
|
+
}, [
|
|
296
|
+
mode,
|
|
297
|
+
flow.flowId,
|
|
298
|
+
store,
|
|
299
|
+
listenersRetry
|
|
300
|
+
]);
|
|
247
301
|
const [pending, setPending] = useState();
|
|
248
302
|
const changed = flow.live != null && flow.live.revisionId != flow.draftRevisionId;
|
|
249
303
|
const publicationStatus = flow.status == "retiring" ? "resource.retiring" : flow.live == null ? "resource.notPublished" : changed ? "resource.unpublishedChanges" : "resource.isPublished";
|
|
@@ -427,12 +481,19 @@ function FlowItem({ badge, busy, flow, href, onSelect, store }) {
|
|
|
427
481
|
"aria-hidden": "true",
|
|
428
482
|
className: cn("status-dot", publicationTone)
|
|
429
483
|
}),
|
|
430
|
-
t(publicationStatus),
|
|
431
|
-
flow.live != null && /* @__PURE__ */ jsxs(
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
children: "
|
|
435
|
-
|
|
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
|
+
})
|
|
436
497
|
]
|
|
437
498
|
})
|
|
438
499
|
]
|
|
@@ -442,14 +503,6 @@ function FlowItem({ badge, busy, flow, href, onSelect, store }) {
|
|
|
442
503
|
"aria-busy": pending != null,
|
|
443
504
|
onClick: openFromRow,
|
|
444
505
|
children: [
|
|
445
|
-
flow.live != null && /* @__PURE__ */ jsx(Switch, {
|
|
446
|
-
"aria-label": t("resource.enableFlow", { name: flow.name }),
|
|
447
|
-
checked: flow.live.enabled,
|
|
448
|
-
disabled: flow.status != "active" || busy != null || pending != null,
|
|
449
|
-
onCheckedChange: (enabled) => void update(enabled),
|
|
450
|
-
size: "sm",
|
|
451
|
-
title: t("resource.enabledHint")
|
|
452
|
-
}),
|
|
453
506
|
flow.status == "active" && /* @__PURE__ */ jsx(Button, {
|
|
454
507
|
onClick: () => onSelect(flow),
|
|
455
508
|
size: "sm",
|
|
@@ -496,18 +549,26 @@ function FlowItem({ badge, busy, flow, href, onSelect, store }) {
|
|
|
496
549
|
initialFocus: cancelDelete,
|
|
497
550
|
finalFocus: deleteButton,
|
|
498
551
|
showCloseButton: false,
|
|
499
|
-
children: [
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
552
|
+
children: [
|
|
553
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, { children: t("sidebar.deleteFlowConfirm", { name: flow.name }) }), /* @__PURE__ */ jsx(DialogDescription, { children: t("resource.deleteDescription") })] }),
|
|
554
|
+
/* @__PURE__ */ jsx(FlowDeletionImpact, {
|
|
555
|
+
listeners,
|
|
556
|
+
failed: listenersFailed,
|
|
557
|
+
onRetry: () => setListenersRetry((value) => value + 1)
|
|
503
558
|
}),
|
|
504
|
-
children:
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
559
|
+
/* @__PURE__ */ jsxs(DialogFooter, { children: [/* @__PURE__ */ jsx(DialogClose, {
|
|
560
|
+
render: /* @__PURE__ */ jsx(Button, {
|
|
561
|
+
ref: cancelDelete,
|
|
562
|
+
variant: "outline"
|
|
563
|
+
}),
|
|
564
|
+
children: t("common.cancel")
|
|
565
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
566
|
+
disabled: busy != null || listeners == null && !listenersFailed,
|
|
567
|
+
onClick: () => void remove(),
|
|
568
|
+
variant: "destructive",
|
|
569
|
+
children: t(busy == "flow" ? "common.deleting" : "common.delete")
|
|
570
|
+
})] })
|
|
571
|
+
]
|
|
511
572
|
})
|
|
512
573
|
})
|
|
513
574
|
]
|
|
@@ -534,7 +595,7 @@ function FlowSkeleton() {
|
|
|
534
595
|
})]
|
|
535
596
|
});
|
|
536
597
|
}
|
|
537
|
-
function FlowBrowser({ catalogWidth, createFlowDisabled, createFlowField, flowBadges, hrefForFlow,
|
|
598
|
+
function FlowBrowser({ catalogWidth, createFlowDisabled, createFlowField, flowBadges, hrefForFlow, onCreateFlow, onSelectFlow, store }) {
|
|
538
599
|
const t = useTranslate();
|
|
539
600
|
const busy = useVal(store.workspace.$.busy);
|
|
540
601
|
const loadFailed = useVal(store.workspace.$.flowLoadFailed);
|
|
@@ -581,107 +642,105 @@ function FlowBrowser({ catalogWidth, createFlowDisabled, createFlowField, flowBa
|
|
|
581
642
|
}), !loading && /* @__PURE__ */ jsx("span", { children: t("resource.flowCount", { count: total ?? flows.length }) })]
|
|
582
643
|
}), /* @__PURE__ */ jsxs("div", {
|
|
583
644
|
className: "resource-list-actions",
|
|
584
|
-
children: [
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
/* @__PURE__ */
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
value: filter
|
|
601
|
-
})]
|
|
602
|
-
}),
|
|
603
|
-
/* @__PURE__ */ jsxs(Button, {
|
|
604
|
-
className: "pr-3",
|
|
605
|
-
disabled: busy != null,
|
|
606
|
-
onClick: () => setCreating(true),
|
|
607
|
-
children: [/* @__PURE__ */ jsx(Icon, {
|
|
608
|
-
"data-icon": "inline-start",
|
|
609
|
-
name: "plus"
|
|
610
|
-
}), t("resource.newFlow")]
|
|
611
|
-
})
|
|
612
|
-
]
|
|
613
|
-
})]
|
|
614
|
-
}),
|
|
615
|
-
/* @__PURE__ */ jsxs("div", {
|
|
616
|
-
"aria-hidden": "true",
|
|
617
|
-
className: "resource-list-columns-shell",
|
|
618
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
619
|
-
className: "resource-list-columns flow-columns",
|
|
620
|
-
children: [
|
|
621
|
-
/* @__PURE__ */ jsx("span", { children: t("resource.name") }),
|
|
622
|
-
/* @__PURE__ */ jsx("span", {
|
|
623
|
-
className: "resource-flow-id-heading",
|
|
624
|
-
children: t("resource.flowId")
|
|
625
|
-
}),
|
|
626
|
-
/* @__PURE__ */ jsx("span", {
|
|
627
|
-
className: "resource-updated-heading",
|
|
628
|
-
children: t("resource.updated")
|
|
629
|
-
}),
|
|
630
|
-
/* @__PURE__ */ jsx("span", { children: t("resource.status") })
|
|
631
|
-
]
|
|
632
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
633
|
-
className: "resource-actions-heading",
|
|
634
|
-
children: t("resource.actions")
|
|
635
|
-
})]
|
|
636
|
-
}),
|
|
637
|
-
/* @__PURE__ */ jsx("div", {
|
|
638
|
-
className: "resource-list",
|
|
639
|
-
children: loading ? Array.from({ length: 5 }, (_, index) => /* @__PURE__ */ jsx(FlowSkeleton, {}, index)) : loadFailed ? /* @__PURE__ */ jsxs(Empty, {
|
|
640
|
-
className: "min-h-64",
|
|
641
|
-
role: "alert",
|
|
642
|
-
children: [/* @__PURE__ */ jsxs(EmptyHeader, { children: [
|
|
643
|
-
/* @__PURE__ */ jsx(EmptyMedia, {
|
|
644
|
-
variant: "icon",
|
|
645
|
-
children: /* @__PURE__ */ jsx(Icon, {
|
|
646
|
-
name: "alert",
|
|
647
|
-
size: 20
|
|
648
|
-
})
|
|
649
|
-
}),
|
|
650
|
-
/* @__PURE__ */ jsx(EmptyTitle, { children: t("resource.flowsLoadFailed") }),
|
|
651
|
-
/* @__PURE__ */ jsx(EmptyDescription, { children: t("resource.flowsLoadFailedDescription") })
|
|
652
|
-
] }), /* @__PURE__ */ jsx(EmptyContent, { children: /* @__PURE__ */ jsx(Button, {
|
|
653
|
-
onClick: () => void store.retryFlows(),
|
|
654
|
-
variant: "outline",
|
|
655
|
-
children: t("empty.retry")
|
|
656
|
-
}) })]
|
|
657
|
-
}) : visible.length == 0 ? /* @__PURE__ */ jsxs(Empty, {
|
|
658
|
-
className: "min-h-64",
|
|
659
|
-
children: [/* @__PURE__ */ jsxs(EmptyHeader, { children: [
|
|
660
|
-
/* @__PURE__ */ jsx(EmptyMedia, {
|
|
661
|
-
variant: "icon",
|
|
662
|
-
children: /* @__PURE__ */ jsx(Icon, {
|
|
663
|
-
name: "flow",
|
|
664
|
-
size: 20
|
|
665
|
-
})
|
|
666
|
-
}),
|
|
667
|
-
/* @__PURE__ */ jsx(EmptyTitle, { children: t(normalized.length == 0 ? "resource.noFlows" : "resource.noMatchingFlows") }),
|
|
668
|
-
/* @__PURE__ */ jsx(EmptyDescription, { children: t(normalized.length == 0 ? "resource.noFlowsDescription" : "resource.noMatchingDescription") })
|
|
669
|
-
] }), 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,
|
|
670
661
|
onClick: () => setCreating(true),
|
|
671
|
-
variant: "outline",
|
|
672
662
|
children: [/* @__PURE__ */ jsx(Icon, {
|
|
673
663
|
"data-icon": "inline-start",
|
|
674
664
|
name: "plus"
|
|
675
665
|
}), t("resource.newFlow")]
|
|
676
|
-
})
|
|
677
|
-
})
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
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
|
+
})
|
|
685
744
|
}),
|
|
686
745
|
nextCursor != null && /* @__PURE__ */ jsx("div", {
|
|
687
746
|
className: "resource-list-footer",
|
|
@@ -1421,87 +1480,34 @@ var PublicationStore = class {
|
|
|
1421
1480
|
//#endregion
|
|
1422
1481
|
//#region src/workbench/browser/runtime/runs/runRequestStore.ts
|
|
1423
1482
|
var initialState$5 = { starting: false };
|
|
1424
|
-
function
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
}
|
|
1433
|
-
}
|
|
1434
|
-
function nodeTitle(node) {
|
|
1435
|
-
if (node.node.name != null) return node.node.name;
|
|
1436
|
-
if (node.kind == "task" || node.kind == "subflow") return node.definition?.name ?? node.id;
|
|
1437
|
-
return node.id;
|
|
1438
|
-
}
|
|
1439
|
-
function inputSpecs(draft, triggerId) {
|
|
1440
|
-
const revision = revisionView(draft);
|
|
1441
|
-
const graph = revision.graph({ kind: "flow" });
|
|
1442
|
-
if (graph == null) return [];
|
|
1443
|
-
const reachable = /* @__PURE__ */ new Set([triggerId]);
|
|
1444
|
-
const pending = [triggerId];
|
|
1445
|
-
while (pending.length > 0) {
|
|
1446
|
-
const source = pending.pop();
|
|
1447
|
-
for (const edge of graph.edges) {
|
|
1448
|
-
if (edge.source != source || reachable.has(edge.target)) continue;
|
|
1449
|
-
reachable.add(edge.target);
|
|
1450
|
-
pending.push(edge.target);
|
|
1451
|
-
}
|
|
1452
|
-
}
|
|
1453
|
-
return Object.entries(graph.nodes).filter(([id]) => reachable.has(id)).toSorted(([left], [right]) => left.localeCompare(right)).flatMap(([nodeId, node]) => {
|
|
1454
|
-
const resolved = revision.resolveNode(nodeId, node);
|
|
1455
|
-
if (resolved.kind == "trigger") {
|
|
1456
|
-
if (resolved.trigger.kind == "manual" || resolved.trigger.kind == "cron") return [];
|
|
1457
|
-
return [{
|
|
1458
|
-
definitions: triggerOutputDefinitions(resolved.trigger),
|
|
1459
|
-
nodeId,
|
|
1460
|
-
title: resolved.trigger.name
|
|
1461
|
-
}];
|
|
1462
|
-
}
|
|
1463
|
-
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({
|
|
1464
|
-
handle,
|
|
1465
|
-
jsonSchema: port.jsonSchema,
|
|
1466
|
-
nullable: port.nullable
|
|
1467
|
-
}, port.description == null ? {} : { description: port.description }));
|
|
1468
|
-
return definitions.length == 0 ? [] : [{
|
|
1469
|
-
definitions,
|
|
1470
|
-
nodeId,
|
|
1471
|
-
title: nodeTitle(resolved)
|
|
1472
|
-
}];
|
|
1473
|
-
});
|
|
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
|
+
};
|
|
1474
1491
|
}
|
|
1475
|
-
function inputSignature(
|
|
1476
|
-
return JSON.stringify(
|
|
1492
|
+
function inputSignature(spec) {
|
|
1493
|
+
return JSON.stringify(spec?.definitions.map((definition) => [
|
|
1477
1494
|
definition.handle,
|
|
1478
1495
|
definition.jsonSchema,
|
|
1479
1496
|
definition.nullable
|
|
1480
|
-
])])
|
|
1497
|
+
]) ?? []);
|
|
1481
1498
|
}
|
|
1482
|
-
async function
|
|
1499
|
+
async function inputEditor(spec, language, values) {
|
|
1500
|
+
if (spec == null) return void 0;
|
|
1483
1501
|
const { FlowRunInputEditorStore } = await import("./flowRunInputEditorStore-Dsxyfwae.js").then((n) => n.t);
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
editor,
|
|
1489
|
-
nodeId: group.nodeId,
|
|
1490
|
-
title: group.title
|
|
1491
|
-
};
|
|
1492
|
-
});
|
|
1493
|
-
}
|
|
1494
|
-
function groupValues(groups) {
|
|
1495
|
-
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;
|
|
1496
1506
|
}
|
|
1497
1507
|
function testOutputs(revision, triggerId) {
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
return {
|
|
1502
|
-
inputs: Object.fromEntries(groups.filter((group) => group.nodeId != triggerId).map((group) => [group.nodeId, group.editor.values()])),
|
|
1503
|
-
outputs: groups.find((group) => group.nodeId == triggerId)?.editor.values() ?? testOutputs(revision, triggerId)
|
|
1504
|
-
};
|
|
1508
|
+
const node = revisionView(revision).graph({ kind: "flow" })?.nodes[triggerId];
|
|
1509
|
+
if (node?.kind == "error") return sampleErrorOutputs;
|
|
1510
|
+
return node?.kind === "cron" ? { scheduledAt: (/* @__PURE__ */ new Date()).toISOString() } : {};
|
|
1505
1511
|
}
|
|
1506
1512
|
var RunRequestStore = class {
|
|
1507
1513
|
#prepareDraft;
|
|
@@ -1567,10 +1573,10 @@ var RunRequestStore = class {
|
|
|
1567
1573
|
}
|
|
1568
1574
|
}
|
|
1569
1575
|
inputStatus(flowId, draft, triggerId) {
|
|
1570
|
-
const
|
|
1571
|
-
if (
|
|
1576
|
+
const spec = inputSpec(draft, triggerId);
|
|
1577
|
+
if (spec == null) return "none";
|
|
1572
1578
|
const saved = this.#savedInputs.get(this.#inputKey(flowId, triggerId));
|
|
1573
|
-
return saved?.valid == true && saved.signature == inputSignature(
|
|
1579
|
+
return saved?.valid == true && saved.signature == inputSignature(spec) ? "ready" : "missing";
|
|
1574
1580
|
}
|
|
1575
1581
|
async requestLive(flow) {
|
|
1576
1582
|
const current = this.#requests.begin();
|
|
@@ -1605,11 +1611,11 @@ var RunRequestStore = class {
|
|
|
1605
1611
|
return false;
|
|
1606
1612
|
}
|
|
1607
1613
|
this.#rememberInputs(request);
|
|
1608
|
-
const
|
|
1614
|
+
const outputs = request.editor?.values() ?? testOutputs(request.revision, request.triggerId);
|
|
1609
1615
|
const started = await this.#start(request.source, request.flow, request.revisionId, {
|
|
1610
1616
|
nodeId: request.triggerId,
|
|
1611
1617
|
outputs
|
|
1612
|
-
},
|
|
1618
|
+
}, request.publicationId);
|
|
1613
1619
|
if (started && this.#state.value.inputRequest === request) this.dismissInputs();
|
|
1614
1620
|
return started;
|
|
1615
1621
|
}
|
|
@@ -1620,18 +1626,18 @@ var RunRequestStore = class {
|
|
|
1620
1626
|
this.#rememberInputs(request);
|
|
1621
1627
|
this.#set({ starting: true });
|
|
1622
1628
|
try {
|
|
1623
|
-
const
|
|
1629
|
+
const spec = inputSpec(request.revision, triggerId);
|
|
1624
1630
|
const saved = this.#savedInputs.get(this.#inputKey(request.flow.flowId, triggerId));
|
|
1625
|
-
const
|
|
1631
|
+
const editor = await inputEditor(spec, this.#i18n.lang$, saved?.values);
|
|
1626
1632
|
if (!current() || this.#state.value.inputRequest !== request) {
|
|
1627
|
-
|
|
1633
|
+
editor?.dispose();
|
|
1628
1634
|
return;
|
|
1629
1635
|
}
|
|
1630
|
-
const valid = compute((get) =>
|
|
1636
|
+
const valid = compute((get) => editor == null || get(editor.valid$));
|
|
1631
1637
|
this.#set({ inputRequest: {
|
|
1632
1638
|
...request,
|
|
1633
1639
|
attempted: false,
|
|
1634
|
-
|
|
1640
|
+
editor,
|
|
1635
1641
|
triggerId,
|
|
1636
1642
|
valid
|
|
1637
1643
|
} });
|
|
@@ -1673,32 +1679,32 @@ var RunRequestStore = class {
|
|
|
1673
1679
|
});
|
|
1674
1680
|
return "unavailable";
|
|
1675
1681
|
}
|
|
1676
|
-
const
|
|
1677
|
-
const signature = inputSignature(
|
|
1682
|
+
const spec = only == null ? void 0 : inputSpec(revision, only.nodeId);
|
|
1683
|
+
const signature = inputSignature(spec);
|
|
1678
1684
|
const saved = only == null ? void 0 : this.#savedInputs.get(this.#inputKey(flow.flowId, only.nodeId));
|
|
1679
|
-
const
|
|
1685
|
+
const editor = await inputEditor(spec, this.#i18n.lang$, saved?.values);
|
|
1680
1686
|
if (!current()) {
|
|
1681
|
-
|
|
1687
|
+
editor?.dispose();
|
|
1682
1688
|
return "unavailable";
|
|
1683
1689
|
}
|
|
1684
|
-
if (!edit && only != null &&
|
|
1690
|
+
if (!edit && only != null && editor == null) return await this.#start(source, flow, revisionId, {
|
|
1685
1691
|
nodeId: only.nodeId,
|
|
1686
1692
|
outputs: testOutputs(revision, only.nodeId)
|
|
1687
|
-
},
|
|
1688
|
-
if (!edit && only != null && saved?.valid == true && saved.signature == signature &&
|
|
1689
|
-
const
|
|
1690
|
-
|
|
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();
|
|
1691
1697
|
return await this.#start(source, flow, revisionId, {
|
|
1692
1698
|
nodeId: only.nodeId,
|
|
1693
|
-
outputs
|
|
1694
|
-
},
|
|
1699
|
+
outputs
|
|
1700
|
+
}, publicationId) ? "started" : "unavailable";
|
|
1695
1701
|
}
|
|
1696
|
-
const valid = compute((get) => only != null &&
|
|
1702
|
+
const valid = compute((get) => only != null && (editor == null || get(editor.valid$)));
|
|
1697
1703
|
this.#set({
|
|
1698
1704
|
inputRequest: {
|
|
1699
1705
|
attempted: false,
|
|
1700
1706
|
flow,
|
|
1701
|
-
|
|
1707
|
+
editor,
|
|
1702
1708
|
revision,
|
|
1703
1709
|
triggers,
|
|
1704
1710
|
triggerId: only?.nodeId,
|
|
@@ -1712,7 +1718,7 @@ var RunRequestStore = class {
|
|
|
1712
1718
|
});
|
|
1713
1719
|
return "input";
|
|
1714
1720
|
}
|
|
1715
|
-
async #start(source, flow, revisionId, trigger,
|
|
1721
|
+
async #start(source, flow, revisionId, trigger, publicationId) {
|
|
1716
1722
|
if (source == "live" && publicationId == null) return false;
|
|
1717
1723
|
const alive = this.#lifetime.capture();
|
|
1718
1724
|
const current = this.#runs.prepareStart();
|
|
@@ -1731,7 +1737,6 @@ var RunRequestStore = class {
|
|
|
1731
1737
|
revisionId
|
|
1732
1738
|
} : { publicationId };
|
|
1733
1739
|
const signature = JSON.stringify({
|
|
1734
|
-
inputs,
|
|
1735
1740
|
trigger,
|
|
1736
1741
|
source,
|
|
1737
1742
|
...target
|
|
@@ -1743,11 +1748,11 @@ var RunRequestStore = class {
|
|
|
1743
1748
|
this.#attempt = attempt;
|
|
1744
1749
|
const run = source == "draft" ? await this.#client.createDraftRun(flow.flowId, revisionId, {
|
|
1745
1750
|
idempotencyKey: attempt.key,
|
|
1746
|
-
inputs,
|
|
1751
|
+
inputs: {},
|
|
1747
1752
|
trigger
|
|
1748
1753
|
}) : await this.#client.createLiveRun(publicationId, {
|
|
1749
1754
|
idempotencyKey: attempt.key,
|
|
1750
|
-
inputs,
|
|
1755
|
+
inputs: {},
|
|
1751
1756
|
trigger
|
|
1752
1757
|
});
|
|
1753
1758
|
if (!alive() || !current()) return false;
|
|
@@ -1766,17 +1771,17 @@ var RunRequestStore = class {
|
|
|
1766
1771
|
#disposeInputRequest(request = this.#state.value.inputRequest) {
|
|
1767
1772
|
if (request == null) return;
|
|
1768
1773
|
request.valid.dispose();
|
|
1769
|
-
|
|
1774
|
+
request.editor?.dispose();
|
|
1770
1775
|
}
|
|
1771
1776
|
#inputKey(flowId, triggerId) {
|
|
1772
1777
|
return `${flowId}\u0000${triggerId}`;
|
|
1773
1778
|
}
|
|
1774
1779
|
#rememberInputs(request) {
|
|
1775
|
-
if (request?.triggerId == null || request.
|
|
1780
|
+
if (request?.triggerId == null || request.editor == null) return;
|
|
1776
1781
|
this.#savedInputs.set(this.#inputKey(request.flow.flowId, request.triggerId), {
|
|
1777
|
-
signature: inputSignature(
|
|
1782
|
+
signature: inputSignature(inputSpec(request.revision, request.triggerId)),
|
|
1778
1783
|
valid: request.valid.value,
|
|
1779
|
-
values:
|
|
1784
|
+
values: request.editor.values()
|
|
1780
1785
|
});
|
|
1781
1786
|
}
|
|
1782
1787
|
#set(patch) {
|
|
@@ -1871,47 +1876,590 @@ function createStore(dbName, storeName) {
|
|
|
1871
1876
|
};
|
|
1872
1877
|
return (txMode, callback) => getDB().then((db) => callback(db.transaction(storeName, txMode).objectStore(storeName)));
|
|
1873
1878
|
}
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
return
|
|
1878
|
-
}
|
|
1879
|
-
/**
|
|
1880
|
-
* Get a value by its key.
|
|
1881
|
-
*
|
|
1882
|
-
* @param key
|
|
1883
|
-
* @param customStore Method to get a custom store. Use with caution (see the docs).
|
|
1884
|
-
*/
|
|
1885
|
-
function get(key, customStore = defaultGetStore()) {
|
|
1886
|
-
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");
|
|
1887
1883
|
}
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
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
|
+
});
|
|
1899
1902
|
});
|
|
1900
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
|
+
}
|
|
1901
2330
|
//#endregion
|
|
1902
|
-
//#region
|
|
1903
|
-
|
|
1904
|
-
var
|
|
1905
|
-
|
|
1906
|
-
|
|
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"
|
|
1907
2338
|
};
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
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");
|
|
1911
2396
|
return {
|
|
1912
|
-
|
|
1913
|
-
|
|
2397
|
+
environment,
|
|
2398
|
+
ownerId
|
|
2399
|
+
};
|
|
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
|
+
}
|
|
1914
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));
|
|
1915
2463
|
}
|
|
1916
2464
|
//#endregion
|
|
1917
2465
|
//#region src/connector/common/actionSchema.ts
|
|
@@ -2086,46 +2634,178 @@ function action(source, providers) {
|
|
|
2086
2634
|
}
|
|
2087
2635
|
//#endregion
|
|
2088
2636
|
//#region src/workbench/browser/runtime/stores/catalogStores.ts
|
|
2089
|
-
|
|
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) {
|
|
2090
2673
|
const source = record(value);
|
|
2091
|
-
if (source.
|
|
2092
|
-
|
|
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();
|
|
2093
2690
|
}
|
|
2094
|
-
|
|
2095
|
-
|
|
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. */
|
|
2096
2733
|
var ProxyStore = class {
|
|
2097
|
-
|
|
2734
|
+
#factory;
|
|
2735
|
+
constructor(client, kind, scope) {
|
|
2098
2736
|
this.client = client;
|
|
2099
2737
|
this.kind = kind;
|
|
2100
|
-
this.options = options;
|
|
2101
2738
|
this.entries = /* @__PURE__ */ new Map();
|
|
2739
|
+
this.#factory = new CacheFactory(scope);
|
|
2102
2740
|
}
|
|
2103
|
-
get(flowId, locale, service, force = false) {
|
|
2104
|
-
const
|
|
2105
|
-
...flowId == null ? {} : { flowId },
|
|
2106
|
-
...service == null ? {} : { service },
|
|
2107
|
-
...locale == null ? {} : { locale }
|
|
2108
|
-
});
|
|
2109
|
-
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);
|
|
2110
2743
|
let entry = this.entries.get(path);
|
|
2111
2744
|
if (entry == null) {
|
|
2112
|
-
|
|
2113
|
-
const cacheParams = new URLSearchParams(params);
|
|
2114
|
-
cacheParams.delete("flowId");
|
|
2115
|
-
const persistence = catalogPersistence(this.options, this.kind, cacheParams.toString());
|
|
2116
|
-
entry = new Resource((etag, signal) => this.client.readProxyCatalog({
|
|
2117
|
-
path,
|
|
2118
|
-
decode
|
|
2119
|
-
}, etag, signal), this.kind == "providers" ? 3e5 : 3e4, persistence == null ? void 0 : {
|
|
2120
|
-
...persistence,
|
|
2121
|
-
decode
|
|
2122
|
-
});
|
|
2745
|
+
entry = new CacheResource(() => this.#cache(flowId, locale, service, path), void 0, false, catalogMaxAge[this.kind]);
|
|
2123
2746
|
this.entries.set(path, entry);
|
|
2124
2747
|
}
|
|
2125
2748
|
return entry.get(force);
|
|
2126
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
|
+
}
|
|
2127
2807
|
retryFailed() {
|
|
2128
|
-
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);
|
|
2129
2809
|
}
|
|
2130
2810
|
refreshFlow(flowId) {
|
|
2131
2811
|
for (const [path, entry] of this.entries) if (new URL(path, "https://open-flow.invalid").searchParams.get("flowId") == flowId) entry.refresh(true);
|
|
@@ -2133,6 +2813,7 @@ var ProxyStore = class {
|
|
|
2133
2813
|
dispose() {
|
|
2134
2814
|
for (const entry of this.entries.values()) entry.dispose();
|
|
2135
2815
|
this.entries.clear();
|
|
2816
|
+
this.#factory.dispose();
|
|
2136
2817
|
}
|
|
2137
2818
|
};
|
|
2138
2819
|
var Views = class {
|
|
@@ -2183,8 +2864,8 @@ var Views = class {
|
|
|
2183
2864
|
};
|
|
2184
2865
|
var ProviderStore = class {
|
|
2185
2866
|
#views = new Views();
|
|
2186
|
-
constructor(client,
|
|
2187
|
-
this.raw = new ProxyStore(client, "providers",
|
|
2867
|
+
constructor(client, scope) {
|
|
2868
|
+
this.raw = new ProxyStore(client, "providers", scope);
|
|
2188
2869
|
}
|
|
2189
2870
|
get(flowId, locale = "en", force = false) {
|
|
2190
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)));
|
|
@@ -2201,33 +2882,17 @@ var ProviderStore = class {
|
|
|
2201
2882
|
}
|
|
2202
2883
|
};
|
|
2203
2884
|
var ConnectionStore = class {
|
|
2204
|
-
#storage = {
|
|
2205
|
-
get: async (key) => {
|
|
2206
|
-
const raw = (this.options?.storage ?? window.sessionStorage).getItem(key);
|
|
2207
|
-
return raw == null ? void 0 : JSON.parse(raw);
|
|
2208
|
-
},
|
|
2209
|
-
set: async (key, value) => {
|
|
2210
|
-
(this.options?.storage ?? window.sessionStorage).setItem(key, JSON.stringify(value));
|
|
2211
|
-
}
|
|
2212
|
-
};
|
|
2213
2885
|
#entries = /* @__PURE__ */ new Map();
|
|
2214
2886
|
#views = /* @__PURE__ */ new Map();
|
|
2215
|
-
|
|
2887
|
+
#factory;
|
|
2888
|
+
constructor(client, scope) {
|
|
2216
2889
|
this.client = client;
|
|
2217
|
-
this
|
|
2890
|
+
this.#factory = new CacheFactory(scope);
|
|
2218
2891
|
}
|
|
2219
2892
|
get(serviceId, flowId, force = false) {
|
|
2220
2893
|
let entry = this.#entries.get(flowId);
|
|
2221
2894
|
if (entry == null) {
|
|
2222
|
-
|
|
2223
|
-
entry = new Resource((etag, signal) => this.client.readCatalog(query, etag, signal), 3e4, this.options == null ? void 0 : {
|
|
2224
|
-
key: `open-flow:connections:v1:${query.path}`,
|
|
2225
|
-
storage: this.#storage,
|
|
2226
|
-
decode: (value) => {
|
|
2227
|
-
if (!Array.isArray(value)) return invalidResponse();
|
|
2228
|
-
return value.map(connection);
|
|
2229
|
-
}
|
|
2230
|
-
});
|
|
2895
|
+
entry = new CacheResource(() => this.#cache(flowId), void 0, false, catalogMaxAge.connections);
|
|
2231
2896
|
this.#entries.set(flowId, entry);
|
|
2232
2897
|
}
|
|
2233
2898
|
const source = entry.get(force);
|
|
@@ -2243,8 +2908,54 @@ var ConnectionStore = class {
|
|
|
2243
2908
|
}
|
|
2244
2909
|
return view;
|
|
2245
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
|
+
}
|
|
2246
2957
|
retryFailed() {
|
|
2247
|
-
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);
|
|
2248
2959
|
}
|
|
2249
2960
|
refreshFlow(flowId) {
|
|
2250
2961
|
this.#entries.get(flowId)?.refresh(true);
|
|
@@ -2254,6 +2965,7 @@ var ConnectionStore = class {
|
|
|
2254
2965
|
this.#views.clear();
|
|
2255
2966
|
for (const entry of this.#entries.values()) entry.dispose();
|
|
2256
2967
|
this.#entries.clear();
|
|
2968
|
+
this.#factory.dispose();
|
|
2257
2969
|
}
|
|
2258
2970
|
};
|
|
2259
2971
|
var ActionStore = class {
|
|
@@ -2262,10 +2974,10 @@ var ActionStore = class {
|
|
|
2262
2974
|
#details = /* @__PURE__ */ new Map();
|
|
2263
2975
|
#searches = /* @__PURE__ */ new Set();
|
|
2264
2976
|
#searchSessions = /* @__PURE__ */ new WeakMap();
|
|
2265
|
-
constructor(client, providers,
|
|
2977
|
+
constructor(client, providers, scope) {
|
|
2266
2978
|
this.client = client;
|
|
2267
2979
|
this.providers = providers;
|
|
2268
|
-
this.#raw = new ProxyStore(client, "actions",
|
|
2980
|
+
this.#raw = new ProxyStore(client, "actions", scope);
|
|
2269
2981
|
}
|
|
2270
2982
|
get(serviceId, flowId, locale = "en", force = false) {
|
|
2271
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) => {
|
|
@@ -2309,7 +3021,6 @@ var ActionStore = class {
|
|
|
2309
3021
|
q: query.trim(),
|
|
2310
3022
|
locale
|
|
2311
3023
|
});
|
|
2312
|
-
const key = params.toString();
|
|
2313
3024
|
let entries = this.#searchSessions.get(signal);
|
|
2314
3025
|
if (entries == null) {
|
|
2315
3026
|
entries = /* @__PURE__ */ new Map();
|
|
@@ -2324,21 +3035,38 @@ var ActionStore = class {
|
|
|
2324
3035
|
this.#searchSessions.delete(signal);
|
|
2325
3036
|
}, { once: true });
|
|
2326
3037
|
}
|
|
3038
|
+
const key = params.toString();
|
|
2327
3039
|
const cached = entries.get(key);
|
|
2328
3040
|
if (cached != null) {
|
|
2329
|
-
cached.refresh();
|
|
3041
|
+
cached.refresh(true);
|
|
2330
3042
|
return cached;
|
|
2331
3043
|
}
|
|
2332
|
-
const
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
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();
|
|
2337
3065
|
else {
|
|
2338
|
-
entries.set(key,
|
|
2339
|
-
this.#searches.add(
|
|
3066
|
+
entries.set(key, result);
|
|
3067
|
+
this.#searches.add(result);
|
|
2340
3068
|
}
|
|
2341
|
-
return
|
|
3069
|
+
return result;
|
|
2342
3070
|
}
|
|
2343
3071
|
retryFailed() {
|
|
2344
3072
|
this.#raw.retryFailed();
|
|
@@ -2356,10 +3084,10 @@ var ActionStore = class {
|
|
|
2356
3084
|
}
|
|
2357
3085
|
};
|
|
2358
3086
|
var CatalogStores = class {
|
|
2359
|
-
constructor(client,
|
|
2360
|
-
this.providers = new ProviderStore(client,
|
|
2361
|
-
this.actions = new ActionStore(client, this.providers,
|
|
2362
|
-
this.connections = new ConnectionStore(client,
|
|
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);
|
|
2363
3091
|
}
|
|
2364
3092
|
dispose() {
|
|
2365
3093
|
this.actions.dispose();
|
|
@@ -2739,8 +3467,9 @@ var ConnectorStore = class {
|
|
|
2739
3467
|
};
|
|
2740
3468
|
this.provideAddNodeOptionChoices = (optionId, signal) => {
|
|
2741
3469
|
const service = optionId.slice(19);
|
|
2742
|
-
const
|
|
2743
|
-
const
|
|
3470
|
+
const flowId = this.#workspace.$.flowId.value;
|
|
3471
|
+
const source = this.data.actions.get(service, flowId, this.#language);
|
|
3472
|
+
const providers = this.data.providers.get(flowId, this.#language);
|
|
2744
3473
|
return scopedValue(signal, (get) => {
|
|
2745
3474
|
const state = get(source);
|
|
2746
3475
|
const provider = get(providers).data?.find((item) => item.serviceId == service);
|
|
@@ -2871,12 +3600,22 @@ var ConnectorStore = class {
|
|
|
2871
3600
|
this.#actionIds.set([]);
|
|
2872
3601
|
this.#services.set([]);
|
|
2873
3602
|
}
|
|
3603
|
+
retryAction(actionId) {
|
|
3604
|
+
const flowId = this.#workspace.$.flowId.value;
|
|
3605
|
+
if (flowId == null || this.#disposed) return;
|
|
3606
|
+
const actionState = this.data.actions.detail(actionId, flowId, this.#language, true);
|
|
3607
|
+
if (this.data.providers.get(flowId, this.#language).value.error != null) this.data.providers.get(flowId, this.#language, true);
|
|
3608
|
+
if (actionState.value.data?.authenticated !== false) this.data.connections.refreshFlow(flowId);
|
|
3609
|
+
}
|
|
2874
3610
|
async resolveAction(actionId) {
|
|
2875
3611
|
const flowId = this.#workspace.$.flowId.value;
|
|
2876
3612
|
if (flowId == null || this.#disposed) throw new Error("Connector Action cannot be resolved without an active Flow.");
|
|
3613
|
+
const actionState = this.data.actions.detail(actionId, flowId, this.#language);
|
|
3614
|
+
await Promise.resolve();
|
|
3615
|
+
const action = await resourceValue(actionState, void 0, true);
|
|
3616
|
+
const connectionState = action.authenticated ? this.data.connections.get(action.serviceId, flowId) : void 0;
|
|
2877
3617
|
await Promise.resolve();
|
|
2878
|
-
const
|
|
2879
|
-
const connections = action.authenticated ? await resourceValue(this.data.connections.get(action.serviceId, flowId), void 0, true) : [];
|
|
3618
|
+
const connections = connectionState == null ? [] : await resourceValue(connectionState, void 0, true);
|
|
2880
3619
|
this.#remember(this.#actionIds, [actionId]);
|
|
2881
3620
|
if (action.authenticated) this.#remember(this.#services, [action.serviceId]);
|
|
2882
3621
|
return {
|
|
@@ -3053,9 +3792,9 @@ var ConnectorStore = class {
|
|
|
3053
3792
|
var TriggerCatalogStore = class {
|
|
3054
3793
|
#language;
|
|
3055
3794
|
#entries;
|
|
3056
|
-
constructor(client, language,
|
|
3795
|
+
constructor(client, language, environment = "production") {
|
|
3057
3796
|
this.client = client;
|
|
3058
|
-
this.
|
|
3797
|
+
this.environment = environment;
|
|
3059
3798
|
this.#entries = /* @__PURE__ */ new Map();
|
|
3060
3799
|
this.retry = () => {
|
|
3061
3800
|
this.get(true);
|
|
@@ -3071,14 +3810,18 @@ var TriggerCatalogStore = class {
|
|
|
3071
3810
|
if (data.locale != locale) throw new Error("Unexpected Trigger catalog language.");
|
|
3072
3811
|
return data;
|
|
3073
3812
|
};
|
|
3074
|
-
const
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3813
|
+
const cache = createPersistentCache({
|
|
3814
|
+
namespace: JSON.stringify(["open-flow:trigger-catalog", this.environment]),
|
|
3815
|
+
schemaVersion: 1,
|
|
3816
|
+
maxAge: 3e5,
|
|
3817
|
+
key: () => locale,
|
|
3818
|
+
decode,
|
|
3819
|
+
load: async (_query, validation) => this.client.readCatalog({
|
|
3820
|
+
path: `/v1/trigger-keys/catalog?locale=${encodeURIComponent(locale)}`,
|
|
3821
|
+
decode
|
|
3822
|
+
}, validation.etag, validation.signal)
|
|
3081
3823
|
});
|
|
3824
|
+
entry = new CacheResource(async () => cache, void 0, true, 3e5);
|
|
3082
3825
|
this.#entries.set(locale, entry);
|
|
3083
3826
|
}
|
|
3084
3827
|
return entry;
|
|
@@ -3157,7 +3900,7 @@ var TriggerStore = class {
|
|
|
3157
3900
|
this.#disposed = false;
|
|
3158
3901
|
this.browseAddNodeOptions = (signal) => this.#options("", signal);
|
|
3159
3902
|
this.provideAddNodeOptions = (searchTerm, signal) => this.#options(searchTerm, signal);
|
|
3160
|
-
this.catalog = new TriggerCatalogStore(client, resolveUiLanguage([i18n.lang]), host);
|
|
3903
|
+
this.catalog = new TriggerCatalogStore(client, resolveUiLanguage([i18n.lang]), host.cacheEnvironment);
|
|
3161
3904
|
this.#client = client;
|
|
3162
3905
|
this.#host = host;
|
|
3163
3906
|
this.#i18n = i18n;
|
|
@@ -3172,7 +3915,7 @@ var TriggerStore = class {
|
|
|
3172
3915
|
if (trigger.kind != "poll" && trigger.kind != "integration") return { authorizationPending: false };
|
|
3173
3916
|
const connections = current == null ? void 0 : get(workspace.catalogs.connections.get(current.provider, get(workspace.$.flowId))).data;
|
|
3174
3917
|
const catalog = connections == null ? void 0 : connectionCatalog(connections);
|
|
3175
|
-
const connectionError = current == null ? void 0 : get(workspace.catalogs.connections.get(current.provider, get(workspace.$.flowId))).error;
|
|
3918
|
+
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;
|
|
3176
3919
|
return {
|
|
3177
3920
|
activeConnections: catalog?.active,
|
|
3178
3921
|
authorizationPending: state.authorizationProvider == current?.provider,
|
|
@@ -3440,6 +4183,13 @@ function inverseFlowChanges(content, operations) {
|
|
|
3440
4183
|
});
|
|
3441
4184
|
break;
|
|
3442
4185
|
}
|
|
4186
|
+
case "graph.trigger.sources.set":
|
|
4187
|
+
restore.push({
|
|
4188
|
+
...operation,
|
|
4189
|
+
before: operation.value,
|
|
4190
|
+
value: operation.before
|
|
4191
|
+
});
|
|
4192
|
+
break;
|
|
3443
4193
|
case "binding.target.set":
|
|
3444
4194
|
restore.push({
|
|
3445
4195
|
...operation,
|
|
@@ -3531,6 +4281,7 @@ function inverseFlowChanges(content, operations) {
|
|
|
3531
4281
|
value: operation.before
|
|
3532
4282
|
});
|
|
3533
4283
|
break;
|
|
4284
|
+
case "task.openapi.set":
|
|
3534
4285
|
case "task.agent.set":
|
|
3535
4286
|
restore.push({
|
|
3536
4287
|
...operation,
|
|
@@ -3595,8 +4346,9 @@ function pasteNodes(revision, target, clipboard, identity) {
|
|
|
3595
4346
|
nodeIds: [],
|
|
3596
4347
|
sourceIds: []
|
|
3597
4348
|
};
|
|
4349
|
+
const hasErrorTrigger = Object.values(revision.graph(target)?.nodes ?? {}).some((node) => node.kind === "error");
|
|
3598
4350
|
const hasManualTrigger = Object.values(revision.graph(target)?.nodes ?? {}).some((node) => node.kind === "manual");
|
|
3599
|
-
const entries = Object.entries(clipboard.nodes).filter(([, node]) => (target.kind == "flow" || "inputs" in node) && (node.kind !== "manual" || !hasManualTrigger) && (node.kind != "task" || node.task == null || clipboard.modules[node.task.moduleId] != null));
|
|
4351
|
+
const entries = Object.entries(clipboard.nodes).filter(([, node]) => (target.kind == "flow" || "inputs" in node) && (node.kind !== "manual" || !hasManualTrigger) && (node.kind !== "error" || !hasErrorTrigger) && (node.kind != "task" || node.task == null || clipboard.modules[node.task.moduleId] != null));
|
|
3600
4352
|
const sourceIds = entries.map(([sourceId]) => sourceId);
|
|
3601
4353
|
const ids = new Map(sourceIds.map((sourceId) => [sourceId, identity()]));
|
|
3602
4354
|
const operations = [];
|
|
@@ -4848,6 +5600,9 @@ var WorkspaceStore = class {
|
|
|
4848
5600
|
this.#set({ busy: void 0 });
|
|
4849
5601
|
}
|
|
4850
5602
|
}
|
|
5603
|
+
getErrorListeners(flowId, signal) {
|
|
5604
|
+
return this.#client.getErrorListeners(flowId, signal);
|
|
5605
|
+
}
|
|
4851
5606
|
async deleteFlow(flowId) {
|
|
4852
5607
|
if (!await this.saveModuleEditor()) return false;
|
|
4853
5608
|
const flow = this.#flows.flow(flowId);
|
|
@@ -5048,6 +5803,16 @@ var WorkspaceStore = class {
|
|
|
5048
5803
|
this.copySelectedNodes();
|
|
5049
5804
|
await this.pasteNodes(positions, offset);
|
|
5050
5805
|
}
|
|
5806
|
+
async saveErrorSources(nodeId, value) {
|
|
5807
|
+
const node = this.$.revision.value?.graph({ kind: "flow" })?.nodes[nodeId];
|
|
5808
|
+
if (node?.kind != "error" || dequal$1(node.sourceFlowIds ?? [], value)) return false;
|
|
5809
|
+
return await this.#editDraft([{
|
|
5810
|
+
kind: "graph.trigger.sources.set",
|
|
5811
|
+
nodeId,
|
|
5812
|
+
before: node.sourceFlowIds,
|
|
5813
|
+
value: value.length == 0 ? void 0 : value
|
|
5814
|
+
}]) != null;
|
|
5815
|
+
}
|
|
5051
5816
|
async saveNodeSettings(nodeId, settings) {
|
|
5052
5817
|
const revision = this.$.revision.value;
|
|
5053
5818
|
const target = this.#model.value.target;
|
|
@@ -5157,6 +5922,9 @@ var WorkspaceStore = class {
|
|
|
5157
5922
|
position
|
|
5158
5923
|
}));
|
|
5159
5924
|
}
|
|
5925
|
+
loadOpenApiDocument(url, signal) {
|
|
5926
|
+
return this.#client.loadOpenApiDocument(url, signal);
|
|
5927
|
+
}
|
|
5160
5928
|
async saveTaskSettings(nodeId, settings) {
|
|
5161
5929
|
const revision = this.$.revision.value;
|
|
5162
5930
|
const target = this.#model.value.target;
|
|
@@ -5706,7 +6474,7 @@ var WorkbenchStore = class {
|
|
|
5706
6474
|
#openingCreatedFlow;
|
|
5707
6475
|
#stopAccessReaction;
|
|
5708
6476
|
#accessLoading;
|
|
5709
|
-
constructor(client, preferences, identity = randomId, i18n = createI18n(), host = blockedExternalPages, variables = true) {
|
|
6477
|
+
constructor(client, preferences, identity = randomId, i18n = createI18n(), host = blockedExternalPages, variables = true, cacheSessionId = crypto.randomUUID()) {
|
|
5710
6478
|
this.#externalRuns = new Latest();
|
|
5711
6479
|
this.#notice = val();
|
|
5712
6480
|
this.#variableNames = val([]);
|
|
@@ -5740,7 +6508,11 @@ var WorkbenchStore = class {
|
|
|
5740
6508
|
this.workspace = new WorkspaceStore(client, setNotice, createAuthoringId, i18n, (event) => {
|
|
5741
6509
|
if (event.kind == "run.created") this.#followExternalRun(client, event);
|
|
5742
6510
|
else this.runs.changed(event.runId);
|
|
5743
|
-
}, new CatalogStores(client,
|
|
6511
|
+
}, new CatalogStores(client, {
|
|
6512
|
+
sessionId: cacheSessionId,
|
|
6513
|
+
environment: host.cacheEnvironment,
|
|
6514
|
+
connectorOwnerId: host.connectorOwnerId
|
|
6515
|
+
}), (flowId) => void this.#openCreatedFlow(flowId), (flowId) => {
|
|
5744
6516
|
this.connectorAccess.changed(flowId);
|
|
5745
6517
|
this.workspace.catalogs.refreshFlow(flowId);
|
|
5746
6518
|
});
|
|
@@ -6118,7 +6890,7 @@ var WorkbenchStore = class {
|
|
|
6118
6890
|
};
|
|
6119
6891
|
//#endregion
|
|
6120
6892
|
//#region src/workbench/browser/runtime/openFlowWorkbench.tsx
|
|
6121
|
-
var FlowWorkspace = lazy(() => import("./flowWorkspace-
|
|
6893
|
+
var FlowWorkspace = lazy(() => import("./flowWorkspace-DLgti4Lk.js"));
|
|
6122
6894
|
function OpenFlowSessionGate({ action, description, error, onSubmit, onTokenChange, pending = false, title, token, tokenLabel }) {
|
|
6123
6895
|
const hasToken = token != null && tokenLabel != null && onTokenChange != null;
|
|
6124
6896
|
const tokenValue = token ?? "";
|
|
@@ -6253,17 +7025,17 @@ function Workbench({ catalogWidth, createFlow, createFlowDisabled, createFlowFie
|
|
|
6253
7025
|
})
|
|
6254
7026
|
});
|
|
6255
7027
|
}
|
|
6256
|
-
function Session({ catalogWidth, createFlow, createFlowDisabled, createFlowField, flowBadges, connectionHref, host, hrefFor, language, location, onConfigureConnector, onManageConnectorAccess, onLanguageChange, onNavigate, preferences, theme, variables = true }) {
|
|
7028
|
+
function Session({ catalogWidth, createFlow, createFlowDisabled, createFlowField, flowBadges, connectionHref, host, hrefFor, language, location, onConfigureConnector, onManageConnectorAccess, onLanguageChange, onNavigate, preferences, sessionKey, theme, variables = true }) {
|
|
6257
7029
|
const navigate = useRef(onNavigate);
|
|
6258
7030
|
navigate.current = onNavigate;
|
|
6259
7031
|
const [{ i18n, navigation, store }] = useState(() => {
|
|
6260
7032
|
const workbenchI18n = createI18n(language);
|
|
6261
7033
|
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, {
|
|
6262
7034
|
openExternalPage: (resolveUrl) => host.openExternalPage(resolveUrl),
|
|
6263
|
-
|
|
6264
|
-
|
|
7035
|
+
cacheEnvironment: host.cacheEnvironment,
|
|
7036
|
+
connectorOwnerId: host.connectorOwnerId,
|
|
6265
7037
|
resolveActor: actorResolver(host, globalThis.location?.origin)
|
|
6266
|
-
}, variables);
|
|
7038
|
+
}, variables, sessionKey);
|
|
6267
7039
|
return {
|
|
6268
7040
|
i18n: workbenchI18n,
|
|
6269
7041
|
navigation: new NavigationStore(workbenchStore, location, (nextLocation, options) => navigate.current(nextLocation, options)),
|
|
@@ -6334,7 +7106,10 @@ function Session({ catalogWidth, createFlow, createFlowDisabled, createFlowField
|
|
|
6334
7106
|
});
|
|
6335
7107
|
}
|
|
6336
7108
|
function OpenFlowWorkbench({ sessionKey, ...props }) {
|
|
6337
|
-
return /* @__PURE__ */ jsx(Session, {
|
|
7109
|
+
return /* @__PURE__ */ jsx(Session, {
|
|
7110
|
+
sessionKey,
|
|
7111
|
+
...props
|
|
7112
|
+
}, `${sessionKey}:${props.host.connectorOwnerId ?? ""}`);
|
|
6338
7113
|
}
|
|
6339
7114
|
//#endregion
|
|
6340
7115
|
export { EventSourcesPage, OpenFlowSessionGate, OpenFlowWorkbench, isUiLanguage as isWorkbenchLanguage, resolveUiLanguage as resolveWorkbenchLanguage, uiLanguageNames as workbenchLanguageNames, uiLanguages as workbenchLanguages };
|