-
+ {sortable !== false ? (
+
+ ) : null}
{step.kind === "script" && scriptName ? (
) : null}
@@ -384,12 +409,6 @@ function NeedsMap({ needs, ids, disabled, onChange }) {
);
}
-function needsMode(needs) {
- if (needs == null) return "none";
- if (Array.isArray(needs)) return "list";
- return "map";
-}
-
function ScriptTryDialog({ script, config, meta, owner, onClose }) {
const existing = useScript(script);
const dryRun = useDryRunScript();
diff --git a/packages/web/src/components/workflow/ScriptsTab.jsx b/packages/web/src/components/workflow/ScriptsTab.jsx
index 408ee34..126f3b3 100644
--- a/packages/web/src/components/workflow/ScriptsTab.jsx
+++ b/packages/web/src/components/workflow/ScriptsTab.jsx
@@ -15,7 +15,7 @@ import {
} from "@dnd-kit/sortable";
import { LuPlus } from "react-icons/lu";
import { defaultConfigFromMeta } from "../../lib/script.js";
-import { newProfileStep, newScriptStep, newSetStep } from "../../lib/workflow-doc.js";
+import { newProfileStep, newScriptStep, newSetStep, withAllocatedStepId } from "../../lib/workflow-doc.js";
import { AddScriptDialog } from "./AddScriptDialog.jsx";
import { ScriptCard } from "./ScriptCard.jsx";
@@ -115,16 +115,11 @@ export function ScriptsTab({
owner={owner}
onClose={() => setAddOpen(false)}
onPick={(picked) => {
- if (picked.kind === "set") {
- patchSteps([...steps, newSetStep()]);
- } else if (picked.kind === "profile") {
- patchSteps([...steps, newProfileStep(picked.name, picked.script)]);
- } else {
- patchSteps([
- ...steps,
- newScriptStep(picked.name, defaultConfigFromMeta(picked.meta)),
- ]);
- }
+ let next;
+ if (picked.kind === "set") next = newSetStep();
+ else if (picked.kind === "profile") next = newProfileStep(picked.name, picked.script);
+ else next = newScriptStep(picked.name, defaultConfigFromMeta(picked.meta));
+ patchSteps([...steps, withAllocatedStepId(next, steps)]);
setAddOpen(false);
}}
/>
diff --git a/packages/web/src/components/workflow/TriggerCard.jsx b/packages/web/src/components/workflow/TriggerCard.jsx
index 15aa3cb..de6d9fb 100644
--- a/packages/web/src/components/workflow/TriggerCard.jsx
+++ b/packages/web/src/components/workflow/TriggerCard.jsx
@@ -8,7 +8,22 @@ import { CRON_CUSTOM, CRON_PRESETS, matchCronPreset, scheduleForPreset } from ".
import { FormInput, FormSelect } from "../FormControls.jsx";
import { AuthPicker } from "./AuthPicker.jsx";
-export function TriggerCard({
+export function TriggerCard(props) {
+ if (props.sortable === false) {
+ return
;
+ }
+ return
;
+}
+
+function TriggerCardSortable(props) {
+ const drag = useSortable({
+ id: props.trigger.uiId,
+ disabled: props.disabled,
+ });
+ return
;
+}
+
+function TriggerCardView({
trigger,
index,
owner,
@@ -19,18 +34,25 @@ export function TriggerCard({
pages = [],
workflows = [],
excludeFile,
+ sortable = true,
+ defaultExpanded = false,
+ drag,
}) {
- const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
- id: trigger.uiId,
- disabled,
- });
+ const { attributes, listeners, setNodeRef, transform, transition, isDragging } = drag ?? {
+ attributes: {},
+ listeners: {},
+ setNodeRef: undefined,
+ transform: null,
+ transition: undefined,
+ isDragging: false,
+ };
const style = {
transform: CSS.Transform.toString(transform),
transition,
opacity: isDragging ? 0.6 : 1,
};
const type = trigger.type;
- const [expanded, setExpanded] = useState(false);
+ const [expanded, setExpanded] = useState(defaultExpanded);
const alertDestinations = triggerDestinations(workflows, { owner, excludeFile });
return (
@@ -43,16 +65,18 @@ export function TriggerCard({
>
-
+ {sortable !== false ? (
+
+ ) : null}
@@ -222,13 +252,11 @@ export function WorkflowTestPanel({
) : null}
-
{}}
- readOnly
- height="100%"
- />
+ {resultValue === undefined ? (
+ Run the workflow to see a result tree.
+ ) : (
+
+ )}
diff --git a/packages/web/src/components/workflow/WorkflowVisualEditor.jsx b/packages/web/src/components/workflow/WorkflowVisualEditor.jsx
index 28aaf7a..39e11a0 100644
--- a/packages/web/src/components/workflow/WorkflowVisualEditor.jsx
+++ b/packages/web/src/components/workflow/WorkflowVisualEditor.jsx
@@ -1,34 +1,14 @@
import { useMemo, useState } from "react";
-import { parse as parseYaml } from "yaml";
import { useHttpAuths, useHttpPages, useProfiles, useScripts, useWorkflows } from "../../api/hooks.js";
import { dataFromInputMeta, firstInputMeta } from "../../lib/script.js";
-import { workflowToFlowchart } from "../../lib/workflow-mermaid.js";
import { parseWorkflowYaml, stringifyWorkflowDoc } from "../../lib/workflow-doc.js";
import { FormInput, FormTextarea } from "../FormControls.jsx";
+import { GraphTab } from "./GraphTab.jsx";
import { ScriptsTab } from "./ScriptsTab.jsx";
import { TriggersTab } from "./TriggersTab.jsx";
import { YamlTab } from "./YamlTab.jsx";
import { WorkflowTestPanel } from "./WorkflowTestPanel.jsx";
-function useYamlPreview(content) {
- return useMemo(() => {
- try {
- const parsedYaml = parseYaml(content);
- return {
- parsed: parsedYaml,
- parseError: null,
- mermaid: workflowToFlowchart(parsedYaml),
- };
- } catch (err) {
- return {
- parsed: null,
- parseError: err instanceof Error ? err.message : String(err),
- mermaid: { chart: "", scriptIds: {} },
- };
- }
- }, [content]);
-}
-
export function WorkflowVisualEditor({
yaml,
onYamlChange,
@@ -40,14 +20,14 @@ export function WorkflowVisualEditor({
testOpen,
onTestClose,
}) {
- const [tab, setTab] = useState("scripts");
+ const [tab, setTab] = useState("graph");
const [lastEdited, setLastEdited] = useState("yaml");
const [doc, setDoc] = useState(() => parseWorkflowYaml(yaml).doc);
- const { parsed, parseError, mermaid } = useYamlPreview(yaml);
const parsedDoc = useMemo(() => parseWorkflowYaml(yaml), [yaml]);
const displayDoc = lastEdited === "visual" && doc ? doc : parsedDoc.doc;
const visualDisabled = !displayDoc;
+ const parseError = parsedDoc.parseError;
const { data: scripts = [] } = useScripts();
const { data: profiles = [] } = useProfiles(owner || undefined, { enabled: Boolean(owner) });
@@ -116,6 +96,20 @@ export function WorkflowVisualEditor({
if (visualDisabled) testDisabledReason = "Fix YAML before running.";
else if (unsaved) testDisabledReason = "Save the workflow before running. Test uses the saved YAML.";
+ const graphProps = {
+ doc: displayDoc,
+ onPatch: patchDoc,
+ disabled: visualDisabled,
+ scripts,
+ profiles,
+ workflows,
+ owner,
+ file,
+ excludeFile: file,
+ auths,
+ pages,
+ };
+
return (
<>
@@ -147,6 +141,14 @@ export function WorkflowVisualEditor({
+
selectTab("graph")}
+ >
+ Graph
+
) : null}
+ {tab === "graph" ? : null}
{tab === "scripts" ? (
) : null}
{tab === "yaml" ? (
-
+
) : null}
{showTest && owner && file ? (
diff --git a/packages/web/src/components/workflow/YamlTab.jsx b/packages/web/src/components/workflow/YamlTab.jsx
index 3e3cb62..fe236a4 100644
--- a/packages/web/src/components/workflow/YamlTab.jsx
+++ b/packages/web/src/components/workflow/YamlTab.jsx
@@ -1,20 +1,12 @@
import { CodeEditor } from "../CodeEditor.jsx";
-import { MermaidDiagram } from "../MermaidDiagram.jsx";
-export function YamlTab({ content, onChange, parseError, mermaid, parsed }) {
+export function YamlTab({ content, onChange, parseError }) {
return (
-
-
+
+ {parseError ?
{parseError}
: null}
+
-
- {parseError ? (
-
{parseError}
- ) : (
-
- )}
- {parsed?.name ?
{parsed.name}
: null}
-
);
}
diff --git a/packages/web/src/components/workflow/graph/GraphNodes.jsx b/packages/web/src/components/workflow/graph/GraphNodes.jsx
new file mode 100644
index 0000000..e0d973d
--- /dev/null
+++ b/packages/web/src/components/workflow/graph/GraphNodes.jsx
@@ -0,0 +1,58 @@
+import { Handle, Position } from "@xyflow/react";
+
+export function TriggerGraphNode({ data, selected }) {
+ return (
+
+
Trigger
+
{data.triggerType || "HTTP"}
+
+ {data.label}
+
+
+
+ );
+}
+
+export function StepGraphNode({ data, selected }) {
+ const kindLabel = data.kind === "set" ? "set" : data.profile ? "profile" : "script";
+ return (
+
+
+
+
{kindLabel}
+ {data.stepId ? (
+
{data.stepId}
+ ) : null}
+ {data.when ? (
+
+ when
+
+ ) : null}
+ {data.needsMode === "map" ? (
+
+ map
+
+ ) : null}
+
+
+ {data.label}
+
+ {data.missingNeeds?.length ? (
+
Unknown needs: {data.missingNeeds.join(", ")}
+ ) : null}
+
+
+ );
+}
diff --git a/packages/web/src/index.css b/packages/web/src/index.css
index 0070d50..5542848 100644
--- a/packages/web/src/index.css
+++ b/packages/web/src/index.css
@@ -25,6 +25,7 @@ body,
transition: transform 0.7s ease-out;
}
-.mermaid-clickable [id^="s"] {
- cursor: pointer;
+.workflow-graph {
+ width: 100%;
+ height: 100%;
}
diff --git a/packages/web/src/lib/workflow-doc.js b/packages/web/src/lib/workflow-doc.js
index ed024aa..c46fd57 100644
--- a/packages/web/src/lib/workflow-doc.js
+++ b/packages/web/src/lib/workflow-doc.js
@@ -78,6 +78,37 @@ export function stringifyWorkflowDoc(doc) {
return stringifyYaml(out, { indent: 2, lineWidth: 0 });
}
+export function nextStepId(existingIds) {
+ const used = existingIds instanceof Set ? existingIds : new Set([...(existingIds ?? [])].filter(Boolean));
+ let n = 1;
+ while (used.has(`step-${n}`)) n += 1;
+ return `step-${n}`;
+}
+
+export function withAllocatedStepId(step, existingSteps) {
+ if (step?.id) return step;
+ const ids = (existingSteps ?? []).map((s) => s.id).filter(Boolean);
+ return { ...step, id: nextStepId(ids) };
+}
+
+export function needsMode(needs) {
+ if (needs == null) return "none";
+ if (Array.isArray(needs)) return "list";
+ if (typeof needs === "object") return "map";
+ return "none";
+}
+
+export function isEmptyNeeds(needs) {
+ if (needs == null) return true;
+ if (Array.isArray(needs)) return needs.length === 0;
+ if (typeof needs === "object") return Object.keys(needs).length === 0;
+ return false;
+}
+
+export function isDagDoc(doc) {
+ return (doc?.scripts ?? []).some((s) => !isEmptyNeeds(s.needs));
+}
+
export function newScriptStep(script, config = {}) {
return {
uiId: nextUiId("step"),
@@ -349,10 +380,3 @@ function dumpTrigger(t) {
}
return { type: t?.type ?? "HTTP", ...(t.extra ?? {}) };
}
-
-function isEmptyNeeds(needs) {
- if (needs == null) return true;
- if (Array.isArray(needs)) return needs.length === 0;
- if (typeof needs === "object") return Object.keys(needs).length === 0;
- return false;
-}
diff --git a/packages/web/src/lib/workflow-graph.js b/packages/web/src/lib/workflow-graph.js
new file mode 100644
index 0000000..521054c
--- /dev/null
+++ b/packages/web/src/lib/workflow-graph.js
@@ -0,0 +1,418 @@
+import { isDagDoc, isEmptyNeeds, needsMode, nextStepId } from "./workflow-doc.js";
+
+export const STEP_NODE_PREFIX = "step:";
+export const TRIGGER_NODE_PREFIX = "trig:";
+
+export function stepNodeId(uiId) {
+ return `${STEP_NODE_PREFIX}${uiId}`;
+}
+
+export function triggerNodeId(uiId) {
+ return `${TRIGGER_NODE_PREFIX}${uiId}`;
+}
+
+export function parseGraphNodeId(id) {
+ if (typeof id !== "string") return null;
+ if (id.startsWith(STEP_NODE_PREFIX)) {
+ return { kind: "step", uiId: id.slice(STEP_NODE_PREFIX.length) };
+ }
+ if (id.startsWith(TRIGGER_NODE_PREFIX)) {
+ return { kind: "trigger", uiId: id.slice(TRIGGER_NODE_PREFIX.length) };
+ }
+ return null;
+}
+
+export function parentIdsFromNeeds(needs) {
+ if (needs == null) return [];
+ if (Array.isArray(needs)) {
+ return needs.filter((x) => typeof x === "string" && x.length > 0);
+ }
+ if (typeof needs === "object") {
+ return Object.values(needs).filter((x) => typeof x === "string" && x.length > 0);
+ }
+ return [];
+}
+
+export function triggerSummary(trigger, owner) {
+ const type = String(trigger?.type ?? "").toLowerCase();
+ if (type === "cron") return trigger.schedule || "cron";
+ if (type === "workflow") return "callable";
+ const method = trigger?.method || "POST";
+ const path = trigger?.path || "/";
+ if (owner) return `${method} /u/${owner}${path.startsWith("/") ? path : `/${path}`}`;
+ return `${method} ${path}`;
+}
+
+export function stepLabel(step) {
+ if (step?.kind === "set") return step.id ? `${step.id}: set` : "set";
+ const target = step?.profile ? `profile ${step.profile}` : step?.script || "untitled";
+ return step?.id ? `${step.id}: ${target}` : target;
+}
+
+export function layoutKeyForTrigger(index) {
+ return `t:${index}`;
+}
+
+export function layoutKeyForStep(step, index) {
+ if (step?.id) return `s-id:${step.id}`;
+ return `s:${index}`;
+}
+
+export function docHasWhen(doc) {
+ return (doc?.scripts ?? []).some((s) => typeof s.when === "string" && s.when.trim());
+}
+
+function cloneScripts(doc) {
+ return (doc?.scripts ?? []).map((s) => ({ ...s }));
+}
+
+function usedIds(scripts) {
+ return new Set(scripts.map((s) => s.id).filter(Boolean));
+}
+
+function ensureStepId(step, used) {
+ if (step.id) {
+ used.add(step.id);
+ return step;
+ }
+ const id = nextStepId(used);
+ used.add(id);
+ return { ...step, id };
+}
+
+export function stripWhenFromScripts(scripts) {
+ return scripts.map((s) => (s.when ? { ...s, when: "" } : s));
+}
+
+/**
+ * Turn implicit linear order into list `needs` (and assign missing ids).
+ * Callers must strip `when` when entering DAG.
+ */
+export function materializeLinearNeeds(scripts) {
+ if (scripts.length === 0) return scripts;
+ const used = usedIds(scripts);
+ const next = scripts.map((s) => ensureStepId({ ...s }, used));
+ for (let i = 1; i < next.length; i++) {
+ const parentId = next[i - 1].id;
+ next[i] = { ...next[i], needs: [parentId], when: "" };
+ }
+ next[0] = { ...next[0], when: "" };
+ return next;
+}
+
+function adjacencyFromScripts(scripts) {
+ const byId = new Map();
+ for (const s of scripts) {
+ if (s.id) byId.set(s.id, s.uiId);
+ }
+ /** @type {Map
} */
+ const children = new Map();
+ for (const s of scripts) children.set(s.uiId, []);
+ const dag = scripts.some((s) => !isEmptyNeeds(s.needs));
+ if (dag) {
+ for (const s of scripts) {
+ for (const pid of parentIdsFromNeeds(s.needs)) {
+ const fromUi = byId.get(pid);
+ if (fromUi) children.get(fromUi)?.push(s.uiId);
+ }
+ }
+ } else {
+ for (let i = 1; i < scripts.length; i++) {
+ children.get(scripts[i - 1].uiId)?.push(scripts[i].uiId);
+ }
+ }
+ return children;
+}
+
+export function wouldCreateCycle(scripts, fromUiId, toUiId) {
+ if (fromUiId === toUiId) return true;
+ const children = adjacencyFromScripts(scripts);
+ const stack = [...(children.get(toUiId) ?? [])];
+ const seen = new Set();
+ while (stack.length) {
+ const cur = stack.pop();
+ if (cur === fromUiId) return true;
+ if (seen.has(cur)) continue;
+ seen.add(cur);
+ for (const n of children.get(cur) ?? []) stack.push(n);
+ }
+ return false;
+}
+
+export function canConnectSteps(doc, fromUiId, toUiId) {
+ const scripts = doc?.scripts ?? [];
+ const from = scripts.find((s) => s.uiId === fromUiId);
+ const to = scripts.find((s) => s.uiId === toUiId);
+ if (!from || !to) return false;
+ if (fromUiId === toUiId) return false;
+ if (needsMode(to.needs) === "map") return false;
+ if (wouldCreateCycle(scripts, fromUiId, toUiId)) return false;
+ return true;
+}
+
+export function addStepEdge(doc, fromUiId, toUiId) {
+ if (!canConnectSteps(doc, fromUiId, toUiId)) return doc?.scripts ?? [];
+ let scripts = cloneScripts(doc);
+ if (!isDagDoc({ scripts })) {
+ scripts = materializeLinearNeeds(scripts);
+ }
+ const from = scripts.find((s) => s.uiId === fromUiId);
+ const toIndex = scripts.findIndex((s) => s.uiId === toUiId);
+ if (!from || toIndex < 0) return scripts;
+ const to = scripts[toIndex];
+ if (needsMode(to.needs) === "map") return scripts;
+ const used = usedIds(scripts);
+ const source = ensureStepId(from, used);
+ scripts = scripts.map((s) => (s.uiId === source.uiId ? source : s));
+ const current = Array.isArray(to.needs) ? [...to.needs] : [];
+ if (!current.includes(source.id)) current.push(source.id);
+ scripts[toIndex] = { ...to, needs: current, when: "" };
+ return stripWhenFromScripts(scripts);
+}
+
+export function removeStepEdge(doc, fromUiId, toUiId) {
+ let scripts = cloneScripts(doc);
+ if (!isDagDoc({ scripts })) {
+ scripts = materializeLinearNeeds(scripts);
+ }
+ const from = scripts.find((s) => s.uiId === fromUiId);
+ const toIndex = scripts.findIndex((s) => s.uiId === toUiId);
+ if (!from?.id || toIndex < 0) return scripts;
+ const to = scripts[toIndex];
+ if (needsMode(to.needs) === "map") return scripts;
+ if (!Array.isArray(to.needs)) return scripts;
+ const nextNeeds = to.needs.filter((id) => id !== from.id);
+ scripts[toIndex] = { ...to, needs: nextNeeds.length ? nextNeeds : null };
+ return scripts;
+}
+
+export function enteringDagWouldStripWhen(doc) {
+ return !isDagDoc(doc) && docHasWhen(doc);
+}
+
+/**
+ * @returns {{ nodes: object[], edges: object[] }}
+ */
+export function buildGraphElements(doc, positions = {}) {
+ const scripts = doc?.scripts ?? [];
+ const triggers = doc?.triggers ?? [];
+ const dag = isDagDoc(doc);
+ const byId = new Map();
+ for (const s of scripts) {
+ if (s.id) byId.set(s.id, s);
+ }
+
+ const auto = autoLayout(doc);
+ const nodes = [];
+ const edges = [];
+
+ for (let i = 0; i < triggers.length; i++) {
+ const t = triggers[i];
+ const id = triggerNodeId(t.uiId);
+ const layoutKey = layoutKeyForTrigger(i);
+ nodes.push({
+ id,
+ type: "trigger",
+ position: positions[layoutKey] ?? auto[layoutKey] ?? { x: 0, y: i * 96 },
+ data: {
+ layoutKey,
+ label: triggerSummary(t),
+ triggerType: t.type,
+ uiId: t.uiId,
+ index: i,
+ },
+ });
+ }
+
+ for (let i = 0; i < scripts.length; i++) {
+ const s = scripts[i];
+ const id = stepNodeId(s.uiId);
+ const layoutKey = layoutKeyForStep(s, i);
+ const mode = needsMode(s.needs);
+ const parents = parentIdsFromNeeds(s.needs);
+ const missing = parents.filter((pid) => !byId.has(pid));
+ nodes.push({
+ id,
+ type: "step",
+ position: positions[layoutKey] ?? auto[layoutKey] ?? { x: 280, y: i * 96 },
+ data: {
+ layoutKey,
+ label: stepLabel(s),
+ kind: s.kind,
+ stepId: s.id || "",
+ when: s.when || "",
+ needsMode: mode,
+ script: s.script || "",
+ profile: s.profile || "",
+ missingNeeds: missing,
+ uiId: s.uiId,
+ index: i,
+ },
+ });
+ }
+
+ /** @type {string[]} */
+ const roots = [];
+ if (dag) {
+ for (const s of scripts) {
+ const parents = parentIdsFromNeeds(s.needs);
+ if (parents.length === 0) roots.push(s.uiId);
+ const mode = needsMode(s.needs);
+ if (mode === "map" && s.needs && typeof s.needs === "object" && !Array.isArray(s.needs)) {
+ for (const [alias, pid] of Object.entries(s.needs)) {
+ if (typeof pid !== "string" || !pid) continue;
+ const from = byId.get(pid);
+ if (!from) continue;
+ edges.push({
+ id: `e:map:${from.uiId}->${s.uiId}:${alias}`,
+ source: stepNodeId(from.uiId),
+ target: stepNodeId(s.uiId),
+ deletable: false,
+ selectable: false,
+ data: { edgeKind: "map", alias },
+ style: { strokeDasharray: "6 4" },
+ label: alias,
+ });
+ }
+ } else {
+ for (const pid of parents) {
+ const from = byId.get(pid);
+ if (!from) continue;
+ edges.push({
+ id: `e:step:${from.uiId}->${s.uiId}`,
+ source: stepNodeId(from.uiId),
+ target: stepNodeId(s.uiId),
+ deletable: true,
+ selectable: true,
+ data: { edgeKind: "list" },
+ });
+ }
+ }
+ }
+ } else {
+ if (scripts[0]) roots.push(scripts[0].uiId);
+ for (let i = 1; i < scripts.length; i++) {
+ const from = scripts[i - 1];
+ const to = scripts[i];
+ edges.push({
+ id: `e:linear:${from.uiId}->${to.uiId}`,
+ source: stepNodeId(from.uiId),
+ target: stepNodeId(to.uiId),
+ deletable: true,
+ data: { edgeKind: "linear" },
+ });
+ }
+ }
+
+ for (const t of triggers) {
+ for (const rid of roots) {
+ edges.push({
+ id: `e:trig:${t.uiId}->${rid}`,
+ source: triggerNodeId(t.uiId),
+ target: stepNodeId(rid),
+ deletable: false,
+ selectable: false,
+ focusable: false,
+ data: { edgeKind: "trigger" },
+ });
+ }
+ }
+
+ return { nodes, edges };
+}
+
+export function autoLayout(doc) {
+ const scripts = doc?.scripts ?? [];
+ const triggers = doc?.triggers ?? [];
+ const dag = isDagDoc(doc);
+ const colW = 240;
+ const rowH = 96;
+ const leftX = 24;
+ const stepX0 = 280;
+
+ /** @type {Record} */
+ const pos = {};
+ for (let i = 0; i < triggers.length; i++) {
+ pos[layoutKeyForTrigger(i)] = { x: leftX, y: 24 + i * rowH };
+ }
+
+ /** @type {number[]} */
+ const ranks = scripts.map(() => 0);
+ if (dag) {
+ const byId = new Map();
+ scripts.forEach((s, i) => {
+ if (s.id) byId.set(s.id, i);
+ });
+ const visiting = new Set();
+ const seen = new Set();
+ function rankOf(i) {
+ if (seen.has(i)) return ranks[i];
+ if (visiting.has(i)) return 0;
+ visiting.add(i);
+ let r = 0;
+ for (const pid of parentIdsFromNeeds(scripts[i].needs)) {
+ const pi = byId.get(pid);
+ if (pi == null) continue;
+ r = Math.max(r, rankOf(pi) + 1);
+ }
+ visiting.delete(i);
+ seen.add(i);
+ ranks[i] = r;
+ return r;
+ }
+ scripts.forEach((_, i) => rankOf(i));
+ } else {
+ scripts.forEach((_, i) => {
+ ranks[i] = i;
+ });
+ }
+
+ /** @type {Map} */
+ const rowAtRank = new Map();
+ scripts.forEach((s, i) => {
+ const rank = ranks[i];
+ const row = rowAtRank.get(rank) ?? 0;
+ rowAtRank.set(rank, row + 1);
+ pos[layoutKeyForStep(s, i)] = {
+ x: stepX0 + rank * colW,
+ y: 24 + row * rowH,
+ };
+ });
+ return pos;
+}
+
+const LAYOUT_PREFIX = "jerapah-flow.workflowGraphLayout:";
+
+export function workflowGraphLayoutKey(owner, file) {
+ return `${LAYOUT_PREFIX}${owner}/${file}`;
+}
+
+export function readGraphLayout(owner, file) {
+ if (typeof localStorage === "undefined" || !owner || !file) return {};
+ try {
+ const raw = localStorage.getItem(workflowGraphLayoutKey(owner, file));
+ if (!raw) return {};
+ const parsed = JSON.parse(raw);
+ return parsed && typeof parsed === "object" ? parsed : {};
+ } catch {
+ return {};
+ }
+}
+
+export function writeGraphLayout(owner, file, positions) {
+ if (typeof localStorage === "undefined" || !owner || !file) return;
+ try {
+ localStorage.setItem(workflowGraphLayoutKey(owner, file), JSON.stringify(positions));
+ } catch {
+ // quota / private mode
+ }
+}
+
+export function clearGraphLayout(owner, file) {
+ if (typeof localStorage === "undefined" || !owner || !file) return;
+ try {
+ localStorage.removeItem(workflowGraphLayoutKey(owner, file));
+ } catch {
+ // ignore
+ }
+}
diff --git a/packages/web/src/lib/workflow-graph.test.js b/packages/web/src/lib/workflow-graph.test.js
new file mode 100644
index 0000000..6de1062
--- /dev/null
+++ b/packages/web/src/lib/workflow-graph.test.js
@@ -0,0 +1,89 @@
+import assert from "node:assert/strict";
+import test from "node:test";
+import { isDagDoc, nextStepId, withAllocatedStepId } from "./workflow-doc.js";
+import {
+ addStepEdge,
+ canConnectSteps,
+ enteringDagWouldStripWhen,
+ removeStepEdge,
+ wouldCreateCycle,
+} from "./workflow-graph.js";
+
+function step(uiId, extra = {}) {
+ return {
+ uiId,
+ kind: "script",
+ script: uiId,
+ profile: "",
+ config: {},
+ id: extra.id ?? "",
+ when: extra.when ?? "",
+ needs: extra.needs ?? null,
+ };
+}
+
+test("nextStepId skips taken ids", () => {
+ assert.equal(nextStepId([]), "step-1");
+ assert.equal(nextStepId(["step-1", "step-2"]), "step-3");
+ assert.equal(nextStepId(["step-1", "step-3"]), "step-2");
+});
+
+test("withAllocatedStepId leaves existing id", () => {
+ const s = withAllocatedStepId(step("a", { id: "weather" }), []);
+ assert.equal(s.id, "weather");
+});
+
+test("addStepEdge materializes linear chain then adds the extra edge", () => {
+ const doc = { scripts: [step("a"), step("b"), step("c")] };
+ const scripts = addStepEdge(doc, "a", "c");
+ assert.equal(isDagDoc({ scripts }), true);
+ assert.equal(scripts[0].id, "step-1");
+ assert.equal(scripts[1].id, "step-2");
+ assert.equal(scripts[2].id, "step-3");
+ assert.deepEqual(scripts[1].needs, ["step-1"]);
+ assert.deepEqual(scripts[2].needs, ["step-2", "step-1"]);
+});
+
+test("addStepEdge strips when when entering DAG", () => {
+ const doc = {
+ scripts: [step("a", { when: "true" }), step("b", { when: "false" })],
+ };
+ assert.equal(enteringDagWouldStripWhen(doc), true);
+ const scripts = addStepEdge(doc, "a", "b");
+ assert.equal(scripts[0].when, "");
+ assert.equal(scripts[1].when, "");
+});
+
+test("canConnectSteps blocks cycles and map targets", () => {
+ const linear = { scripts: [step("a"), step("b"), step("c")] };
+ assert.equal(canConnectSteps(linear, "a", "c"), true);
+ assert.equal(canConnectSteps(linear, "c", "a"), false);
+ const dag = {
+ scripts: [
+ step("a", { id: "a" }),
+ step("b", { id: "b", needs: ["a"] }),
+ step("c", { id: "c", needs: ["b"] }),
+ ],
+ };
+ assert.equal(wouldCreateCycle(dag.scripts, "c", "a"), true);
+ assert.equal(canConnectSteps(dag, "c", "a"), false);
+ const mapped = {
+ scripts: [
+ step("a", { id: "a" }),
+ step("b", { id: "b", needs: { current: "a" } }),
+ ],
+ };
+ assert.equal(canConnectSteps(mapped, "a", "b"), false);
+});
+
+test("removeStepEdge drops a list dependency", () => {
+ const doc = {
+ scripts: [
+ step("a", { id: "a" }),
+ step("b", { id: "b", needs: ["a"] }),
+ ],
+ };
+ const scripts = removeStepEdge(doc, "a", "b");
+ assert.equal(scripts[1].needs, null);
+ assert.equal(isDagDoc({ scripts }), false);
+});
diff --git a/packages/web/src/lib/workflow-mermaid.js b/packages/web/src/lib/workflow-mermaid.js
deleted file mode 100644
index 94740e3..0000000
--- a/packages/web/src/lib/workflow-mermaid.js
+++ /dev/null
@@ -1,161 +0,0 @@
-function parseStep(step) {
- if (typeof step === "string") {
- return { kind: "script", script: step, profile: null, id: null, needs: null, when: null };
- }
- if (step?.set) {
- return {
- kind: "set",
- script: null,
- profile: null,
- id: typeof step.id === "string" && step.id ? step.id : null,
- needs: step.needs ?? null,
- when: typeof step.when === "string" && step.when ? step.when : null,
- };
- }
- if (step?.script || step?.profile) {
- return {
- kind: "script",
- script: typeof step.script === "string" && step.script ? step.script : null,
- profile: typeof step.profile === "string" && step.profile ? step.profile : null,
- id: typeof step.id === "string" && step.id ? step.id : null,
- needs: step.needs ?? null,
- when: typeof step.when === "string" && step.when ? step.when : null,
- };
- }
- return null;
-}
-
-function parentIdsFromNeeds(needs) {
- if (needs == null) return null;
- if (Array.isArray(needs)) {
- return needs.filter((x) => typeof x === "string" && x.length > 0);
- }
- if (typeof needs === "object") {
- return Object.values(needs).filter((x) => typeof x === "string" && x.length > 0);
- }
- return [];
-}
-
-function mermaidLabel(text) {
- return String(text ?? "")
- .replace(/"/g, "#quot;")
- .replace(/[[\]]/g, " ")
- .trim() || "node";
-}
-
-function triggerLabel(t) {
- const type = String(t?.type ?? "").toLowerCase();
- if (type === "cron") return `cron ${t.schedule ?? ""}`.trim();
- if (type === "workflow") return "workflow";
- const method = t?.method ?? "POST";
- const path = t?.path ?? "";
- return `${method} ${path}`.trim();
-}
-
-function stepLabel(s) {
- if (s.kind === "set") {
- const base = s.id ? `${s.id}: set` : "set";
- return s.when ? `${base} when: ${s.when}` : base;
- }
- const target = s.profile ? `profile ${s.profile}` : s.script;
- const base = s.id ? `${s.id}: ${target}` : target;
- return s.when ? `${base} when: ${s.when}` : base;
-}
-
-export function workflowToFlowchart(parsed) {
- /** @type {Record} */
- const scriptIds = {};
- if (!parsed || typeof parsed !== "object") {
- return { chart: "", scriptIds };
- }
-
- const lines = ["flowchart LR"];
-
- const triggerIds = [];
- const triggers = Array.isArray(parsed.triggers) ? parsed.triggers : [];
- triggers.forEach((t, i) => {
- const id = `t${i}`;
- lines.push(` ${id}(["${mermaidLabel(triggerLabel(t))}"])`);
- let outbound = id;
- if (t?.auth != null && t.auth !== false) {
- const authId = `${id}auth`;
- const label =
- typeof t.auth === "string"
- ? `auth ${t.auth}`
- : typeof t.auth === "object" && t.auth?.name
- ? `auth ${t.auth.name}`
- : typeof t.auth === "object" && t.auth?.type
- ? `auth ${t.auth.type}`
- : "auth";
- lines.push(` ${authId}(["${mermaidLabel(label)}"])`);
- lines.push(` ${id} --> ${authId}`);
- outbound = authId;
- }
- triggerIds.push(outbound);
- });
-
- const scripts = Array.isArray(parsed.scripts) ? parsed.scripts : [];
- const parsedSteps = [];
- scripts.forEach((step, i) => {
- const parsedStep = parseStep(step);
- if (!parsedStep) return;
- parsedSteps.push({ ...parsedStep, mermaidId: `s${i}` });
- });
-
- const dagMode = parsedSteps.some((s) => s.needs != null);
-
- /** @type {Record} */
- const idToMermaid = {};
- for (const s of parsedSteps) {
- if (s.id) idToMermaid[s.id] = s.mermaidId;
- }
-
- for (const s of parsedSteps) {
- const label = mermaidLabel(stepLabel(s));
- if (s.kind === "set") {
- lines.push(` ${s.mermaidId}(["${label}"])`);
- } else {
- scriptIds[s.mermaidId] = s.script || (s.profile ? `profile:${s.profile}` : "");
- lines.push(` ${s.mermaidId}["${label}"]`);
- }
- }
-
- if (dagMode) {
- const roots = [];
- for (const s of parsedSteps) {
- const parents = parentIdsFromNeeds(s.needs);
- if (!parents || parents.length === 0) {
- roots.push(s.mermaidId);
- continue;
- }
- for (const pid of parents) {
- const from = idToMermaid[pid];
- if (from) lines.push(` ${from} --> ${s.mermaidId}`);
- }
- }
- for (const tid of triggerIds) {
- for (const rid of roots) {
- lines.push(` ${tid} --> ${rid}`);
- }
- }
- } else {
- let prev = null;
- let firstScript = null;
- for (const s of parsedSteps) {
- if (!firstScript) firstScript = s.mermaidId;
- if (prev) lines.push(` ${prev} --> ${s.mermaidId}`);
- prev = s.mermaidId;
- }
- if (firstScript) {
- for (const tid of triggerIds) {
- lines.push(` ${tid} --> ${firstScript}`);
- }
- }
- }
-
- if (lines.length === 1) {
- return { chart: "", scriptIds };
- }
-
- return { chart: lines.join("\n"), scriptIds };
-}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1f1db6c..0b69a5e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -121,15 +121,15 @@ importers:
'@uiw/react-json-view':
specifier: 2.0.0-alpha.43
version: 2.0.0-alpha.43(@babel/runtime@8.0.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ '@xyflow/react':
+ specifier: ^12.11.3
+ version: 12.11.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
axios:
specifier: ^1.11.0
version: 1.19.0(debug@4.4.3(supports-color@7.2.0))(supports-color@7.2.0)
cronstrue:
specifier: ^3.24.0
version: 3.24.0
- mermaid:
- specifier: ^11.9.0
- version: 11.16.1
react:
specifier: ^19.1.1
version: 19.2.8
@@ -179,9 +179,6 @@ importers:
packages:
- '@antfu/install-pkg@1.1.0':
- resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==}
-
'@aws-sdk/checksums@3.1000.28':
resolution: {integrity: sha512-VCpnmyHQ1IH49ni3LXnQj7DPr7rmcJmzYeiCkYdCcfgNtkvOj38cdcL9lapBWoItZWFACJPFJlymqC7/gem3Gw==}
engines: {node: '>=20.0.0'}
@@ -344,15 +341,9 @@ packages:
resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==}
engines: {node: '>=6.9.0'}
- '@braintree/sanitize-url@7.1.2':
- resolution: {integrity: sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==}
-
'@buttercup/fetch@0.2.1':
resolution: {integrity: sha512-sCgECOx8wiqY8NN1xN22BqqKzXYIG2AicNLlakOAI4f0WgyLVUbAigMf8CZhBtJxdudTcB1gD5lciqi44jwJvg==}
- '@chevrotain/types@11.1.2':
- resolution: {integrity: sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw==}
-
'@dnd-kit/accessibility@3.1.1':
resolution: {integrity: sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==}
peerDependencies:
@@ -625,12 +616,6 @@ packages:
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
engines: {node: '>=18.18'}
- '@iconify/types@2.0.0':
- resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
-
- '@iconify/utils@3.1.4':
- resolution: {integrity: sha512-b1S7B1k9ohZ+iNTi2ATxbRYG9fTrJmUT0rc46bvVnNxqNRGW7dyo/vRREwyniI5IRN2RSJHDcm+s3BjWrSAjHw==}
-
'@ioredis/commands@2.0.0':
resolution: {integrity: sha512-vrx0AE/T0h7cRZwfo1M39Cr+ZhZrkf0V8mQN75wucKCxCLD9l/VX6no3gFvrLqD1IlG/1LtzWovqEw3t0Vr9zg==}
@@ -658,9 +643,6 @@ packages:
resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==}
engines: {node: '>=8'}
- '@mermaid-js/parser@1.2.0':
- resolution: {integrity: sha512-oYPyv8A4As1yH5Bx+04iQEQxXuIQDe0GKCNSRgao6z8AM9jixXIfP0vsppRLvGf+nKIOb9/LdpWA4YuJiVvESA==}
-
'@monaco-editor/loader@1.7.0':
resolution: {integrity: sha512-gIwR1HrJrrx+vfyOhYmCZ0/JcWqG5kbfG7+d3f/C1LXk2EvzAbHSg3MQ5lO2sMlo9izoAZ04shohfKLVT6crVA==}
@@ -1018,108 +1000,30 @@ packages:
'@types/chai@5.2.3':
resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
- '@types/d3-array@3.2.2':
- resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==}
-
- '@types/d3-axis@3.0.6':
- resolution: {integrity: sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==}
-
- '@types/d3-brush@3.0.6':
- resolution: {integrity: sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==}
-
- '@types/d3-chord@3.0.6':
- resolution: {integrity: sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==}
-
'@types/d3-color@3.1.3':
resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==}
- '@types/d3-contour@3.0.6':
- resolution: {integrity: sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==}
-
- '@types/d3-delaunay@6.0.4':
- resolution: {integrity: sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==}
-
- '@types/d3-dispatch@3.0.7':
- resolution: {integrity: sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==}
-
'@types/d3-drag@3.0.7':
resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==}
- '@types/d3-dsv@3.0.7':
- resolution: {integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==}
-
- '@types/d3-ease@3.0.2':
- resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==}
-
- '@types/d3-fetch@3.0.7':
- resolution: {integrity: sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==}
-
- '@types/d3-force@3.0.10':
- resolution: {integrity: sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==}
-
- '@types/d3-format@3.0.4':
- resolution: {integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==}
-
- '@types/d3-geo@3.1.1':
- resolution: {integrity: sha512-65Emv9fQiQQqphLlRkuQ5ypPsOmWPhtBGCMv61JDPEPMvsx+gzhGf74yw1a78xFKPj6zw4AgQICJoQv0vK9M2w==}
-
- '@types/d3-hierarchy@3.1.7':
- resolution: {integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==}
-
'@types/d3-interpolate@3.0.4':
resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==}
- '@types/d3-path@3.1.1':
- resolution: {integrity: sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==}
-
- '@types/d3-polygon@3.0.2':
- resolution: {integrity: sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==}
-
- '@types/d3-quadtree@3.0.6':
- resolution: {integrity: sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==}
-
- '@types/d3-random@3.0.4':
- resolution: {integrity: sha512-UHYId5WTCx4L4YNel7NU00XUXXgvgpgZOvp10PuvsQENjMDXhh2RyFc0KBjO7B45ne4Ha1yVH7ii0vnzKkuzWA==}
-
- '@types/d3-scale-chromatic@3.1.0':
- resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==}
-
- '@types/d3-scale@4.0.9':
- resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==}
-
'@types/d3-selection@3.0.11':
resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==}
- '@types/d3-shape@3.1.8':
- resolution: {integrity: sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==}
-
- '@types/d3-time-format@4.0.3':
- resolution: {integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==}
-
- '@types/d3-time@3.0.4':
- resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==}
-
- '@types/d3-timer@3.0.2':
- resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==}
-
'@types/d3-transition@3.0.9':
resolution: {integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==}
'@types/d3-zoom@3.0.8':
resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==}
- '@types/d3@7.4.3':
- resolution: {integrity: sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==}
-
'@types/deep-eql@4.0.2':
resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
'@types/estree@1.0.9':
resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
- '@types/geojson@7946.0.16':
- resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==}
-
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
@@ -1133,9 +1037,6 @@ packages:
react: '>=18.0.0'
react-dom: '>=18.0.0'
- '@upsetjs/venn.js@2.0.0':
- resolution: {integrity: sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw==}
-
'@vitejs/plugin-react@5.2.0':
resolution: {integrity: sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1171,6 +1072,22 @@ packages:
'@vitest/utils@3.2.7':
resolution: {integrity: sha512-x6BDOd7dyo3PFLY3I9/HJ25X/6OurhGXk2/B9gOZNPF7XDVjeBK4k01lQE5uvDpbuheErh91qYuE1E2OEjK3Rw==}
+ '@xyflow/react@12.11.3':
+ resolution: {integrity: sha512-G3jogHz2GWUtIOkhavUGno2YzY9u6fILIJBttfsBendb0/HWB90JG+sOTAvlIMEwyvq9zgy9V9ZQSwyQjR5QzQ==}
+ peerDependencies:
+ '@types/react': '>=17'
+ '@types/react-dom': '>=17'
+ react: '>=17'
+ react-dom: '>=17'
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@xyflow/system@0.0.80':
+ resolution: {integrity: sha512-ywc3ZqG91brzWrH1WlwMdIX4goOfrpBy6AbLdVSaof/Xx9l138ijIKRExM6EkMro2F+OImGmSiA/WKcXvKVcfA==}
+
abstract-logging@2.0.1:
resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==}
@@ -1456,6 +1373,9 @@ packages:
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
engines: {node: '>= 8.10.0'}
+ classcat@5.0.5:
+ resolution: {integrity: sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==}
+
cli-tableau@2.0.1:
resolution: {integrity: sha512-he+WTicka9cl0Fg/y+YyxcN6/bfQ/1O3QmgxRXDhABKqLzvoOSM4fMzp39uMyLBulAFuywD2N7UaoQE7WaADxQ==}
engines: {node: '>=8.10.0'}
@@ -1485,14 +1405,6 @@ packages:
commander@2.15.1:
resolution: {integrity: sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==}
- commander@7.2.0:
- resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
- engines: {node: '>= 10'}
-
- commander@8.3.0:
- resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==}
- engines: {node: '>= 12'}
-
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
@@ -1515,12 +1427,6 @@ packages:
resolution: {integrity: sha512-yuToqVvRrj6pfDXREyQAAv8SkAEk/8GS3jQRTiUMm66TVtBYmqQeoEjL2Lmq8Rpo6271vH76InTChTitEAm65w==}
engines: {node: '>=22'}
- cose-base@1.0.3:
- resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==}
-
- cose-base@2.2.0:
- resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==}
-
cpu-features@0.0.10:
resolution: {integrity: sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==}
engines: {node: '>=10.0.0'}
@@ -1553,51 +1459,10 @@ packages:
culvert@0.1.2:
resolution: {integrity: sha512-yi1x3EAWKjQTreYWeSd98431AV+IEE0qoDyOoaHJ7KJ21gv6HtBXHVLX74opVSGqcR8/AbjJBHAHpcOy2bj5Gg==}
- cytoscape-cose-bilkent@4.1.0:
- resolution: {integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==}
- peerDependencies:
- cytoscape: ^3.2.0
-
- cytoscape-fcose@2.2.0:
- resolution: {integrity: sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==}
- peerDependencies:
- cytoscape: ^3.2.0
-
- cytoscape@3.34.1:
- resolution: {integrity: sha512-Lr0RvH9H75y9ar8h9Toy6u4lxRSCcxUq+hHcQ26sVWo6BnaQp1gwEZOYqwuYTZhyW7npyKnNLP8oJ2p1/3OZ7g==}
- engines: {node: '>=0.10'}
-
- d3-array@2.12.1:
- resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==}
-
- d3-array@3.2.4:
- resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==}
- engines: {node: '>=12'}
-
- d3-axis@3.0.0:
- resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==}
- engines: {node: '>=12'}
-
- d3-brush@3.0.0:
- resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==}
- engines: {node: '>=12'}
-
- d3-chord@3.0.1:
- resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==}
- engines: {node: '>=12'}
-
d3-color@3.1.0:
resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==}
engines: {node: '>=12'}
- d3-contour@4.0.2:
- resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==}
- engines: {node: '>=12'}
-
- d3-delaunay@6.0.4:
- resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==}
- engines: {node: '>=12'}
-
d3-dispatch@3.0.1:
resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==}
engines: {node: '>=12'}
@@ -1606,88 +1471,18 @@ packages:
resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==}
engines: {node: '>=12'}
- d3-dsv@3.0.1:
- resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==}
- engines: {node: '>=12'}
- hasBin: true
-
d3-ease@3.0.1:
resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==}
engines: {node: '>=12'}
- d3-fetch@3.0.1:
- resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==}
- engines: {node: '>=12'}
-
- d3-force@3.0.0:
- resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==}
- engines: {node: '>=12'}
-
- d3-format@3.1.2:
- resolution: {integrity: sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==}
- engines: {node: '>=12'}
-
- d3-geo@3.1.1:
- resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==}
- engines: {node: '>=12'}
-
- d3-hierarchy@3.1.2:
- resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==}
- engines: {node: '>=12'}
-
d3-interpolate@3.0.1:
resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==}
engines: {node: '>=12'}
- d3-path@1.0.9:
- resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==}
-
- d3-path@3.1.0:
- resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==}
- engines: {node: '>=12'}
-
- d3-polygon@3.0.1:
- resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==}
- engines: {node: '>=12'}
-
- d3-quadtree@3.0.1:
- resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==}
- engines: {node: '>=12'}
-
- d3-random@3.0.1:
- resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==}
- engines: {node: '>=12'}
-
- d3-sankey@0.12.3:
- resolution: {integrity: sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==}
-
- d3-scale-chromatic@3.1.0:
- resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==}
- engines: {node: '>=12'}
-
- d3-scale@4.0.2:
- resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==}
- engines: {node: '>=12'}
-
d3-selection@3.0.0:
resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==}
engines: {node: '>=12'}
- d3-shape@1.3.7:
- resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==}
-
- d3-shape@3.2.0:
- resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==}
- engines: {node: '>=12'}
-
- d3-time-format@4.1.0:
- resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==}
- engines: {node: '>=12'}
-
- d3-time@3.1.0:
- resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==}
- engines: {node: '>=12'}
-
d3-timer@3.0.1:
resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==}
engines: {node: '>=12'}
@@ -1702,13 +1497,6 @@ packages:
resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==}
engines: {node: '>=12'}
- d3@7.9.0:
- resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==}
- engines: {node: '>=12'}
-
- dagre-d3-es@7.0.14:
- resolution: {integrity: sha512-P4rFMVq9ESWqmOgK+dlXvOtLwYg0i7u0HBGJER0LZDJT2VHIPAMZ/riPxqJceWMStH5+E61QxFra9kIS3AqdMg==}
-
daisyui@5.7.16:
resolution: {integrity: sha512-V9CJxvrWIXTDuP/0tpijjWaKaKJNYo2IrULJfTWs3/DjW9rPqswk1n8NCLQRLrTutmlG2Ech7nkJDpCnF+6Dzw==}
@@ -1741,9 +1529,6 @@ packages:
dayjs@1.11.15:
resolution: {integrity: sha512-MC+DfnSWiM9APs7fpiurHGCoeIx0Gdl6QZBy+5lu8MbYKN5FZEXqOgrundfibdfhGZ15o9hzmZ2xJjZnbvgKXQ==}
- dayjs@1.11.21:
- resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==}
-
dayjs@1.8.36:
resolution: {integrity: sha512-3VmRXEtw7RZKAf+4Tv1Ym9AGeo8r8+CjDi26x+7SYQil1UqtqdaokhzoEJohqlzt0m5kacJSDhJQkG/LWhpRBw==}
@@ -1792,9 +1577,6 @@ packages:
resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==}
engines: {node: '>= 14'}
- delaunator@5.1.0:
- resolution: {integrity: sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==}
-
delayed-stream@1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
@@ -1825,9 +1607,6 @@ packages:
resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
engines: {node: '>= 4'}
- dompurify@3.4.13:
- resolution: {integrity: sha512-2vmYIoqjze2d+kakP8S/nS5shfsl587kzwEjcGlTdiksUVgFHnFCsLYDVj/JNqJVOQZGSYBTmuycv0PodwmnMQ==}
-
dompurify@3.4.8:
resolution: {integrity: sha512-yb1cEmaOum7wFvOCSQxyfgVlv5D47Rc30iZWoMpbDIWTnJ6grDDQyu2KFJzB2k7u0pMuJcQ1zphH//fFnw2tjQ==}
@@ -1905,9 +1684,6 @@ packages:
resolution: {integrity: sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==}
engines: {node: '>= 0.4'}
- es-toolkit@1.50.0:
- resolution: {integrity: sha512-OyZKhUVvEep9ITEiwHn8GKnMRQIVqoSIX7WnRbkWgJkllCujilqP2rD0u979tkl8wqyc8ICwlc1UBVv/Sl1G6w==}
-
esbuild@0.28.2:
resolution: {integrity: sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==}
engines: {node: '>=18'}
@@ -2223,9 +1999,6 @@ packages:
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
- hachure-fill@0.5.2:
- resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==}
-
has-bigints@1.1.0:
resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
engines: {node: '>= 0.4'}
@@ -2276,10 +2049,6 @@ packages:
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
engines: {node: '>=0.10.0'}
- iconv-lite@0.6.3:
- resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
- engines: {node: '>=0.10.0'}
-
ignore@5.3.2:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'}
@@ -2288,9 +2057,6 @@ packages:
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
engines: {node: '>=6'}
- import-meta-resolve@4.2.0:
- resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==}
-
imurmurhash@0.1.4:
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
engines: {node: '>=0.8.19'}
@@ -2305,13 +2071,6 @@ packages:
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
engines: {node: '>= 0.4'}
- internmap@1.0.1:
- resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==}
-
- internmap@2.0.3:
- resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
- engines: {node: '>=12'}
-
interpret@2.2.0:
resolution: {integrity: sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==}
engines: {node: '>= 0.10'}
@@ -2509,16 +2268,9 @@ packages:
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
engines: {node: '>=4.0'}
- katex@0.16.47:
- resolution: {integrity: sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==}
- hasBin: true
-
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
- khroma@2.1.0:
- resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==}
-
knex@3.3.0:
resolution: {integrity: sha512-LgWl031hNuLv9Lhxdd9093zULa2aNcoP04Bk29e5NidgRcEr/T0rAr2WYi4BhjTiCDoQiRU56meUE5rppLKZzQ==}
engines: {node: '>=16'}
@@ -2563,12 +2315,6 @@ packages:
layerr@3.0.0:
resolution: {integrity: sha512-tv754Ki2dXpPVApOrjTyRo4/QegVb9eVFq4mjqp4+NM5NaX7syQvN5BBNfV/ZpAHCEHV24XdUVrBAoka4jt3pA==}
- layout-base@1.0.2:
- resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==}
-
- layout-base@2.0.1:
- resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==}
-
levn@0.4.1:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
@@ -2654,9 +2400,6 @@ packages:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
- lodash-es@4.18.1:
- resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==}
-
lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
@@ -2693,11 +2436,6 @@ packages:
engines: {node: '>= 18'}
hasBin: true
- marked@16.4.2:
- resolution: {integrity: sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==}
- engines: {node: '>= 20'}
- hasBin: true
-
math-intrinsics@1.1.0:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
@@ -2705,9 +2443,6 @@ packages:
md5@2.3.0:
resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==}
- mermaid@11.16.1:
- resolution: {integrity: sha512-TQsq6u22fAn3rek5VOubrhKPo1g5hwC3FXUN9hiyupTckcYiGuuKGkNQrKYwGJkXUxZdojwRG46gsSCFZMDp4g==}
-
mime-db@1.52.0:
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
engines: {node: '>= 0.6'}
@@ -2892,9 +2627,6 @@ packages:
package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
- package-manager-detector@1.8.0:
- resolution: {integrity: sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==}
-
pako@0.2.9:
resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==}
@@ -2902,9 +2634,6 @@ packages:
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
engines: {node: '>=6'}
- path-data-parser@0.1.0:
- resolution: {integrity: sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==}
-
path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
@@ -2992,12 +2721,6 @@ packages:
engines: {node: '>=16.0.0'}
hasBin: true
- points-on-curve@0.2.0:
- resolution: {integrity: sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==}
-
- points-on-path@0.2.1:
- resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==}
-
possible-typed-array-names@1.1.0:
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
engines: {node: '>= 0.4'}
@@ -3145,26 +2868,17 @@ packages:
rfdc@1.4.1:
resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
- robust-predicates@3.0.3:
- resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==}
-
rollup@4.62.4:
resolution: {integrity: sha512-RXOqwaPsBGjMNMa4sQjDjHieHEZDFoj/Rdr46l2MU5DfEs16wHJPC2RPTPHWhNl+M3aI472LLqFkFKut4SblOg==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
- roughjs@4.6.6:
- resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==}
-
rss-parser@3.13.0:
resolution: {integrity: sha512-7jWUBV5yGN3rqMMj7CZufl/291QAhvrrGpDNE4k/02ZchL0npisiYYqULF71jCEKoIiHvK/Q2e6IkDwPziT7+w==}
run-series@1.1.9:
resolution: {integrity: sha512-Arc4hUN896vjkqCYrUXquBFtRZdv1PfLbTYP71efP6butxyQ0kWpiNJyAgsxscmQg1cqvHY32/UCBzXedTpU2g==}
- rw@1.3.3:
- resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==}
-
safe-array-concat@1.1.4:
resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==}
engines: {node: '>=0.4'}
@@ -3368,9 +3082,6 @@ packages:
strnum@2.4.2:
resolution: {integrity: sha512-rDG3Ah4TV0k1hWvLSzkZtMmLN9+eS+h3knq4MP6A42Y3Yh5qGNnOUs1jJkoSr8FG5dsL28c7KgkIBzSEykqtuw==}
- stylis@4.4.0:
- resolution: {integrity: sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==}
-
supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
@@ -3410,10 +3121,6 @@ packages:
tinyexec@0.3.2:
resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
- tinyexec@1.3.0:
- resolution: {integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==}
- engines: {node: '>=18'}
-
tinyglobby@0.2.17:
resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
engines: {node: '>=12.0.0'}
@@ -3442,10 +3149,6 @@ packages:
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
engines: {node: '>=0.6'}
- ts-dedent@2.3.0:
- resolution: {integrity: sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg==}
- engines: {node: '>=6.10'}
-
tslib@1.9.3:
resolution: {integrity: sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==}
@@ -3505,13 +3208,14 @@ packages:
url-parse@1.5.10:
resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==}
+ use-sync-external-store@1.6.0:
+ resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
- uuid@14.0.1:
- resolution: {integrity: sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==}
- hasBin: true
-
vite-node@3.2.4:
resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
@@ -3682,12 +3386,22 @@ packages:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
-snapshots:
+ zustand@4.5.7:
+ resolution: {integrity: sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==}
+ engines: {node: '>=12.7.0'}
+ peerDependencies:
+ '@types/react': '>=16.8'
+ immer: '>=9.0.6'
+ react: '>=16.8'
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ immer:
+ optional: true
+ react:
+ optional: true
- '@antfu/install-pkg@1.1.0':
- dependencies:
- package-manager-detector: 1.8.0
- tinyexec: 1.3.0
+snapshots:
'@aws-sdk/checksums@3.1000.28':
dependencies:
@@ -3977,14 +3691,10 @@ snapshots:
'@babel/helper-string-parser': 7.29.7
'@babel/helper-validator-identifier': 7.29.7
- '@braintree/sanitize-url@7.1.2': {}
-
'@buttercup/fetch@0.2.1':
optionalDependencies:
node-fetch: 3.3.2
- '@chevrotain/types@11.1.2': {}
-
'@dnd-kit/accessibility@3.1.1(react@19.2.8)':
dependencies:
react: 19.2.8
@@ -4210,14 +3920,6 @@ snapshots:
'@humanwhocodes/retry@0.4.3': {}
- '@iconify/types@2.0.0': {}
-
- '@iconify/utils@3.1.4':
- dependencies:
- '@antfu/install-pkg': 1.1.0
- '@iconify/types': 2.0.0
- import-meta-resolve: 4.2.0
-
'@ioredis/commands@2.0.0': {}
'@isaacs/cliui@9.0.0': {}
@@ -4243,10 +3945,6 @@ snapshots:
'@lukeed/ms@2.0.2': {}
- '@mermaid-js/parser@1.2.0':
- dependencies:
- '@chevrotain/types': 11.1.2
-
'@monaco-editor/loader@1.7.0':
dependencies:
state-local: 1.0.7
@@ -4548,81 +4246,18 @@ snapshots:
'@types/deep-eql': 4.0.2
assertion-error: 2.0.1
- '@types/d3-array@3.2.2': {}
-
- '@types/d3-axis@3.0.6':
- dependencies:
- '@types/d3-selection': 3.0.11
-
- '@types/d3-brush@3.0.6':
- dependencies:
- '@types/d3-selection': 3.0.11
-
- '@types/d3-chord@3.0.6': {}
-
'@types/d3-color@3.1.3': {}
- '@types/d3-contour@3.0.6':
- dependencies:
- '@types/d3-array': 3.2.2
- '@types/geojson': 7946.0.16
-
- '@types/d3-delaunay@6.0.4': {}
-
- '@types/d3-dispatch@3.0.7': {}
-
'@types/d3-drag@3.0.7':
dependencies:
'@types/d3-selection': 3.0.11
- '@types/d3-dsv@3.0.7': {}
-
- '@types/d3-ease@3.0.2': {}
-
- '@types/d3-fetch@3.0.7':
- dependencies:
- '@types/d3-dsv': 3.0.7
-
- '@types/d3-force@3.0.10': {}
-
- '@types/d3-format@3.0.4': {}
-
- '@types/d3-geo@3.1.1':
- dependencies:
- '@types/geojson': 7946.0.16
-
- '@types/d3-hierarchy@3.1.7': {}
-
'@types/d3-interpolate@3.0.4':
dependencies:
'@types/d3-color': 3.1.3
- '@types/d3-path@3.1.1': {}
-
- '@types/d3-polygon@3.0.2': {}
-
- '@types/d3-quadtree@3.0.6': {}
-
- '@types/d3-random@3.0.4': {}
-
- '@types/d3-scale-chromatic@3.1.0': {}
-
- '@types/d3-scale@4.0.9':
- dependencies:
- '@types/d3-time': 3.0.4
-
'@types/d3-selection@3.0.11': {}
- '@types/d3-shape@3.1.8':
- dependencies:
- '@types/d3-path': 3.1.1
-
- '@types/d3-time-format@4.0.3': {}
-
- '@types/d3-time@3.0.4': {}
-
- '@types/d3-timer@3.0.2': {}
-
'@types/d3-transition@3.0.9':
dependencies:
'@types/d3-selection': 3.0.11
@@ -4632,45 +4267,10 @@ snapshots:
'@types/d3-interpolate': 3.0.4
'@types/d3-selection': 3.0.11
- '@types/d3@7.4.3':
- dependencies:
- '@types/d3-array': 3.2.2
- '@types/d3-axis': 3.0.6
- '@types/d3-brush': 3.0.6
- '@types/d3-chord': 3.0.6
- '@types/d3-color': 3.1.3
- '@types/d3-contour': 3.0.6
- '@types/d3-delaunay': 6.0.4
- '@types/d3-dispatch': 3.0.7
- '@types/d3-drag': 3.0.7
- '@types/d3-dsv': 3.0.7
- '@types/d3-ease': 3.0.2
- '@types/d3-fetch': 3.0.7
- '@types/d3-force': 3.0.10
- '@types/d3-format': 3.0.4
- '@types/d3-geo': 3.1.1
- '@types/d3-hierarchy': 3.1.7
- '@types/d3-interpolate': 3.0.4
- '@types/d3-path': 3.1.1
- '@types/d3-polygon': 3.0.2
- '@types/d3-quadtree': 3.0.6
- '@types/d3-random': 3.0.4
- '@types/d3-scale': 4.0.9
- '@types/d3-scale-chromatic': 3.1.0
- '@types/d3-selection': 3.0.11
- '@types/d3-shape': 3.1.8
- '@types/d3-time': 3.0.4
- '@types/d3-time-format': 4.0.3
- '@types/d3-timer': 3.0.2
- '@types/d3-transition': 3.0.9
- '@types/d3-zoom': 3.0.8
-
'@types/deep-eql@4.0.2': {}
'@types/estree@1.0.9': {}
- '@types/geojson@7946.0.16': {}
-
'@types/json-schema@7.0.15': {}
'@types/trusted-types@2.0.7':
@@ -4682,11 +4282,6 @@ snapshots:
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
- '@upsetjs/venn.js@2.0.0':
- optionalDependencies:
- d3-selection: 3.0.0
- d3-transition: 3.0.1(d3-selection@3.0.0)
-
'@vitejs/plugin-react@5.2.0(supports-color@7.2.0)(vite@7.3.6(jiti@2.7.0)(lightningcss@1.32.0)(yaml@2.9.0))':
dependencies:
'@babel/core': 7.29.7(supports-color@7.2.0)
@@ -4741,6 +4336,28 @@ snapshots:
loupe: 3.2.1
tinyrainbow: 2.0.0
+ '@xyflow/react@12.11.3(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
+ dependencies:
+ '@xyflow/system': 0.0.80
+ classcat: 5.0.5
+ react: 19.2.8
+ react-dom: 19.2.8(react@19.2.8)
+ zustand: 4.5.7(react@19.2.8)
+ transitivePeerDependencies:
+ - immer
+
+ '@xyflow/system@0.0.80':
+ dependencies:
+ '@types/d3-drag': 3.0.7
+ '@types/d3-interpolate': 3.0.4
+ '@types/d3-selection': 3.0.11
+ '@types/d3-transition': 3.0.9
+ '@types/d3-zoom': 3.0.8
+ d3-drag: 3.0.0
+ d3-interpolate: 3.0.1
+ d3-selection: 3.0.0
+ d3-zoom: 3.0.0
+
abstract-logging@2.0.1: {}
acorn-jsx@5.3.2(acorn@8.18.0):
@@ -5037,6 +4654,8 @@ snapshots:
optionalDependencies:
fsevents: 2.3.3
+ classcat@5.0.5: {}
+
cli-tableau@2.0.1:
dependencies:
chalk: 3.0.0
@@ -5059,10 +4678,6 @@ snapshots:
commander@2.15.1: {}
- commander@7.2.0: {}
-
- commander@8.3.0: {}
-
concat-map@0.0.1: {}
concat-stream@2.0.0:
@@ -5082,14 +4697,6 @@ snapshots:
cookie@2.0.1: {}
- cose-base@1.0.3:
- dependencies:
- layout-base: 1.0.2
-
- cose-base@2.2.0:
- dependencies:
- layout-base: 2.0.1
-
cpu-features@0.0.10:
dependencies:
buildcheck: 0.0.7
@@ -5124,50 +4731,8 @@ snapshots:
culvert@0.1.2: {}
- cytoscape-cose-bilkent@4.1.0(cytoscape@3.34.1):
- dependencies:
- cose-base: 1.0.3
- cytoscape: 3.34.1
-
- cytoscape-fcose@2.2.0(cytoscape@3.34.1):
- dependencies:
- cose-base: 2.2.0
- cytoscape: 3.34.1
-
- cytoscape@3.34.1: {}
-
- d3-array@2.12.1:
- dependencies:
- internmap: 1.0.1
-
- d3-array@3.2.4:
- dependencies:
- internmap: 2.0.3
-
- d3-axis@3.0.0: {}
-
- d3-brush@3.0.0:
- dependencies:
- d3-dispatch: 3.0.1
- d3-drag: 3.0.0
- d3-interpolate: 3.0.1
- d3-selection: 3.0.0
- d3-transition: 3.0.1(d3-selection@3.0.0)
-
- d3-chord@3.0.1:
- dependencies:
- d3-path: 3.1.0
-
d3-color@3.1.0: {}
- d3-contour@4.0.2:
- dependencies:
- d3-array: 3.2.4
-
- d3-delaunay@6.0.4:
- dependencies:
- delaunator: 5.1.0
-
d3-dispatch@3.0.1: {}
d3-drag@3.0.0:
@@ -5175,82 +4740,14 @@ snapshots:
d3-dispatch: 3.0.1
d3-selection: 3.0.0
- d3-dsv@3.0.1:
- dependencies:
- commander: 7.2.0
- iconv-lite: 0.6.3
- rw: 1.3.3
-
d3-ease@3.0.1: {}
- d3-fetch@3.0.1:
- dependencies:
- d3-dsv: 3.0.1
-
- d3-force@3.0.0:
- dependencies:
- d3-dispatch: 3.0.1
- d3-quadtree: 3.0.1
- d3-timer: 3.0.1
-
- d3-format@3.1.2: {}
-
- d3-geo@3.1.1:
- dependencies:
- d3-array: 3.2.4
-
- d3-hierarchy@3.1.2: {}
-
d3-interpolate@3.0.1:
dependencies:
d3-color: 3.1.0
- d3-path@1.0.9: {}
-
- d3-path@3.1.0: {}
-
- d3-polygon@3.0.1: {}
-
- d3-quadtree@3.0.1: {}
-
- d3-random@3.0.1: {}
-
- d3-sankey@0.12.3:
- dependencies:
- d3-array: 2.12.1
- d3-shape: 1.3.7
-
- d3-scale-chromatic@3.1.0:
- dependencies:
- d3-color: 3.1.0
- d3-interpolate: 3.0.1
-
- d3-scale@4.0.2:
- dependencies:
- d3-array: 3.2.4
- d3-format: 3.1.2
- d3-interpolate: 3.0.1
- d3-time: 3.1.0
- d3-time-format: 4.1.0
-
d3-selection@3.0.0: {}
- d3-shape@1.3.7:
- dependencies:
- d3-path: 1.0.9
-
- d3-shape@3.2.0:
- dependencies:
- d3-path: 3.1.0
-
- d3-time-format@4.1.0:
- dependencies:
- d3-time: 3.1.0
-
- d3-time@3.1.0:
- dependencies:
- d3-array: 3.2.4
-
d3-timer@3.0.1: {}
d3-transition@3.0.1(d3-selection@3.0.0):
@@ -5270,44 +4767,6 @@ snapshots:
d3-selection: 3.0.0
d3-transition: 3.0.1(d3-selection@3.0.0)
- d3@7.9.0:
- dependencies:
- d3-array: 3.2.4
- d3-axis: 3.0.0
- d3-brush: 3.0.0
- d3-chord: 3.0.1
- d3-color: 3.1.0
- d3-contour: 4.0.2
- d3-delaunay: 6.0.4
- d3-dispatch: 3.0.1
- d3-drag: 3.0.0
- d3-dsv: 3.0.1
- d3-ease: 3.0.1
- d3-fetch: 3.0.1
- d3-force: 3.0.0
- d3-format: 3.1.2
- d3-geo: 3.1.1
- d3-hierarchy: 3.1.2
- d3-interpolate: 3.0.1
- d3-path: 3.1.0
- d3-polygon: 3.0.1
- d3-quadtree: 3.0.1
- d3-random: 3.0.1
- d3-scale: 4.0.2
- d3-scale-chromatic: 3.1.0
- d3-selection: 3.0.0
- d3-shape: 3.2.0
- d3-time: 3.1.0
- d3-time-format: 4.1.0
- d3-timer: 3.0.1
- d3-transition: 3.0.1(d3-selection@3.0.0)
- d3-zoom: 3.0.0
-
- dagre-d3-es@7.0.14:
- dependencies:
- d3: 7.9.0
- lodash-es: 4.18.1
-
daisyui@5.7.16: {}
damerau-levenshtein@1.0.8: {}
@@ -5338,8 +4797,6 @@ snapshots:
dayjs@1.11.15: {}
- dayjs@1.11.21: {}
-
dayjs@1.8.36: {}
debug@3.2.7(supports-color@7.2.0):
@@ -5382,10 +4839,6 @@ snapshots:
escodegen: 2.1.0
esprima: 4.0.1
- delaunator@5.1.0:
- dependencies:
- robust-predicates: 3.0.3
-
delayed-stream@1.0.0: {}
denque@2.1.0: {}
@@ -5408,10 +4861,6 @@ snapshots:
dependencies:
domelementtype: 2.3.0
- dompurify@3.4.13:
- optionalDependencies:
- '@types/trusted-types': 2.0.7
-
dompurify@3.4.8:
optionalDependencies:
'@types/trusted-types': 2.0.7
@@ -5547,8 +4996,6 @@ snapshots:
is-date-object: 1.1.0
is-symbol: 1.1.1
- es-toolkit@1.50.0: {}
-
esbuild@0.28.2:
optionalDependencies:
'@esbuild/aix-ppc64': 0.28.2
@@ -5952,8 +5399,6 @@ snapshots:
graceful-fs@4.2.11: {}
- hachure-fill@0.5.2: {}
-
has-bigints@1.1.0: {}
has-flag@4.0.0: {}
@@ -6011,10 +5456,6 @@ snapshots:
dependencies:
safer-buffer: 2.1.2
- iconv-lite@0.6.3:
- dependencies:
- safer-buffer: 2.1.2
-
ignore@5.3.2: {}
import-fresh@3.3.1:
@@ -6022,8 +5463,6 @@ snapshots:
parent-module: 1.0.1
resolve-from: 4.0.0
- import-meta-resolve@4.2.0: {}
-
imurmurhash@0.1.4: {}
inherits@2.0.4: {}
@@ -6036,10 +5475,6 @@ snapshots:
hasown: 2.0.4
side-channel: 1.1.1
- internmap@1.0.1: {}
-
- internmap@2.0.3: {}
-
interpret@2.2.0: {}
ioredis@6.0.0(supports-color@7.2.0):
@@ -6234,16 +5669,10 @@ snapshots:
object.assign: 4.1.7
object.values: 1.2.1
- katex@0.16.47:
- dependencies:
- commander: 8.3.0
-
keyv@4.5.4:
dependencies:
json-buffer: 3.0.1
- khroma@2.1.0: {}
-
knex@3.3.0(better-sqlite3@13.0.3)(supports-color@7.2.0):
dependencies:
colorette: 2.0.19
@@ -6273,10 +5702,6 @@ snapshots:
layerr@3.0.0: {}
- layout-base@1.0.2: {}
-
- layout-base@2.0.1: {}
-
levn@0.4.1:
dependencies:
prelude-ls: 1.2.1
@@ -6341,8 +5766,6 @@ snapshots:
dependencies:
p-locate: 5.0.0
- lodash-es@4.18.1: {}
-
lodash.merge@4.6.2: {}
lodash@4.18.1: {}
@@ -6369,8 +5792,6 @@ snapshots:
marked@14.0.0: {}
- marked@16.4.2: {}
-
math-intrinsics@1.1.0: {}
md5@2.3.0:
@@ -6379,30 +5800,6 @@ snapshots:
crypt: 0.0.2
is-buffer: 1.1.6
- mermaid@11.16.1:
- dependencies:
- '@braintree/sanitize-url': 7.1.2
- '@iconify/utils': 3.1.4
- '@mermaid-js/parser': 1.2.0
- '@types/d3': 7.4.3
- '@upsetjs/venn.js': 2.0.0
- cytoscape: 3.34.1
- cytoscape-cose-bilkent: 4.1.0(cytoscape@3.34.1)
- cytoscape-fcose: 2.2.0(cytoscape@3.34.1)
- d3: 7.9.0
- d3-sankey: 0.12.3
- dagre-d3-es: 7.0.14
- dayjs: 1.11.21
- dompurify: 3.4.13
- es-toolkit: 1.50.0
- katex: 0.16.47
- khroma: 2.1.0
- marked: 16.4.2
- roughjs: 4.6.6
- stylis: 4.4.0
- ts-dedent: 2.3.0
- uuid: 14.0.1
-
mime-db@1.52.0: {}
mime-types@2.1.35:
@@ -6592,16 +5989,12 @@ snapshots:
package-json-from-dist@1.0.1: {}
- package-manager-detector@1.8.0: {}
-
pako@0.2.9: {}
parent-module@1.0.1:
dependencies:
callsites: 3.1.0
- path-data-parser@0.1.0: {}
-
path-exists@4.0.0: {}
path-expression-matcher@1.6.2: {}
@@ -6736,13 +6129,6 @@ snapshots:
- supports-color
- utf-8-validate
- points-on-curve@0.2.0: {}
-
- points-on-path@0.2.1:
- dependencies:
- path-data-parser: 0.1.0
- points-on-curve: 0.2.0
-
possible-typed-array-names@1.1.0: {}
postcss@8.5.26:
@@ -6884,8 +6270,6 @@ snapshots:
rfdc@1.4.1: {}
- robust-predicates@3.0.3: {}
-
rollup@4.62.4:
dependencies:
'@types/estree': 1.0.9
@@ -6918,13 +6302,6 @@ snapshots:
'@rollup/rollup-win32-x64-msvc': 4.62.4
fsevents: 2.3.3
- roughjs@4.6.6:
- dependencies:
- hachure-fill: 0.5.2
- path-data-parser: 0.1.0
- points-on-curve: 0.2.0
- points-on-path: 0.2.1
-
rss-parser@3.13.0:
dependencies:
entities: 2.2.0
@@ -6932,8 +6309,6 @@ snapshots:
run-series@1.1.9: {}
- rw@1.3.3: {}
-
safe-array-concat@1.1.4:
dependencies:
call-bind: 1.0.9
@@ -7159,8 +6534,6 @@ snapshots:
dependencies:
anynum: 1.0.1
- stylis@4.4.0: {}
-
supports-color@7.2.0:
dependencies:
has-flag: 4.0.0
@@ -7186,8 +6559,6 @@ snapshots:
tinyexec@0.3.2: {}
- tinyexec@1.3.0: {}
-
tinyglobby@0.2.17:
dependencies:
fdir: 6.5.0(picomatch@4.0.5)
@@ -7207,8 +6578,6 @@ snapshots:
toidentifier@1.0.1: {}
- ts-dedent@2.3.0: {}
-
tslib@1.9.3: {}
tslib@2.8.1: {}
@@ -7285,9 +6654,11 @@ snapshots:
querystringify: 2.2.0
requires-port: 1.0.0
- util-deprecate@1.0.2: {}
+ use-sync-external-store@1.6.0(react@19.2.8):
+ dependencies:
+ react: 19.2.8
- uuid@14.0.1: {}
+ util-deprecate@1.0.2: {}
vite-node@3.2.4(jiti@2.7.0)(lightningcss@1.32.0)(supports-color@7.2.0)(yaml@2.9.0):
dependencies:
@@ -7463,3 +6834,9 @@ snapshots:
yaml@2.9.0: {}
yocto-queue@0.1.0: {}
+
+ zustand@4.5.7(react@19.2.8):
+ dependencies:
+ use-sync-external-store: 1.6.0(react@19.2.8)
+ optionalDependencies:
+ react: 19.2.8