From 7599a43ac75ff3313e4b5b12b1365cd175b91445 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 23 May 2026 13:36:39 -0700 Subject: [PATCH 01/20] Checkpoint Tauri graph rendering --- package-lock.json | 23 +++- package.json | 3 +- src-tauri/.cargo/config.toml | 6 +- src/App.css | 38 ++++++ src/App.tsx | 211 +++++++++++++++++++++++++++++++++- src/vendor/sigma-runtime.d.ts | 15 +++ src/vendor/sigma-runtime.js | 3 + 7 files changed, 291 insertions(+), 8 deletions(-) create mode 100644 src/vendor/sigma-runtime.d.ts create mode 100644 src/vendor/sigma-runtime.js diff --git a/package-lock.json b/package-lock.json index 7771eb0..452d221 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,18 @@ { "name": "bugscope", - "version": "0.1.0", + "version": "0.15.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "bugscope", - "version": "0.1.0", + "version": "0.15.1", "dependencies": { "@tauri-apps/api": "^2", "react": "^19.2.0", "react-dom": "^19.2.0", - "react-force-graph-2d": "^1.29.1" + "react-force-graph-2d": "^1.29.1", + "sigma": "file:../sigma.js/packages/sigma" }, "devDependencies": { "@eslint/js": "^9.39.1", @@ -28,6 +29,18 @@ "vite": "^7.3.1" } }, + "../sigma.js/packages/sigma": { + "version": "3.0.3", + "license": "MIT", + "dependencies": { + "@ladybugmem/icebug": "^12.7.0", + "apache-arrow": "^21.1.0", + "events": "^3.3.0" + }, + "devDependencies": { + "vite": "^6.0.7" + } + }, "node_modules/@babel/code-frame": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", @@ -3415,6 +3428,10 @@ "node": ">=8" } }, + "node_modules/sigma": { + "resolved": "../sigma.js/packages/sigma", + "link": true + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", diff --git a/package.json b/package.json index de34faf..4f3ae7f 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "@tauri-apps/api": "^2", "react": "^19.2.0", "react-dom": "^19.2.0", - "react-force-graph-2d": "^1.29.1" + "react-force-graph-2d": "^1.29.1", + "sigma": "file:../sigma.js/packages/sigma" }, "devDependencies": { "@eslint/js": "^9.39.1", diff --git a/src-tauri/.cargo/config.toml b/src-tauri/.cargo/config.toml index b017fa7..40558af 100644 --- a/src-tauri/.cargo/config.toml +++ b/src-tauri/.cargo/config.toml @@ -8,15 +8,15 @@ LBUG_SHARED = "1" # Embed rpath so the binary can find liblbug.dylib at runtime. # First rpath: for production .app bundles (Contents/Frameworks/) -# Second rpath: for development (liblbug/ dir relative to the binary in target/) +# Second rpath: for development (src-tauri/liblbug/ relative to target/debug/) [target.aarch64-apple-darwin] rustflags = [ "-C", "link-arg=-Wl,-rpath,@executable_path/../Frameworks", - "-C", "link-arg=-Wl,-rpath,@executable_path/../liblbug", + "-C", "link-arg=-Wl,-rpath,@executable_path/../../liblbug", ] [target.x86_64-apple-darwin] rustflags = [ "-C", "link-arg=-Wl,-rpath,@executable_path/../Frameworks", - "-C", "link-arg=-Wl,-rpath,@executable_path/../liblbug", + "-C", "link-arg=-Wl,-rpath,@executable_path/../../liblbug", ] diff --git a/src/App.css b/src/App.css index 3404e90..786d138 100644 --- a/src/App.css +++ b/src/App.css @@ -124,6 +124,38 @@ body { gap: 12px; } +.renderer-toggle { + display: inline-grid; + grid-template-columns: 1fr 1fr; + background-color: var(--bg-tertiary); + border: 1px solid var(--border-color); + border-radius: 6px; + overflow: hidden; +} + +.renderer-toggle button { + min-width: 68px; + padding: 8px 12px; + background: transparent; + color: var(--text-secondary); + border: 0; + cursor: pointer; + font-size: 14px; +} + +.renderer-toggle button + button { + border-left: 1px solid var(--border-color); +} + +.renderer-toggle button.active { + background-color: var(--accent-color); + color: white; +} + +.renderer-toggle button:hover:not(.active) { + color: var(--text-primary); +} + .query-box { display: flex; align-items: flex-start; @@ -223,6 +255,12 @@ body { overflow: hidden; } +.sigma-canvas { + position: absolute; + inset: 0; + background-color: var(--bg-primary); +} + .add-db-btn { padding: 6px 12px; background-color: var(--accent-color); diff --git a/src/App.tsx b/src/App.tsx index 32e5f91..99d9253 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,6 +2,7 @@ import { useState, useEffect, useMemo, useCallback, useRef } from 'react' import { invoke } from '@tauri-apps/api/core' import ForceGraph2D from 'react-force-graph-2d' import type { NodeObject } from 'react-force-graph-2d' +import { Sigma } from './vendor/sigma-runtime.js' import './App.css' interface Database { @@ -28,6 +29,191 @@ interface GraphData { links: GraphLink[] } +interface SigmaNodeAttributes extends Record { + x: number + y: number + size: number + color: string + label: string + nodeType: string +} + +interface SigmaEdgeAttributes extends Record { + size: number + color: string + label: string +} + +interface SigmaGraphViewProps { + graphData: GraphData + darkMode: boolean + getNodeColor: (label: string) => string + getEdgeColor: (label: string) => string +} + +class SigmaGraph< + N extends Record = Record, + E extends Record = Record, +> { + private nodeAttributes = new Map() + private edgeRecords = new Map() + + get order() { + return this.nodeAttributes.size + } + + addNode(key: string, attributes = {} as N): void { + if (this.nodeAttributes.has(key)) throw new Error(`SigmaGraph: node "${key}" already exists.`) + this.nodeAttributes.set(key, attributes) + } + + addEdge(key: string, source: string, target: string, attributes = {} as E): void { + if (this.edgeRecords.has(key)) throw new Error(`SigmaGraph: edge "${key}" already exists.`) + if (!this.nodeAttributes.has(source)) this.addNode(source) + if (!this.nodeAttributes.has(target)) this.addNode(target) + this.edgeRecords.set(key, { source, target, attributes }) + } + + hasNode(key: string): boolean { + return this.nodeAttributes.has(key) + } + + hasEdge(key: string): boolean { + return this.edgeRecords.has(key) + } + + nodes(): string[] { + return [...this.nodeAttributes.keys()] + } + + edges(): string[] { + return [...this.edgeRecords.keys()] + } + + forEachNode(callback: (key: string, attributes: N) => void): void { + this.nodeAttributes.forEach((attributes, key) => callback(key, attributes)) + } + + forEachEdge(callback: (key: string, attributes: E) => void): void { + this.edgeRecords.forEach(({ attributes }, key) => callback(key, attributes)) + } + + getNodeAttributes(key: string): N { + const attributes = this.nodeAttributes.get(key) + if (!attributes) throw new Error(`SigmaGraph: node "${key}" not found.`) + return attributes + } + + getEdgeAttributes(key: string): E { + const record = this.edgeRecords.get(key) + if (!record) throw new Error(`SigmaGraph: edge "${key}" not found.`) + return record.attributes + } + + extremities(key: string): [string, string] { + const record = this.edgeRecords.get(key) + if (!record) throw new Error(`SigmaGraph: edge "${key}" not found.`) + return [record.source, record.target] + } + + on(): void {} + + removeListener(): void {} +} + +function createInitialLayout(graphData: GraphData) { + const nodeCount = Math.max(1, graphData.nodes.length) + const degrees: Record = {} + const positions: Record = {} + + graphData.nodes.forEach(node => { + degrees[node.id] = 0 + }) + + graphData.links.forEach(link => { + degrees[link.source] = (degrees[link.source] || 0) + 1 + degrees[link.target] = (degrees[link.target] || 0) + 1 + }) + + const rankedNodes = [...graphData.nodes].sort((a, b) => (degrees[b.id] || 0) - (degrees[a.id] || 0)) + const radius = Math.max(4, Math.sqrt(nodeCount) * 2.4) + + rankedNodes.forEach((node, index) => { + const angle = index * Math.PI * (3 - Math.sqrt(5)) + const ring = radius * Math.sqrt((index + 0.5) / nodeCount) + positions[node.id] = { + x: Math.cos(angle) * ring, + y: Math.sin(angle) * ring, + } + }) + + return { degrees, positions } +} + +function SigmaGraphView({ graphData, darkMode, getNodeColor, getEdgeColor }: SigmaGraphViewProps) { + const containerRef = useRef(null) + const rendererRef = useRef(null) + + const graph = useMemo(() => { + const { degrees, positions } = createInitialLayout(graphData) + const maxDegree = Math.max(1, ...Object.values(degrees)) + const sigmaGraph = new SigmaGraph() + + graphData.nodes.forEach(node => { + const position = positions[node.id] || { x: 0, y: 0 } + const degree = degrees[node.id] || 0 + sigmaGraph.addNode(node.id, { + x: position.x, + y: position.y, + size: 4 + (degree / maxDegree) * 14, + color: getNodeColor(node.label), + label: node.name || node.id, + nodeType: node.label, + }) + }) + + const edgeCounts = new Map() + graphData.links.forEach((link, index) => { + if (!sigmaGraph.hasNode(link.source) || !sigmaGraph.hasNode(link.target)) return + const pairKey = `${link.source}->${link.target}` + const pairIndex = edgeCounts.get(pairKey) || 0 + edgeCounts.set(pairKey, pairIndex + 1) + sigmaGraph.addEdge(`${pairKey}#${pairIndex}-${index}`, link.source, link.target, { + size: 1.8, + color: getEdgeColor(link.label || 'edge'), + label: link.label || '', + }) + }) + + return sigmaGraph + }, [graphData, getNodeColor, getEdgeColor]) + + useEffect(() => { + const container = containerRef.current + if (!container) return + + rendererRef.current?.kill() + rendererRef.current = new Sigma(graph, container, { + allowInvalidContainer: true, + defaultEdgeType: 'arrow', + labelColor: { color: darkMode ? '#f3f4f6' : '#172033' }, + renderEdgeLabels: false, + labelRenderedSizeThreshold: 9, + minCameraRatio: 0.03, + maxCameraRatio: 12, + }) + + rendererRef.current.refresh() + + return () => { + rendererRef.current?.kill() + rendererRef.current = null + } + }, [graph, darkMode]) + + return
+} + function App() { const [databases, setDatabases] = useState([]) const [selectedId, setSelectedId] = useState(0) @@ -46,6 +232,7 @@ function App() { const [customQuery, setCustomQuery] = useState('') const [isCustomQuery, setIsCustomQuery] = useState(false) const [queryActivated, setQueryActivated] = useState(false) + const [renderer, setRenderer] = useState<'sigma' | 'force'>('sigma') // eslint-disable-next-line @typescript-eslint/no-explicit-any const graphRef = useRef(null) const customQueryRef = useRef('') @@ -280,6 +467,20 @@ function App() {
+
+ + +
- {!loading && !error && graphData.nodes.length > 0 && ( + {!loading && !error && graphData.nodes.length > 0 && renderer === 'sigma' && ( + + )} + {!loading && !error && graphData.nodes.length > 0 && renderer === 'force' && ( Date: Sat, 23 May 2026 13:38:07 -0700 Subject: [PATCH 02/20] Update liblbug download scripts --- scripts/download-liblbug.sh | 128 +++++++++++++++++++++++++++--------- scripts/download_lbug.sh | 69 +++++++++++++++++++ 2 files changed, 165 insertions(+), 32 deletions(-) create mode 100755 scripts/download_lbug.sh diff --git a/scripts/download-liblbug.sh b/scripts/download-liblbug.sh index d6424ff..132904c 100755 --- a/scripts/download-liblbug.sh +++ b/scripts/download-liblbug.sh @@ -1,41 +1,85 @@ #!/usr/bin/env bash -# Download prebuilt liblbug shared library from GitHub releases. -# This is required before building the Tauri app. +# Download prebuilt liblbug archives from GitHub releases or workflow artifacts. set -euo pipefail -LBUG_VERSION="latest" -RELEASE_URL="https://github.com/LadybugDB/ladybug/releases/${LBUG_VERSION}/download" +LIB_KIND="${LBUG_LIB_KIND:-shared}" +LINUX_VARIANT="${LBUG_LINUX_VARIANT:-compat}" +REPOSITORY="${LBUG_GITHUB_REPOSITORY:-LadybugDB/ladybug}" +RUN_ID="${LBUG_PRECOMPILED_RUN_ID:-}" +VERSION_OVERRIDE="${LBUG_VERSION:-}" + +if [ "$LIB_KIND" != "shared" ] && [ "$LIB_KIND" != "static" ]; then + echo "Unsupported LBUG_LIB_KIND: $LIB_KIND (expected 'shared' or 'static')" >&2 + exit 1 +fi + +if [ "$LINUX_VARIANT" != "compat" ] && [ "$LINUX_VARIANT" != "perf" ]; then + echo "Unsupported LBUG_LINUX_VARIANT: $LINUX_VARIANT (expected 'compat' or 'perf')" >&2 + exit 1 +fi + SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" -TARGET_DIR="$PROJECT_DIR/src-tauri/liblbug" +TARGET_DIR="${LBUG_TARGET_DIR:-$PROJECT_DIR/lib}" -# Determine platform OS="$(uname -s)" ARCH="$(uname -m)" case "$OS" in Darwin) - ARCHIVE="liblbug-osx-universal.tar.gz" + if [ "$ARCH" = "x86_64" ]; then + MACOS_ARCHIVE_ARCH="x86_64" + elif [ "$ARCH" = "arm64" ]; then + MACOS_ARCHIVE_ARCH="arm64" + else + echo "Unsupported macOS architecture: $ARCH" >&2 + exit 1 + fi + if [ "$LIB_KIND" = "static" ]; then + ARCHIVE="liblbug-static-osx-${MACOS_ARCHIVE_ARCH}.tar.gz" + ARTIFACT_NAME="liblbug-static-osx-${MACOS_ARCHIVE_ARCH}" + LIB_NAME="liblbug.a" + else + ARCHIVE="liblbug-osx-${MACOS_ARCHIVE_ARCH}.tar.gz" + ARTIFACT_NAME="liblbug-osx-${MACOS_ARCHIVE_ARCH}" + LIB_NAME="liblbug.dylib" + fi ;; Linux) if [ "$ARCH" = "x86_64" ]; then - ARCHIVE="liblbug-linux-x86_64.tar.gz" - elif [ "$ARCH" = "aarch64" ]; then - ARCHIVE="liblbug-linux-aarch64.tar.gz" + LINUX_ARCHIVE_ARCH="x86_64" + elif [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then + LINUX_ARCHIVE_ARCH="aarch64" else echo "Unsupported Linux architecture: $ARCH" >&2 exit 1 fi + if [ "$LIB_KIND" = "static" ]; then + ARCHIVE="liblbug-static-linux-${LINUX_ARCHIVE_ARCH}-${LINUX_VARIANT}.tar.gz" + ARTIFACT_NAME="liblbug-static-linux-${LINUX_ARCHIVE_ARCH}-${LINUX_VARIANT}" + LIB_NAME="liblbug.a" + else + ARCHIVE="liblbug-linux-${LINUX_ARCHIVE_ARCH}.tar.gz" + ARTIFACT_NAME="liblbug-linux-${LINUX_ARCHIVE_ARCH}" + LIB_NAME="liblbug.so" + fi ;; MINGW*|MSYS*|CYGWIN*) - if [ "$ARCH" = "x86_64" ]; then - ARCHIVE="liblbug-windows-x86_64.zip" - elif [ "$ARCH" = "aarch64" ]; then - ARCHIVE="liblbug-windows-aarch64.zip" + if [ "$ARCH" = "x86_64" ] || [ "$ARCH" = "AMD64" ]; then + WINDOWS_ARCHIVE_ARCH="x86_64" else echo "Unsupported Windows architecture: $ARCH" >&2 exit 1 fi + if [ "$LIB_KIND" = "static" ]; then + ARCHIVE="liblbug-static-windows-${WINDOWS_ARCHIVE_ARCH}.zip" + ARTIFACT_NAME="liblbug-static-windows-${WINDOWS_ARCHIVE_ARCH}" + LIB_NAME="lbug.lib" + else + ARCHIVE="liblbug-windows-${WINDOWS_ARCHIVE_ARCH}.zip" + ARTIFACT_NAME="liblbug-windows-${WINDOWS_ARCHIVE_ARCH}" + LIB_NAME="lbug_shared.dll" + fi ;; *) echo "Unsupported OS: $OS" >&2 @@ -43,33 +87,53 @@ case "$OS" in ;; esac -DOWNLOAD_URL="${RELEASE_URL}/${ARCHIVE}" - -# Check if already downloaded -if [ -f "$TARGET_DIR/liblbug.dylib" ] || [ -f "$TARGET_DIR/liblbug.so" ] || [ -f "$TARGET_DIR/liblbug.dll" ]; then +if [ -f "$TARGET_DIR/$LIB_NAME" ]; then echo "liblbug already exists in $TARGET_DIR" - echo "To re-download, remove the directory first: rm -rf $TARGET_DIR" exit 0 fi -echo "Downloading liblbug v${LBUG_VERSION} for ${OS}/${ARCH}..." -echo " URL: $DOWNLOAD_URL" -echo " Target: $TARGET_DIR" - mkdir -p "$TARGET_DIR" +TMPDIR="$(mktemp -d)" +trap 'rm -rf "$TMPDIR"' EXIT -# Download and extract -TMPFILE="$(mktemp)" -trap "rm -f '$TMPFILE'" EXIT +fetch_release_archive() { + local version + if [ -n "$VERSION_OVERRIDE" ]; then + version="$VERSION_OVERRIDE" + else + version="$(curl -sS "https://api.github.com/repos/${REPOSITORY}/releases/latest" | grep -o '"tag_name": "v\([^"]*\)"' | cut -d'"' -f4 | cut -c2-)" + fi + local download_url="https://github.com/${REPOSITORY}/releases/download/v${version}/${ARCHIVE}" + curl -fSL "$download_url" -o "$TMPDIR/$ARCHIVE" + echo "release:v${version}" +} -curl -fSL "$DOWNLOAD_URL" -o "$TMPFILE" +fetch_run_artifact() { + if ! command -v gh >/dev/null 2>&1; then + echo "gh CLI is required when LBUG_PRECOMPILED_RUN_ID is set" >&2 + exit 1 + fi + gh run download "$RUN_ID" --repo "$REPOSITORY" --name "$ARTIFACT_NAME" --dir "$TMPDIR/artifact" >/dev/null + local extracted_archive + extracted_archive="$(find "$TMPDIR/artifact" -type f -name "$ARCHIVE" | head -n1)" + if [ -z "$extracted_archive" ]; then + echo "Artifact ${ARTIFACT_NAME} does not contain ${ARCHIVE}" >&2 + exit 1 + fi + mv "$extracted_archive" "$TMPDIR/$ARCHIVE" + echo "run:${RUN_ID}/${ARTIFACT_NAME}" +} + +if [ -n "$RUN_ID" ]; then + SOURCE_DESC="$(fetch_run_artifact)" +else + SOURCE_DESC="$(fetch_release_archive)" +fi if [[ "$ARCHIVE" == *.zip ]]; then - unzip -o "$TMPFILE" -d "$TARGET_DIR" + unzip -o "$TMPDIR/$ARCHIVE" -d "$TARGET_DIR" else - tar xzf "$TMPFILE" -C "$TARGET_DIR" + tar xzf "$TMPDIR/$ARCHIVE" -C "$TARGET_DIR" fi -echo "" -echo "liblbug v${LBUG_VERSION} installed to $TARGET_DIR" -ls -lh "$TARGET_DIR" +echo "Installed ${ARCHIVE} from ${SOURCE_DESC} to $TARGET_DIR" diff --git a/scripts/download_lbug.sh b/scripts/download_lbug.sh new file mode 100755 index 0000000..85b3ee2 --- /dev/null +++ b/scripts/download_lbug.sh @@ -0,0 +1,69 @@ +#!/bin/sh +# Wrapper around upstream download-liblbug.sh (same pattern as go-ladybug). +# Downloads prebuilt liblbug into a local cache and writes CMake env flags. +set -eu + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" + +ENV_FILE="${1:-$PROJECT_DIR/.cache/lbug-prebuilt.env}" +CACHE_LIB_DIR="${LBUG_TARGET_DIR:-$PROJECT_DIR/.cache/lbug-prebuilt/lib}" +LIB_KIND="${LBUG_LIB_KIND:-static}" +UPSTREAM_SCRIPT="$SCRIPT_DIR/download-liblbug.sh" +UPSTREAM_URL="https://raw.githubusercontent.com/LadybugDB/ladybug/refs/heads/main/scripts/download-liblbug.sh" + +# Fetch the upstream helper if needed. +if [ ! -f "$UPSTREAM_SCRIPT" ]; then + echo "Fetching $UPSTREAM_URL ..." + curl -fsSL "$UPSTREAM_URL" -o "$UPSTREAM_SCRIPT" + chmod +x "$UPSTREAM_SCRIPT" +fi + +LBUG_TARGET_DIR="$CACHE_LIB_DIR" LBUG_LIB_KIND="$LIB_KIND" bash "$UPSTREAM_SCRIPT" + +OS="$(uname -s)" +if [ "$LIB_KIND" = "shared" ]; then + case "$OS" in + Darwin) + LIB_PATH="$CACHE_LIB_DIR/liblbug.dylib" + ;; + Linux) + LIB_PATH="$CACHE_LIB_DIR/liblbug.so" + ;; + MINGW*|MSYS*|CYGWIN*) + LIB_PATH="$CACHE_LIB_DIR/lbug_shared.dll" + ;; + *) + echo "Unsupported OS: $OS" >&2 + exit 1 + ;; + esac +else + case "$OS" in + MINGW*|MSYS*|CYGWIN*) + LIB_PATH="$CACHE_LIB_DIR/lbug.lib" + ;; + *) + LIB_PATH="$CACHE_LIB_DIR/liblbug.a" + ;; + esac +fi + +if [ ! -f "$LIB_PATH" ]; then + echo "Expected precompiled library not found at $LIB_PATH" >&2 + exit 1 +fi + +mkdir -p "$(dirname "$ENV_FILE")" +if [ "$LIB_KIND" = "shared" ]; then + cat > "$ENV_FILE" < "$ENV_FILE" < Date: Sat, 23 May 2026 14:39:12 -0700 Subject: [PATCH 03/20] cli: allow opening db passed as an arg Also fixes a couple of sigma vs force rendering bug --- src-tauri/src/lib.rs | 110 ++++++++++++++++++++++++++++--------------- src/App.tsx | 78 +++++++++++++++++++++++------- 2 files changed, 133 insertions(+), 55 deletions(-) diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 629de95..7fc0ca9 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -54,6 +54,7 @@ struct DirectoryListing { struct AppState { custom_databases: Mutex>, + initial_database_path: Option, data_dir: PathBuf, } @@ -97,6 +98,40 @@ fn get_all_databases(state: &AppState) -> Vec { all } +fn database_info_from_path(file_path: &str) -> Result { + if file_path.is_empty() { + return Err("filePath is required".to_string()); + } + + let abs_path = if Path::new(file_path).is_absolute() { + PathBuf::from(file_path) + } else { + std::env::current_dir().unwrap_or_default().join(file_path) + }; + + if !abs_path.exists() { + return Err("File not found".to_string()); + } + + if abs_path.extension().and_then(|e| e.to_str()) != Some("lbdb") { + return Err("Only .lbdb files are supported".to_string()); + } + + let abs_path_str = abs_path.to_string_lossy().to_string(); + let name = abs_path + .file_stem() + .unwrap_or_default() + .to_string_lossy() + .to_string(); + + Ok(DatabaseInfo { + id: 0, + name, + path: abs_path_str.clone(), + relative_path: abs_path_str, + }) +} + fn value_to_string(val: &Value) -> String { match val { Value::String(s) => s.clone(), @@ -121,50 +156,34 @@ fn get_databases(state: State) -> Vec { } #[tauri::command] -fn add_database(state: State, file_path: String) -> Result { - if file_path.is_empty() { - return Err("filePath is required".to_string()); - } - - let abs_path = if Path::new(&file_path).is_absolute() { - PathBuf::from(&file_path) - } else { - std::env::current_dir().unwrap_or_default().join(&file_path) - }; - - if !abs_path.exists() { - return Err("File not found".to_string()); - } - - if abs_path.extension().and_then(|e| e.to_str()) != Some("lbdb") { - return Err("Only .lbdb files are supported".to_string()); - } - - let abs_path_str = abs_path.to_string_lossy().to_string(); +fn get_initial_database_id(state: State) -> Option { + let initial_path = state.initial_database_path.as_ref()?; + get_all_databases(&state) + .iter() + .find(|db| db.path == *initial_path) + .map(|db| db.id) +} +fn add_database_info(state: &AppState, db_info: DatabaseInfo) -> Result { let mut custom = state.custom_databases.lock().unwrap(); - if custom.iter().any(|d| d.path == abs_path_str) { + if custom.iter().any(|d| d.path == db_info.path) { return Err("Database already added".to_string()); } - - let name = abs_path - .file_stem() - .unwrap_or_default() - .to_string_lossy() - .to_string(); - - let db_info = DatabaseInfo { - id: 0, // will be recalculated - name, - path: abs_path_str.clone(), - relative_path: abs_path_str, - }; custom.push(db_info.clone()); // Return with correct id drop(custom); let all = get_all_databases(&state); - Ok(all.last().cloned().unwrap_or(db_info)) + Ok(all + .into_iter() + .find(|db| db.path == db_info.path) + .unwrap_or(db_info)) +} + +#[tauri::command] +fn add_database(state: State, file_path: String) -> Result { + let db_info = database_info_from_path(&file_path)?; + add_database_info(&state, db_info) } #[tauri::command] @@ -178,10 +197,12 @@ fn get_directories( if resolved.is_absolute() { resolved } else { - state.data_dir.join(p) + std::env::current_dir() + .unwrap_or_else(|_| state.data_dir.clone()) + .join(p) } } - _ => state.data_dir.clone(), + _ => std::env::current_dir().unwrap_or_else(|_| state.data_dir.clone()), }; let entries = fs::read_dir(&dir).map_err(|e| e.to_string())?; @@ -405,14 +426,27 @@ pub fn run() { .app_data_dir() .expect("Failed to get app data dir"); std::fs::create_dir_all(&data_dir).ok(); + let initial_database = std::env::args() + .skip(1) + .find(|arg| !arg.starts_with('-')) + .and_then(|arg| match database_info_from_path(&arg) { + Ok(db_info) => Some(db_info), + Err(err) => { + eprintln!("Ignoring database path {arg:?}: {err}"); + None + } + }); + let initial_database_path = initial_database.as_ref().map(|db| db.path.clone()); app.manage(AppState { - custom_databases: Mutex::new(Vec::new()), + custom_databases: Mutex::new(initial_database.into_iter().collect()), + initial_database_path, data_dir, }); Ok(()) }) .invoke_handler(tauri::generate_handler![ get_databases, + get_initial_database_id, add_database, get_directories, get_graph, diff --git a/src/App.tsx b/src/App.tsx index 99d9253..3025186 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -19,8 +19,8 @@ interface GraphNode { } interface GraphLink { - source: string - target: string + source: string | NodeObject + target: string | NodeObject label: string } @@ -29,6 +29,17 @@ interface GraphData { links: GraphLink[] } +interface NormalizedGraphLink { + source: string + target: string + label: string +} + +interface NormalizedGraphData { + nodes: GraphNode[] + links: NormalizedGraphLink[] +} + interface SigmaNodeAttributes extends Record { x: number y: number @@ -45,7 +56,7 @@ interface SigmaEdgeAttributes extends Record { } interface SigmaGraphViewProps { - graphData: GraphData + graphData: NormalizedGraphData darkMode: boolean getNodeColor: (label: string) => string getEdgeColor: (label: string) => string @@ -121,7 +132,29 @@ class SigmaGraph< removeListener(): void {} } -function createInitialLayout(graphData: GraphData) { +function getEndpointId(endpoint: string | NodeObject): string { + return typeof endpoint === 'object' ? String(endpoint.id) : endpoint +} + +function normalizeGraphData(graphData: GraphData): NormalizedGraphData { + return { + nodes: graphData.nodes.map(node => ({ ...node })), + links: graphData.links.map(link => ({ + source: getEndpointId(link.source), + target: getEndpointId(link.target), + label: link.label, + })), + } +} + +function cloneGraphData(graphData: NormalizedGraphData): NormalizedGraphData { + return { + nodes: graphData.nodes.map(node => ({ ...node })), + links: graphData.links.map(link => ({ ...link })), + } +} + +function createInitialLayout(graphData: NormalizedGraphData) { const nodeCount = Math.max(1, graphData.nodes.length) const degrees: Record = {} const positions: Record = {} @@ -239,8 +272,16 @@ function App() { const debounceTimerRef = useRef | null>(null) const fetchDatabases = () => { - invoke('get_databases') - .then(setDatabases) + Promise.all([ + invoke('get_databases'), + invoke('get_initial_database_id'), + ]) + .then(([items, initialId]) => { + setDatabases(items) + if (typeof initialId === 'number') { + setSelectedId(initialId) + } + }) .catch(err => setError(String(err))) } @@ -343,17 +384,18 @@ function App() { const colorMapRef = useRef>({}) const edgeColorMapRef = useRef>({}) + const normalizedGraphData = useMemo(() => normalizeGraphData(graphData), [graphData]) + const forceGraphData = useMemo(() => cloneGraphData(normalizedGraphData), [normalizedGraphData]) + const nodeDegree = useMemo(() => { const degrees: Record = {} - graphData.nodes.forEach(n => degrees[n.id] = 0) - graphData.links.forEach(link => { - const src = typeof link.source === 'object' ? (link.source as NodeObject).id : link.source - const dst = typeof link.target === 'object' ? (link.target as NodeObject).id : link.target - degrees[src as string] = (degrees[src as string] || 0) + 1 - degrees[dst as string] = (degrees[dst as string] || 0) + 1 + normalizedGraphData.nodes.forEach(n => degrees[n.id] = 0) + normalizedGraphData.links.forEach(link => { + degrees[link.source] = (degrees[link.source] || 0) + 1 + degrees[link.target] = (degrees[link.target] || 0) + 1 }) return degrees - }, [graphData]) + }, [normalizedGraphData]) const maxDegree = useMemo(() => Math.max(1, ...Object.values(nodeDegree)), [nodeDegree]) @@ -379,7 +421,7 @@ function App() { }, [nodeDegree, maxDegree]) const labelSizeThreshold = useMemo(() => { - const sizes = graphData.nodes.map(n => { + const sizes = normalizedGraphData.nodes.map(n => { const degree = nodeDegree[n.id] || 0 return 4 + (degree / maxDegree) * 12 }) @@ -387,7 +429,7 @@ function App() { // Label the top 20% of nodes, but at least the top 5 const cutoffIndex = Math.max(4, Math.floor(sizes.length * 0.2) - 1) return sizes[Math.min(cutoffIndex, sizes.length - 1)] ?? 16 - }, [graphData.nodes, nodeDegree, maxDegree]) + }, [normalizedGraphData.nodes, nodeDegree, maxDegree]) // eslint-disable-next-line @typescript-eslint/no-explicit-any const paintNode = useCallback((node: any, ctx: CanvasRenderingContext2D) => { @@ -493,7 +535,8 @@ function App() {
{!loading && !error && graphData.nodes.length > 0 && renderer === 'sigma' && ( 0 && renderer === 'force' && ( { const s = getNodeSize(node); return s * s; }} nodeRelSize={1} From 88ca3904b60347965c61648e0cb5ca2da6d4d9ca Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 23 May 2026 16:16:29 -0700 Subject: [PATCH 04/20] Add incremental graph expansion UI --- src-tauri/src/lib.rs | 356 +++++++++++++++++++++++++--------- src/App.tsx | 201 ++++++++++++++++--- src/vendor/sigma-runtime.d.ts | 11 ++ 3 files changed, 457 insertions(+), 111 deletions(-) diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 7fc0ca9..aeb1055 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,6 +1,6 @@ use lbug::{Connection, Database, SystemConfig, Value}; use serde::{Deserialize, Serialize}; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::fs; use std::path::{Path, PathBuf}; use std::sync::Mutex; @@ -21,6 +21,14 @@ struct GraphNode { id: String, name: String, label: String, + #[serde(rename = "expansionKind", skip_serializing_if = "Option::is_none")] + expansion_kind: Option, + #[serde(rename = "expandNodeId", skip_serializing_if = "Option::is_none")] + expand_node_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + offset: Option, + #[serde(rename = "hiddenCount", skip_serializing_if = "Option::is_none")] + hidden_count: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -36,6 +44,11 @@ struct GraphData { links: Vec, } +const SEED_NODE_COUNT: usize = 8; +const EXPAND_BATCH_SIZE: usize = 8; +const EDGE_SCAN_LIMIT: usize = 10_000; +const EXPANDER_PREFIX: &str = "__expand__:"; + #[derive(Debug, Clone, Serialize, Deserialize)] struct DirEntry { name: String, @@ -150,6 +163,233 @@ fn id_to_string(id: &lbug::InternalID) -> String { format!("{}:{}", id.table_id, id.offset) } +fn make_expander_node(parent_id: &str, hidden_count: usize, offset: usize) -> GraphNode { + GraphNode { + id: format!("{EXPANDER_PREFIX}node:{parent_id}:{offset}"), + name: format!("+{hidden_count}"), + label: "More".to_string(), + expansion_kind: Some("node".to_string()), + expand_node_id: Some(parent_id.to_string()), + offset: Some(offset), + hidden_count: Some(hidden_count), + } +} + +fn merge_node(nodes: &mut HashMap, node: GraphNode) { + nodes.entry(node.id.clone()).or_insert(node); +} + +fn merge_link(links: &mut Vec, seen: &mut HashSet<(String, String, String)>, link: GraphLink) { + let key = (link.source.clone(), link.target.clone(), link.label.clone()); + if seen.insert(key) { + links.push(link); + } +} + +fn collect_edge_graph(conn: &Connection, limit: usize) -> Result { + let mut result = conn + .query(&format!("MATCH (a)-[r]->(b) RETURN a, r, b LIMIT {limit}")) + .map_err(|e| format!("Relationship query failed: {}", e))?; + + let mut nodes = HashMap::new(); + let mut links = Vec::new(); + let mut seen_links = HashSet::new(); + + for row in &mut result { + if row.len() < 3 { + continue; + } + let (source_node, rel, target_node) = match (&row[0], &row[1], &row[2]) { + (Value::Node(source_node), Value::Rel(rel), Value::Node(target_node)) => { + (source_node, rel, target_node) + } + _ => continue, + }; + + let source = id_to_string(rel.get_src_node()); + let target = id_to_string(rel.get_dst_node()); + for node_val in [source_node, target_node] { + let props = node_val.get_properties(); + let name = props + .iter() + .find(|(k, _)| k == "name") + .or_else(|| props.iter().find(|(k, _)| k == "id")) + .or_else(|| props.iter().find(|(k, _)| k == "title")) + .map(|(_, val)| value_to_string(val)) + .unwrap_or_else(|| "Node".to_string()); + merge_node( + &mut nodes, + GraphNode { + id: id_to_string(node_val.get_node_id()), + name, + label: node_val.get_label_name().clone(), + expansion_kind: None, + expand_node_id: None, + offset: None, + hidden_count: None, + }, + ); + } + merge_link( + &mut links, + &mut seen_links, + GraphLink { + source, + target, + label: rel.get_label_name().clone(), + }, + ); + } + + Ok(GraphData { + nodes: nodes.into_values().collect(), + links, + }) +} + +fn add_expanders(graph: &GraphData, visible_ids: &HashSet, nodes: &mut Vec, links: &mut Vec) { + let known_ids: HashSet = graph.nodes.iter().map(|node| node.id.clone()).collect(); + let mut neighbors: HashMap> = HashMap::new(); + for link in &graph.links { + neighbors + .entry(link.source.clone()) + .or_default() + .insert(link.target.clone()); + neighbors + .entry(link.target.clone()) + .or_default() + .insert(link.source.clone()); + } + + for node_id in visible_ids { + let hidden_count = neighbors + .get(node_id) + .map(|items| { + items + .iter() + .filter(|neighbor_id| !visible_ids.contains(*neighbor_id) && known_ids.contains(*neighbor_id)) + .count() + }) + .unwrap_or(0); + if hidden_count == 0 { + continue; + } + + let expander = make_expander_node(node_id, hidden_count, 0); + links.push(GraphLink { + source: node_id.clone(), + target: expander.id.clone(), + label: "more".to_string(), + }); + nodes.push(expander); + } +} + +fn seed_graph_from_full(full_graph: GraphData) -> GraphData { + let mut degrees: HashMap = HashMap::new(); + for node in &full_graph.nodes { + degrees.entry(node.id.clone()).or_insert(0); + } + for link in &full_graph.links { + *degrees.entry(link.source.clone()).or_insert(0) += 1; + *degrees.entry(link.target.clone()).or_insert(0) += 1; + } + + let mut ranked_nodes = full_graph.nodes.clone(); + ranked_nodes.sort_by_key(|node| std::cmp::Reverse(*degrees.get(&node.id).unwrap_or(&0))); + let visible_ids: HashSet = ranked_nodes + .iter() + .take(SEED_NODE_COUNT) + .map(|node| node.id.clone()) + .collect(); + + let mut nodes: Vec = ranked_nodes + .into_iter() + .filter(|node| visible_ids.contains(&node.id)) + .collect(); + let mut links: Vec = full_graph + .links + .iter() + .filter(|link| visible_ids.contains(&link.source) && visible_ids.contains(&link.target)) + .cloned() + .collect(); + + add_expanders(&full_graph, &visible_ids, &mut nodes, &mut links); + GraphData { nodes, links } +} + +fn expand_node_from_full(full_graph: GraphData, node_id: &str, visible_node_ids: &[String], offset: usize) -> GraphData { + let visible_ids: HashSet = visible_node_ids + .iter() + .filter(|id| !id.starts_with(EXPANDER_PREFIX)) + .cloned() + .collect(); + + let mut degrees: HashMap = HashMap::new(); + for link in &full_graph.links { + *degrees.entry(link.source.clone()).or_insert(0) += 1; + *degrees.entry(link.target.clone()).or_insert(0) += 1; + } + + let mut neighbor_ids: Vec = full_graph + .links + .iter() + .filter_map(|link| { + if link.source == node_id { + Some(link.target.clone()) + } else if link.target == node_id { + Some(link.source.clone()) + } else { + None + } + }) + .filter(|neighbor_id| !visible_ids.contains(neighbor_id)) + .collect(); + neighbor_ids.sort(); + neighbor_ids.dedup(); + neighbor_ids.sort_by_key(|id| std::cmp::Reverse(*degrees.get(id).unwrap_or(&0))); + + let selected_ids: HashSet = neighbor_ids + .iter() + .skip(offset) + .take(EXPAND_BATCH_SIZE) + .cloned() + .collect(); + + let full_node_by_id: HashMap = full_graph + .nodes + .iter() + .map(|node| (node.id.clone(), node.clone())) + .collect(); + let mut return_ids = visible_ids.clone(); + return_ids.extend(selected_ids.iter().cloned()); + + let mut nodes: Vec = selected_ids + .iter() + .filter_map(|id| full_node_by_id.get(id).cloned()) + .collect(); + let mut links: Vec = full_graph + .links + .iter() + .filter(|link| return_ids.contains(&link.source) && return_ids.contains(&link.target)) + .cloned() + .collect(); + + let next_offset = offset + selected_ids.len(); + let remaining = neighbor_ids.len().saturating_sub(next_offset); + if remaining > 0 { + let expander = make_expander_node(node_id, remaining, next_offset); + links.push(GraphLink { + source: node_id.to_string(), + target: expander.id.clone(), + label: "more".to_string(), + }); + nodes.push(expander); + } + + GraphData { nodes, links } +} + #[tauri::command] fn get_databases(state: State) -> Vec { get_all_databases(&state) @@ -258,94 +498,31 @@ fn get_graph(state: State, id: usize) -> Result { .map_err(|e| format!("Failed to open database: {}", e))?; let conn = Connection::new(&db).map_err(|e| format!("Failed to create connection: {}", e))?; - // Query nodes - let mut nodes_result = conn - .query("MATCH (n) RETURN n, LABEL(n) as label, ID(n) as nodeId LIMIT 500") - .map_err(|e| format!("Node query failed: {}", e))?; - - let mut nodes = Vec::new(); - for row in &mut nodes_result { - // row is Vec with 3 columns: [node, label, nodeId] - if row.len() < 3 { - continue; - } - - let node_id = match &row[2] { - Value::InternalID(id) => id_to_string(id), - _ => continue, - }; - - let label = match &row[1] { - Value::String(s) => s.clone(), - _ => "Node".to_string(), - }; - - // Extract display name from node properties - let name = match &row[0] { - Value::Node(node_val) => { - let props = node_val.get_properties(); - let name_val = props - .iter() - .find(|(k, _)| k == "name") - .or_else(|| props.iter().find(|(k, _)| k == "id")) - .or_else(|| props.iter().find(|(k, _)| k == "title")); - match name_val { - Some((_, val)) => value_to_string(val), - None => "Node".to_string(), - } - } - _ => "Node".to_string(), - }; - - nodes.push(GraphNode { - id: node_id, - name, - label, - }); - } - - // Query links - let mut links_result = conn - .query( - "MATCH (a)-[r]->(b) RETURN ID(a) as src, ID(b) as dst, LABEL(r) as relType LIMIT 500", - ) - .map_err(|e| format!("Link query failed: {}", e))?; - - let node_id_set: HashSet = nodes.iter().map(|n| n.id.clone()).collect(); - - let mut links = Vec::new(); - for row in &mut links_result { - // row is Vec with 3 columns: [src, dst, relType] - if row.len() < 3 { - continue; - } - - let source = match &row[0] { - Value::InternalID(id) => id_to_string(id), - _ => continue, - }; - - let target = match &row[1] { - Value::InternalID(id) => id_to_string(id), - _ => continue, - }; - - let label = match &row[2] { - Value::String(s) => s.clone(), - _ => String::new(), - }; + collect_edge_graph(&conn, EDGE_SCAN_LIMIT).map(seed_graph_from_full) +} - // Only include links where both endpoints exist in our node set - if node_id_set.contains(&source) && node_id_set.contains(&target) { - links.push(GraphLink { - source, - target, - label, - }); - } - } +#[tauri::command] +fn expand_node( + state: State, + id: usize, + node_id: String, + visible_node_ids: Vec, + offset: Option, +) -> Result { + let databases = get_all_databases(&state); + let db_info = databases.get(id).ok_or("Database not found")?; - Ok(GraphData { nodes, links }) + let db = Database::new(&db_info.path, SystemConfig::default()) + .map_err(|e| format!("Failed to open database: {}", e))?; + let conn = Connection::new(&db).map_err(|e| format!("Failed to create connection: {}", e))?; + let full_graph = collect_edge_graph(&conn, EDGE_SCAN_LIMIT)?; + + Ok(expand_node_from_full( + full_graph, + &node_id, + &visible_node_ids, + offset.unwrap_or(0), + )) } #[tauri::command] @@ -389,6 +566,10 @@ fn execute_query(state: State, id: usize, query: String) -> Result { interface SigmaGraphViewProps { graphData: NormalizedGraphData + labelNodeIds: Set darkMode: boolean getNodeColor: (label: string) => string getEdgeColor: (label: string) => string + onNodeClick: (nodeId: string) => void +} + +interface SigmaLabelData { + x: number + y: number + size: number + label?: string + color: string } class SigmaGraph< @@ -147,13 +161,102 @@ function normalizeGraphData(graphData: GraphData): NormalizedGraphData { } } -function cloneGraphData(graphData: NormalizedGraphData): NormalizedGraphData { +function cloneGraphData(graphData: GraphData): GraphData { return { nodes: graphData.nodes.map(node => ({ ...node })), links: graphData.links.map(link => ({ ...link })), } } +const EXPANDER_PREFIX = '__expand__:' + +function isExpanderNode(node: GraphNode) { + return Boolean(node.expansionKind) || node.id.startsWith(EXPANDER_PREFIX) +} + +function mergeGraphData(current: GraphData, incoming: GraphData, expandedNodeId?: string): GraphData { + const nodesById = new Map() + current.nodes + .filter(node => node.id !== expandedNodeId) + .forEach(node => nodesById.set(node.id, { ...node })) + incoming.nodes.forEach(node => nodesById.set(node.id, { ...node })) + + const linksByKey = new Map() + current.links + .filter(link => getEndpointId(link.source) !== expandedNodeId && getEndpointId(link.target) !== expandedNodeId) + .forEach(link => linksByKey.set(`${getEndpointId(link.source)}\t${getEndpointId(link.target)}\t${link.label}`, { ...link })) + incoming.links.forEach(link => { + linksByKey.set(`${getEndpointId(link.source)}\t${getEndpointId(link.target)}\t${link.label}`, { ...link }) + }) + + return { + nodes: [...nodesById.values()], + links: [...linksByKey.values()], + } +} + +function drawRoundedRect( + context: CanvasRenderingContext2D, + x: number, + y: number, + width: number, + height: number, + radius: number, +) { + context.beginPath() + context.moveTo(x + radius, y) + context.lineTo(x + width - radius, y) + context.quadraticCurveTo(x + width, y, x + width, y + radius) + context.lineTo(x + width, y + height - radius) + context.quadraticCurveTo(x + width, y + height, x + width - radius, y + height) + context.lineTo(x + radius, y + height) + context.quadraticCurveTo(x, y + height, x, y + height - radius) + context.lineTo(x, y + radius) + context.quadraticCurveTo(x, y, x + radius, y) + context.closePath() +} + +function drawSigmaLabel( + context: CanvasRenderingContext2D, + data: SigmaLabelData, + textColor: string, + backgroundColor: string, + strongBackground: boolean, +) { + if (!data.label) return + + const fontSize = 13 + const paddingX = strongBackground ? 7 : 4 + const paddingY = strongBackground ? 4 : 2 + + context.font = `600 ${fontSize}px system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif` + context.textBaseline = 'middle' + + const textWidth = context.measureText(data.label).width + const boxWidth = textWidth + paddingX * 2 + const boxHeight = fontSize + paddingY * 2 + const canvasWidth = context.canvas.width + const canvasHeight = context.canvas.height + const margin = 6 + const preferredX = data.x + data.size + 5 - paddingX + const preferredY = data.y - fontSize / 2 - paddingY + const boxX = Math.min(Math.max(preferredX, margin), Math.max(margin, canvasWidth - boxWidth - margin)) + const boxY = Math.min(Math.max(preferredY, margin), Math.max(margin, canvasHeight - boxHeight - margin)) + const textX = boxX + paddingX + const textY = boxY + boxHeight / 2 + + context.save() + context.fillStyle = backgroundColor + drawRoundedRect(context, boxX, boxY, boxWidth, boxHeight, strongBackground ? 6 : 4) + context.fill() + + context.fillStyle = textColor + context.shadowColor = strongBackground ? 'transparent' : backgroundColor + context.shadowBlur = strongBackground ? 0 : 3 + context.fillText(data.label, textX, textY) + context.restore() +} + function createInitialLayout(graphData: NormalizedGraphData) { const nodeCount = Math.max(1, graphData.nodes.length) const degrees: Record = {} @@ -183,7 +286,7 @@ function createInitialLayout(graphData: NormalizedGraphData) { return { degrees, positions } } -function SigmaGraphView({ graphData, darkMode, getNodeColor, getEdgeColor }: SigmaGraphViewProps) { +function SigmaGraphView({ graphData, labelNodeIds, darkMode, getNodeColor, getEdgeColor, onNodeClick }: SigmaGraphViewProps) { const containerRef = useRef(null) const rendererRef = useRef(null) @@ -199,8 +302,8 @@ function SigmaGraphView({ graphData, darkMode, getNodeColor, getEdgeColor }: Sig x: position.x, y: position.y, size: 4 + (degree / maxDegree) * 14, - color: getNodeColor(node.label), - label: node.name || node.id, + color: isExpanderNode(node) ? '#f59e0b' : getNodeColor(node.label), + label: isExpanderNode(node) || labelNodeIds.has(node.id) ? node.name || node.id : '', nodeType: node.label, }) }) @@ -219,21 +322,45 @@ function SigmaGraphView({ graphData, darkMode, getNodeColor, getEdgeColor }: Sig }) return sigmaGraph - }, [graphData, getNodeColor, getEdgeColor]) + }, [graphData, labelNodeIds, getNodeColor, getEdgeColor]) useEffect(() => { const container = containerRef.current if (!container) return + const labelTextColor = '#111827' + const labelBackgroundColor = darkMode ? 'rgba(248, 250, 252, 0.94)' : 'rgba(255, 255, 255, 0.9)' + const hoverTextColor = '#111827' + const hoverBackgroundColor = darkMode ? 'rgba(255, 255, 255, 0.98)' : 'rgba(255, 255, 255, 0.98)' + rendererRef.current?.kill() rendererRef.current = new Sigma(graph, container, { allowInvalidContainer: true, defaultEdgeType: 'arrow', - labelColor: { color: darkMode ? '#f3f4f6' : '#172033' }, + labelColor: { color: labelTextColor }, renderEdgeLabels: false, - labelRenderedSizeThreshold: 9, + labelRenderedSizeThreshold: 0, minCameraRatio: 0.03, maxCameraRatio: 12, + defaultDrawNodeLabel: (context, data) => { + drawSigmaLabel(context, data, labelTextColor, labelBackgroundColor, false) + }, + defaultDrawNodeHover: (context, data) => { + context.save() + context.fillStyle = data.color + context.strokeStyle = hoverTextColor + context.lineWidth = 2 + context.beginPath() + context.arc(data.x, data.y, data.size + 2, 0, Math.PI * 2) + context.fill() + context.stroke() + context.restore() + + drawSigmaLabel(context, data, hoverTextColor, hoverBackgroundColor, true) + }, + }) + rendererRef.current.on('clickNode', ({ node }: { node: string }) => { + onNodeClick(node) }) rendererRef.current.refresh() @@ -242,7 +369,7 @@ function SigmaGraphView({ graphData, darkMode, getNodeColor, getEdgeColor }: Sig rendererRef.current?.kill() rendererRef.current = null } - }, [graph, darkMode]) + }, [graph, darkMode, onNodeClick]) return
} @@ -384,6 +511,28 @@ function App() { const colorMapRef = useRef>({}) const edgeColorMapRef = useRef>({}) + const handleNodeClick = useCallback((nodeId: string) => { + const node = graphData.nodes.find(item => item.id === nodeId) + if (!node?.expansionKind || node.expansionKind !== 'node' || !node.expandNodeId) return + + setLoading(true) + setError(null) + invoke('expand_node', { + id: selectedId, + nodeId: node.expandNodeId, + visibleNodeIds: graphData.nodes.map(item => item.id), + offset: node.offset ?? 0, + }) + .then(data => { + setGraphData(current => mergeGraphData(current, data, node.id)) + setLoading(false) + }) + .catch(err => { + setError(String(err)) + setLoading(false) + }) + }, [graphData.nodes, selectedId]) + const normalizedGraphData = useMemo(() => normalizeGraphData(graphData), [graphData]) const forceGraphData = useMemo(() => cloneGraphData(normalizedGraphData), [normalizedGraphData]) @@ -399,6 +548,16 @@ function App() { const maxDegree = useMemo(() => Math.max(1, ...Object.values(nodeDegree)), [nodeDegree]) + const topLabelNodeIds = useMemo(() => { + return new Set( + [...normalizedGraphData.nodes] + .sort((a, b) => (nodeDegree[b.id] || 0) - (nodeDegree[a.id] || 0)) + .filter(node => !isExpanderNode(node)) + .slice(0, 5) + .map(node => node.id), + ) + }, [normalizedGraphData.nodes, nodeDegree]) + const getNodeColor = useCallback((label: string) => { if (!colorMapRef.current[label]) { const colors = ['#4e79a7', '#f28e2c', '#e15759', '#76b7b2', '#59a14f', '#edc949', '#af7aa1', '#ff9da7', '#9c755f', '#bab0ab'] @@ -420,21 +579,10 @@ function App() { return 4 + (degree / maxDegree) * 12 }, [nodeDegree, maxDegree]) - const labelSizeThreshold = useMemo(() => { - const sizes = normalizedGraphData.nodes.map(n => { - const degree = nodeDegree[n.id] || 0 - return 4 + (degree / maxDegree) * 12 - }) - sizes.sort((a, b) => b - a) - // Label the top 20% of nodes, but at least the top 5 - const cutoffIndex = Math.max(4, Math.floor(sizes.length * 0.2) - 1) - return sizes[Math.min(cutoffIndex, sizes.length - 1)] ?? 16 - }, [normalizedGraphData.nodes, nodeDegree, maxDegree]) - // eslint-disable-next-line @typescript-eslint/no-explicit-any const paintNode = useCallback((node: any, ctx: CanvasRenderingContext2D) => { const size = getNodeSize(node) - const color = getNodeColor(node.label) + const color = isExpanderNode(node) ? '#f59e0b' : getNodeColor(node.label) ctx.fillStyle = color ctx.beginPath() @@ -445,7 +593,7 @@ function App() { ctx.lineWidth = 1 ctx.stroke() - if (size >= labelSizeThreshold && node.name) { + if ((isExpanderNode(node) || topLabelNodeIds.has(node.id)) && node.name) { const fontSize = 3 ctx.font = `${fontSize}px Sans-Serif` ctx.textAlign = 'center' @@ -463,7 +611,7 @@ function App() { } ctx.fillText(label, node.x, node.y) } - }, [getNodeSize, getNodeColor, darkMode, labelSizeThreshold]) + }, [getNodeSize, getNodeColor, darkMode, topLabelNodeIds]) return (
@@ -488,7 +636,9 @@ function App() {
  • setSelectedId(db.id)} + onClick={() => { + setSelectedId(db.id) + }} title={db.relativePath} > {db.name} @@ -537,17 +687,20 @@ function App() { )} {!loading && !error && graphData.nodes.length > 0 && renderer === 'force' && ( handleNodeClick(String(node.id))} nodeVal={(node) => { const s = getNodeSize(node); return s * s; }} nodeRelSize={1} nodeLabel={(node) => `${node.label}: ${node.name}`} diff --git a/src/vendor/sigma-runtime.d.ts b/src/vendor/sigma-runtime.d.ts index 4a44f65..21cb4d5 100644 --- a/src/vendor/sigma-runtime.d.ts +++ b/src/vendor/sigma-runtime.d.ts @@ -6,10 +6,21 @@ export interface SigmaSettings { labelRenderedSizeThreshold?: number minCameraRatio?: number maxCameraRatio?: number + defaultDrawNodeLabel?: (context: CanvasRenderingContext2D, data: SigmaLabelData) => void + defaultDrawNodeHover?: (context: CanvasRenderingContext2D, data: SigmaLabelData) => void +} + +export interface SigmaLabelData { + x: number + y: number + size: number + label?: string + color: string } export class Sigma { constructor(graph: unknown, container: HTMLElement, settings?: SigmaSettings) + on(event: 'clickNode', callback: (payload: { node: string }) => void): void refresh(): void kill(): void } From 9650facc2bff39ed42e99e11d89e63fddd82bd6c Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 23 May 2026 16:19:02 -0700 Subject: [PATCH 05/20] Improve graph label inspection --- src/App.tsx | 27 ++++++++++++++++++++++++--- src/vendor/sigma-runtime.d.ts | 1 + 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index bdd0f64..c1dd6dc 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -50,6 +50,7 @@ interface SigmaNodeAttributes extends Record { size: number color: string label: string + hoverLabel: string nodeType: string } @@ -73,6 +74,7 @@ interface SigmaLabelData { y: number size: number label?: string + hoverLabel?: string color: string } @@ -304,6 +306,7 @@ function SigmaGraphView({ graphData, labelNodeIds, darkMode, getNodeColor, getEd size: 4 + (degree / maxDegree) * 14, color: isExpanderNode(node) ? '#f59e0b' : getNodeColor(node.label), label: isExpanderNode(node) || labelNodeIds.has(node.id) ? node.name || node.id : '', + hoverLabel: node.name || node.id, nodeType: node.label, }) }) @@ -346,6 +349,11 @@ function SigmaGraphView({ graphData, labelNodeIds, darkMode, getNodeColor, getEd drawSigmaLabel(context, data, labelTextColor, labelBackgroundColor, false) }, defaultDrawNodeHover: (context, data) => { + const labelData = { + ...data, + label: typeof data.hoverLabel === 'string' ? data.hoverLabel : data.label, + } + context.save() context.fillStyle = data.color context.strokeStyle = hoverTextColor @@ -356,7 +364,7 @@ function SigmaGraphView({ graphData, labelNodeIds, darkMode, getNodeColor, getEd context.stroke() context.restore() - drawSigmaLabel(context, data, hoverTextColor, hoverBackgroundColor, true) + drawSigmaLabel(context, labelData, hoverTextColor, hoverBackgroundColor, true) }, }) rendererRef.current.on('clickNode', ({ node }: { node: string }) => { @@ -393,6 +401,7 @@ function App() { const [isCustomQuery, setIsCustomQuery] = useState(false) const [queryActivated, setQueryActivated] = useState(false) const [renderer, setRenderer] = useState<'sigma' | 'force'>('sigma') + const [expandedLabelNodeIds, setExpandedLabelNodeIds] = useState>(() => new Set()) // eslint-disable-next-line @typescript-eslint/no-explicit-any const graphRef = useRef(null) const customQueryRef = useRef('') @@ -450,6 +459,7 @@ function App() { invoke('execute_query', { id: selectedId, query }) .then(data => { setGraphData(data) + setExpandedLabelNodeIds(new Set()) setLoading(false) setTimeout(() => { if (graphRef.current) { @@ -465,6 +475,7 @@ function App() { invoke('get_graph', { id: selectedId }) .then(data => { setGraphData(data) + setExpandedLabelNodeIds(new Set()) setLoading(false) setTimeout(() => { if (graphRef.current) { @@ -525,6 +536,13 @@ function App() { }) .then(data => { setGraphData(current => mergeGraphData(current, data, node.id)) + setExpandedLabelNodeIds(current => { + const next = new Set(current) + data.nodes + .filter(item => !isExpanderNode(item)) + .forEach(item => next.add(item.id)) + return next + }) setLoading(false) }) .catch(err => { @@ -550,13 +568,16 @@ function App() { const topLabelNodeIds = useMemo(() => { return new Set( - [...normalizedGraphData.nodes] + [ + ...expandedLabelNodeIds, + ...[...normalizedGraphData.nodes] .sort((a, b) => (nodeDegree[b.id] || 0) - (nodeDegree[a.id] || 0)) .filter(node => !isExpanderNode(node)) .slice(0, 5) .map(node => node.id), + ] ) - }, [normalizedGraphData.nodes, nodeDegree]) + }, [expandedLabelNodeIds, normalizedGraphData.nodes, nodeDegree]) const getNodeColor = useCallback((label: string) => { if (!colorMapRef.current[label]) { diff --git a/src/vendor/sigma-runtime.d.ts b/src/vendor/sigma-runtime.d.ts index 21cb4d5..2681788 100644 --- a/src/vendor/sigma-runtime.d.ts +++ b/src/vendor/sigma-runtime.d.ts @@ -15,6 +15,7 @@ export interface SigmaLabelData { y: number size: number label?: string + hoverLabel?: string color: string } From 68e6837b50538ea4b53c94aee5621cf9bd76c2f2 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 23 May 2026 16:23:50 -0700 Subject: [PATCH 06/20] Highlight newly expanded graph nodes --- src/App.tsx | 125 +++++++++++++++++++++++----------- src/vendor/sigma-runtime.d.ts | 1 + 2 files changed, 87 insertions(+), 39 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index c1dd6dc..32f8748 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,7 @@ import { useState, useEffect, useMemo, useCallback, useRef } from 'react' import { invoke } from '@tauri-apps/api/core' import ForceGraph2D from 'react-force-graph-2d' -import type { NodeObject } from 'react-force-graph-2d' +import type { GraphData as ForceGraphData, NodeObject } from 'react-force-graph-2d' import { Sigma } from './vendor/sigma-runtime.js' import './App.css' @@ -44,6 +44,10 @@ interface NormalizedGraphData { links: NormalizedGraphLink[] } +interface ForceGraphLink { + label: string +} + interface SigmaNodeAttributes extends Record { x: number y: number @@ -51,6 +55,7 @@ interface SigmaNodeAttributes extends Record { color: string label: string hoverLabel: string + isNewlyExpanded: boolean nodeType: string } @@ -63,6 +68,7 @@ interface SigmaEdgeAttributes extends Record { interface SigmaGraphViewProps { graphData: NormalizedGraphData labelNodeIds: Set + newlyExpandedNodeIds: Set darkMode: boolean getNodeColor: (label: string) => string getEdgeColor: (label: string) => string @@ -76,6 +82,7 @@ interface SigmaLabelData { label?: string hoverLabel?: string color: string + isNewlyExpanded?: boolean } class SigmaGraph< @@ -163,13 +170,6 @@ function normalizeGraphData(graphData: GraphData): NormalizedGraphData { } } -function cloneGraphData(graphData: GraphData): GraphData { - return { - nodes: graphData.nodes.map(node => ({ ...node })), - links: graphData.links.map(link => ({ ...link })), - } -} - const EXPANDER_PREFIX = '__expand__:' function isExpanderNode(node: GraphNode) { @@ -197,6 +197,10 @@ function mergeGraphData(current: GraphData, incoming: GraphData, expandedNodeId? } } +function realNodeIds(nodes: GraphNode[]): Set { + return new Set(nodes.filter(node => !isExpanderNode(node)).map(node => node.id)) +} + function drawRoundedRect( context: CanvasRenderingContext2D, x: number, @@ -259,6 +263,34 @@ function drawSigmaLabel( context.restore() } +function drawSigmaNode( + context: CanvasRenderingContext2D, + data: SigmaLabelData, + highlighted: boolean, +) { + context.save() + if (highlighted) { + context.fillStyle = 'rgba(245, 158, 11, 0.22)' + context.beginPath() + context.arc(data.x, data.y, data.size + 7, 0, Math.PI * 2) + context.fill() + } + + context.fillStyle = data.color + context.beginPath() + context.arc(data.x, data.y, data.size, 0, Math.PI * 2) + context.fill() + + if (highlighted) { + context.strokeStyle = '#f59e0b' + context.lineWidth = 3 + context.beginPath() + context.arc(data.x, data.y, data.size + 2, 0, Math.PI * 2) + context.stroke() + } + context.restore() +} + function createInitialLayout(graphData: NormalizedGraphData) { const nodeCount = Math.max(1, graphData.nodes.length) const degrees: Record = {} @@ -288,7 +320,7 @@ function createInitialLayout(graphData: NormalizedGraphData) { return { degrees, positions } } -function SigmaGraphView({ graphData, labelNodeIds, darkMode, getNodeColor, getEdgeColor, onNodeClick }: SigmaGraphViewProps) { +function SigmaGraphView({ graphData, labelNodeIds, newlyExpandedNodeIds, darkMode, getNodeColor, getEdgeColor, onNodeClick }: SigmaGraphViewProps) { const containerRef = useRef(null) const rendererRef = useRef(null) @@ -307,6 +339,7 @@ function SigmaGraphView({ graphData, labelNodeIds, darkMode, getNodeColor, getEd color: isExpanderNode(node) ? '#f59e0b' : getNodeColor(node.label), label: isExpanderNode(node) || labelNodeIds.has(node.id) ? node.name || node.id : '', hoverLabel: node.name || node.id, + isNewlyExpanded: newlyExpandedNodeIds.has(node.id), nodeType: node.label, }) }) @@ -325,7 +358,7 @@ function SigmaGraphView({ graphData, labelNodeIds, darkMode, getNodeColor, getEd }) return sigmaGraph - }, [graphData, labelNodeIds, getNodeColor, getEdgeColor]) + }, [graphData, labelNodeIds, newlyExpandedNodeIds, getNodeColor, getEdgeColor]) useEffect(() => { const container = containerRef.current @@ -333,6 +366,8 @@ function SigmaGraphView({ graphData, labelNodeIds, darkMode, getNodeColor, getEd const labelTextColor = '#111827' const labelBackgroundColor = darkMode ? 'rgba(248, 250, 252, 0.94)' : 'rgba(255, 255, 255, 0.9)' + const expandedTextColor = '#111827' + const expandedBackgroundColor = 'rgba(254, 243, 199, 0.96)' const hoverTextColor = '#111827' const hoverBackgroundColor = darkMode ? 'rgba(255, 255, 255, 0.98)' : 'rgba(255, 255, 255, 0.98)' @@ -346,7 +381,13 @@ function SigmaGraphView({ graphData, labelNodeIds, darkMode, getNodeColor, getEd minCameraRatio: 0.03, maxCameraRatio: 12, defaultDrawNodeLabel: (context, data) => { - drawSigmaLabel(context, data, labelTextColor, labelBackgroundColor, false) + drawSigmaLabel( + context, + data, + data.isNewlyExpanded ? expandedTextColor : labelTextColor, + data.isNewlyExpanded ? expandedBackgroundColor : labelBackgroundColor, + Boolean(data.isNewlyExpanded), + ) }, defaultDrawNodeHover: (context, data) => { const labelData = { @@ -354,15 +395,7 @@ function SigmaGraphView({ graphData, labelNodeIds, darkMode, getNodeColor, getEd label: typeof data.hoverLabel === 'string' ? data.hoverLabel : data.label, } - context.save() - context.fillStyle = data.color - context.strokeStyle = hoverTextColor - context.lineWidth = 2 - context.beginPath() - context.arc(data.x, data.y, data.size + 2, 0, Math.PI * 2) - context.fill() - context.stroke() - context.restore() + drawSigmaNode(context, data, Boolean(data.isNewlyExpanded)) drawSigmaLabel(context, labelData, hoverTextColor, hoverBackgroundColor, true) }, @@ -401,7 +434,7 @@ function App() { const [isCustomQuery, setIsCustomQuery] = useState(false) const [queryActivated, setQueryActivated] = useState(false) const [renderer, setRenderer] = useState<'sigma' | 'force'>('sigma') - const [expandedLabelNodeIds, setExpandedLabelNodeIds] = useState>(() => new Set()) + const [lastExpandedNodeIds, setLastExpandedNodeIds] = useState>(() => new Set()) // eslint-disable-next-line @typescript-eslint/no-explicit-any const graphRef = useRef(null) const customQueryRef = useRef('') @@ -459,7 +492,7 @@ function App() { invoke('execute_query', { id: selectedId, query }) .then(data => { setGraphData(data) - setExpandedLabelNodeIds(new Set()) + setLastExpandedNodeIds(new Set()) setLoading(false) setTimeout(() => { if (graphRef.current) { @@ -475,7 +508,7 @@ function App() { invoke('get_graph', { id: selectedId }) .then(data => { setGraphData(data) - setExpandedLabelNodeIds(new Set()) + setLastExpandedNodeIds(new Set()) setLoading(false) setTimeout(() => { if (graphRef.current) { @@ -535,24 +568,29 @@ function App() { offset: node.offset ?? 0, }) .then(data => { - setGraphData(current => mergeGraphData(current, data, node.id)) - setExpandedLabelNodeIds(current => { - const next = new Set(current) - data.nodes - .filter(item => !isExpanderNode(item)) - .forEach(item => next.add(item.id)) - return next + const beforeNodeIds = realNodeIds(graphData.nodes) + const returnedNodeIds = realNodeIds(data.nodes) + const merged = mergeGraphData(graphData, data, node.id) + const highlightedNodeIds = realNodeIds(merged.nodes) + + beforeNodeIds.forEach(id => { + if (!returnedNodeIds.has(id)) highlightedNodeIds.delete(id) }) + setGraphData(merged) + setLastExpandedNodeIds(highlightedNodeIds) setLoading(false) }) .catch(err => { setError(String(err)) setLoading(false) }) - }, [graphData.nodes, selectedId]) + }, [graphData, selectedId]) const normalizedGraphData = useMemo(() => normalizeGraphData(graphData), [graphData]) - const forceGraphData = useMemo(() => cloneGraphData(normalizedGraphData), [normalizedGraphData]) + const forceGraphData = useMemo>(() => ({ + nodes: normalizedGraphData.nodes.map(node => ({ ...node })), + links: normalizedGraphData.links.map(link => ({ ...link })), + }), [normalizedGraphData]) const nodeDegree = useMemo(() => { const degrees: Record = {} @@ -569,7 +607,7 @@ function App() { const topLabelNodeIds = useMemo(() => { return new Set( [ - ...expandedLabelNodeIds, + ...lastExpandedNodeIds, ...[...normalizedGraphData.nodes] .sort((a, b) => (nodeDegree[b.id] || 0) - (nodeDegree[a.id] || 0)) .filter(node => !isExpanderNode(node)) @@ -577,7 +615,7 @@ function App() { .map(node => node.id), ] ) - }, [expandedLabelNodeIds, normalizedGraphData.nodes, nodeDegree]) + }, [lastExpandedNodeIds, normalizedGraphData.nodes, nodeDegree]) const getNodeColor = useCallback((label: string) => { if (!colorMapRef.current[label]) { @@ -604,14 +642,22 @@ function App() { const paintNode = useCallback((node: any, ctx: CanvasRenderingContext2D) => { const size = getNodeSize(node) const color = isExpanderNode(node) ? '#f59e0b' : getNodeColor(node.label) + const highlighted = lastExpandedNodeIds.has(node.id) + + if (highlighted) { + ctx.fillStyle = 'rgba(245, 158, 11, 0.22)' + ctx.beginPath() + ctx.arc(node.x, node.y, size + 7, 0, 2 * Math.PI) + ctx.fill() + } ctx.fillStyle = color ctx.beginPath() ctx.arc(node.x, node.y, size, 0, 2 * Math.PI) ctx.fill() - ctx.strokeStyle = darkMode ? '#222' : '#ddd' - ctx.lineWidth = 1 + ctx.strokeStyle = highlighted ? '#f59e0b' : darkMode ? '#222' : '#ddd' + ctx.lineWidth = highlighted ? 3 : 1 ctx.stroke() if ((isExpanderNode(node) || topLabelNodeIds.has(node.id)) && node.name) { @@ -619,7 +665,7 @@ function App() { ctx.font = `${fontSize}px Sans-Serif` ctx.textAlign = 'center' ctx.textBaseline = 'middle' - ctx.fillStyle = '#fff' + ctx.fillStyle = highlighted ? '#f59e0b' : '#fff' const maxWidth = size * 1.6 let label = node.name @@ -632,7 +678,7 @@ function App() { } ctx.fillText(label, node.x, node.y) } - }, [getNodeSize, getNodeColor, darkMode, topLabelNodeIds]) + }, [getNodeSize, getNodeColor, darkMode, topLabelNodeIds, lastExpandedNodeIds]) return (
    @@ -709,6 +755,7 @@ function App() { key="sigma" graphData={normalizedGraphData} labelNodeIds={topLabelNodeIds} + newlyExpandedNodeIds={lastExpandedNodeIds} darkMode={darkMode} getNodeColor={getNodeColor} getEdgeColor={getEdgeColor} @@ -719,7 +766,7 @@ function App() { handleNodeClick(String(node.id))} nodeVal={(node) => { const s = getNodeSize(node); return s * s; }} diff --git a/src/vendor/sigma-runtime.d.ts b/src/vendor/sigma-runtime.d.ts index 2681788..7be702d 100644 --- a/src/vendor/sigma-runtime.d.ts +++ b/src/vendor/sigma-runtime.d.ts @@ -17,6 +17,7 @@ export interface SigmaLabelData { label?: string hoverLabel?: string color: string + isNewlyExpanded?: boolean } export class Sigma { From 36f1e02b53681cf9210bf5c48a1fd20c66db20fb Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 23 May 2026 16:39:45 -0700 Subject: [PATCH 07/20] Keep renderer toggle visible in force view --- src/App.css | 4 ++++ src/App.tsx | 32 +++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/App.css b/src/App.css index 786d138..310ca3d 100644 --- a/src/App.css +++ b/src/App.css @@ -110,6 +110,9 @@ body { align-items: center; justify-content: space-between; gap: 16px; + flex-shrink: 0; + position: relative; + z-index: 2; } .header-left { @@ -253,6 +256,7 @@ body { min-height: 0; position: relative; overflow: hidden; + z-index: 1; } .sigma-canvas { diff --git a/src/App.tsx b/src/App.tsx index 32f8748..a17d8e8 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -437,6 +437,8 @@ function App() { const [lastExpandedNodeIds, setLastExpandedNodeIds] = useState>(() => new Set()) // eslint-disable-next-line @typescript-eslint/no-explicit-any const graphRef = useRef(null) + const graphContainerRef = useRef(null) + const [graphSize, setGraphSize] = useState({ width: 1, height: 1 }) const customQueryRef = useRef('') const debounceTimerRef = useRef | null>(null) @@ -479,6 +481,32 @@ function App() { document.documentElement.setAttribute('data-theme', darkMode ? 'dark' : 'light') }, [darkMode]) + useEffect(() => { + const container = graphContainerRef.current + if (!container) return + + const updateGraphSize = () => { + const rect = container.getBoundingClientRect() + const width = Math.max(1, Math.floor(rect.width)) + const height = Math.max(1, Math.floor(rect.height)) + setGraphSize(current => ( + current.width === width && current.height === height + ? current + : { width, height } + )) + } + + updateGraphSize() + const observer = new ResizeObserver(updateGraphSize) + observer.observe(container) + window.addEventListener('resize', updateGraphSize) + + return () => { + observer.disconnect() + window.removeEventListener('resize', updateGraphSize) + } + }, []) + const fetchGraphData = useCallback(() => { if (databases.length === 0) { setGraphData({ nodes: [], links: [] }) @@ -749,7 +777,7 @@ function App() {
  • -
    +
    {!loading && !error && graphData.nodes.length > 0 && renderer === 'sigma' && ( handleNodeClick(String(node.id))} From 94f4cd948f81b49273e5147d82fab7910481bd88 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 23 May 2026 16:42:57 -0700 Subject: [PATCH 08/20] Show edge labels in sigma view --- src/App.tsx | 85 ++++++++++++++++++++++++++++++++++- src/vendor/sigma-runtime.d.ts | 20 +++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/src/App.tsx b/src/App.tsx index a17d8e8..f3f551e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -63,6 +63,7 @@ interface SigmaEdgeAttributes extends Record { size: number color: string label: string + forceLabel: boolean } interface SigmaGraphViewProps { @@ -85,6 +86,17 @@ interface SigmaLabelData { isNewlyExpanded?: boolean } +interface SigmaEdgeLabelData { + label?: string + size: number +} + +interface SigmaEdgeLabelNodeData { + x: number + y: number + size: number +} + class SigmaGraph< N extends Record = Record, E extends Record = Record, @@ -291,6 +303,61 @@ function drawSigmaNode( context.restore() } +function drawSigmaEdgeLabel( + context: CanvasRenderingContext2D, + edgeData: SigmaEdgeLabelData, + sourceData: SigmaEdgeLabelNodeData, + targetData: SigmaEdgeLabelNodeData, + textColor: string, + backgroundColor: string, +) { + if (!edgeData.label) return + + const dx = targetData.x - sourceData.x + const dy = targetData.y - sourceData.y + const distance = Math.hypot(dx, dy) + if (distance < sourceData.size + targetData.size + 18) return + + const fontSize = 11 + const paddingX = 5 + const paddingY = 3 + const unitX = dx / distance + const unitY = dy / distance + const startX = sourceData.x + unitX * sourceData.size + const startY = sourceData.y + unitY * sourceData.size + const endX = targetData.x - unitX * targetData.size + const endY = targetData.y - unitY * targetData.size + const midX = (startX + endX) / 2 + const midY = (startY + endY) / 2 + const availableWidth = Math.max(12, Math.hypot(endX - startX, endY - startY) - 8) + + context.save() + context.font = `600 ${fontSize}px system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif` + context.textBaseline = 'middle' + + let label = edgeData.label + let textWidth = context.measureText(label).width + if (textWidth > availableWidth) { + while (label.length > 1 && context.measureText(`${label}...`).width > availableWidth) { + label = label.slice(0, -1) + } + label = `${label}...` + textWidth = context.measureText(label).width + } + + const boxWidth = textWidth + paddingX * 2 + const boxHeight = fontSize + paddingY * 2 + const boxX = midX - boxWidth / 2 + const boxY = midY - boxHeight / 2 + + context.fillStyle = backgroundColor + drawRoundedRect(context, boxX, boxY, boxWidth, boxHeight, 4) + context.fill() + context.fillStyle = textColor + context.fillText(label, boxX + paddingX, midY) + context.restore() +} + function createInitialLayout(graphData: NormalizedGraphData) { const nodeCount = Math.max(1, graphData.nodes.length) const degrees: Record = {} @@ -354,6 +421,7 @@ function SigmaGraphView({ graphData, labelNodeIds, newlyExpandedNodeIds, darkMod size: 1.8, color: getEdgeColor(link.label || 'edge'), label: link.label || '', + forceLabel: Boolean(link.label), }) }) @@ -370,16 +438,31 @@ function SigmaGraphView({ graphData, labelNodeIds, newlyExpandedNodeIds, darkMod const expandedBackgroundColor = 'rgba(254, 243, 199, 0.96)' const hoverTextColor = '#111827' const hoverBackgroundColor = darkMode ? 'rgba(255, 255, 255, 0.98)' : 'rgba(255, 255, 255, 0.98)' + const edgeLabelTextColor = '#111827' + const edgeLabelBackgroundColor = darkMode ? 'rgba(248, 250, 252, 0.92)' : 'rgba(255, 255, 255, 0.92)' rendererRef.current?.kill() rendererRef.current = new Sigma(graph, container, { allowInvalidContainer: true, defaultEdgeType: 'arrow', labelColor: { color: labelTextColor }, - renderEdgeLabels: false, + renderEdgeLabels: true, + edgeLabelColor: { color: edgeLabelTextColor }, + edgeLabelSize: 11, + edgeLabelWeight: '600', labelRenderedSizeThreshold: 0, minCameraRatio: 0.03, maxCameraRatio: 12, + defaultDrawEdgeLabel: (context, edgeData, sourceData, targetData) => { + drawSigmaEdgeLabel( + context, + edgeData, + sourceData, + targetData, + edgeLabelTextColor, + edgeLabelBackgroundColor, + ) + }, defaultDrawNodeLabel: (context, data) => { drawSigmaLabel( context, diff --git a/src/vendor/sigma-runtime.d.ts b/src/vendor/sigma-runtime.d.ts index 7be702d..ffae679 100644 --- a/src/vendor/sigma-runtime.d.ts +++ b/src/vendor/sigma-runtime.d.ts @@ -3,13 +3,33 @@ export interface SigmaSettings { defaultEdgeType?: string labelColor?: { color: string } | { attribute: string; color?: string } renderEdgeLabels?: boolean + edgeLabelColor?: { color: string } | { attribute: string; color?: string } + edgeLabelSize?: number + edgeLabelWeight?: string labelRenderedSizeThreshold?: number minCameraRatio?: number maxCameraRatio?: number + defaultDrawEdgeLabel?: ( + context: CanvasRenderingContext2D, + edgeData: SigmaEdgeLabelData, + sourceData: SigmaEdgeLabelNodeData, + targetData: SigmaEdgeLabelNodeData, + ) => void defaultDrawNodeLabel?: (context: CanvasRenderingContext2D, data: SigmaLabelData) => void defaultDrawNodeHover?: (context: CanvasRenderingContext2D, data: SigmaLabelData) => void } +export interface SigmaEdgeLabelData { + label?: string + size: number +} + +export interface SigmaEdgeLabelNodeData { + x: number + y: number + size: number +} + export interface SigmaLabelData { x: number y: number From c7cc7ab4c002ec52cebedbd2a6315b7ffe7622d6 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 23 May 2026 16:55:03 -0700 Subject: [PATCH 09/20] Use CI-safe sigma checkout --- .github/workflows/build.yml | 14 ++++++++++++++ .gitignore | 1 + eslint.config.js | 2 +- package-lock.json | 6 +++--- package.json | 2 +- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f7d11a0..a6d15a1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,6 +18,13 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Checkout Sigma + uses: actions/checkout@v4 + with: + repository: adsharma/sigma.js + ref: icebug-arrow-graph + path: .deps/sigma.js + - name: Install Node.js uses: actions/setup-node@v4 with: @@ -55,6 +62,13 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 + - name: Checkout Sigma + uses: actions/checkout@v4 + with: + repository: adsharma/sigma.js + ref: icebug-arrow-graph + path: .deps/sigma.js + - name: Install Node.js uses: actions/setup-node@v4 with: diff --git a/.gitignore b/.gitignore index ad0d5de..3100e22 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ pnpm-debug.log* lerna-debug.log* node_modules +.deps dist dist-ssr *.local diff --git a/eslint.config.js b/eslint.config.js index 1097190..10b5b93 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -6,7 +6,7 @@ import tseslint from 'typescript-eslint' import { defineConfig, globalIgnores } from 'eslint/config' export default defineConfig([ - globalIgnores(['dist', 'src-tauri/target', 'src-tauri/src-tauri', 'src-tauri/gen']), + globalIgnores(['.deps', 'dist', 'src-tauri/target', 'src-tauri/src-tauri', 'src-tauri/gen']), { files: ['**/*.{ts,tsx}'], extends: [ diff --git a/package-lock.json b/package-lock.json index 452d221..02c6fc7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "react": "^19.2.0", "react-dom": "^19.2.0", "react-force-graph-2d": "^1.29.1", - "sigma": "file:../sigma.js/packages/sigma" + "sigma": "file:.deps/sigma.js/packages/sigma" }, "devDependencies": { "@eslint/js": "^9.39.1", @@ -29,7 +29,7 @@ "vite": "^7.3.1" } }, - "../sigma.js/packages/sigma": { + ".deps/sigma.js/packages/sigma": { "version": "3.0.3", "license": "MIT", "dependencies": { @@ -3429,7 +3429,7 @@ } }, "node_modules/sigma": { - "resolved": "../sigma.js/packages/sigma", + "resolved": ".deps/sigma.js/packages/sigma", "link": true }, "node_modules/source-map-js": { diff --git a/package.json b/package.json index 4f3ae7f..b668826 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "react": "^19.2.0", "react-dom": "^19.2.0", "react-force-graph-2d": "^1.29.1", - "sigma": "file:../sigma.js/packages/sigma" + "sigma": "file:.deps/sigma.js/packages/sigma" }, "devDependencies": { "@eslint/js": "^9.39.1", From be15da884accdc105d8e616161efcbc8efbf7493 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 23 May 2026 16:56:26 -0700 Subject: [PATCH 10/20] Update package-lock.json --- package-lock.json | 775 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 767 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 02c6fc7..c3ec496 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,6 +41,565 @@ "vite": "^6.0.7" } }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + ".deps/sigma.js/packages/sigma/node_modules/vite": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz", + "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, "node_modules/@babel/code-frame": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", @@ -1024,6 +1583,19 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@ladybugmem/icebug": { + "version": "12.7.0", + "resolved": "https://registry.npmjs.org/@ladybugmem/icebug/-/icebug-12.7.0.tgz", + "integrity": "sha512-09MSrJi/QtXUHw2wmQYj4+W29d+qj1ZU9g3GuRhkWR7dEooxwkAtosmh8n0vArhusQqy7h3jaHMXMxPlVOdM7Q==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-rc.3", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", @@ -1381,6 +1953,15 @@ "win32" ] }, + "node_modules/@swc/helpers": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.21.tgz", + "integrity": "sha512-jI/VAmtdjB/RnI8GTnokyX7Ug8c+g+ffD6QRLa6XQewtnGyukKkKSk3wLTM3b5cjt1jNh9x0jfVlagdN2gDKQg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, "node_modules/@tauri-apps/api": { "version": "2.10.1", "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.10.1.tgz", @@ -1442,6 +2023,18 @@ "@babel/types": "^7.28.2" } }, + "node_modules/@types/command-line-args": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.2.3.tgz", + "integrity": "sha512-uv0aG6R0Y8WHZLTamZwtfsDLVRnOa+n+n5rEvFWL5Na5gZ8V2Teab/duDPFzIIIhs9qizDpcavCusCLJZu62Kw==", + "license": "MIT" + }, + "node_modules/@types/command-line-usage": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/command-line-usage/-/command-line-usage-5.0.4.tgz", + "integrity": "sha512-BwR5KP3Es/CSht0xqBcUXS3qCAUVXwpRKsV2+arxeb65atasuXG9LykC9Ab10Cw3s2raH92ZqOeILaQbsB2ACg==", + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -1460,7 +2053,6 @@ "version": "24.10.13", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.13.tgz", "integrity": "sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg==", - "dev": true, "license": "MIT", "dependencies": { "undici-types": "~7.16.0" @@ -1855,7 +2447,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -1867,6 +2458,26 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/apache-arrow": { + "version": "21.1.0", + "resolved": "https://registry.npmjs.org/apache-arrow/-/apache-arrow-21.1.0.tgz", + "integrity": "sha512-kQrYLxhC+NTVVZ4CCzGF6L/uPVOzJmD1T3XgbiUnP7oTeVFOFgEUu6IKNwCDkpFoBVqDKQivlX4RUFqqnWFlEA==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.11", + "@types/command-line-args": "^5.2.3", + "@types/command-line-usage": "^5.0.4", + "@types/node": "^24.0.3", + "command-line-args": "^6.0.1", + "command-line-usage": "^7.0.1", + "flatbuffers": "^25.1.24", + "json-bignum": "^0.0.3", + "tslib": "^2.6.2" + }, + "bin": { + "arrow2csv": "bin/arrow2csv.js" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1874,6 +2485,15 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/array-back": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.3.tgz", + "integrity": "sha512-SGDvmg6QTYiTxCBkYVmThcoa67uLl35pyzRHdpCGBOcqFy6BtwnphoFPk7LhJshD+Yk1Kt35WGWeZPTgwR4Fhw==", + "license": "MIT", + "engines": { + "node": ">=12.17" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1996,7 +2616,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -2009,11 +2628,25 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chalk-template": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", + "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/chalk-template?sponsor=1" + } + }, "node_modules/chalk/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -2026,7 +2659,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -2039,9 +2671,46 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, + "node_modules/command-line-args": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-6.0.2.tgz", + "integrity": "sha512-AIjYVxrV9X752LmPDLbVYv8aMCuHPSLZJXEo2qo/xJfv+NYhaZ4sMSF01rM+gHPaMgvPM0l5D/F+Qx+i2WfSmQ==", + "license": "MIT", + "dependencies": { + "array-back": "^6.2.3", + "find-replace": "^5.0.2", + "lodash.camelcase": "^4.3.0", + "typical": "^7.3.0" + }, + "engines": { + "node": ">=12.20" + }, + "peerDependencies": { + "@75lb/nature": "latest" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, + "node_modules/command-line-usage": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-7.0.4.tgz", + "integrity": "sha512-85UdvzTNx/+s5CkSgBm/0hzP80RFHAa7PsfeADE5ezZF3uHz3/Tqj9gIKGT9PTtpycc3Ua64T0oVulGfKxzfqg==", + "license": "MIT", + "dependencies": { + "array-back": "^6.2.2", + "chalk-template": "^0.4.0", + "table-layout": "^4.1.1", + "typical": "^7.3.0" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2575,6 +3244,15 @@ "node": ">=0.10.0" } }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2627,6 +3305,23 @@ "node": ">=16.0.0" } }, + "node_modules/find-replace": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-5.0.2.tgz", + "integrity": "sha512-Y45BAiE3mz2QsrN2fb5QEtO4qb44NcS7en/0y9PEVsg351HsLeVclP8QPMH79Le9sH3rs5RSwJu99W0WPZO43Q==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@75lb/nature": "latest" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -2658,6 +3353,12 @@ "node": ">=16" } }, + "node_modules/flatbuffers": { + "version": "25.9.23", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.9.23.tgz", + "integrity": "sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==", + "license": "Apache-2.0" + }, "node_modules/flatted": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", @@ -2760,7 +3461,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2909,6 +3609,14 @@ "node": ">=6" } }, + "node_modules/json-bignum": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/json-bignum/-/json-bignum-0.0.3.tgz", + "integrity": "sha512-2WHyXj3OfHSgNyuzDbSxI1w2jgw5gkWSWhS7Qg4bWXx1nLk3jnbwfUeS0PSba3IzpTUWdHxBieELUzXRjQB2zg==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -3001,6 +3709,12 @@ "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", "license": "MIT" }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -3076,6 +3790,15 @@ "dev": true, "license": "MIT" }, + "node_modules/node-addon-api": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.8.0.tgz", + "integrity": "sha512-c5Ko1fZJIJmzhFIkhRN76WTq+fC6tWnGy9CXA0fA+XygsWZmEwG8vmbkNqxMyoaa0Tin4djul49NzdVcJJcjeA==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, "node_modules/node-releases": { "version": "2.0.27", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", @@ -3455,6 +4178,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/table-layout": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-4.1.1.tgz", + "integrity": "sha512-iK5/YhZxq5GO5z8wb0bY1317uDF3Zjpha0QFFLA8/trAoiLbQD0HUbMesEaxyzUgDxi2QlcbM8IvqOlEjgoXBA==", + "license": "MIT", + "dependencies": { + "array-back": "^6.2.2", + "wordwrapjs": "^5.1.0" + }, + "engines": { + "node": ">=12.17" + } + }, "node_modules/tinycolor2": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", @@ -3491,6 +4227,12 @@ "typescript": ">=4.8.4" } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -3542,11 +4284,19 @@ "typescript": ">=4.8.4 <6.0.0" } }, + "node_modules/typical": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-7.3.0.tgz", + "integrity": "sha512-ya4mg/30vm+DOWfBg4YK3j2WD6TWtRkCbasOJr40CseYENzCUby/7rIvXA99JGsQHeNxLbnXdyLLxKSv3tauFw==", + "license": "MIT", + "engines": { + "node": ">=12.17" + } + }, "node_modules/undici-types": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true, "license": "MIT" }, "node_modules/update-browserslist-db": { @@ -3691,6 +4441,15 @@ "node": ">=0.10.0" } }, + "node_modules/wordwrapjs": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-5.1.1.tgz", + "integrity": "sha512-0yweIbkINJodk27gX9LBGMzyQdBDan3s/dEAiwBOj+Mf0PPyWL6/rikalkv8EeD0E8jm4o5RXEOrFTP3NXbhJg==", + "license": "MIT", + "engines": { + "node": ">=12.17" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", From 29871baaf1b4f2b9a2b1765b23a047adf53c5d92 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 23 May 2026 17:04:31 -0700 Subject: [PATCH 11/20] Show sigma edge labels on hover --- src/App.tsx | 23 ++++++++++++++++++++--- src/vendor/sigma-runtime.d.ts | 5 +++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index f3f551e..8762947 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -87,8 +87,10 @@ interface SigmaLabelData { } interface SigmaEdgeLabelData { + key?: string label?: string size: number + forceLabel?: boolean } interface SigmaEdgeLabelNodeData { @@ -308,9 +310,11 @@ function drawSigmaEdgeLabel( edgeData: SigmaEdgeLabelData, sourceData: SigmaEdgeLabelNodeData, targetData: SigmaEdgeLabelNodeData, + hoveredEdgeId: string | null, textColor: string, backgroundColor: string, ) { + if (edgeData.key !== hoveredEdgeId) return if (!edgeData.label) return const dx = targetData.x - sourceData.x @@ -390,6 +394,7 @@ function createInitialLayout(graphData: NormalizedGraphData) { function SigmaGraphView({ graphData, labelNodeIds, newlyExpandedNodeIds, darkMode, getNodeColor, getEdgeColor, onNodeClick }: SigmaGraphViewProps) { const containerRef = useRef(null) const rendererRef = useRef(null) + const hoveredEdgeRef = useRef(null) const graph = useMemo(() => { const { degrees, positions } = createInitialLayout(graphData) @@ -417,11 +422,13 @@ function SigmaGraphView({ graphData, labelNodeIds, newlyExpandedNodeIds, darkMod const pairKey = `${link.source}->${link.target}` const pairIndex = edgeCounts.get(pairKey) || 0 edgeCounts.set(pairKey, pairIndex + 1) - sigmaGraph.addEdge(`${pairKey}#${pairIndex}-${index}`, link.source, link.target, { + const edgeKey = `${pairKey}#${pairIndex}-${index}` + const edgeLabel = link.label === 'more' ? '' : link.label || '' + sigmaGraph.addEdge(edgeKey, link.source, link.target, { size: 1.8, color: getEdgeColor(link.label || 'edge'), - label: link.label || '', - forceLabel: Boolean(link.label), + label: edgeLabel, + forceLabel: Boolean(edgeLabel), }) }) @@ -445,6 +452,7 @@ function SigmaGraphView({ graphData, labelNodeIds, newlyExpandedNodeIds, darkMod rendererRef.current = new Sigma(graph, container, { allowInvalidContainer: true, defaultEdgeType: 'arrow', + enableEdgeEvents: true, labelColor: { color: labelTextColor }, renderEdgeLabels: true, edgeLabelColor: { color: edgeLabelTextColor }, @@ -459,6 +467,7 @@ function SigmaGraphView({ graphData, labelNodeIds, newlyExpandedNodeIds, darkMod edgeData, sourceData, targetData, + hoveredEdgeRef.current, edgeLabelTextColor, edgeLabelBackgroundColor, ) @@ -486,6 +495,14 @@ function SigmaGraphView({ graphData, labelNodeIds, newlyExpandedNodeIds, darkMod rendererRef.current.on('clickNode', ({ node }: { node: string }) => { onNodeClick(node) }) + rendererRef.current.on('enterEdge', ({ edge }: { edge: string }) => { + hoveredEdgeRef.current = edge + rendererRef.current?.refresh() + }) + rendererRef.current.on('leaveEdge', () => { + hoveredEdgeRef.current = null + rendererRef.current?.refresh() + }) rendererRef.current.refresh() diff --git a/src/vendor/sigma-runtime.d.ts b/src/vendor/sigma-runtime.d.ts index ffae679..c528130 100644 --- a/src/vendor/sigma-runtime.d.ts +++ b/src/vendor/sigma-runtime.d.ts @@ -1,6 +1,7 @@ export interface SigmaSettings { allowInvalidContainer?: boolean defaultEdgeType?: string + enableEdgeEvents?: boolean labelColor?: { color: string } | { attribute: string; color?: string } renderEdgeLabels?: boolean edgeLabelColor?: { color: string } | { attribute: string; color?: string } @@ -20,8 +21,10 @@ export interface SigmaSettings { } export interface SigmaEdgeLabelData { + key?: string label?: string size: number + forceLabel?: boolean } export interface SigmaEdgeLabelNodeData { @@ -43,6 +46,8 @@ export interface SigmaLabelData { export class Sigma { constructor(graph: unknown, container: HTMLElement, settings?: SigmaSettings) on(event: 'clickNode', callback: (payload: { node: string }) => void): void + on(event: 'enterEdge', callback: (payload: { edge: string }) => void): void + on(event: 'leaveEdge', callback: (payload: { edge: string }) => void): void refresh(): void kill(): void } From 7bbc9fad93e87bc67b097a4398bf3a1e7f986dd9 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 23 May 2026 17:05:58 -0700 Subject: [PATCH 12/20] Use Node 24 in CI --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a6d15a1..e39f9a3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,7 +28,7 @@ jobs: - name: Install Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 cache: 'npm' - name: Install dependencies @@ -72,7 +72,7 @@ jobs: - name: Install Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 cache: 'npm' - name: Install Rust stable From 32dc3370fa0f67be3ce69d153baaafe30bb3f707 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 23 May 2026 18:49:41 -0700 Subject: [PATCH 13/20] Use latest ladybug artifacts --- .github/workflows/build.yml | 54 ++ src-tauri/Cargo.lock | 1353 +++++++++++++++-------------------- src-tauri/Cargo.toml | 2 +- 3 files changed, 623 insertions(+), 786 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e39f9a3..8ba4e43 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,6 +8,10 @@ on: branches: [main] workflow_dispatch: +permissions: + actions: read + contents: read + concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true @@ -62,6 +66,13 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 + - name: Checkout ladybug + uses: actions/checkout@v4 + with: + repository: LadybugDB/ladybug + fetch-depth: 1 + path: ladybug + - name: Checkout Sigma uses: actions/checkout@v4 with: @@ -98,7 +109,49 @@ jobs: - name: Enable pnpm run: corepack enable + - name: Resolve compatible lbug artifact run + working-directory: ladybug + shell: bash + env: + GITHUB_TOKEN: ${{ github.token }} + run: | + SHA="$(git rev-parse HEAD)" + API_URL="https://api.github.com/repos/LadybugDB/ladybug/actions/workflows/build-and-deploy.yml/runs" + AUTH_HEADER="Authorization: Bearer $GITHUB_TOKEN" + ACCEPT_HEADER="Accept: application/vnd.github+json" + VERSION_HEADER="X-GitHub-Api-Version: 2022-11-28" + + RUN_ID="$( + curl -fsSL \ + -H "$AUTH_HEADER" \ + -H "$ACCEPT_HEADER" \ + -H "$VERSION_HEADER" \ + "$API_URL?head_sha=$SHA&status=success&per_page=1" \ + | python -c 'import json,sys; data=json.load(sys.stdin); runs=data.get("workflow_runs") or []; print(runs[0]["id"] if runs else "")' + )" + + if [ -z "$RUN_ID" ]; then + RUN_ID="$( + curl -fsSL \ + -H "$AUTH_HEADER" \ + -H "$ACCEPT_HEADER" \ + -H "$VERSION_HEADER" \ + "$API_URL?branch=main&status=success&per_page=1" \ + | python -c 'import json,sys; data=json.load(sys.stdin); runs=data.get("workflow_runs") or []; print(runs[0]["id"] if runs else "")' + )" + fi + + if [ -z "$RUN_ID" ]; then + echo "Could not find a successful LadybugDB/ladybug build-and-deploy run." >&2 + exit 1 + fi + + echo "Using Ladybug build-and-deploy RUN_ID=$RUN_ID for SHA=$SHA" + echo "LBUG_PRECOMPILED_RUN_ID=$RUN_ID" >> "$GITHUB_ENV" + - name: Download liblbug + env: + GH_TOKEN: ${{ github.token }} run: bash scripts/download-liblbug.sh - name: Build Tauri app (Linux) @@ -131,6 +184,7 @@ jobs: if: startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest permissions: + actions: read contents: write steps: diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 65db55a..b9878bb 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -43,9 +43,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anyhow" @@ -90,9 +90,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "base64" @@ -106,6 +106,21 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + [[package]] name = "bitflags" version = "1.3.2" @@ -114,9 +129,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" dependencies = [ "serde_core", ] @@ -160,6 +175,15 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + [[package]] name = "bugscope" version = "0.15.1" @@ -175,9 +199,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.20.2" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "bytemuck" @@ -206,7 +230,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "cairo-sys-rs", "glib", "libc", @@ -269,9 +293,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.56" +version = "1.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" dependencies = [ "find-msvc-tools", "shlex", @@ -324,18 +348,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.60" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.60" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstyle", "clap_lex", @@ -344,15 +368,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "cmake" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" dependencies = [ "cc", ] @@ -377,12 +401,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - [[package]] name = "cookie" version = "0.18.1" @@ -411,11 +429,11 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-graphics" -version = "0.24.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" +checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "core-foundation", "core-graphics-types", "foreign-types", @@ -428,7 +446,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "core-foundation", "libc", ] @@ -478,19 +496,15 @@ dependencies = [ [[package]] name = "cssparser" -version = "0.29.6" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa" +checksum = "dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2" dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "matches", - "phf 0.10.1", - "proc-macro2", - "quote", + "phf", "smallvec", - "syn 1.0.109", ] [[package]] @@ -505,14 +519,20 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.9" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" +checksum = "352d39c2f7bef1d6ad73db6f5160efcaed66d94ef8c6c573a8410c00bf909a98" dependencies = [ - "quote", - "syn 2.0.117", + "ctor-proc-macro", + "dtor", ] +[[package]] +name = "ctor-proc-macro" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" + [[package]] name = "cxx" version = "1.0.138" @@ -523,7 +543,7 @@ dependencies = [ "cxxbridge-cmd", "cxxbridge-flags", "cxxbridge-macro", - "foldhash", + "foldhash 0.1.5", "link-cplusplus", ] @@ -574,9 +594,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" dependencies = [ "darling_core", "darling_macro", @@ -584,11 +604,10 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" dependencies = [ - "fnv", "ident_case", "proc-macro2", "quote", @@ -598,32 +617,51 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.21.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core", "quote", "syn 2.0.117", ] +[[package]] +name = "dbus" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b942602992bb7acfd1f51c49811c58a610ef9181b6e66f3e519d79b540a3bf73" +dependencies = [ + "libc", + "libdbus-sys", + "windows-sys 0.61.2", +] + [[package]] name = "deranged" -version = "0.3.11" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", - "serde", + "serde_core", ] [[package]] name = "derive_more" -version = "0.99.20" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ - "convert_case", "proc-macro2", "quote", "rustc_version", @@ -682,19 +720,15 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - [[package]] name = "dispatch2" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", + "block2", + "libc", "objc2", ] @@ -732,6 +766,21 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "dom_query" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521e380c0c8afb8d9a1e83a1822ee03556fc3e3e7dbc1fd30be14e37f9cb3f89" +dependencies = [ + "bit-set", + "cssparser", + "foldhash 0.2.0", + "html5ever", + "precomputed-hash", + "selectors", + "tendril", +] + [[package]] name = "dpi" version = "0.1.2" @@ -756,6 +805,21 @@ dependencies = [ "dtoa", ] +[[package]] +name = "dtor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1057d6c64987086ff8ed0fd3fbf377a6b7d205cc7715868cd401705f715cbe4" +dependencies = [ + "dtor-proc-macro", +] + +[[package]] +name = "dtor-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" + [[package]] name = "dunce" version = "1.0.5" @@ -770,14 +834,14 @@ checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "embed-resource" -version = "3.0.6" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55a075fc573c64510038d7ee9abc7990635863992f83ebc52c8b433b8411a02e" +checksum = "c31a88c8d26de40ed18fe748c547845aa39de1db3afd958f8cb91579f3644bcb" dependencies = [ "cc", "memchr", "rustc_version", - "toml 0.9.12+spec-1.1.0", + "toml 1.1.2+spec-1.1.0", "vswhom", "winreg", ] @@ -796,15 +860,21 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "erased-serde" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e8918065695684b2b0702da20382d5ae6065cf3327bc2d6436bd49a71ce9f3" +checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" dependencies = [ "serde", "serde_core", "typeid", ] +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + [[package]] name = "fdeflate" version = "0.3.7" @@ -852,6 +922,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "foreign-types" version = "0.5.0" @@ -888,16 +964,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "futf" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" -dependencies = [ - "mac", - "new_debug_unreachable", -] - [[package]] name = "futures-channel" version = "0.3.32" @@ -969,15 +1035,6 @@ dependencies = [ "slab", ] -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - [[package]] name = "gdk" version = "0.18.2" @@ -1087,17 +1144,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.17" @@ -1106,7 +1152,7 @@ checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -1117,19 +1163,19 @@ checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", ] [[package]] name = "getrandom" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 6.0.0", "wasip2", "wasip3", ] @@ -1172,7 +1218,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "futures-channel", "futures-core", "futures-executor", @@ -1294,14 +1340,14 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "foldhash", + "foldhash 0.1.5", ] [[package]] name = "hashbrown" -version = "0.16.1" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "heck" @@ -1323,14 +1369,12 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "html5ever" -version = "0.29.1" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c" +checksum = "1054432bae2f14e0061e33d23402fbaa67a921d319d56adc6bcf887ddad1cbc2" dependencies = [ "log", - "mac", "markup5ever", - "match_token", ] [[package]] @@ -1374,9 +1418,9 @@ checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "hyper" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" dependencies = [ "atomic-waker", "bytes", @@ -1387,7 +1431,6 @@ dependencies = [ "httparse", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -1447,17 +1490,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e795dff5605e0f04bff85ca41b51a96b83e80b281e96231bcaaf1ac35103371" dependencies = [ "byteorder", - "png", + "png 0.17.16", ] [[package]] name = "icu_collections" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", + "utf8_iter", "yoke", "zerofrom", "zerovec", @@ -1465,9 +1509,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -1478,9 +1522,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -1492,15 +1536,15 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ "icu_collections", "icu_locale_core", @@ -1512,15 +1556,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", @@ -1556,9 +1600,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ "icu_normalizer", "icu_properties", @@ -1577,12 +1621,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.1", "serde", "serde_core", ] @@ -1598,25 +1642,15 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "iri-string" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" -dependencies = [ - "memchr", - "serde", -] +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "javascriptcore-rs" @@ -1650,7 +1684,7 @@ dependencies = [ "cesu8", "cfg-if", "combine", - "jni-sys", + "jni-sys 0.3.1", "log", "thiserror 1.0.69", "walkdir", @@ -1659,16 +1693,40 @@ dependencies = [ [[package]] name = "jni-sys" -version = "0.3.0" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.117", +] [[package]] name = "js-sys" -version = "0.3.90" +version = "0.3.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dc6f6450b3f6d4ed5b16327f38fed626d375a886159ca555bd7822c0c3a5a6" +checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" dependencies = [ + "cfg-if", + "futures-util", "once_cell", "wasm-bindgen", ] @@ -1701,40 +1759,22 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "serde", "unicode-segmentation", ] -[[package]] -name = "kuchikiki" -version = "0.8.8-speedreader" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02cb977175687f33fa4afa0c95c112b987ea1443e5a51c8f8ff27dc618270cc2" -dependencies = [ - "cssparser", - "html5ever", - "indexmap 2.13.0", - "selectors", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - [[package]] name = "lbug" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28fde1b078a1ca4c30926a396f43c092fb2e11e74b3542c66ef9287922331a7a" +version = "0.17.0" +source = "git+https://github.com/LadybugDB/ladybug-rust#fcf1f94b10dffb4e0d11aa0b4822f3a85721abb1" dependencies = [ "cmake", "cxx", "cxx-build", "rust_decimal", "rustversion", + "serde_json", "time", "uuid", ] @@ -1771,9 +1811,18 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.182" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libdbus-sys" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "328c4789d42200f1eeec05bd86c9c13c7f091d2ba9a6ea35acdf51f31bc0f043" +dependencies = [ + "pkg-config", +] [[package]] name = "libloading" @@ -1787,11 +1836,10 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.12" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" dependencies = [ - "bitflags 2.11.0", "libc", ] @@ -1806,9 +1854,9 @@ dependencies = [ [[package]] name = "litemap" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "lock_api" @@ -1825,43 +1873,17 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" -[[package]] -name = "mac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" - [[package]] name = "markup5ever" -version = "0.14.1" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18" +checksum = "8983d30f2915feeaaab2d6babdd6bc7e9ed1a00b66b5e6d74df19aa9c0e91862" dependencies = [ "log", - "phf 0.11.3", - "phf_codegen 0.11.3", - "string_cache", - "string_cache_codegen", "tendril", + "web_atoms", ] -[[package]] -name = "match_token" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - [[package]] name = "memchr" version = "2.8.0" @@ -1895,20 +1917,20 @@ dependencies = [ [[package]] name = "mio" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "windows-sys 0.61.2", ] [[package]] name = "muda" -version = "0.17.1" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01c1738382f66ed56b3b9c8119e794a2e23148ac8ea214eda86622d4cb9d415a" +checksum = "47a2e3dff89cd322c66647942668faee0a2b1f88ea6cbb4d374b4a8d7e92528c" dependencies = [ "crossbeam-channel", "dpi", @@ -1919,10 +1941,10 @@ dependencies = [ "objc2-core-foundation", "objc2-foundation", "once_cell", - "png", + "png 0.18.1", "serde", "thiserror 2.0.18", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -1931,8 +1953,8 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.11.0", - "jni-sys", + "bitflags 2.11.1", + "jni-sys 0.3.1", "log", "ndk-sys", "num_enum", @@ -1940,19 +1962,13 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - [[package]] name = "ndk-sys" version = "0.6.0+11769913" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" dependencies = [ - "jni-sys", + "jni-sys 0.3.1", ] [[package]] @@ -1961,17 +1977,11 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-traits" @@ -1984,9 +1994,9 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" dependencies = [ "num_enum_derive", "rustversion", @@ -1994,11 +2004,11 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ - "proc-macro-crate 3.4.0", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", "syn 2.0.117", @@ -2006,9 +2016,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" dependencies = [ "objc2-encode", "objc2-exception-helper", @@ -2020,19 +2030,11 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "block2", - "libc", "objc2", - "objc2-cloud-kit", - "objc2-core-data", "objc2-core-foundation", - "objc2-core-graphics", - "objc2-core-image", - "objc2-core-text", - "objc2-core-video", "objc2-foundation", - "objc2-quartz-core", ] [[package]] @@ -2041,7 +2043,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "objc2", "objc2-foundation", ] @@ -2052,7 +2054,6 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" dependencies = [ - "bitflags 2.11.0", "objc2", "objc2-foundation", ] @@ -2063,7 +2064,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "dispatch2", "objc2", ] @@ -2074,7 +2075,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "dispatch2", "objc2", "objc2-core-foundation", @@ -2092,28 +2093,25 @@ dependencies = [ ] [[package]] -name = "objc2-core-text" +name = "objc2-core-location" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" +checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009" dependencies = [ - "bitflags 2.11.0", "objc2", - "objc2-core-foundation", - "objc2-core-graphics", + "objc2-foundation", ] [[package]] -name = "objc2-core-video" +name = "objc2-core-text" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" +checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "objc2", "objc2-core-foundation", "objc2-core-graphics", - "objc2-io-surface", ] [[package]] @@ -2137,9 +2135,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "block2", - "libc", "objc2", "objc2-core-foundation", ] @@ -2150,17 +2147,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags 2.11.0", - "objc2", - "objc2-core-foundation", -] - -[[package]] -name = "objc2-javascript-core" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a1e6550c4caed348956ce3370c9ffeca70bb1dbed4fa96112e7c6170e074586" -dependencies = [ + "bitflags 2.11.1", "objc2", "objc2-core-foundation", ] @@ -2171,32 +2158,40 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "objc2", "objc2-core-foundation", "objc2-foundation", ] [[package]] -name = "objc2-security" +name = "objc2-ui-kit" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", + "block2", "objc2", + "objc2-cloud-kit", + "objc2-core-data", "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image", + "objc2-core-location", + "objc2-core-text", + "objc2-foundation", + "objc2-quartz-core", + "objc2-user-notifications", ] [[package]] -name = "objc2-ui-kit" +name = "objc2-user-notifications" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" +checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e" dependencies = [ - "bitflags 2.11.0", "objc2", - "objc2-core-foundation", "objc2-foundation", ] @@ -2206,21 +2201,19 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "block2", "objc2", "objc2-app-kit", "objc2-core-foundation", "objc2-foundation", - "objc2-javascript-core", - "objc2-security", ] [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "option-ext" @@ -2284,164 +2277,77 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "phf" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" -dependencies = [ - "phf_shared 0.8.0", -] - -[[package]] -name = "phf" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" -dependencies = [ - "phf_macros 0.10.0", - "phf_shared 0.10.0", - "proc-macro-hack", -] - -[[package]] -name = "phf" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" -dependencies = [ - "phf_macros 0.11.3", - "phf_shared 0.11.3", -] - -[[package]] -name = "phf_codegen" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" -dependencies = [ - "phf_generator 0.8.0", - "phf_shared 0.8.0", -] - -[[package]] -name = "phf_codegen" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" -dependencies = [ - "phf_generator 0.11.3", - "phf_shared 0.11.3", -] - -[[package]] -name = "phf_generator" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" -dependencies = [ - "phf_shared 0.8.0", - "rand 0.7.3", -] - -[[package]] -name = "phf_generator" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" -dependencies = [ - "phf_shared 0.10.0", - "rand 0.8.5", -] - -[[package]] -name = "phf_generator" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" dependencies = [ - "phf_shared 0.11.3", - "rand 0.8.5", -] - -[[package]] -name = "phf_macros" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" -dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn 1.0.109", + "phf_macros", + "phf_shared", + "serde", ] [[package]] -name = "phf_macros" -version = "0.11.3" +name = "phf_codegen" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1" dependencies = [ - "phf_generator 0.11.3", - "phf_shared 0.11.3", - "proc-macro2", - "quote", - "syn 2.0.117", + "phf_generator", + "phf_shared", ] [[package]] -name = "phf_shared" -version = "0.8.0" +name = "phf_generator" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" dependencies = [ - "siphasher 0.3.11", + "fastrand", + "phf_shared", ] [[package]] -name = "phf_shared" -version = "0.10.0" +name = "phf_macros" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" dependencies = [ - "siphasher 0.3.11", + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] name = "phf_shared" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" dependencies = [ - "siphasher 1.0.2", + "siphasher", ] [[package]] name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "plist" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" +checksum = "092791278e026273c1b65bbdcfbba3a300f2994c896bd01ab01da613c29c46f1" dependencies = [ "base64 0.22.1", - "indexmap 2.13.0", + "indexmap 2.14.0", "quick-xml", "serde", "time", @@ -2460,11 +2366,24 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.11.1", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + [[package]] name = "potential_utf" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -2475,15 +2394,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - [[package]] name = "precomputed-hash" version = "0.1.1" @@ -2522,11 +2432,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.23.10+spec-1.0.0", + "toml_edit 0.25.11+spec-1.1.0", ] [[package]] @@ -2553,12 +2463,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - [[package]] name = "proc-macro2" version = "1.0.106" @@ -2570,18 +2474,18 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.38.4" +version = "0.39.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" +checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -2593,85 +2497,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", - "rand_pcg", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.17", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_pcg" -version = "0.2.1" +name = "r-efi" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" -dependencies = [ - "rand_core 0.5.1", -] +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "raw-window-handle" @@ -2685,7 +2514,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", ] [[package]] @@ -2761,9 +2590,9 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" dependencies = [ "base64 0.22.1", "bytes", @@ -2795,14 +2624,20 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.40.0" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61f703d19852dbf87cbc513643fa81428361eb6940f1ac14fd58155d295a3eb0" +checksum = "0c5108e3d4d903e21aac27f12ba5377b6b34f9f44b325e4894c7924169d06995" dependencies = [ "arrayvec", "num-traits", ] +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + [[package]] name = "rustc_version" version = "0.4.1" @@ -2892,27 +2727,28 @@ checksum = "d68f2ec51b097e4c1a75b681a8bec621909b5e91f15bb7b840c4f2f7b01148b2" [[package]] name = "selectors" -version = "0.24.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c37578180969d00692904465fb7f6b3d50b9a2b952b87c23d0e2e5cb5013416" +checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.11.1", "cssparser", "derive_more", - "fxhash", "log", - "phf 0.8.0", - "phf_codegen 0.8.0", + "new_debug_unreachable", + "phf", + "phf_codegen", "precomputed-hash", + "rustc-hash", "servo_arc", "smallvec", ] [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" dependencies = [ "serde", "serde_core", @@ -2973,9 +2809,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ "itoa", "memchr", @@ -3006,24 +2842,25 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.4" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ "serde_core", ] [[package]] name = "serde_with" -version = "3.17.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "381b283ce7bc6b476d903296fb59d0d36633652b633b27f64db4fb46dcbfc3b9" +checksum = "e72c1c2cb7b223fafb600a619537a871c2818583d619401b785e7c0b746ccde2" dependencies = [ "base64 0.22.1", + "bs58", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.13.0", + "indexmap 2.14.0", "schemars 0.9.0", "schemars 1.2.1", "serde_core", @@ -3034,9 +2871,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.17.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6d4e30573c8cb306ed6ab1dca8423eec9a463ea0e155f45399455e0368b27e0" +checksum = "b90c488738ecb4fb0262f41f43bc40efc5868d9fb744319ddf5f5317f417bfac" dependencies = [ "darling", "proc-macro2", @@ -3068,11 +2905,10 @@ dependencies = [ [[package]] name = "servo_arc" -version = "0.2.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52aa42f8fdf0fed91e5ce7f23d8138441002fa31dca008acf47e6fd4721f741" +checksum = "170fb83ab34de17dc69aa7c67482b22218ddb85da56546f9bd6b929e32a05930" dependencies = [ - "nodrop", "stable_deref_trait", ] @@ -3095,21 +2931,15 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "simd-adler32" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" - -[[package]] -name = "siphasher" -version = "0.3.11" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] name = "siphasher" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" [[package]] name = "slab" @@ -3125,12 +2955,12 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -3189,25 +3019,24 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "string_cache" -version = "0.8.9" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" +checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901" dependencies = [ "new_debug_unreachable", "parking_lot", - "phf_shared 0.11.3", + "phf_shared", "precomputed-hash", - "serde", ] [[package]] name = "string_cache_codegen" -version = "0.5.4" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" +checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69" dependencies = [ - "phf_generator 0.11.3", - "phf_shared 0.11.3", + "phf_generator", + "phf_shared", "proc-macro2", "quote", ] @@ -3236,7 +3065,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", - "quote", "unicode-ident", ] @@ -3286,35 +3114,35 @@ dependencies = [ [[package]] name = "tao" -version = "0.34.5" +version = "0.35.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a753bdc39c07b192151523a3f77cd0394aa75413802c883a0f6f6a0e5ee2e7" +checksum = "d1c93047acf68669466a34690ac58cca7010bd1b201e1ec86f1fd0a75d3dd4a9" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "block2", "core-foundation", "core-graphics", "crossbeam-channel", - "dispatch", + "dbus", + "dispatch2", "dlopen2", "dpi", "gdkwayland-sys", "gdkx11-sys", "gtk", "jni", - "lazy_static", "libc", "log", "ndk", - "ndk-context", "ndk-sys", "objc2", "objc2-app-kit", "objc2-foundation", + "objc2-ui-kit", "once_cell", "parking_lot", + "percent-encoding", "raw-window-handle", - "scopeguard", "tao-macros", "unicode-segmentation", "url", @@ -3343,9 +3171,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.10.2" +version = "2.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463ae8677aa6d0f063a900b9c41ecd4ac2b7ca82f0b058cc4491540e55b20129" +checksum = "437404997acf375d85f1177afa7e11bb971f274ed6a7b83a2a3e339015f4cc28" dependencies = [ "anyhow", "bytes", @@ -3394,9 +3222,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.5.5" +version = "2.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca7bd893329425df750813e95bd2b643d5369d929438da96d5bbb7cc2c918f74" +checksum = "4aa1f9055fc23919a54e4e125052bed16ed04aef0487086e758fe01a67b451c7" dependencies = [ "anyhow", "cargo_toml", @@ -3410,22 +3238,21 @@ dependencies = [ "serde_json", "tauri-utils", "tauri-winres", - "toml 0.9.12+spec-1.1.0", "walkdir", ] [[package]] name = "tauri-codegen" -version = "2.5.4" +version = "2.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac423e5859d9f9ccdd32e3cf6a5866a15bedbf25aa6630bcb2acde9468f6ae3" +checksum = "e4a0319528a025a38c4078e7dae2c446f4e63620ddb0659a643ede1cb38f90e9" dependencies = [ "base64 0.22.1", "brotli", "ico", "json-patch", "plist", - "png", + "png 0.17.16", "proc-macro2", "quote", "semver", @@ -3443,9 +3270,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.5.4" +version = "2.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6a1bd2861ff0c8766b1d38b32a6a410f6dc6532d4ef534c47cfb2236092f59" +checksum = "ae6cb4e3896c21d2f6da5b31251d2faea0153bba56ed0e970f918115dbee4924" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -3457,9 +3284,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.10.0" +version = "2.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b885ffeac82b00f1f6fd292b6e5aabfa7435d537cef57d11e38a489956535651" +checksum = "48222d7116c8807eaa6fe2f372e023fae125084e61e6eca6d70b7961cdf129ef" dependencies = [ "cookie", "dpi", @@ -3482,9 +3309,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.10.0" +version = "2.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5204682391625e867d16584fedc83fc292fb998814c9f7918605c789cd876314" +checksum = "b83849ee63ecb27a8e8d0fe51915ca215076914aca43f96db1179f0f415f6cd9" dependencies = [ "gtk", "http", @@ -3492,7 +3319,6 @@ dependencies = [ "log", "objc2", "objc2-app-kit", - "objc2-foundation", "once_cell", "percent-encoding", "raw-window-handle", @@ -3509,24 +3335,24 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.8.2" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcd169fccdff05eff2c1033210b9b94acd07a47e6fa9a3431cf09cfd4f01c87e" +checksum = "092379df9a707631978e6c56b1bc2401d387f01e2d4a3c123360d167bbb9aa95" dependencies = [ "anyhow", "brotli", "cargo_metadata", "ctor", + "dom_query", "dunce", "glob", - "html5ever", "http", "infer", "json-patch", - "kuchikiki", "log", "memchr", - "phf 0.11.3", + "phf", + "plist", "proc-macro2", "quote", "regex", @@ -3538,7 +3364,7 @@ dependencies = [ "serde_with", "swift-rs", "thiserror 2.0.18", - "toml 0.9.12+spec-1.1.0", + "toml 1.1.2+spec-1.1.0", "url", "urlpattern", "uuid", @@ -3547,23 +3373,22 @@ dependencies = [ [[package]] name = "tauri-winres" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1087b111fe2b005e42dbdc1990fc18593234238d47453b0c99b7de1c9ab2c1e0" +checksum = "cc65d45c68858bfe420dd29e834b5d15dbecf8a07a8a16cf4d532c7b1f69d4b6" dependencies = [ "dunce", "embed-resource", - "toml 0.9.12+spec-1.1.0", + "toml 1.1.2+spec-1.1.0", ] [[package]] name = "tendril" -version = "0.4.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +checksum = "c4790fc369d5a530f4b544b094e31388b9b3a37c0f4652ade4505945f5660d24" dependencies = [ - "futf", - "mac", + "new_debug_unreachable", "utf-8", ] @@ -3618,30 +3443,30 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", "num-conv", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -3649,19 +3474,34 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", ] +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" -version = "1.49.0" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes", "libc", @@ -3702,13 +3542,28 @@ version = "0.9.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ - "indexmap 2.13.0", + "indexmap 2.14.0", "serde_core", - "serde_spanned 1.0.4", + "serde_spanned 1.1.1", "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", - "winnow 0.7.14", + "winnow 0.7.15", +] + +[[package]] +name = "toml" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" +dependencies = [ + "indexmap 2.14.0", + "serde_core", + "serde_spanned 1.1.1", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 1.0.3", ] [[package]] @@ -3729,13 +3584,22 @@ dependencies = [ "serde_core", ] +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.13.0", + "indexmap 2.14.0", "toml_datetime 0.6.3", "winnow 0.5.40", ] @@ -3746,7 +3610,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ - "indexmap 2.13.0", + "indexmap 2.14.0", "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.3", @@ -3755,30 +3619,30 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.23.10+spec-1.0.0" +version = "0.25.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" dependencies = [ - "indexmap 2.13.0", - "toml_datetime 0.7.5+spec-1.1.0", + "indexmap 2.14.0", + "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow 0.7.14", + "winnow 1.0.3", ] [[package]] name = "toml_parser" -version = "1.0.9+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 0.7.14", + "winnow 1.0.3", ] [[package]] name = "toml_writer" -version = "1.0.6+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "tower" @@ -3797,20 +3661,20 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "bytes", "futures-util", "http", "http-body", - "iri-string", "pin-project-lite", "tower", "tower-layer", "tower-service", + "url", ] [[package]] @@ -3846,9 +3710,9 @@ dependencies = [ [[package]] name = "tray-icon" -version = "0.21.3" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e85aa143ceb072062fc4d6356c1b520a51d636e7bc8e77ec94be3608e5e80c" +checksum = "15edbb0d80583e85ee8df283410038e17314df5cba30da2087a54a85216c0773" dependencies = [ "crossbeam-channel", "dirs 6.0.0", @@ -3860,10 +3724,10 @@ dependencies = [ "objc2-core-graphics", "objc2-foundation", "once_cell", - "png", + "png 0.18.1", "serde", "thiserror 2.0.18", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -3880,9 +3744,9 @@ checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "unic-char-property" @@ -3933,9 +3797,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[package]] name = "unicode-width" @@ -3988,11 +3852,11 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.21.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ - "getrandom 0.4.1", + "getrandom 0.4.2", "js-sys", "serde_core", "wasm-bindgen", @@ -4049,12 +3913,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -4063,11 +3921,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.2+wasi-0.2.9" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", ] [[package]] @@ -4076,14 +3934,14 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.51.0", ] [[package]] name = "wasm-bindgen" -version = "0.2.113" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60722a937f594b7fde9adb894d7c092fc1bb6612897c46368d18e7a20208eff2" +checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" dependencies = [ "cfg-if", "once_cell", @@ -4094,23 +3952,19 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.63" +version = "0.4.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a89f4650b770e4521aa6573724e2aed4704372151bd0de9d16a3bbabb87441a" +checksum = "9473dbd2991ae90b6291c3c32c30c6187ac49aa32f9905d1cce280ec1e110b0f" dependencies = [ - "cfg-if", - "futures-util", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.113" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac8c6395094b6b91c4af293f4c79371c163f9a6f56184d2c9a85f5a95f3950" +checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4118,9 +3972,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.113" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3fabce6159dc20728033842636887e4877688ae94382766e00b180abac9d60" +checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" dependencies = [ "bumpalo", "proc-macro2", @@ -4131,9 +3985,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.113" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de0e091bdb824da87dc01d967388880d017a0a9bc4f3bdc0d86ee9f9336e3bb5" +checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" dependencies = [ "unicode-ident", ] @@ -4155,7 +4009,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" dependencies = [ "anyhow", - "indexmap 2.13.0", + "indexmap 2.14.0", "wasm-encoder", "wasmparser", ] @@ -4179,22 +4033,34 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "hashbrown 0.15.5", - "indexmap 2.13.0", + "indexmap 2.14.0", "semver", ] [[package]] name = "web-sys" -version = "0.3.90" +version = "0.3.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "705eceb4ce901230f8625bd1d665128056ccbe4b7408faa625eec1ba80f59a97" +checksum = "6d621441cfc37b84979402712047321980c178f299193a3589d05b99e8763436" dependencies = [ "js-sys", "wasm-bindgen", ] +[[package]] +name = "web_atoms" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7cff6eef815df1834fd250e3a2ff436044d82a9f1bc1980ca1dbdf07effc538" +dependencies = [ + "phf", + "phf_codegen", + "string_cache", + "string_cache_codegen", +] + [[package]] name = "webkit2gtk" version = "2.0.2" @@ -4487,15 +4353,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", -] - [[package]] name = "windows-sys" version = "0.61.2" @@ -4544,30 +4401,13 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", + "windows_i686_gnullvm", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link 0.2.1", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - [[package]] name = "windows-threading" version = "0.1.0" @@ -4604,12 +4444,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -4628,12 +4462,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -4652,24 +4480,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -4688,12 +4504,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -4712,12 +4522,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -4736,12 +4540,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -4760,12 +4558,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "winnow" version = "0.5.40" @@ -4777,9 +4569,15 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.14" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" + +[[package]] +name = "winnow" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" dependencies = [ "memchr", ] @@ -4803,6 +4601,12 @@ dependencies = [ "wit-bindgen-rust-macro", ] +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + [[package]] name = "wit-bindgen-core" version = "0.51.0" @@ -4822,7 +4626,7 @@ checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" dependencies = [ "anyhow", "heck 0.5.0", - "indexmap 2.13.0", + "indexmap 2.14.0", "prettyplease", "syn 2.0.117", "wasm-metadata", @@ -4852,8 +4656,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags 2.11.0", - "indexmap 2.13.0", + "bitflags 2.11.1", + "indexmap 2.14.0", "log", "serde", "serde_derive", @@ -4872,7 +4676,7 @@ checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ "anyhow", "id-arena", - "indexmap 2.13.0", + "indexmap 2.14.0", "log", "semver", "serde", @@ -4884,30 +4688,29 @@ dependencies = [ [[package]] name = "writeable" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "wry" -version = "0.54.2" +version = "0.55.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb26159b420aa77684589a744ae9a9461a95395b848764ad12290a14d960a11a" +checksum = "186f9871daa55fd9c016578b810d149de58367113db7fb72b462d2323ce19514" dependencies = [ "base64 0.22.1", "block2", "cookie", "crossbeam-channel", "dirs 6.0.0", + "dom_query", "dpi", "dunce", "gdkx11", "gtk", - "html5ever", "http", "javascriptcore-rs", "jni", - "kuchikiki", "libc", "ndk", "objc2", @@ -4956,9 +4759,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -4967,9 +4770,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", @@ -4977,40 +4780,20 @@ dependencies = [ "synstructure", ] -[[package]] -name = "zerocopy" -version = "0.8.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", @@ -5020,9 +4803,9 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -5031,9 +4814,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -5042,9 +4825,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 8916bd1..e99dcca 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -14,6 +14,6 @@ tauri-build = { version = "2", features = [] } tauri = { version = "2", features = [] } serde = { version = "1", features = ["derive"] } serde_json = "1" -lbug = "0.15.1" +lbug = { git = "https://github.com/LadybugDB/ladybug-rust" } walkdir = "2" dirs = "5" From d02940a052f588a2d3b1ccb8dc1045898a9c3ea6 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 23 May 2026 20:59:31 -0700 Subject: [PATCH 14/20] Approve pnpm build scripts --- pnpm-workspace.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index eac80f4..1b105df 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,2 +1,4 @@ onlyBuiltDependencies: + - '@ladybugmem/icebug' + - esbuild - lbug From 726ae821504f47936af4daa882da73f835f8730d Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 23 May 2026 22:05:01 -0700 Subject: [PATCH 15/20] Use pnpm 11 build approvals --- pnpm-workspace.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 1b105df..93c36a1 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,4 +1,4 @@ -onlyBuiltDependencies: - - '@ladybugmem/icebug' - - esbuild - - lbug +allowBuilds: + '@ladybugmem/icebug': true + esbuild: true + lbug: true From a047fe6ba168699aeaf25c883d4d0cfc9d2770f1 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 23 May 2026 22:19:20 -0700 Subject: [PATCH 16/20] Build sigma package in CI --- .github/workflows/build.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8ba4e43..c6b7746 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -106,6 +106,11 @@ jobs: - name: Install frontend dependencies run: npm ci + - name: Build Sigma package + run: | + npm ci --prefix .deps/sigma.js + npm run build --prefix .deps/sigma.js + - name: Enable pnpm run: corepack enable From 26e1afbd5d072dcaa016072f609d8bc7e850a48f Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 23 May 2026 22:31:50 -0700 Subject: [PATCH 17/20] Install liblbug into Tauri path --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c6b7746..8a860fa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -157,6 +157,7 @@ jobs: - name: Download liblbug env: GH_TOKEN: ${{ github.token }} + LBUG_TARGET_DIR: ${{ github.workspace }}/src-tauri/liblbug run: bash scripts/download-liblbug.sh - name: Build Tauri app (Linux) From d37b6701f1ead9e7eea44e9770bc5a8d5d534986 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 23 May 2026 22:32:41 -0700 Subject: [PATCH 18/20] Cache Tauri CLI in CI --- .github/workflows/build.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8a860fa..968b3e1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -89,7 +89,18 @@ jobs: - name: Install Rust stable uses: dtolnay/rust-toolchain@stable + - name: Cache Tauri CLI + id: cache-tauri-cli + uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/cargo-tauri + ~/.cargo/registry + ~/.cargo/git + key: ${{ runner.os }}-${{ matrix.target }}-cargo-tauri-v2-${{ hashFiles('src-tauri/Cargo.lock') }} + - name: Install Tauri CLI (cargo plugin) + if: steps.cache-tauri-cli.outputs.cache-hit != 'true' run: cargo install tauri-cli --locked - name: Install dependencies (macOS) From 0743f3124be975eead9fe7dcede23cb24cc2134d Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sun, 24 May 2026 13:09:20 -0700 Subject: [PATCH 19/20] Update icebug to 12.8 --- package-lock.json | 7 ++++--- package.json | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index c3ec496..8308d5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "bugscope", "version": "0.15.1", "dependencies": { + "@ladybugmem/icebug": "^12.8.0", "@tauri-apps/api": "^2", "react": "^19.2.0", "react-dom": "^19.2.0", @@ -1584,9 +1585,9 @@ } }, "node_modules/@ladybugmem/icebug": { - "version": "12.7.0", - "resolved": "https://registry.npmjs.org/@ladybugmem/icebug/-/icebug-12.7.0.tgz", - "integrity": "sha512-09MSrJi/QtXUHw2wmQYj4+W29d+qj1ZU9g3GuRhkWR7dEooxwkAtosmh8n0vArhusQqy7h3jaHMXMxPlVOdM7Q==", + "version": "12.8.0", + "resolved": "https://registry.npmjs.org/@ladybugmem/icebug/-/icebug-12.8.0.tgz", + "integrity": "sha512-9gAi0d/T5x2EW9e3leJO5A/fDeqHsvw4Z0/Np4q2PVyH662fz2ZqIwtnEjqItoGXAf5o19PaXYB0WzGJ2rCWGQ==", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index b668826..a4229fa 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "preview": "vite preview" }, "dependencies": { + "@ladybugmem/icebug": "^12.8.0", "@tauri-apps/api": "^2", "react": "^19.2.0", "react-dom": "^19.2.0", From 21dcfb68aae9ecf07b6a3418c5d1eaa2dd2b5414 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sun, 24 May 2026 15:44:37 -0700 Subject: [PATCH 20/20] Exclude ladybugmem from minimumReleaseAge policy --- pnpm-workspace.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 93c36a1..c26f5e5 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,3 +2,5 @@ allowBuilds: '@ladybugmem/icebug': true esbuild: true lbug: true +minimumReleaseAgeExclude: + - "@ladybugmem/*"