diff --git a/.bazelrc b/.bazelrc new file mode 100644 index 00000000..4939c9b5 --- /dev/null +++ b/.bazelrc @@ -0,0 +1,56 @@ +# SteleKit .bazelrc +# All Bazel flags for local and CI builds. +# +# Machine-specific overrides (ANDROID_HOME path, extra tool paths, etc.) go in +# .bazelrc.user — that file is gitignored and imported below. Copy +# .bazelrc.user.example to .bazelrc.user and edit for your machine. +try-import %workspace%/.bazelrc.user + +# ── Bazel server JVM heap ───────────────────────────────────────────────────── +# Caps the Bazel server at 6 GB so Maven resolution doesn't OOM the host. +# Coursier's transitive graph for Compose+AndroidX is large; capping forces GC +# before the machine swaps out. Increase to -Xmx8g on 32 GB machines. +startup --host_jvm_args=-Xmx6g + +# ── JVM toolchain ───────────────────────────────────────────────────────────── +build --java_runtime_version=21 +build --tool_java_runtime_version=21 + +# ── Android SDK ─────────────────────────────────────────────────────────────── +# android_sdk_repository_extension runs at repo-loading time (before config +# flags), so ANDROID_HOME must be a global repo_env, not scoped to :android. +# The value is supplied by .bazelrc.user locally and by the CI environment on +# GitHub Actions (android-actions/setup-android sets ANDROID_HOME). +build --repo_env=ANDROID_HOME + +# --android_sdk and the toolchain flag are kept in :android so that JVM-only +# targets (business_tests, desktop_app) do not trigger Android toolchain +# resolution. Pass --config=android when building Android targets. +build:android --android_sdk=@androidsdk//:sdk + +# ── Correctness / hermetic sandbox ──────────────────────────────────────────── +build --sandbox_default_allow_network=false +build --incompatible_strict_action_env + +# ── X11 socket access for Compose Desktop tests ─────────────────────────────── +# Compose Desktop tests require an X display. The Linux sandbox creates a new +# mount namespace and does not include /tmp/.X11-unix by default, so the X11 +# socket (DISPLAY=:N → /tmp/.X11-unix/XN) is inaccessible even when DISPLAY is +# inherited. Mount the X11 socket directory into every test sandbox. +# Locally: use whatever X server is running. +# CI: xvfb-run --auto-servernum creates the socket before bazel runs. +test --sandbox_add_mount_pair=/tmp/.X11-unix + +# ── CI caching ──────────────────────────────────────────────────────────────── +# Bazel caching in CI is handled entirely by bazel-contrib/setup-bazel@0.19.0 +# (disk-cache, repository-cache, external-cache inputs) which uses GitHub Actions +# native cache — no third-party service required. See .github/workflows/bazel-ci.yml. + +# ── Remote HTTP cache (bazel-cache-proxy) ───────────────────────────────────── +# Enable with --config=remote-cache. CI starts bazel-cache-proxy on port 9090 +# backed by the GHA cache API; all jobs on the same PR share the cache. +# PRs write to their own scoped namespace so main's cache is never polluted. +# Local use: start `bazel-cache-proxy serve` with a disk backend, then pass +# --config=remote-cache to any bazel command. +build:remote-cache --remote_cache=http://127.0.0.1:9090 +build:remote-cache --remote_upload_local_results diff --git a/.bazelrc.user.example b/.bazelrc.user.example new file mode 100644 index 00000000..9478046c --- /dev/null +++ b/.bazelrc.user.example @@ -0,0 +1,25 @@ +# Copy this file to .bazelrc.user (gitignored) and edit for your machine. +# .bazelrc.user is imported by .bazelrc via try-import — it is NOT committed. + +# ── Android SDK path ────────────────────────────────────────────────────────── +# build --repo_env=ANDROID_HOME=/home//Android/Sdk # Linux +# build --repo_env=ANDROID_HOME=/Users//Library/Android/sdk # macOS + +# ── Tool PATH (if unzip is outside the hermetic PATH, e.g. Homebrew) ───────── +# build --action_env=PATH=/home/linuxbrew/.linuxbrew/bin:/usr/local/bin:/usr/bin:/bin + +# ── Local disk cache ───────────────────────────────────────────────────────── +# Persists build action results between sessions and workspace switches. +# Dramatically speeds up incremental builds — similar benefit to ccache for C++. +# Grows unboundedly; run `bazel clean --expunge` or delete the dir to reclaim space. +# build --disk_cache=~/.cache/bazel-disk-cache + +# ── Remote cache (optional — for sharing across machines) ──────────────────── +# If you build on multiple machines and want a shared cache, you can point at +# any Bazel-compatible remote cache (BuildBuddy free tier, self-hosted bazel-remote, etc.): +# build --remote_cache=grpcs://remote.buildbuddy.io +# build --remote_header=x-buildbuddy-api-key= +# build --remote_cache_compression=zstd +# +# CI uses GitHub Actions native caching (setup-bazel disk/repo/external-cache) +# so no API key is needed there. diff --git a/.github/workflows/bazel-ci.yml b/.github/workflows/bazel-ci.yml new file mode 100644 index 00000000..e8e46248 --- /dev/null +++ b/.github/workflows/bazel-ci.yml @@ -0,0 +1,262 @@ +name: Bazel CI + +on: + push: + branches: [main] + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + workflow_dispatch: + +permissions: + contents: read + +# Only one CI run per branch at a time; newer push cancels in-progress run. +concurrency: + group: bazel-ci-${{ github.ref }} + cancel-in-progress: true + +jobs: + # ── JVM / Desktop tests ──────────────────────────────────────────────────── + bazel-jvm: + name: Bazel JVM tests + runs-on: ubuntu-latest + timeout-minutes: 30 + if: github.event.pull_request.draft == false + steps: + - uses: actions/checkout@v4 + + - name: Cache bazel-cache-proxy binary + id: bcp-cache + uses: actions/cache@v4 + with: + path: ~/.cargo/bin/bazel-cache-proxy + key: bcp-${{ runner.os }}-7806c5f + + - name: Install bazel-cache-proxy + if: steps.bcp-cache.outputs.cache-hit != 'true' + run: | + sudo apt-get install -y --no-install-recommends protobuf-compiler + cargo install --git https://github.com/tstapler/bazel-cache-proxy --rev 7806c5f bazel-cache-proxy --locked + + - name: Start bazel-cache-proxy (GHA backend) + run: | + printf '[backend]\ntype = "gha"\n' > /tmp/bcp.toml + ~/.cargo/bin/bazel-cache-proxy serve --config /tmp/bcp.toml & + sleep 2 + curl -sf http://127.0.0.1:9090/healthz + + - name: Set up Bazel + uses: bazel-contrib/setup-bazel@0.19.0 + with: + bazelisk-version: "1.x" + # Persistent disk cache for build action results (compiled Kotlin, JARs). + # Keyed per-job so JVM and Android caches don't collide. + disk-cache: jvm + # Shared Maven/artifact download cache across all jobs (keyed by MODULE.bazel). + repository-cache: true + # Cache large individual external repos (Compose Desktop, AndroidX) separately. + external-cache: true + # Only write cache on main-branch pushes; PRs read but don't pollute. + cache-save: ${{ github.event_name != 'pull_request' }} + + - name: Install Xvfb (headless display for Compose Desktop tests) + run: | + sudo apt-get install -y --no-install-recommends xvfb + # Ensure /tmp/.X11-unix exists before Bazel sandbox tries to bind-mount it + # (xvfb-run creates the socket, but Bazel validates the mount source at startup) + mkdir -p /tmp/.X11-unix + + - name: Build JVM target + run: bazel build //kmp:desktop_app --config=remote-cache + + - name: Run JVM tests + run: | + xvfb-run --auto-servernum bazel test //kmp:jvm_tests \ + --config=remote-cache \ + --test_output=all \ + --sandbox_add_mount_pair=/tmp/.X11-unix \ + --test_env=DISPLAY \ + --test_env=XAUTHORITY + + # ── Android build ────────────────────────────────────────────────────────── + bazel-android: + name: Bazel Android build + runs-on: ubuntu-latest + timeout-minutes: 45 + if: github.event.pull_request.draft == false + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK 21 + Android SDK + uses: actions/setup-java@v4 + with: + java-version: "21" + distribution: "temurin" + + - name: Set up Android SDK + uses: android-actions/setup-android@v3 + + - name: Install host tools required by aar_import + run: sudo apt-get install -y --no-install-recommends unzip + + - name: Cache bazel-cache-proxy binary + id: bcp-cache + uses: actions/cache@v4 + with: + path: ~/.cargo/bin/bazel-cache-proxy + key: bcp-${{ runner.os }}-7806c5f + + - name: Install bazel-cache-proxy + if: steps.bcp-cache.outputs.cache-hit != 'true' + run: | + sudo apt-get install -y --no-install-recommends protobuf-compiler + cargo install --git https://github.com/tstapler/bazel-cache-proxy --rev 7806c5f bazel-cache-proxy --locked + + - name: Start bazel-cache-proxy (GHA backend) + run: | + printf '[backend]\ntype = "gha"\n' > /tmp/bcp.toml + ~/.cargo/bin/bazel-cache-proxy serve --config /tmp/bcp.toml & + sleep 2 + curl -sf http://127.0.0.1:9090/healthz + + - name: Set up Bazel + uses: bazel-contrib/setup-bazel@0.19.0 + with: + bazelisk-version: "1.x" + disk-cache: android + repository-cache: true + external-cache: true + cache-save: ${{ github.event_name != 'pull_request' }} + + - name: Build Android APK + run: bazel build //kmp:android_app --config=android --config=remote-cache + + # ── Android unit tests ───────────────────────────────────────────────────── + bazel-android-tests: + name: Bazel Android unit tests + runs-on: ubuntu-latest + timeout-minutes: 30 + if: github.event.pull_request.draft == false + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK 21 + Android SDK + uses: actions/setup-java@v4 + with: + java-version: "21" + distribution: "temurin" + + - name: Set up Android SDK + uses: android-actions/setup-android@v3 + + - name: Install host tools required by aar_import + run: sudo apt-get install -y --no-install-recommends unzip + + - name: Cache bazel-cache-proxy binary + id: bcp-cache + uses: actions/cache@v4 + with: + path: ~/.cargo/bin/bazel-cache-proxy + key: bcp-${{ runner.os }}-7806c5f + + - name: Install bazel-cache-proxy + if: steps.bcp-cache.outputs.cache-hit != 'true' + run: | + sudo apt-get install -y --no-install-recommends protobuf-compiler + cargo install --git https://github.com/tstapler/bazel-cache-proxy --rev 7806c5f bazel-cache-proxy --locked + + - name: Start bazel-cache-proxy (GHA backend) + run: | + printf '[backend]\ntype = "gha"\n' > /tmp/bcp.toml + ~/.cargo/bin/bazel-cache-proxy serve --config /tmp/bcp.toml & + sleep 2 + curl -sf http://127.0.0.1:9090/healthz + + - name: Set up Bazel + uses: bazel-contrib/setup-bazel@0.19.0 + with: + bazelisk-version: "1.x" + disk-cache: android-tests + repository-cache: true + external-cache: true + cache-save: ${{ github.event_name != 'pull_request' }} + + - name: Run Android unit tests + run: | + bazel test //kmp/src/androidUnitTest/kotlin:android_unit_tests \ + --config=android \ + --config=remote-cache \ + --test_output=all \ + --experimental_ui_max_stdouterr_bytes=4194304 + + # ── WASM/JS web build ───────────────────────────────────────────────────── + # rules_kotlin does not yet support Kotlin/WASM natively (rules_kotlin#567). + # //kmp:web_app is a genrule that delegates to Gradle's wasmJsBrowserDistribution. + # Gradle's own incremental cache is preserved via the gradle-home cache key. + bazel-web: + name: Bazel web (WASM/JS via Gradle genrule) + runs-on: ubuntu-latest + timeout-minutes: 30 + if: github.event.pull_request.draft == false + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: "21" + distribution: "temurin" + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Cache Gradle home + uses: actions/cache@v4 + with: + path: ~/.gradle + key: gradle-web-${{ runner.os }}-${{ hashFiles('kmp/build.gradle.kts', 'settings.gradle.kts', 'gradle.properties') }}-${{ github.sha }} + restore-keys: | + gradle-web-${{ runner.os }}-${{ hashFiles('kmp/build.gradle.kts', 'settings.gradle.kts', 'gradle.properties') }}- + gradle-web-${{ runner.os }}- + + - name: Cache bazel-cache-proxy binary + id: bcp-cache + uses: actions/cache@v4 + with: + path: ~/.cargo/bin/bazel-cache-proxy + key: bcp-${{ runner.os }}-7806c5f + + - name: Install bazel-cache-proxy + if: steps.bcp-cache.outputs.cache-hit != 'true' + run: | + sudo apt-get install -y --no-install-recommends protobuf-compiler + cargo install --git https://github.com/tstapler/bazel-cache-proxy --rev 7806c5f bazel-cache-proxy --locked + + - name: Start bazel-cache-proxy (GHA backend) + run: | + printf '[backend]\ntype = "gha"\n' > /tmp/bcp.toml + ~/.cargo/bin/bazel-cache-proxy serve --config /tmp/bcp.toml & + sleep 2 + curl -sf http://127.0.0.1:9090/healthz + + - name: Set up Bazel + uses: bazel-contrib/setup-bazel@0.19.0 + with: + bazelisk-version: "1.x" + disk-cache: web + repository-cache: true + external-cache: true + cache-save: ${{ github.event_name != 'pull_request' }} + + - name: Build web bundle + run: bazel build //kmp:web_app --config=remote-cache + + - name: Upload web distribution artifact + if: github.event_name == 'push' + uses: actions/upload-artifact@v4 + with: + name: web-dist + path: bazel-bin/kmp/web_dist.tar.gz + retention-days: 7 diff --git a/.gitignore b/.gitignore index ee3710e9..1aff6fac 100644 --- a/.gitignore +++ b/.gitignore @@ -168,4 +168,15 @@ fdroid/archive/ *.rej *.bak *.tmp -*.tempuploads/ +*.temp +uploads/ + +# -------------------- +# Bazel +# -------------------- +/bazel-bin +/bazel-out +/bazel-testlogs +/bazel-* +# Machine-specific overrides (ANDROID_HOME, tool paths) — see .bazelrc.user.example +.bazelrc.user diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 00000000..75306a9f --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,86 @@ +""" +Root BUILD.bazel — Kotlin toolchain + Compose compiler plugin + Android toolchain. +All sub-packages reference //:compose_compiler_plugin and the toolchain +registered here. +""" + +load("@rules_kotlin//kotlin:core.bzl", "define_kt_toolchain", "kt_compiler_plugin", "kt_kotlinc_options") +load("@rules_android//toolchains/android:toolchain.bzl", "android_toolchain") + +# ── Kotlinc options for KMP JVM targets ─────────────────────────────────────── +# KMP source sets (commonMain + jvmCommonMain + jvmMain) are compiled together +# in one kt_jvm_library. This requires: +# -Xmulti-platform → allows expect/actual declarations in the compilation +# -opt-in → matches Gradle's freeCompilerArgs in kmp/build.gradle.kts +kt_kotlinc_options( + name = "kmp_jvm_kotlinc_opts", + jvm_target = "21", + x_multi_platform = True, + x_optin = ["kotlin.time.ExperimentalTime"], + visibility = ["//visibility:public"], +) + +# ── Kotlinc options for KMP Android targets ─────────────────────────────────── +# KMP source sets (commonMain + jvmCommonMain + androidMain) are compiled together +# in one kt_android_library. Same requirements as JVM but Android-targeted. +kt_kotlinc_options( + name = "kmp_android_kotlinc_opts", + x_multi_platform = True, + x_optin = ["kotlin.time.ExperimentalTime"], + visibility = ["//visibility:public"], +) + +# ── Kotlin JVM toolchain ─────────────────────────────────────────────────────── +define_kt_toolchain( + name = "kotlin_toolchain", + api_version = "2.1", + jvm_target = "21", + language_version = "2.1", +) + +# ── Compose compiler plugin ──────────────────────────────────────────────────── +# Uses the embeddable compiler plugin jar from Maven. +# suppressKotlinVersionCompatibilityCheck is required because the Compose +# compiler plugin may not yet list Kotlin 2.3.21 as a known-compatible version +# (see ADR-004 and rules_kotlin issue #1388). +kt_compiler_plugin( + name = "compose_compiler_plugin", + id = "androidx.compose.compiler.plugins.kotlin", + target_embedded_compiler = True, + visibility = ["//visibility:public"], + options = { + "suppressKotlinVersionCompatibilityCheck": "2.3.21", + "sourceInformation": "true", + }, + deps = ["@maven//:org_jetbrains_kotlin_kotlin_compose_compiler_plugin_embeddable"], +) + +# ── kotlinx.serialization compiler plugin ───────────────────────────────────── +# Required for @Serializable code generation (UndoManager, JsonExporter, etc.). +# Matches the kotlin("plugin.serialization") applied globally in build.gradle.kts. +kt_compiler_plugin( + name = "serialization_compiler_plugin", + id = "org.jetbrains.kotlinx.serialization", + target_embedded_compiler = True, + visibility = ["//visibility:public"], + deps = ["@maven//:org_jetbrains_kotlin_kotlin_serialization_compiler_plugin_embeddable"], +) + +# ── Android toolchain — Bazel-built unzip ───────────────────────────────────── +# rules_android's aar_import uses an `unzip` tool to extract AAR manifests. +# The default wrapper calls bare `unzip` which fails when the action env is +# cleared (exec env -). This custom toolchain swaps in the InfoZip unzip 6.0 +# binary built from source via @unzip_src (declared in MODULE.bazel). +# Registered before the rules_android default so it wins toolchain resolution. +android_toolchain( + name = "stelekit_android_toolchain_impl", + unzip_tool = "@unzip_src//:unzip", + visibility = ["//visibility:public"], +) + +toolchain( + name = "stelekit_android_toolchain", + toolchain = ":stelekit_android_toolchain_impl", + toolchain_type = "@rules_android//toolchains/android:toolchain_type", + visibility = ["//visibility:public"], +) diff --git a/CLAUDE.md b/CLAUDE.md index 5b4274df..b497cf70 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,7 +6,49 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co SteleKit is a Kotlin Multiplatform (KMP) migration of Logseq — a Markdown-based outliner/note-taking app. It targets Desktop (JVM), Android, iOS, and Web from a single shared codebase in the `kmp/` module. -## Build & Run Commands +## Bazel Build Commands + +**Bazel is the canonical build system.** Use Bazel for all JVM/Desktop, Android, and Web +work. Gradle is kept only for iOS (no Bazel KMP support yet), screenshot tests +(Roborazzi), and benchmarks until those are migrated (Epic 7). + +| Gradle (legacy) | Bazel (canonical) | +|--------|-------| +| `./gradlew run` | `bazel run //kmp:desktop_app` | +| `./gradlew jvmTest` | `bazel test //kmp:jvm_tests` | +| `./gradlew allTests` | `bazel test //...` | +| `./gradlew ciCheck` | `bazel test //... --config=ci` | +| `./gradlew installAndroid` | `bazel mobile-install //kmp:android_app --config=android` | +| `./gradlew packageDistributionForCurrentOS` | _(Gradle only — see Future Epic D)_ | +| `./gradlew testDebugUnitTest` | `bazel test //kmp/src/androidUnitTest/kotlin:android_unit_tests --config=android` | +| `./gradlew wasmJsBrowserDistribution` | `bazel build //kmp:web_app` | + +```bash +# Launch desktop app +bazel run //kmp:desktop_app + +# Run all JVM tests (excluding screenshot tests which remain Gradle-only) +bazel test //kmp:jvm_tests + +# Run only business-logic tests (no UI, fastest) +bazel test //kmp:business_tests + +# Build Android APK (requires ANDROID_HOME to be set) +bazel build //kmp:android_app --config=android + +# Build web (WASM/JS) bundle — output: bazel-bin/kmp/web_dist.tar.gz +# Note: delegates to Gradle internally until rules_kotlin#567 lands +bazel build //kmp:web_app + +# Run all Bazel tests +bazel test //... + +# Re-generate SQLDelight sources (when .sq files change) +./gradlew :kmp:generateCommonMainSteleDatabase +rsync -a kmp/build/generated/sqldelight/code/SteleDatabase/commonMain/ kmp/src/generated/sqldelight/ +``` + +## Gradle Build & Run Commands **Always use `./gradlew`, never the system `gradle` command.** The wrapper pins Gradle 9.5.0; the system install is 9.3.1 and cannot share daemons with wrapper builds — using it silently doubles the daemon count and memory footprint. diff --git a/MODULE.bazel b/MODULE.bazel index b1065463..0f0312ed 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,4 +1,397 @@ +""" +SteleKit — MODULE.bazel +Bzlmod-only (no WORKSPACE). JVM/Desktop + Android targets in scope. +iOS and WASM remain Gradle-only until rules_kotlin adds Kotlin/Native support. +""" + module( name = "stelekit", - version = "0.1", + version = "0.0.0", ) + +############################################################################### +# Core Bazel rules +############################################################################### + +bazel_dep(name = "rules_kotlin", version = "2.3.20") + +# Patch rules_kotlin to add common_srcs support for Kotlin Multiplatform (KMP) compilation. +# common_srcs enables -Xcommon-sources, allowing expect/actual to work when commonMain and +# jvmMain sources are compiled together in a single kt_jvm_library. +single_version_override( + module_name = "rules_kotlin", + patches = ["//third_party/patches:rules_kotlin_kmp.patch"], + patch_strip = 1, +) +bazel_dep(name = "rules_cc", version = "0.1.1") +bazel_dep(name = "rules_android", version = "0.7.1") +bazel_dep(name = "rules_jvm_external", version = "6.9") +bazel_dep(name = "bazel_skylib", version = "1.8.2") +bazel_dep(name = "rules_java", version = "9.3.0") +# rules_robolectric is available in BCR and provides @rules_robolectric//bazel:android-all +# which carries the robolectric-deps.properties file needed by android_local_test at runtime. +# Version 4.16.1 matches our org.robolectric:robolectric:4.16 Maven artifact. +# rules_android 0.7.1 depends on rules_robolectric 4.14.1.2; we declare 4.16.1 so Bzlmod +# selects the higher version, compatible with our Maven 4.16 Robolectric test runner. +bazel_dep(name = "rules_robolectric", version = "4.16.1") + +############################################################################### +# Android SDK +############################################################################### + +android_sdk_repository_extension = use_extension( + "@rules_android//rules/android_sdk_repository:rule.bzl", + "android_sdk_repository_extension", +) +android_sdk_repository_extension.configure( + api_level = 36, + build_tools_version = "35.0.0", +) + +############################################################################### +# InfoZip unzip — built from source by Bazel. +# rules_android's aar_import extracts AAR manifests using an `unzip` tool; by +# building it here we avoid any system-level unzip dependency. The resulting +# binary is exposed via a custom android_toolchain registered in BUILD.bazel. +############################################################################### + +http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +http_archive( + name = "unzip_src", + urls = ["https://downloads.sourceforge.net/infozip/unzip60.tar.gz"], + sha256 = "036d96991646d0449ed0aa952e4fbe21b476ce994abc276e49d30e686708bd37", + strip_prefix = "unzip60", + build_file = "//:third_party/unzip.BUILD", + # InfoZip 6.0 has K&R-style time declarations that conflict with modern + # glibc headers. Guard them so they only apply on truly ancient platforms. + patch_cmds = [ + "sed -i 's/ struct tm \\*gmtime(), \\*localtime();/#if !defined(__GLIBC__) \\&\\& !defined(linux)\\n struct tm *gmtime(), *localtime();\\n#endif/' unix/unxcfg.h", + ], +) + +############################################################################### +# Maven artifacts +# +# KMP classifier notes (Task 1.2.1): +# +# Library JVM artifact Android artifact +# ───────────────────────────────────────────────────────────────────────────────────────────── +# app.cash.sqldelight:runtime runtime-jvm (JVM SQLite driver) android-driver (Android) +# app.cash.sqldelight:coroutines-ext coroutines-extensions-jvm coroutines-extensions-jvm +# app.cash.sqldelight:async-ext async-extensions-jvm async-extensions-jvm +# io.arrow-kt:arrow-core arrow-core-jvm (explicit -jvm suffix) arrow-core-jvm +# io.arrow-kt:arrow-optics arrow-optics-jvm arrow-optics-jvm +# io.arrow-kt:arrow-fx-coroutines arrow-fx-coroutines-jvm arrow-fx-coroutines-jvm +# io.arrow-kt:arrow-resilience arrow-resilience-jvm arrow-resilience-jvm +# org.jetbrains.kotlinx:coroutines kotlinx-coroutines-core-jvm kotlinx-coroutines-core-jvm +# io.ktor:ktor-client-core ktor-client-core-jvm ktor-client-core-jvm +# io.coil-kt.coil3:coil-compose coil-compose-jvm coil-compose-jvm (+ android below) +# io.github.petertrr:km-diff kotlin-multiplatform-diff-jvm kotlin-multiplatform-diff-jvm +# com.fleeksoft.ksoup:ksoup ksoup-jvm ksoup-jvm +# org.jetbrains:markdown markdown-jvm markdown-jvm +# org.jetbrains.androidx.lifecycle lifecycle-runtime-compose (no -jvm) lifecycle-runtime-compose +# org.eclipse.jgit (desktop 7.x) declared separately; Android uses 5.13.x +# NOTE: rules_jvm_external does not allow the same groupId:artifactId at two +# versions. The JVM target uses jgit 7.x; Android target falls back to +# the higher-versioned resolution (7.x) which is safe for JVM. The Android +# target is documented in androidMain/BUILD.bazel with a note about this +# version pinning constraint. +############################################################################### + +# ── Maven resolution memory note ────────────────────────────────────────────── +# The full Compose Multiplatform + AndroidX + KMP dependency graph contains +# ~300+ direct artifacts with a deep transitive graph (~4000+ targets after +# rules_jvm_external expansion). On memory-constrained machines (<12 GB free), +# the Bazel analysis phase may OOM. +# +# Workaround for developers on constrained machines: +# echo "startup --host_jvm_args=-Xmx8g" >> ~/.bazelrc +# bazel shutdown +# +# On CI (GitHub Actions ubuntu-latest with 16 GB RAM), this resolves cleanly. +# +# To regenerate the lockfile after adding/removing Maven deps: +# bazel run @maven//:pin +# Then commit rules_jvm_external++maven+maven_install.json. +# ────────────────────────────────────────────────────────────────────────────── + +maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven") + +maven.install( + name = "maven", + # Generated by: bazel run @maven//:pin (Bzlmod naming convention) + lock_file = "//:rules_jvm_external++maven+maven_install.json", + known_contributing_modules = ["protobuf", "stelekit"], + # aar_import is no longer a native Bazel rule in Bazel 8+. With + # use_starlark_android_rules = True, the generated @maven BUILD loads + # aar_import from rules_android instead of using the removed native rule. + use_starlark_android_rules = True, + aar_import_bzl_label = "@rules_android//android:rules.bzl", + # Use "pinned" strategy so coursier picks the highest compatible version + # rather than failing on conflicting version constraints from transitive deps + # (Compose Multiplatform and AndroidX have many cross-cutting version constraints). + version_conflict_policy = "pinned", + # Do not generate compat (underscore-to-dot) alias targets — reduces the + # total number of targets from ~8000 to ~4000, which helps with Bazel + # analysis-phase memory on constrained hosts. + generate_compat_repositories = False, + # Skip source JARs — halves the number of Coursier fetch operations. + # Source JARs are only useful for IDE navigation, not for builds. + fetch_sources = False, + artifacts = [ + # ── Kotlin stdlib (required by rules_kotlin kt_jvm_library) ────────── + "org.jetbrains.kotlin:kotlin-stdlib:2.3.21", + "org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.3.21", + "org.jetbrains.kotlin:kotlin-reflect:2.3.21", + "org.jetbrains.kotlin:kotlin-test-junit:2.3.21", + + # ── Compiler plugins (embeddable — used as kt_compiler_plugin deps) ──── + "org.jetbrains.kotlin:kotlin-compose-compiler-plugin-embeddable:2.3.21", + "org.jetbrains.kotlin:kotlin-serialization-compiler-plugin-embeddable:2.3.21", + + # ── Arrow 2.2.1.1 (KMP — use -jvm classifier) ─────────────────────── + "io.arrow-kt:arrow-core-jvm:2.2.1.1", + "io.arrow-kt:arrow-optics-jvm:2.2.1.1", + "io.arrow-kt:arrow-fx-coroutines-jvm:2.2.1.1", + "io.arrow-kt:arrow-resilience-jvm:2.2.1.1", + + # ── Kotlinx ────────────────────────────────────────────────────────── + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.10.2", + "org.jetbrains.kotlinx:kotlinx-coroutines-swing:1.10.2", + "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.2", + "org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm:1.10.2", + "org.jetbrains.kotlinx:kotlinx-datetime-jvm:0.7.1", + "org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.10.0", + + # ── Jetbrains markdown (KMP — use -jvm classifier) ─────────────────── + "org.jetbrains:markdown-jvm:0.7.3", + + # ── SQLDelight 2.3.2 ────────────────────────────────────────────────── + "app.cash.sqldelight:runtime-jvm:2.3.2", + "app.cash.sqldelight:coroutines-extensions-jvm:2.3.2", + "app.cash.sqldelight:async-extensions-jvm:2.3.2", + "app.cash.sqldelight:sqlite-driver:2.3.2", # JVM SQLite driver + "app.cash.sqldelight:android-driver:2.3.2", # Android SQLite driver + "com.github.requery:sqlite-android:3.49.0", # Android custom SQLite + + # ── Compose Desktop (JVM) — correct group IDs verified on Maven Central ─ + # Skiko AWT runtime is a transitive dep; pin to match Gradle resolutionStrategy + "org.jetbrains.skiko:skiko-awt-runtime-linux-x64:0.9.37.4", + "org.jetbrains.skiko:skiko-awt-runtime-macos-arm64:0.9.37.4", + "org.jetbrains.skiko:skiko-awt-runtime-macos-x64:0.9.37.4", + "org.jetbrains.skiko:skiko-awt-runtime-windows-x64:0.9.37.4", + + # Compose Multiplatform — exact versions as resolved by Gradle (from Gradle resolution analysis) + # Note: compose.material3 1.10.3 does not exist on Maven Central; Gradle resolves to 1.9.0. + # compose.material:material-icons-extended resolves to 1.7.3 with -desktop suffix. + "org.jetbrains.compose.runtime:runtime-desktop:1.10.3", + "org.jetbrains.compose.foundation:foundation-desktop:1.10.3", + "org.jetbrains.compose.material3:material3-desktop:1.9.0", # 1.10.3 not on Maven Central; 1.9.0 resolved by Gradle + "org.jetbrains.compose.material:material-icons-extended-desktop:1.7.3", # Gradle-resolved version + "org.jetbrains.compose.components:components-resources-desktop:1.10.3", + "org.jetbrains.compose.desktop:desktop-jvm-linux-x64:1.10.3", + "org.jetbrains.compose.ui:ui-test-junit4-desktop:1.10.3", + + # ── Jetpack lifecycle (KMP — no -jvm suffix; correct IDs verified on Maven Central) ─── + # Compose 1.10.3 (org.jetbrains.compose.ui:ui) requires lifecycle 2.9.6. + # lifecycle-runtime-compose:2.8.4 has a hard constraint [lifecycle-runtime:2.8.4] + # which conflicts. Gradle silently upgrades to 2.9.6; we must match that. + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose:2.9.6", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose:2.9.6", + + # ── Coil 3 (KMP — use -jvm classifier) ─────────────────────────────── + "io.coil-kt.coil3:coil-compose-jvm:3.2.0", + "io.coil-kt.coil3:coil-network-ktor3-jvm:3.2.0", + + # ── Ktor 3.1.3 (KMP — use -jvm classifier) ──────────────────────────── + "io.ktor:ktor-client-core-jvm:3.1.3", + "io.ktor:ktor-client-content-negotiation-jvm:3.1.3", + "io.ktor:ktor-serialization-kotlinx-json-jvm:3.1.3", + "io.ktor:ktor-client-okhttp-jvm:3.1.3", + "io.ktor:ktor-client-mock-jvm:3.1.3", + + # ── Ksoup (KMP — use -jvm classifier) ──────────────────────────────── + "com.fleeksoft.ksoup:ksoup-jvm:0.2.6", + + # ── Kotlin Multiplatform Diff (KMP — use -jvm classifier) ───────────── + "io.github.petertrr:kotlin-multiplatform-diff-jvm:1.3.0", + + # ── OpenTelemetry (JVM/Android shared) ─────────────────────────────── + "io.opentelemetry:opentelemetry-api:1.43.0", + "io.opentelemetry:opentelemetry-sdk:1.43.0", + "io.opentelemetry:opentelemetry-exporter-logging:1.43.0", + + # ── BouncyCastle ────────────────────────────────────────────────────── + "org.bouncycastle:bcprov-jdk18on:1.80", + + # ── PDFBox — PDF text extraction for asset OCR pipeline (JVM only) ─── + "org.apache.pdfbox:pdfbox:3.0.4", + + # ── JGit — one version per groupId:artifactId (rules_jvm_external constraint) + # Desktop uses 7.x; Android also resolves to 7.x (version conflict + # resolved to higher version). See CLAUDE.md note on version pinning. + "org.eclipse.jgit:org.eclipse.jgit:7.3.0.202506031305-r", + "org.eclipse.jgit:org.eclipse.jgit.ssh.apache:7.3.0.202506031305-r", + # JGit SSH/JSch for Android (5.13.x group; artifactId is different) + "org.eclipse.jgit:org.eclipse.jgit.ssh.jsch:5.13.3.202401111512-r", + "com.github.mwiede:jsch:0.2.21", + + # ── Transitive version conflict pins ───────────────────────────────── + # This project mixes two Compose stacks: JetBrains Compose 1.10.3 + # (built against AndroidX Compose 1.10.5) and AndroidX Compose + # (used directly on Android). Coursier fails on the hard-range conflicts + # these two stacks generate. Strategy: pin all common AndroidX transitives + # at the highest version Gradle resolves, so Coursier's "pinned wins" + # policy overrides the hard ranges from older transitive POMs. + # Versions are taken from: ./gradlew :kmp:dependencies + # --configuration debugRuntimeClasspath (Android resolved versions, highest wins). + + # Compose runtime — align to 1.10.5 (what JetBrains Compose 1.10.3 expects) + "androidx.compose.runtime:runtime-annotation:1.10.5", + + # collection — Glance 1.1.1 constrains [1.4.2]; pin at 1.5.0 (Gradle resolves 1.5.0) + "androidx.collection:collection:1.5.0", + "androidx.collection:collection-jvm:1.5.0", + + # emoji2 — MLKit common → appcompat:1.6.1 → [emoji2:1.2.0]; pin at 1.4.0 + "androidx.emoji2:emoji2:1.4.0", + "androidx.emoji2:emoji2-views-helper:1.4.0", + + # lifecycle — various old artifacts constrain older versions; pin at 2.9.4 + "androidx.lifecycle:lifecycle-common:2.9.4", + "androidx.lifecycle:lifecycle-common-java8:2.9.4", + "androidx.lifecycle:lifecycle-runtime:2.9.4", + "androidx.lifecycle:lifecycle-runtime-ktx:2.9.4", + "androidx.lifecycle:lifecycle-viewmodel:2.9.4", + "androidx.lifecycle:lifecycle-viewmodel-ktx:2.9.4", + "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.9.4", + "androidx.lifecycle:lifecycle-livedata-core:2.9.4", + "androidx.lifecycle:lifecycle-livedata-core-ktx:2.9.4", + "androidx.lifecycle:lifecycle-livedata:2.9.4", + "androidx.lifecycle:lifecycle-process:2.9.4", + "androidx.lifecycle:lifecycle-service:2.9.4", + + # savedstate — lifecycle/activity transitives constrain older versions; pin at 1.3.3 + "androidx.savedstate:savedstate:1.3.3", + "androidx.savedstate:savedstate-ktx:1.3.3", + + # customview — older Glance UI transitives + "androidx.customview:customview:1.1.0", + "androidx.customview:customview-poolingcontainer:1.0.0", + + # core — MLKit and older Glance/Compat pull 1.13.0; pin at 1.16.0 + "androidx.core:core:1.16.0", + + # annotation — various old artifacts constrain older versions + "androidx.annotation:annotation:1.9.1", + "androidx.annotation:annotation-jvm:1.9.1", + + # Test infrastructure — ui-test-junit4 → espresso-core:3.5.0 → runner:1.5.0 + # runner:1.5.0 has hard constraint [monitor:1.6.0]; pin everything at latest + "androidx.test:monitor:1.8.0", + "androidx.test:runner:1.6.2", + "androidx.test:rules:1.6.0", + "androidx.test.services:storage:1.6.0", + "androidx.test.espresso:espresso-core:3.6.0", + "androidx.test.espresso:espresso-idling-resource:3.6.0", + + # Fragment — activity and espresso pull older versions with hard ranges + "androidx.fragment:fragment:1.8.5", + "androidx.fragment:fragment-ktx:1.8.5", + + # Window — Glance and newer compose pull different versions + "androidx.window:window:1.5.0", + "androidx.window:window-core:1.5.0", + + # Tracing — compose and old APIs conflict + "androidx.tracing:tracing:1.3.0", + + # startup — ProfileInstaller and others have constraints + "androidx.startup:startup-runtime:1.2.0", + + # profileinstaller — Compose pulls this transitively + "androidx.profileinstaller:profileinstaller:1.4.0", + + # ── AndroidX ───────────────────────────────────────────────────────── + "androidx.activity:activity-compose:1.9.2", + "androidx.appcompat:appcompat:1.7.0", + "androidx.core:core-ktx:1.15.0", + "androidx.documentfile:documentfile:1.0.1", + "androidx.metrics:metrics-performance:1.0.0-beta02", + "androidx.security:security-crypto:1.1.0-alpha06", + "androidx.glance:glance-appwidget:1.1.1", + "androidx.glance:glance-material3:1.1.1", + "androidx.work:work-runtime-ktx:2.9.1", + "androidx.arch.core:core-testing:2.2.0", + "androidx.glance:glance-appwidget-testing:1.1.1", + + # ── Jetpack Compose (Android) ───────────────────────────────────────── + # Pinned at 1.10.5 to match the AndroidX Compose version that JetBrains + # Compose Multiplatform 1.10.3 was compiled against. + "androidx.compose.ui:ui:1.10.5", + "androidx.compose.ui:ui-graphics:1.10.5", + "androidx.compose.material3:material3:1.4.0", + "androidx.compose.ui:ui-test-junit4:1.10.5", + "androidx.compose.ui:ui-test-manifest:1.10.5", + + # ── MLKit (Android) ─────────────────────────────────────────────────── + "com.google.mlkit:genai-prompt:1.0.0-beta2", + "com.google.mlkit:image-labeling:17.0.9", + "com.google.mlkit:text-recognition:16.0.1", + + # ── ARCore (Android) ───────────────────────────────────────────────── + "com.google.ar:core:1.46.0", + + # ── CameraX (Android) ──────────────────────────────────────────────── + "androidx.camera:camera-core:1.4.1", + "androidx.camera:camera-camera2:1.4.1", + "androidx.camera:camera-lifecycle:1.4.1", + + # ── ONNX Runtime Android ────────────────────────────────────────────── + "com.microsoft.onnxruntime:onnxruntime-android:1.20.0", + + # ── ExifInterface (Android) ─────────────────────────────────────────── + "androidx.exifinterface:exifinterface:1.3.7", + + # ── PDFBox Android ──────────────────────────────────────────────────── + "com.tom-roush:pdfbox-android:2.0.27.0", + + # ── Kable BLE (Android) ─────────────────────────────────────────────── + "com.juul.kable:core-android:0.32.0", + + # ── Okio (KMP — used by commonMain for cross-platform file I/O) ─────── + "com.squareup.okio:okio-jvm:3.17.0", + + # ── Compose material icons extended (Android) ───────────────────────── + # JVM (desktop) uses material-icons-extended-desktop:1.7.3 (already pinned above). + # Android compilation needs the Jetpack AAR. 1.10.5 doesn't exist on Google Maven; + # the latest Jetpack release is 1.7.8 — use that. + "androidx.compose.material:material-icons-extended:1.7.8", + + + # ── Test dependencies ───────────────────────────────────────────────── + "junit:junit:4.13.2", + "org.robolectric:robolectric:4.16", + "androidx.test:core:1.6.1", + "androidx.test.ext:junit:1.2.1", + + # ── BlockHound ──────────────────────────────────────────────────────── + "io.projectreactor.tools:blockhound:1.0.9.RELEASE", + + # ── Core library desugaring (Android) ──────────────────────────────── + "com.android.tools:desugar_jdk_libs:2.1.4", + ], + repositories = [ + "https://repo1.maven.org/maven2", + "https://maven.google.com", + "https://jitpack.io", + "https://oss.sonatype.org/content/repositories/snapshots", + "https://maven.pkg.jetbrains.space/public/p/compose/dev", + ], +) + +use_repo(maven, "maven") + +# Custom android toolchain that uses the Bazel-built unzip (registered before +# the rules_android default so it wins toolchain resolution for aar_import). +register_toolchains("//:stelekit_android_toolchain") diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock new file mode 100644 index 00000000..d8719fff --- /dev/null +++ b/MODULE.bazel.lock @@ -0,0 +1,852 @@ +{ + "lockFileVersion": 26, + "registryFileHashes": { + "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", + "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", + "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589", + "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16", + "https://bcr.bazel.build/modules/abseil-cpp/20250127.0/MODULE.bazel": "d1086e248cda6576862b4b3fe9ad76a214e08c189af5b42557a6e1888812c5d5", + "https://bcr.bazel.build/modules/abseil-cpp/20250127.1/MODULE.bazel": "c4a89e7ceb9bf1e25cf84a9f830ff6b817b72874088bf5141b314726e46a57c1", + "https://bcr.bazel.build/modules/abseil-cpp/20250512.1/MODULE.bazel": "d209fdb6f36ffaf61c509fcc81b19e81b411a999a934a032e10cd009a0226215", + "https://bcr.bazel.build/modules/abseil-cpp/20250814.1/MODULE.bazel": "51f2312901470cdab0dbdf3b88c40cd21c62a7ed58a3de45b365ddc5b11bcab2", + "https://bcr.bazel.build/modules/abseil-cpp/20250814.1/source.json": "cea3901d7e299da7320700abbaafe57a65d039f10d0d7ea601c4a66938ea4b0c", + "https://bcr.bazel.build/modules/abseil-py/2.1.0/MODULE.bazel": "5ebe5bf853769c65707e5c28f216798f7a4b1042015e6a36e6d03094d94bec8a", + "https://bcr.bazel.build/modules/abseil-py/2.1.0/source.json": "0e8fc4f088ce07099c1cd6594c20c7ddbb48b4b3c0849b7d94ba94be88ff042b", + "https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896", + "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85", + "https://bcr.bazel.build/modules/apple_support/1.21.0/MODULE.bazel": "ac1824ed5edf17dee2fdd4927ada30c9f8c3b520be1b5fd02a5da15bc10bff3e", + "https://bcr.bazel.build/modules/apple_support/1.21.1/MODULE.bazel": "5809fa3efab15d1f3c3c635af6974044bac8a4919c62238cce06acee8a8c11f1", + "https://bcr.bazel.build/modules/apple_support/1.24.2/MODULE.bazel": "0e62471818affb9f0b26f128831d5c40b074d32e6dda5a0d3852847215a41ca4", + "https://bcr.bazel.build/modules/apple_support/1.24.2/source.json": "2c22c9827093250406c5568da6c54e6fdf0ef06238def3d99c71b12feb057a8d", + "https://bcr.bazel.build/modules/bazel_features/1.1.0/MODULE.bazel": "cfd42ff3b815a5f39554d97182657f8c4b9719568eb7fded2b9135f084bf760b", + "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", + "https://bcr.bazel.build/modules/bazel_features/1.10.0/MODULE.bazel": "f75e8807570484a99be90abcd52b5e1f390362c258bcb73106f4544957a48101", + "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", + "https://bcr.bazel.build/modules/bazel_features/1.13.0/MODULE.bazel": "c14c33c7c3c730612bdbe14ebbb5e61936b6f11322ea95a6e91cd1ba962f94df", + "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d", + "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d", + "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a", + "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58", + "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b", + "https://bcr.bazel.build/modules/bazel_features/1.23.0/MODULE.bazel": "fd1ac84bc4e97a5a0816b7fd7d4d4f6d837b0047cf4cbd81652d616af3a6591a", + "https://bcr.bazel.build/modules/bazel_features/1.27.0/MODULE.bazel": "621eeee06c4458a9121d1f104efb80f39d34deff4984e778359c60eaf1a8cb65", + "https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d", + "https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9", + "https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87", + "https://bcr.bazel.build/modules/bazel_features/1.33.0/MODULE.bazel": "8b8dc9d2a4c88609409c3191165bccec0e4cb044cd7a72ccbe826583303459f6", + "https://bcr.bazel.build/modules/bazel_features/1.39.0/MODULE.bazel": "28739425c1fc283c91931619749c832b555e60bcd1010b40d8441ce0a5cf726d", + "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", + "https://bcr.bazel.build/modules/bazel_features/1.42.1/MODULE.bazel": "275a59b5406ff18c01739860aa70ad7ccb3cfb474579411decca11c93b951080", + "https://bcr.bazel.build/modules/bazel_features/1.42.1/source.json": "fcd4396b2df85f64f2b3bb436ad870793ecf39180f1d796f913cc9276d355309", + "https://bcr.bazel.build/modules/bazel_features/1.9.0/MODULE.bazel": "885151d58d90d8d9c811eb75e3288c11f850e1d6b481a8c9f766adee4712358b", + "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", + "https://bcr.bazel.build/modules/bazel_lib/3.1.0/MODULE.bazel": "6809765c14e3c766a9b9286c7b0ec56ed87a73326e48fe01749f0c0fdcfe3287", + "https://bcr.bazel.build/modules/bazel_lib/3.1.0/source.json": "aaf7c2dc816219f4cb356c9d65f2555fb7f9543e537199f74a921f7877d23dfb", + "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", + "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", + "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686", + "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a", + "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5", + "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d", + "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651", + "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138", + "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", + "https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6", + "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67", + "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/source.json": "34a3c8bcf233b835eb74be9d628899bb32999d3e0eadef1947a0a562a2b16ffb", + "https://bcr.bazel.build/modules/bazel_worker_api/0.0.8/MODULE.bazel": "396c1ef53835aafe3d42ce6619080531ee770648303731f16cfaa33fa056bf0c", + "https://bcr.bazel.build/modules/bazel_worker_api/0.0.8/source.json": "abaf8ac9d2ab2f47bda9af4c0c080ff7907378888e1f4bc62a0539dd13ba61e8", + "https://bcr.bazel.build/modules/bazel_worker_java/0.0.8/MODULE.bazel": "e76479eae70bd4e8f5f4c2dfc5d03ab971cfb18750246c7b3f3454c5c2ee6629", + "https://bcr.bazel.build/modules/bazel_worker_java/0.0.8/source.json": "9395c4679444bc47bf7e51a710366a4480aa371c6f6bed01868e2fabcf11acec", + "https://bcr.bazel.build/modules/buildozer/8.5.1/MODULE.bazel": "a35d9561b3fc5b18797c330793e99e3b834a473d5fbd3d7d7634aafc9bdb6f8f", + "https://bcr.bazel.build/modules/buildozer/8.5.1/source.json": "e3386e6ff4529f2442800dee47ad28d3e6487f36a1f75ae39ae56c70f0cd2fbd", + "https://bcr.bazel.build/modules/gazelle/0.32.0/MODULE.bazel": "b499f58a5d0d3537f3cf5b76d8ada18242f64ec474d8391247438bf04f58c7b8", + "https://bcr.bazel.build/modules/gazelle/0.33.0/MODULE.bazel": "a13a0f279b462b784fb8dd52a4074526c4a2afe70e114c7d09066097a46b3350", + "https://bcr.bazel.build/modules/gazelle/0.34.0/MODULE.bazel": "abdd8ce4d70978933209db92e436deb3a8b737859e9354fb5fd11fb5c2004c8a", + "https://bcr.bazel.build/modules/gazelle/0.36.0/MODULE.bazel": "e375d5d6e9a6ca59b0cb38b0540bc9a05b6aa926d322f2de268ad267a2ee74c0", + "https://bcr.bazel.build/modules/gazelle/0.47.0/MODULE.bazel": "b61bb007c4efad134aa30ee7f4a8e2a39b22aa5685f005edaa022fbd1de43ebc", + "https://bcr.bazel.build/modules/gazelle/0.47.0/source.json": "aeb2e5df14b7fb298625d75d08b9c65bdb0b56014c5eb89da9e5dd0572280ae6", + "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", + "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", + "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", + "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", + "https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108", + "https://bcr.bazel.build/modules/googletest/1.17.0/MODULE.bazel": "dbec758171594a705933a29fcf69293d2468c49ec1f2ebca65c36f504d72df46", + "https://bcr.bazel.build/modules/googletest/1.17.0/source.json": "38e4454b25fc30f15439c0378e57909ab1fd0a443158aa35aec685da727cd713", + "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075", + "https://bcr.bazel.build/modules/jsoncpp/1.9.6/MODULE.bazel": "2f8d20d3b7d54143213c4dfc3d98225c42de7d666011528dc8fe91591e2e17b0", + "https://bcr.bazel.build/modules/jsoncpp/1.9.6/source.json": "a04756d367a2126c3541682864ecec52f92cdee80a35735a3cb249ce015ca000", + "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", + "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74", + "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/source.json": "f448c6e8963fdfa7eb831457df83ad63d3d6355018f6574fb017e8169deb43a9", + "https://bcr.bazel.build/modules/package_metadata/0.0.3/MODULE.bazel": "77890552ecea9e284b5424c9de827a58099348763a4359e975c359a83d4faa83", + "https://bcr.bazel.build/modules/package_metadata/0.0.5/MODULE.bazel": "ef4f9439e3270fdd6b9fd4dbc3d2f29d13888e44c529a1b243f7a31dfbc2e8e4", + "https://bcr.bazel.build/modules/package_metadata/0.0.5/source.json": "2326db2f6592578177751c3e1f74786b79382cd6008834c9d01ec865b9126a85", + "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", + "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f", + "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", + "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", + "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", + "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814", + "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d", + "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc", + "https://bcr.bazel.build/modules/platforms/1.0.0/MODULE.bazel": "f05feb42b48f1b3c225e4ccf351f367be0371411a803198ec34a389fb22aa580", + "https://bcr.bazel.build/modules/platforms/1.0.0/source.json": "f4ff1fd412e0246fd38c82328eb209130ead81d62dcd5a9e40910f867f733d96", + "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", + "https://bcr.bazel.build/modules/protobuf/23.1/MODULE.bazel": "88b393b3eb4101d18129e5db51847cd40a5517a53e81216144a8c32dfeeca52a", + "https://bcr.bazel.build/modules/protobuf/24.4/MODULE.bazel": "7bc7ce5f2abf36b3b7b7c8218d3acdebb9426aeb35c2257c96445756f970eb12", + "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c", + "https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d", + "https://bcr.bazel.build/modules/protobuf/27.2/MODULE.bazel": "32450b50673882e4c8c3d10a83f3bc82161b213ed2f80d17e38bece8f165c295", + "https://bcr.bazel.build/modules/protobuf/29.0-rc2.bcr.1/MODULE.bazel": "52f4126f63a2f0bbf36b99c2a87648f08467a4eaf92ba726bc7d6a500bbf770c", + "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df", + "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92", + "https://bcr.bazel.build/modules/protobuf/29.1/MODULE.bazel": "557c3457560ff49e122ed76c0bc3397a64af9574691cb8201b4e46d4ab2ecb95", + "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", + "https://bcr.bazel.build/modules/protobuf/3.19.2/MODULE.bazel": "532ffe5f2186b69fdde039efe6df13ba726ff338c6bc82275ad433013fa10573", + "https://bcr.bazel.build/modules/protobuf/3.19.6/MODULE.bazel": "9233edc5e1f2ee276a60de3eaa47ac4132302ef9643238f23128fea53ea12858", + "https://bcr.bazel.build/modules/protobuf/31.1/MODULE.bazel": "379a389bb330b7b8c1cdf331cc90bf3e13de5614799b3b52cdb7c6f389f6b38e", + "https://bcr.bazel.build/modules/protobuf/32.1/MODULE.bazel": "89cd2866a9cb07fee9ff74c41ceace11554f32e0d849de4e23ac55515cfada4d", + "https://bcr.bazel.build/modules/protobuf/33.4/MODULE.bazel": "114775b816b38b6d0ca620450d6b02550c60ceedfdc8d9a229833b34a223dc42", + "https://bcr.bazel.build/modules/protobuf/33.4/source.json": "555f8686b4c7d6b5ba731fbea13bf656b4bfd9a7ff629c1d9d3f6e1d6155de79", + "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", + "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34", + "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680", + "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", + "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/MODULE.bazel": "b4963dda9b31080be1905ef085ecd7dd6cd47c05c79b9cdf83ade83ab2ab271a", + "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/source.json": "2ff292be6ef3340325ce8a045ecc326e92cbfab47c7cbab4bd85d28971b97ac4", + "https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa", + "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8", + "https://bcr.bazel.build/modules/rules_android/0.7.1/MODULE.bazel": "a806fc382a774252f228a40e3b11b9fcc6276f8778c7fb33e9f72937c6258363", + "https://bcr.bazel.build/modules/rules_android/0.7.1/source.json": "151440aed3f0f73a00d4ed5cec5d31f63a6fef9b95d8fab1eb1810150fa525f2", + "https://bcr.bazel.build/modules/rules_apple/3.16.0/MODULE.bazel": "0d1caf0b8375942ce98ea944be754a18874041e4e0459401d925577624d3a54a", + "https://bcr.bazel.build/modules/rules_apple/4.1.0/MODULE.bazel": "76e10fd4a48038d3fc7c5dc6e63b7063bbf5304a2e3bd42edda6ec660eebea68", + "https://bcr.bazel.build/modules/rules_apple/4.1.0/source.json": "8ee81e1708756f81b343a5eb2b2f0b953f1d25c4ab3d4a68dc02754872e80715", + "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647", + "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002", + "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191", + "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc", + "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87", + "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a", + "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", + "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", + "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", + "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", + "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513", + "https://bcr.bazel.build/modules/rules_cc/0.1.2/MODULE.bazel": "557ddc3a96858ec0d465a87c0a931054d7dcfd6583af2c7ed3baf494407fd8d0", + "https://bcr.bazel.build/modules/rules_cc/0.1.5/MODULE.bazel": "88dfc9361e8b5ae1008ac38f7cdfd45ad738e4fa676a3ad67d19204f045a1fd8", + "https://bcr.bazel.build/modules/rules_cc/0.2.0/MODULE.bazel": "b5c17f90458caae90d2ccd114c81970062946f49f355610ed89bebf954f5783c", + "https://bcr.bazel.build/modules/rules_cc/0.2.13/MODULE.bazel": "eecdd666eda6be16a8d9dc15e44b5c75133405e820f620a234acc4b1fdc5aa37", + "https://bcr.bazel.build/modules/rules_cc/0.2.14/MODULE.bazel": "353c99ed148887ee89c54a17d4100ae7e7e436593d104b668476019023b58df8", + "https://bcr.bazel.build/modules/rules_cc/0.2.17/MODULE.bazel": "1849602c86cb60da8613d2de887f9566a6d354a6df6d7009f9d04a14402f9a84", + "https://bcr.bazel.build/modules/rules_cc/0.2.17/source.json": "3832f45d145354049137c0090df04629d9c2b5493dc5c2bf46f1834040133a07", + "https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642", + "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", + "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", + "https://bcr.bazel.build/modules/rules_go/0.41.0/MODULE.bazel": "55861d8e8bb0e62cbd2896f60ff303f62ffcb0eddb74ecb0e5c0cbe36fc292c8", + "https://bcr.bazel.build/modules/rules_go/0.42.0/MODULE.bazel": "8cfa875b9aa8c6fce2b2e5925e73c1388173ea3c32a0db4d2b4804b453c14270", + "https://bcr.bazel.build/modules/rules_go/0.46.0/MODULE.bazel": "3477df8bdcc49e698b9d25f734c4f3a9f5931ff34ee48a2c662be168f5f2d3fd", + "https://bcr.bazel.build/modules/rules_go/0.53.0/MODULE.bazel": "a4ed760d3ac0dbc0d7b967631a9a3fd9100d28f7d9fcf214b4df87d4bfff5f9a", + "https://bcr.bazel.build/modules/rules_go/0.59.0/MODULE.bazel": "b7e43e7414a3139a7547d1b4909b29085fbe5182b6c58cbe1ed4c6272815aeae", + "https://bcr.bazel.build/modules/rules_go/0.59.0/source.json": "1df17bb7865cfc029492c30163cee891d0dd8658ea0d5bfdf252c4b6db5c1ef6", + "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", + "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86", + "https://bcr.bazel.build/modules/rules_java/6.3.0/MODULE.bazel": "a97c7678c19f236a956ad260d59c86e10a463badb7eb2eda787490f4c969b963", + "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31", + "https://bcr.bazel.build/modules/rules_java/7.1.0/MODULE.bazel": "30d9135a2b6561c761bd67bd4990da591e6bdc128790ce3e7afd6a3558b2fb64", + "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a", + "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6", + "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab", + "https://bcr.bazel.build/modules/rules_java/7.4.0/MODULE.bazel": "a592852f8a3dd539e82ee6542013bf2cadfc4c6946be8941e189d224500a8934", + "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", + "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017", + "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939", + "https://bcr.bazel.build/modules/rules_java/8.6.0/MODULE.bazel": "9c064c434606d75a086f15ade5edb514308cccd1544c2b2a89bbac4310e41c71", + "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2", + "https://bcr.bazel.build/modules/rules_java/8.9.0/MODULE.bazel": "e17c876cb53dcd817b7b7f0d2985b710610169729e8c371b2221cacdcd3dce4a", + "https://bcr.bazel.build/modules/rules_java/9.1.0/MODULE.bazel": "ee63f27e36a3fada80342869361182f120a9819c74320e8e65b1e04ba0cd7a9d", + "https://bcr.bazel.build/modules/rules_java/9.3.0/MODULE.bazel": "f657c72d65ac449caae9abf2e68e66c0d36f9416848c4c4903d0b3234229e7f2", + "https://bcr.bazel.build/modules/rules_java/9.3.0/source.json": "59ae7e662c3c7042b88bbb42ad12483523e234c65ebe4c51611baa43e85cb248", + "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", + "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909", + "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", + "https://bcr.bazel.build/modules/rules_jvm_external/6.2/MODULE.bazel": "36a6e52487a855f33cb960724eb56547fa87e2c98a0474c3acad94339d7f8e99", + "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0", + "https://bcr.bazel.build/modules/rules_jvm_external/6.7/MODULE.bazel": "e717beabc4d091ecb2c803c2d341b88590e9116b8bf7947915eeb33aab4f96dd", + "https://bcr.bazel.build/modules/rules_jvm_external/6.9/MODULE.bazel": "07c5db05527db7744a54fcffd653e1550d40e0540207a7f7e6d0a4de5bef8274", + "https://bcr.bazel.build/modules/rules_jvm_external/6.9/source.json": "b12970214f3cc144b26610caeb101fa622d910f1ab3d98f0bae1058edbd00bd4", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.5/MODULE.bazel": "043a16a572f610558ec2030db3ff0c9938574e7dd9f58bded1bb07c0192ef025", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3", + "https://bcr.bazel.build/modules/rules_kotlin/2.3.20/MODULE.bazel": "3443d53d275e14fecfebd0b491f01d06ea3883c04a1b3336e7ae9d5ec9066bef", + "https://bcr.bazel.build/modules/rules_kotlin/2.3.20/source.json": "5a5553cffea43f2c5156c8ad0de4a14ad95413ceb39cd4d08f50e2aea86927e8", + "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", + "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", + "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c", + "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb", + "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a", + "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06", + "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7", + "https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483", + "https://bcr.bazel.build/modules/rules_proto/6.0.0/MODULE.bazel": "b531d7f09f58dce456cd61b4579ce8c86b38544da75184eadaf0a7cb7966453f", + "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73", + "https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2", + "https://bcr.bazel.build/modules/rules_proto/7.1.0/MODULE.bazel": "002d62d9108f75bb807cd56245d45648f38275cb3a99dcd45dfb864c5d74cb96", + "https://bcr.bazel.build/modules/rules_proto/7.1.0/source.json": "39f89066c12c24097854e8f57ab8558929f9c8d474d34b2c00ac04630ad8940e", + "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", + "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300", + "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382", + "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed", + "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", + "https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937", + "https://bcr.bazel.build/modules/rules_python/0.37.2/MODULE.bazel": "b5ffde91410745750b6c13be1c5dc4555ef5bc50562af4a89fd77807fdde626a", + "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", + "https://bcr.bazel.build/modules/rules_python/1.0.0/MODULE.bazel": "898a3d999c22caa585eb062b600f88654bf92efb204fa346fb55f6f8edffca43", + "https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13", + "https://bcr.bazel.build/modules/rules_python/1.4.1/MODULE.bazel": "8991ad45bdc25018301d6b7e1d3626afc3c8af8aaf4bc04f23d0b99c938b73a6", + "https://bcr.bazel.build/modules/rules_python/1.6.0/MODULE.bazel": "7e04ad8f8d5bea40451cf80b1bd8262552aa73f841415d20db96b7241bd027d8", + "https://bcr.bazel.build/modules/rules_python/1.7.0/MODULE.bazel": "d01f995ecd137abf30238ad9ce97f8fc3ac57289c8b24bd0bf53324d937a14f8", + "https://bcr.bazel.build/modules/rules_python/1.7.0/source.json": "028a084b65dcf8f4dc4f82f8778dbe65df133f234b316828a82e060d81bdce32", + "https://bcr.bazel.build/modules/rules_robolectric/4.14.1.2/MODULE.bazel": "d44fec647d0aeb67b9f3b980cf68ba634976f3ae7ccd6c07d790b59b87a4f251", + "https://bcr.bazel.build/modules/rules_robolectric/4.16.1/MODULE.bazel": "9e8e8dd7b19457855fb40b6e9df8e7751584508630f704f26a798b9d1e827197", + "https://bcr.bazel.build/modules/rules_robolectric/4.16.1/source.json": "3e8c1302ace2d8b4a03666db61d97435744e5a712f4b462701e50454403eafb4", + "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", + "https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b", + "https://bcr.bazel.build/modules/rules_shell/0.4.1/MODULE.bazel": "00e501db01bbf4e3e1dd1595959092c2fadf2087b2852d3f553b5370f5633592", + "https://bcr.bazel.build/modules/rules_shell/0.6.1/MODULE.bazel": "72e76b0eea4e81611ef5452aa82b3da34caca0c8b7b5c0c9584338aa93bae26b", + "https://bcr.bazel.build/modules/rules_shell/0.6.1/source.json": "20ec05cd5e592055e214b2da8ccb283c7f2a421ea0dc2acbf1aa792e11c03d0c", + "https://bcr.bazel.build/modules/rules_swift/1.16.0/MODULE.bazel": "4a09f199545a60d09895e8281362b1ff3bb08bbde69c6fc87aff5b92fcc916ca", + "https://bcr.bazel.build/modules/rules_swift/2.1.1/MODULE.bazel": "494900a80f944fc7aa61500c2073d9729dff0b764f0e89b824eb746959bc1046", + "https://bcr.bazel.build/modules/rules_swift/2.4.0/MODULE.bazel": "1639617eb1ede28d774d967a738b4a68b0accb40650beadb57c21846beab5efd", + "https://bcr.bazel.build/modules/rules_swift/3.1.2/MODULE.bazel": "72c8f5cf9d26427cee6c76c8e3853eb46ce6b0412a081b2b6db6e8ad56267400", + "https://bcr.bazel.build/modules/rules_swift/3.1.2/source.json": "e85761f3098a6faf40b8187695e3de6d97944e98abd0d8ce579cb2daf6319a66", + "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", + "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", + "https://bcr.bazel.build/modules/stardoc/0.6.2/MODULE.bazel": "7060193196395f5dd668eda046ccbeacebfd98efc77fed418dbe2b82ffaa39fd", + "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", + "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5", + "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216", + "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91", + "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/MODULE.bazel": "75aab2373a4bbe2a1260b9bf2a1ebbdbf872d3bd36f80bff058dccd82e89422f", + "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/source.json": "5fba48bbe0ba48761f9e9f75f92876cafb5d07c0ce059cc7a8027416de94a05b", + "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", + "https://bcr.bazel.build/modules/upb/0.0.0-20230516-61a97ef/MODULE.bazel": "c0df5e35ad55e264160417fd0875932ee3c9dda63d9fccace35ac62f45e1b6f9", + "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", + "https://bcr.bazel.build/modules/zlib/1.2.12/MODULE.bazel": "3b1a8834ada2a883674be8cbd36ede1b6ec481477ada359cd2d3ddc562340b27", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806", + "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198" + }, + "selectedYankedVersions": {}, + "moduleExtensions": { + "@@pybind11_bazel+//:internal_configure.bzl%internal_configure_extension": { + "general": { + "bzlTransitiveDigest": "b+RP7Sgl8KN0VHamrgTqzGLuYPcQ/Mo4ptNkkHUIIlA=", + "usagesDigest": "D1r3lfzMuUBFxgG8V6o0bQTLMk3GkaGOaPzw53wrwyw=", + "recordedInputs": [ + "REPO_MAPPING:pybind11_bazel+,bazel_tools bazel_tools", + "FILE:@@pybind11_bazel+//MODULE.bazel e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34" + ], + "generatedRepoSpecs": { + "pybind11": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "build_file": "@@pybind11_bazel+//:pybind11-BUILD.bazel", + "strip_prefix": "pybind11-2.12.0", + "urls": [ + "https://github.com/pybind/pybind11/archive/v2.12.0.zip" + ] + } + } + } + } + }, + "@@rules_android+//bzlmod_extensions:apksig.bzl%apksig_extension": { + "general": { + "bzlTransitiveDigest": "IiT2UgJGnHaKiyP2A1yh3U/QWN4W9g/Byolrm78hC/s=", + "usagesDigest": "zr/niBQ/s2fHozWAsg4vI70wAxcuFjG+QtM15qGkq9o=", + "recordedInputs": [ + "REPO_MAPPING:rules_android+,bazel_tools bazel_tools" + ], + "generatedRepoSpecs": { + "apksig": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://android.googlesource.com/platform/tools/apksig/+archive/24e3075e68ebe17c0b529bb24bfda819db5e2f3b.tar.gz", + "build_file": "@@rules_android+//bzlmod_extensions:apksig.BUILD" + } + } + } + } + }, + "@@rules_android+//bzlmod_extensions:com_android_dex.bzl%com_android_dex_extension": { + "general": { + "bzlTransitiveDigest": "toD4gOZwGNfBEM+xec6eRi3BM2Z9EZ4oQrORZQH3sNY=", + "usagesDigest": "c1Y/KGGjUYCyd8zNIVTUh1bynVXRFz6xGKaSCBpQANM=", + "recordedInputs": [ + "REPO_MAPPING:rules_android+,bazel_tools bazel_tools" + ], + "generatedRepoSpecs": { + "com_android_dex": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://android.googlesource.com/platform/dalvik/+archive/5a81c499a569731e2395f7c8d13c0e0d4e17a2b6.tar.gz", + "build_file": "@@rules_android+//bzlmod_extensions:com_android_dex.BUILD" + } + } + } + } + }, + "@@rules_android+//rules/android_sdk_repository:rule.bzl%android_sdk_repository_extension": { + "general": { + "bzlTransitiveDigest": "+rMrzIrv7sImYmkbXJYv+gFpTJQ79X3MpwwMLI2A+oA=", + "usagesDigest": "VcVykmylnBLjc28g0eMzwGReXqnBcKjaHhiK6ahpgUc=", + "recordedInputs": [], + "generatedRepoSpecs": { + "androidsdk": { + "repoRuleId": "@@rules_android+//rules/android_sdk_repository:rule.bzl%_android_sdk_repository", + "attributes": { + "api_level": 36, + "build_tools_version": "35.0.0", + "path": "" + } + } + } + } + }, + "@@rules_python+//python/extensions:config.bzl%config": { + "general": { + "bzlTransitiveDigest": "iibnRYgg8LpcfmH7EAnVwYePC3jsVaJ6Id8XxUjSZps=", + "usagesDigest": "ZVSXMAGpD+xzVNPuvF1IoLBkty7TROO0+akMapt1pAg=", + "recordedInputs": [ + "REPO_MAPPING:rules_python+,bazel_tools bazel_tools", + "REPO_MAPPING:rules_python+,pypi__build rules_python++config+pypi__build", + "REPO_MAPPING:rules_python+,pypi__click rules_python++config+pypi__click", + "REPO_MAPPING:rules_python+,pypi__colorama rules_python++config+pypi__colorama", + "REPO_MAPPING:rules_python+,pypi__importlib_metadata rules_python++config+pypi__importlib_metadata", + "REPO_MAPPING:rules_python+,pypi__installer rules_python++config+pypi__installer", + "REPO_MAPPING:rules_python+,pypi__more_itertools rules_python++config+pypi__more_itertools", + "REPO_MAPPING:rules_python+,pypi__packaging rules_python++config+pypi__packaging", + "REPO_MAPPING:rules_python+,pypi__pep517 rules_python++config+pypi__pep517", + "REPO_MAPPING:rules_python+,pypi__pip rules_python++config+pypi__pip", + "REPO_MAPPING:rules_python+,pypi__pip_tools rules_python++config+pypi__pip_tools", + "REPO_MAPPING:rules_python+,pypi__pyproject_hooks rules_python++config+pypi__pyproject_hooks", + "REPO_MAPPING:rules_python+,pypi__setuptools rules_python++config+pypi__setuptools", + "REPO_MAPPING:rules_python+,pypi__tomli rules_python++config+pypi__tomli", + "REPO_MAPPING:rules_python+,pypi__wheel rules_python++config+pypi__wheel", + "REPO_MAPPING:rules_python+,pypi__zipp rules_python++config+pypi__zipp" + ], + "generatedRepoSpecs": { + "rules_python_internal": { + "repoRuleId": "@@rules_python+//python/private:internal_config_repo.bzl%internal_config_repo", + "attributes": { + "transition_setting_generators": {}, + "transition_settings": [] + } + }, + "pypi__build": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/e2/03/f3c8ba0a6b6e30d7d18c40faab90807c9bb5e9a1e3b2fe2008af624a9c97/build-1.2.1-py3-none-any.whl", + "sha256": "75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__click": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", + "sha256": "ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__colorama": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", + "sha256": "4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__importlib_metadata": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/2d/0a/679461c511447ffaf176567d5c496d1de27cbe34a87df6677d7171b2fbd4/importlib_metadata-7.1.0-py3-none-any.whl", + "sha256": "30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__installer": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/e5/ca/1172b6638d52f2d6caa2dd262ec4c811ba59eee96d54a7701930726bce18/installer-0.7.0-py3-none-any.whl", + "sha256": "05d1933f0a5ba7d8d6296bb6d5018e7c94fa473ceb10cf198a92ccea19c27b53", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__more_itertools": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/50/e2/8e10e465ee3987bb7c9ab69efb91d867d93959095f4807db102d07995d94/more_itertools-10.2.0-py3-none-any.whl", + "sha256": "686b06abe565edfab151cb8fd385a05651e1fdf8f0a14191e4439283421f8684", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__packaging": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl", + "sha256": "2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pep517": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/25/6e/ca4a5434eb0e502210f591b97537d322546e4833dcb4d470a48c375c5540/pep517-0.13.1-py3-none-any.whl", + "sha256": "31b206f67165b3536dd577c5c3f1518e8fbaf38cbc57efff8369a392feff1721", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pip": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/8a/6a/19e9fe04fca059ccf770861c7d5721ab4c2aebc539889e97c7977528a53b/pip-24.0-py3-none-any.whl", + "sha256": "ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pip_tools": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/0d/dc/38f4ce065e92c66f058ea7a368a9c5de4e702272b479c0992059f7693941/pip_tools-7.4.1-py3-none-any.whl", + "sha256": "4c690e5fbae2f21e87843e89c26191f0d9454f362d8acdbd695716493ec8b3a9", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pyproject_hooks": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/ae/f3/431b9d5fe7d14af7a32340792ef43b8a714e7726f1d7b69cc4e8e7a3f1d7/pyproject_hooks-1.1.0-py3-none-any.whl", + "sha256": "7ceeefe9aec63a1064c18d939bdc3adf2d8aa1988a510afec15151578b232aa2", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__setuptools": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/90/99/158ad0609729111163fc1f674a5a42f2605371a4cf036d0441070e2f7455/setuptools-78.1.1-py3-none-any.whl", + "sha256": "c3a9c4211ff4c309edb8b8c4f1cbfa7ae324c4ba9f91ff254e3d305b9fd54561", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__tomli": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl", + "sha256": "939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__wheel": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl", + "sha256": "55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__zipp": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/da/55/a03fd7240714916507e1fcf7ae355bd9d9ed2e6db492595f1a67f61681be/zipp-3.18.2-py3-none-any.whl", + "sha256": "dce197b859eb796242b0622af1b8beb0a722d52aa2f57133ead08edd5bf5374e", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + } + } + } + }, + "@@rules_python+//python/uv:uv.bzl%uv": { + "general": { + "bzlTransitiveDigest": "ijW9KS7qsIY+yBVvJ+Nr1mzwQox09j13DnE3iIwaeTM=", + "usagesDigest": "H8dQoNZcoqP+Mu0tHZTi4KHATzvNkM5ePuEqoQdklIU=", + "recordedInputs": [ + "REPO_MAPPING:rules_python+,bazel_tools bazel_tools", + "REPO_MAPPING:rules_python+,platforms platforms" + ], + "generatedRepoSpecs": { + "uv": { + "repoRuleId": "@@rules_python+//python/uv/private:uv_toolchains_repo.bzl%uv_toolchains_repo", + "attributes": { + "toolchain_type": "'@@rules_python+//python/uv:uv_toolchain_type'", + "toolchain_names": [ + "none" + ], + "toolchain_implementations": { + "none": "'@@rules_python+//python:none'" + }, + "toolchain_compatible_with": { + "none": [ + "@platforms//:incompatible" + ] + }, + "toolchain_target_settings": {} + } + } + } + } + } + }, + "facts": { + "@@rules_go+//go:extensions.bzl%go_sdk": { + "1.22.4": { + "aix_ppc64": [ + "go1.22.4.aix-ppc64.tar.gz", + "b9647fa9fc83a0cc5d4f092a19eaeaecf45f063a5aa7d4962fde65aeb7ae6ce1" + ], + "darwin_amd64": [ + "go1.22.4.darwin-amd64.tar.gz", + "c95967f50aa4ace34af0c236cbdb49a9a3e80ee2ad09d85775cb4462a5c19ed3" + ], + "darwin_arm64": [ + "go1.22.4.darwin-arm64.tar.gz", + "242b78dc4c8f3d5435d28a0d2cec9b4c1aa999b601fb8aa59fb4e5a1364bf827" + ], + "dragonfly_amd64": [ + "go1.22.4.dragonfly-amd64.tar.gz", + "f2fbb51af4719d3616efb482d6ed2b96579b474156f85a7ddc6f126764feec4b" + ], + "freebsd_386": [ + "go1.22.4.freebsd-386.tar.gz", + "7c54884bb9f274884651d41e61d1bc12738863ad1497e97ea19ad0e9aa6bf7b5" + ], + "freebsd_amd64": [ + "go1.22.4.freebsd-amd64.tar.gz", + "88d44500e1701dd35797619774d6dd51bf60f45a8338b0a82ddc018e4e63fb78" + ], + "freebsd_arm64": [ + "go1.22.4.freebsd-arm64.tar.gz", + "726dc093cf020277be45debf03c3b02b43c2efb3e2a5d4fba8f52579d65327dc" + ], + "freebsd_armv6l": [ + "go1.22.4.freebsd-arm.tar.gz", + "3d9efe47db142a22679aba46b1772e3900b0d87ae13bd2b3bc80dbf2ac0b2cd6" + ], + "freebsd_riscv64": [ + "go1.22.4.freebsd-riscv64.tar.gz", + "5f6b67e5e32f1d6ccb2d4dcb44934a5e2e870a877ba7443d86ec43cfc28afa71" + ], + "illumos_amd64": [ + "go1.22.4.illumos-amd64.tar.gz", + "d56ecc2f85b6418a21ef83879594d0c42ab4f65391a676bb12254870e6690d63" + ], + "linux_386": [ + "go1.22.4.linux-386.tar.gz", + "47a2a8d249a91eb8605c33bceec63aedda0441a43eac47b4721e3975ff916cec" + ], + "linux_amd64": [ + "go1.22.4.linux-amd64.tar.gz", + "ba79d4526102575196273416239cca418a651e049c2b099f3159db85e7bade7d" + ], + "linux_arm64": [ + "go1.22.4.linux-arm64.tar.gz", + "a8e177c354d2e4a1b61020aca3562e27ea3e8f8247eca3170e3fa1e0c2f9e771" + ], + "linux_armv6l": [ + "go1.22.4.linux-armv6l.tar.gz", + "e2b143fbacbc9cbd448e9ef41ac3981f0488ce849af1cf37e2341d09670661de" + ], + "linux_loong64": [ + "go1.22.4.linux-loong64.tar.gz", + "e2ff9436e4b34bf6926b06d97916e26d67a909a2effec17967245900f0816f1d" + ], + "linux_mips": [ + "go1.22.4.linux-mips.tar.gz", + "73f0dcc60458c4770593b05a7bc01cc0d31fc98f948c0c2334812c7a1f2fc3f1" + ], + "linux_mips64": [ + "go1.22.4.linux-mips64.tar.gz", + "417af97fc2630a647052375768be4c38adcc5af946352ea5b28613ea81ca5d45" + ], + "linux_mips64le": [ + "go1.22.4.linux-mips64le.tar.gz", + "7486e2d7dd8c98eb44df815ace35a7fe7f30b7c02326e3741bd934077508139b" + ], + "linux_mipsle": [ + "go1.22.4.linux-mipsle.tar.gz", + "69479c8aad301e459a8365b40cad1074a0dbba5defb9291669f94809c4c4be6e" + ], + "linux_ppc64": [ + "go1.22.4.linux-ppc64.tar.gz", + "dd238847e65bc3e2745caca475a5db6522a2fcf85cf6c38fc36a06642b19efd7" + ], + "linux_ppc64le": [ + "go1.22.4.linux-ppc64le.tar.gz", + "a3e5834657ef92523f570f798fed42f1f87bc18222a16815ec76b84169649ec4" + ], + "linux_riscv64": [ + "go1.22.4.linux-riscv64.tar.gz", + "56a827ff7dc6245bcd7a1e9288dffaa1d8b0fd7468562264c1523daf3b4f1b4a" + ], + "linux_s390x": [ + "go1.22.4.linux-s390x.tar.gz", + "7590c3e278e2dc6040aae0a39da3ca1eb2e3921673a7304cc34d588c45889eec" + ], + "netbsd_386": [ + "go1.22.4.netbsd-386.tar.gz", + "ddd2eebe34471a2502de6c5dad04ab27c9fc80cbde7a9ad5b3c66ecec4504e1d" + ], + "netbsd_amd64": [ + "go1.22.4.netbsd-amd64.tar.gz", + "33af79f6f935f6fbacc5d23876450b3567b79348fc065beef8e64081127dd234" + ], + "netbsd_arm64": [ + "go1.22.4.netbsd-arm64.tar.gz", + "c9a2971dec9f6d320c6f2b049b2353c6d0a2d35e87b8a4b2d78a2f0d62545f8e" + ], + "netbsd_armv6l": [ + "go1.22.4.netbsd-arm.tar.gz", + "fa3550ebd5375a70b3bcd342b5a71f4bd271dcbbfaf4eabefa2144ab5d8924b6" + ], + "openbsd_386": [ + "go1.22.4.openbsd-386.tar.gz", + "d21af022331bfdc2b5b161d616c3a1a4573d33cf7a30416ee509a8f3641deb47" + ], + "openbsd_amd64": [ + "go1.22.4.openbsd-amd64.tar.gz", + "72c0094c43f7e5722ec49c2a3e9dfa7a1123ac43a5f3a63eecf3e3795d3ff0ae" + ], + "openbsd_arm64": [ + "go1.22.4.openbsd-arm64.tar.gz", + "a7ab8d4e0b02bf06ed144ba42c61c0e93ee00f2b433415dfd4ad4b6e79f31650" + ], + "openbsd_armv6l": [ + "go1.22.4.openbsd-arm.tar.gz", + "1096831ea3c5ea3ca57d14251d9eda3786889531eb40d7d6775dcaa324d4b065" + ], + "openbsd_ppc64": [ + "go1.22.4.openbsd-ppc64.tar.gz", + "9716327c8a628358798898dc5148c49dbbeb5196bf2cbf088e550721a6e4f60b" + ], + "plan9_386": [ + "go1.22.4.plan9-386.tar.gz", + "a8dd4503c95c32a502a616ab78870a19889c9325fe9bd31eb16dd69346e4bfa8" + ], + "plan9_amd64": [ + "go1.22.4.plan9-amd64.tar.gz", + "5423a25808d76fe5aca8607a2e5ac5673abf45446b168cb5e9d8519ee9fe39a1" + ], + "plan9_armv6l": [ + "go1.22.4.plan9-arm.tar.gz", + "6af939ad583f5c85c09c53728ab7d38c3cc2b39167562d6c18a07c5c6608b370" + ], + "solaris_amd64": [ + "go1.22.4.solaris-amd64.tar.gz", + "e8cabe69c03085725afdb32a6f9998191a3e55a747b270d835fd05000d56abba" + ], + "windows_386": [ + "go1.22.4.windows-386.zip", + "aca4e2c37278a10f1c70dd0df142f7d66b50334fcee48978d409202d308d6d25" + ], + "windows_amd64": [ + "go1.22.4.windows-amd64.zip", + "26321c4d945a0035d8a5bc4a1965b0df401ff8ceac66ce2daadabf9030419a98" + ], + "windows_arm64": [ + "go1.22.4.windows-arm64.zip", + "8a2daa9ea28cbdafddc6171aefed384f4e5b6e714fb52116fe9ed25a132f37ed" + ], + "windows_armv6l": [ + "go1.22.4.windows-arm.zip", + "5fcd0671a49cecf39b41021621ee1b6e7aa1370f37122b72e80d4fd4185833b6" + ] + }, + "1.25.0": { + "aix_ppc64": [ + "go1.25.0.aix-ppc64.tar.gz", + "e5234a7dac67bc86c528fe9752fc9d63557918627707a733ab4cac1a6faed2d4" + ], + "darwin_amd64": [ + "go1.25.0.darwin-amd64.tar.gz", + "5bd60e823037062c2307c71e8111809865116714d6f6b410597cf5075dfd80ef" + ], + "darwin_arm64": [ + "go1.25.0.darwin-arm64.tar.gz", + "544932844156d8172f7a28f77f2ac9c15a23046698b6243f633b0a0b00c0749c" + ], + "dragonfly_amd64": [ + "go1.25.0.dragonfly-amd64.tar.gz", + "5ed3cf9a810a1483822538674f1336c06b51aa1b94d6d545a1a0319a48177120" + ], + "freebsd_386": [ + "go1.25.0.freebsd-386.tar.gz", + "abea5d5c6697e6b5c224731f2158fe87c602996a2a233ac0c4730cd57bf8374e" + ], + "freebsd_amd64": [ + "go1.25.0.freebsd-amd64.tar.gz", + "86e6fe0a29698d7601c4442052dac48bd58d532c51cccb8f1917df648138730b" + ], + "freebsd_arm": [ + "go1.25.0.freebsd-arm.tar.gz", + "d90b78e41921f72f30e8bbc81d9dec2cff7ff384a33d8d8debb24053e4336bfe" + ], + "freebsd_arm64": [ + "go1.25.0.freebsd-arm64.tar.gz", + "451d0da1affd886bfb291b7c63a6018527b269505db21ce6e14724f22ab0662e" + ], + "freebsd_riscv64": [ + "go1.25.0.freebsd-riscv64.tar.gz", + "7b565f76bd8bda46549eeaaefe0e53b251e644c230577290c0f66b1ecdb3cdbe" + ], + "illumos_amd64": [ + "go1.25.0.illumos-amd64.tar.gz", + "b1e1fdaab1ad25aa1c08d7a36c97d45d74b98b89c3f78c6d2145f77face54a2c" + ], + "linux_386": [ + "go1.25.0.linux-386.tar.gz", + "8c602dd9d99bc9453b3995d20ce4baf382cc50855900a0ece5de9929df4a993a" + ], + "linux_amd64": [ + "go1.25.0.linux-amd64.tar.gz", + "2852af0cb20a13139b3448992e69b868e50ed0f8a1e5940ee1de9e19a123b613" + ], + "linux_arm64": [ + "go1.25.0.linux-arm64.tar.gz", + "05de75d6994a2783699815ee553bd5a9327d8b79991de36e38b66862782f54ae" + ], + "linux_armv6l": [ + "go1.25.0.linux-armv6l.tar.gz", + "a5a8f8198fcf00e1e485b8ecef9ee020778bf32a408a4e8873371bfce458cd09" + ], + "linux_loong64": [ + "go1.25.0.linux-loong64.tar.gz", + "cab86b1cf761b1cb3bac86a8877cfc92e7b036fc0d3084123d77013d61432afc" + ], + "linux_mips": [ + "go1.25.0.linux-mips.tar.gz", + "d66b6fb74c3d91b9829dc95ec10ca1f047ef5e89332152f92e136cf0e2da5be1" + ], + "linux_mips64": [ + "go1.25.0.linux-mips64.tar.gz", + "4082e4381a8661bc2a839ff94ba3daf4f6cde20f8fb771b5b3d4762dc84198a2" + ], + "linux_mips64le": [ + "go1.25.0.linux-mips64le.tar.gz", + "70002c299ec7f7175ac2ef673b1b347eecfa54ae11f34416a6053c17f855afcc" + ], + "linux_mipsle": [ + "go1.25.0.linux-mipsle.tar.gz", + "b00a3a39eff099f6df9f1c7355bf28e4589d0586f42d7d4a394efb763d145a73" + ], + "linux_ppc64": [ + "go1.25.0.linux-ppc64.tar.gz", + "df166f33bd98160662560a72ff0b4ba731f969a80f088922bddcf566a88c1ec1" + ], + "linux_ppc64le": [ + "go1.25.0.linux-ppc64le.tar.gz", + "0f18a89e7576cf2c5fa0b487a1635d9bcbf843df5f110e9982c64df52a983ad0" + ], + "linux_riscv64": [ + "go1.25.0.linux-riscv64.tar.gz", + "c018ff74a2c48d55c8ca9b07c8e24163558ffec8bea08b326d6336905d956b67" + ], + "linux_s390x": [ + "go1.25.0.linux-s390x.tar.gz", + "34e5a2e19f2292fbaf8783e3a241e6e49689276aef6510a8060ea5ef54eee408" + ], + "netbsd_386": [ + "go1.25.0.netbsd-386.tar.gz", + "f8586cdb7aa855657609a5c5f6dbf523efa00c2bbd7c76d3936bec80aa6c0aba" + ], + "netbsd_amd64": [ + "go1.25.0.netbsd-amd64.tar.gz", + "ae8dc1469385b86a157a423bb56304ba45730de8a897615874f57dd096db2c2a" + ], + "netbsd_arm": [ + "go1.25.0.netbsd-arm.tar.gz", + "1ff7e4cc764425fc9dd6825eaee79d02b3c7cafffbb3691687c8d672ade76cb7" + ], + "netbsd_arm64": [ + "go1.25.0.netbsd-arm64.tar.gz", + "e1b310739f26724216aa6d7d7208c4031f9ff54c9b5b9a796ddc8bebcb4a5f16" + ], + "openbsd_386": [ + "go1.25.0.openbsd-386.tar.gz", + "4802a9b20e533da91adb84aab42e94aa56cfe3e5475d0550bed3385b182e69d8" + ], + "openbsd_amd64": [ + "go1.25.0.openbsd-amd64.tar.gz", + "c016cd984bebe317b19a4f297c4f50def120dc9788490540c89f28e42f1dabe1" + ], + "openbsd_arm": [ + "go1.25.0.openbsd-arm.tar.gz", + "a1e31d0bf22172ddde42edf5ec811ef81be43433df0948ece52fecb247ccfd8d" + ], + "openbsd_arm64": [ + "go1.25.0.openbsd-arm64.tar.gz", + "343ea8edd8c218196e15a859c6072d0dd3246fbbb168481ab665eb4c4140458d" + ], + "openbsd_ppc64": [ + "go1.25.0.openbsd-ppc64.tar.gz", + "694c14da1bcaeb5e3332d49bdc2b6d155067648f8fe1540c5de8f3cf8e157154" + ], + "openbsd_riscv64": [ + "go1.25.0.openbsd-riscv64.tar.gz", + "aa510ad25cf54c06cd9c70b6d80ded69cb20188ac6e1735655eef29ff7e7885f" + ], + "plan9_386": [ + "go1.25.0.plan9-386.tar.gz", + "46f8cef02086cf04bf186c5912776b56535178d4cb319cd19c9fdbdd29231986" + ], + "plan9_amd64": [ + "go1.25.0.plan9-amd64.tar.gz", + "29b34391d84095e44608a228f63f2f88113a37b74a79781353ec043dfbcb427b" + ], + "plan9_arm": [ + "go1.25.0.plan9-arm.tar.gz", + "0a047107d13ebe7943aaa6d54b1d7bbd2e45e68ce449b52915a818da715799c2" + ], + "solaris_amd64": [ + "go1.25.0.solaris-amd64.tar.gz", + "9977f9e4351984364a3b2b78f8b88bfd1d339812356d5237678514594b7d3611" + ], + "windows_386": [ + "go1.25.0.windows-386.zip", + "df9f39db82a803af0db639e3613a36681ab7a42866b1384b3f3a1045663961a7" + ], + "windows_amd64": [ + "go1.25.0.windows-amd64.zip", + "89efb4f9b30812eee083cc1770fdd2913c14d301064f6454851428f9707d190b" + ], + "windows_arm64": [ + "go1.25.0.windows-arm64.zip", + "27bab004c72b3d7bd05a69b6ec0fc54a309b4b78cc569dd963d8b3ec28bfdb8c" + ] + } + } + } +} diff --git a/androidApp/BUILD.bazel b/androidApp/BUILD.bazel new file mode 100644 index 00000000..629c498f --- /dev/null +++ b/androidApp/BUILD.bazel @@ -0,0 +1,25 @@ +""" +androidApp — Android application binary (debug APK). + +Produces a debug APK with native multidex and Java 8 core library desugaring. +The `plugin.properties` exclusion from Gradle packaging is handled by the +android_binary rule's default resource exclusion behavior. + +Developer command: bazel build //androidApp:android_app +""" + +load("@rules_android//rules:rules.bzl", "android_binary") + +exports_files([ + "BazelAndroidManifest.xml", + "src/main/AndroidManifest.xml", +]) + +android_binary( + name = "android_app", + manifest = "BazelAndroidManifest.xml", + custom_package = "dev.stapler.stelekit.android", + deps = ["//kmp/src/androidMain/kotlin:android_main"], + multidex = "native", + visibility = ["//visibility:public"], +) diff --git a/androidApp/BazelAndroidManifest.xml b/androidApp/BazelAndroidManifest.xml new file mode 100644 index 00000000..069dc34d --- /dev/null +++ b/androidApp/BazelAndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index 0d564264..0768ec76 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -32,7 +32,7 @@ android { versionCode = computedVersionCode versionName = appVersionStr testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - buildConfigField("String", "GIT_COMMIT_HASH", "\"$gitCommitHash\"") + resValue("string", "git_commit_hash", gitCommitHash) } signingConfigs { @@ -79,7 +79,6 @@ android { buildFeatures { compose = true - buildConfig = true } lint { diff --git a/androidApp/src/main/kotlin/dev/stapler/stelekit/SteleKitApplication.kt b/androidApp/src/main/kotlin/dev/stapler/stelekit/SteleKitApplication.kt index 996ac3bc..506ec415 100644 --- a/androidApp/src/main/kotlin/dev/stapler/stelekit/SteleKitApplication.kt +++ b/androidApp/src/main/kotlin/dev/stapler/stelekit/SteleKitApplication.kt @@ -9,9 +9,9 @@ import dev.stapler.stelekit.platform.PlatformFileSystem import dev.stapler.stelekit.platform.PlatformSettings import dev.stapler.stelekit.platform.SteleKitContext import dev.stapler.stelekit.platform.WriteBehindQueue -import dev.stapler.stelekit.platform.measurement.MeasurementDeviceRegistry -import dev.stapler.stelekit.app.BuildConfig +import dev.stapler.stelekit.app.R import dev.stapler.stelekit.performance.BuildInfo +import dev.stapler.stelekit.platform.measurement.MeasurementDeviceRegistry import dev.stapler.stelekit.platform.measurement.ble.KableBleScanner import dev.stapler.stelekit.platform.sensor.AndroidCameraProvider import dev.stapler.stelekit.platform.sensor.ARCoreDepthProvider @@ -55,8 +55,8 @@ class SteleKitApplication : Application() { override fun onCreate() { super.onCreate() try { - BuildInfo.commitHash = BuildConfig.GIT_COMMIT_HASH - BuildInfo.appVersion = BuildConfig.VERSION_NAME + BuildInfo.commitHash = getString(R.string.git_commit_hash) + BuildInfo.appVersion = packageManager.getPackageInfo(packageName, 0).versionName.orEmpty() SteleKitContext.init(this) DriverFactory.setContext(this) CredentialStore.init(this) diff --git a/kmp/BUILD.bazel b/kmp/BUILD.bazel new file mode 100644 index 00000000..c86be9dd --- /dev/null +++ b/kmp/BUILD.bazel @@ -0,0 +1,103 @@ +""" +kmp/ package — top-level developer-facing aliases. + +Developer commands: + bazel run //kmp:desktop_app # Launch SteleKit desktop UI + bazel build //kmp:android_app # Build Android APK + bazel test //kmp:jvm_tests # Run JVM (desktop + shared) test suite + bazel test //kmp:business_tests # Run business-logic only tests (no UI) + bazel mobile-install //kmp:android_app # Install APK on connected device + +See CLAUDE.md for the full Gradle → Bazel command equivalence table. +""" + +load("@rules_android//rules:rules.bzl", "android_library") + +# ── Android KMP resources ───────────────────────────────────────────────────── +# res/ lives in the kmp/ Bazel package (no BUILD in src/androidMain/), so the +# android_library that exposes R must be defined here. +android_library( + name = "kmp_android_resources", + manifest = "src/androidMain/AndroidManifest.xml", + resource_files = glob(["src/androidMain/res/**"]), + custom_package = "dev.stapler.stelekit", + visibility = ["//kmp/src/androidMain/kotlin:__pkg__"], +) + +# ── JVM / Desktop ───────────────────────────────────────────────────────────── + +alias( + name = "desktop_app", + actual = "//kmp/src/jvmMain/kotlin:desktop_app", + visibility = ["//visibility:public"], +) + +# ── Android ─────────────────────────────────────────────────────────────────── + +alias( + name = "android_app", + actual = "//androidApp:android_app", + visibility = ["//visibility:public"], +) + +# ── Tests ───────────────────────────────────────────────────────────────────── + +test_suite( + name = "jvm_tests", + tests = ["//kmp/src/jvmTest/kotlin:jvm_tests"], + visibility = ["//visibility:public"], +) + +test_suite( + name = "business_tests", + tests = ["//kmp/src/businessTest/kotlin:business_tests"], + visibility = ["//visibility:public"], +) + +# ── Web / WASM-JS ───────────────────────────────────────────────────────────── +# +# Kotlin/WASM is not yet supported by rules_kotlin (tracking: rules_kotlin#567). +# This genrule wraps the Gradle wasmJsBrowserDistribution task so the web bundle +# is addressable as a Bazel target today. When rules_kotlin ships native WASM +# support the genrule can be replaced with kt_wasm_library + bundler rules. +# +# The target runs without sandboxing (tags = ["local"]) because Gradle manages +# its own dependency resolution and the hermetic Bazel sandbox would block it. +# Gradle's own incremental cache provides action-level caching in the interim. +# +# Build: bazel build //kmp:web_app +# Output: bazel-bin/kmp/web_dist.tar.gz (unpack to serve the browser bundle) +genrule( + name = "web_dist", + srcs = [], + outs = ["web_dist.tar.gz"], + cmd = """ + WORKSPACE=$$(dirname $$(realpath gradlew)) && \ + "$$WORKSPACE/gradlew" :kmp:wasmJsBrowserDistribution \ + --project-dir "$$WORKSPACE" \ + -PenableJs=true --no-daemon --quiet && \ + tar -czf $(OUTS) -C "$$WORKSPACE/kmp/build/dist/wasmJs/productionExecutable" . + """, + tags = ["local"], + visibility = ["//visibility:public"], +) + +alias( + name = "web_app", + actual = ":web_dist", + visibility = ["//visibility:public"], +) + +# ── Detekt linting ──────────────────────────────────────────────────────────── +# Option A (plan.md §6.1.1): Detekt runs as a standalone CI step via the Gradle +# wrapper — not a Bazel target — because Bazel caching does not benefit a fast +# linter that already has its own incremental cache. +# +# CI invocation (in .github/workflows/ci.yml, existing job): +# ./gradlew :kmp:detekt +# +# The buildSrc custom ruleset (buildSrc.jar) is picked up automatically by the +# Gradle detekt task. No Bazel rule needed for Detekt at this time (see plan ADR). +# +# If Detekt becomes a bottleneck, switch to Option B: genrule that downloads +# the Detekt CLI JAR via rules_jvm_external and runs it against source directories. diff --git a/kmp/build.gradle.kts b/kmp/build.gradle.kts index dd755f54..4cc84c71 100644 --- a/kmp/build.gradle.kts +++ b/kmp/build.gradle.kts @@ -250,8 +250,8 @@ kotlin { // Model (~100MB) is downloaded on first use via DepthModelDownloader, not bundled. implementation("com.microsoft.onnxruntime:onnxruntime-android:1.20.0") - // JGit 5.13.x — Android git operations (Android-safe; Java 11 APIs with desugaring) - implementation("org.eclipse.jgit:org.eclipse.jgit:5.13.3.202401111512-r") + // JGit 7.x — Android git operations (matches Bazel-resolved version; desugaring handles Java 11 APIs) + implementation("org.eclipse.jgit:org.eclipse.jgit:7.3.0.202506031305-r") // JGit SSH/JSch integration module (provides JschConfigSessionFactory) // Excludes com.jcraft:jsch so the mwiede fork below is the sole jsch on classpath implementation("org.eclipse.jgit:org.eclipse.jgit.ssh.jsch:5.13.3.202401111512-r") { diff --git a/kmp/src/androidMain/kotlin/BUILD.bazel b/kmp/src/androidMain/kotlin/BUILD.bazel new file mode 100644 index 00000000..f09e33ce --- /dev/null +++ b/kmp/src/androidMain/kotlin/BUILD.bazel @@ -0,0 +1,162 @@ +""" +androidMain — Android-specific source files (Activity, SQLite driver, etc.). + +Compiled together with commonMain and jvmCommonMain in a single kt_android_library +so that Kotlin Multiplatform expect/actual resolution works under Bazel. +This mirrors how jvm_main_lib combines commonMain + jvmCommonMain + jvmMain for JVM. + +Note on JGit versioning: rules_jvm_external cannot resolve the same +groupId:artifactId at two different versions. The JGit 5.13.x ssh.jsch +module (org.eclipse.jgit:org.eclipse.jgit.ssh.jsch:5.13.3) has a different +artifactId than the 7.x ssh.apache module, so both can co-exist in the +artifact list. However org.eclipse.jgit:org.eclipse.jgit:7.3.0 is the +resolved version — Android code calling JGit 5.13.x APIs must be aware +that the 7.x JAR is on the compile classpath. +""" + +load("@rules_kotlin//kotlin:android.bzl", "kt_android_library") + +kt_android_library( + name = "android_main", + srcs = [ + "//kmp/src/commonMain/kotlin:kt_srcs", + "//kmp/src/jvmCommonMain/kotlin:kt_srcs", + ] + glob(["**/*.kt"]), + common_srcs = ["//kmp/src/commonMain/kotlin:kt_srcs"], + kotlinc_opts = "//:kmp_android_kotlinc_opts", + plugins = [ + "//:compose_compiler_plugin", + "//:serialization_compiler_plugin", + ], + custom_package = "dev.stapler.stelekit", + deps = [ + # Android string resources (R.string.no_graph_*) — defined in kmp/ package + # because kmp/src/androidMain/res/ has no own BUILD file. + "//kmp:kmp_android_resources", + + # SQLDelight (from commonMain) + "//kmp/src/generated/sqldelight:sqldelight_generated_jvm", + "@maven//:app_cash_sqldelight_runtime_jvm", + "@maven//:app_cash_sqldelight_coroutines_extensions_jvm", + "@maven//:app_cash_sqldelight_async_extensions_jvm", + + # SQLDelight Android driver (from androidMain) + "@maven//:app_cash_sqldelight_android_driver", + "@maven//:com_github_requery_sqlite_android", + + # Arrow (from commonMain) + "@maven//:io_arrow_kt_arrow_core_jvm", + "@maven//:io_arrow_kt_arrow_optics_jvm", + "@maven//:io_arrow_kt_arrow_fx_coroutines_jvm", + "@maven//:io_arrow_kt_arrow_resilience_jvm", + + # Kotlinx (from commonMain) + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_core_jvm", + "@maven//:org_jetbrains_kotlinx_kotlinx_datetime_jvm", + "@maven//:org_jetbrains_kotlinx_kotlinx_serialization_json_jvm", + + # Kotlin coroutines Android (from androidMain) + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_android", + + # Markdown (from commonMain) + "@maven//:org_jetbrains_markdown_jvm", + + # Jetpack Compose Android (from commonMain) + "@maven//:androidx_compose_ui_ui", + "@maven//:androidx_compose_ui_ui_graphics", + "@maven//:androidx_compose_material3_material3", + + # AndroidX (from androidMain) + "@maven//:androidx_activity_activity_compose", + "@maven//:androidx_appcompat_appcompat", + "@maven//:androidx_core_core_ktx", + "@maven//:androidx_documentfile_documentfile", + + # Lifecycle (from commonMain) + "@maven//:org_jetbrains_androidx_lifecycle_lifecycle_runtime_compose", + "@maven//:org_jetbrains_androidx_lifecycle_lifecycle_viewmodel_compose", + + # Coil (from commonMain) + "@maven//:io_coil_kt_coil3_coil_compose_jvm", + "@maven//:io_coil_kt_coil3_coil_network_ktor3_jvm", + + # Ktor (from commonMain) + "@maven//:io_ktor_ktor_client_core_jvm", + "@maven//:io_ktor_ktor_client_content_negotiation_jvm", + "@maven//:io_ktor_ktor_serialization_kotlinx_json_jvm", + + # Ktor OkHttp engine (from androidMain) + "@maven//:io_ktor_ktor_client_okhttp_jvm", + + # OpenTelemetry API (from jvmCommonMain) + SDK (from androidMain) + "@maven//:io_opentelemetry_opentelemetry_api", + "@maven//:io_opentelemetry_opentelemetry_sdk", + "@maven//:io_opentelemetry_opentelemetry_exporter_logging", + + # Ksoup (from commonMain) + "@maven//:com_fleeksoft_ksoup_ksoup_jvm", + + # Kotlin Multiplatform Diff (from commonMain) + "@maven//:io_github_petertrr_kotlin_multiplatform_diff_jvm", + + # JankStats (from androidMain) + "@maven//:androidx_metrics_metrics_performance", + + # Security-crypto (from androidMain) + "@maven//:androidx_security_security_crypto", + + # MLKit on-device LLM (from androidMain) + "@maven//:com_google_mlkit_genai_prompt", + + # MLKit Image Labeling (from androidMain) + "@maven//:com_google_mlkit_image_labeling", + + # MLKit Text Recognition (from androidMain) + "@maven//:com_google_mlkit_text_recognition", + + # ARCore Depth API (from androidMain) + "@maven//:com_google_ar_core", + + # CameraX (from androidMain) + "@maven//:androidx_camera_camera_core", + "@maven//:androidx_camera_camera_camera2", + "@maven//:androidx_camera_camera_lifecycle", + + # Lifecycle process (required by CameraX camera-lifecycle; from androidMain) + "@maven//:androidx_lifecycle_lifecycle_process", + + # ONNX Runtime Android (from androidMain) + "@maven//:com_microsoft_onnxruntime_onnxruntime_android", + + # ExifInterface (from androidMain) + "@maven//:androidx_exifinterface_exifinterface", + + # PDFBox Android (from androidMain) + "@maven//:com_tom_roush_pdfbox_android", + + # Kable BLE Android (from androidMain) + "@maven//:com_juul_kable_core_android", + + # Okio — cross-platform file I/O (from commonMain) + "@maven//:com_squareup_okio_okio_jvm", + + # Compose material icons extended (Android — JVM uses -desktop variant) + "@maven//:androidx_compose_material_material_icons_extended", + + # Glance (from androidMain) + "@maven//:androidx_glance_glance_appwidget", + "@maven//:androidx_glance_glance_material3", + + # WorkManager (from androidMain) + "@maven//:androidx_work_work_runtime_ktx", + + # JGit (from androidMain — see note above about version conflict) + "@maven//:org_eclipse_jgit_org_eclipse_jgit", + "@maven//:org_eclipse_jgit_org_eclipse_jgit_ssh_jsch", + "@maven//:com_github_mwiede_jsch", + + # Kotlin stdlib + "@maven//:org_jetbrains_kotlin_kotlin_stdlib", + ], + visibility = ["//kmp:__subpackages__", "//androidApp:__subpackages__"], +) diff --git a/kmp/src/androidMain/kotlin/dev/stapler/stelekit/git/AndroidGitRepository.kt b/kmp/src/androidMain/kotlin/dev/stapler/stelekit/git/AndroidGitRepository.kt index 639b7680..8eff157f 100644 --- a/kmp/src/androidMain/kotlin/dev/stapler/stelekit/git/AndroidGitRepository.kt +++ b/kmp/src/androidMain/kotlin/dev/stapler/stelekit/git/AndroidGitRepository.kt @@ -81,6 +81,8 @@ class AndroidGitRepository( override fun update(completed: Int) {} override fun endTask() {} override fun isCancelled() = job?.isCancelled == true + // showDuration added in JGit 7.x; Bazel resolves to 7.x on Android too + override fun showDuration(enabled: Boolean) {} }) configureAuth(cmd, auth, preResolvedToken) diff --git a/kmp/src/androidUnitTest/kotlin/BUILD.bazel b/kmp/src/androidUnitTest/kotlin/BUILD.bazel new file mode 100644 index 00000000..6783376b --- /dev/null +++ b/kmp/src/androidUnitTest/kotlin/BUILD.bazel @@ -0,0 +1,56 @@ +""" +androidUnitTest — Android local unit tests via Robolectric. + +Screenshot tests using roborazzi are excluded (kept in Gradle). + +Note: The @robolectric//bazel:android-all shorthand is not available because +the robolectric module is not in BCR for the required version. Instead, +android-all is declared as a Maven artifact directly. + +To run: bazel test //kmp/src/androidUnitTest/kotlin:android_unit_tests +""" + +load("@rules_android//rules:rules.bzl", "android_local_test") +load("@rules_kotlin//kotlin:android.bzl", "kt_android_library") + +# Compile test sources into an Android library first +kt_android_library( + name = "android_unit_test_lib", + srcs = glob( + ["**/*.kt"], + exclude = [ + # Roborazzi screenshot tests — no Bazel integration; kept in Gradle + "**/*Roborazzi*.kt", + "**/*Screenshot*.kt", + ], + ), + custom_package = "dev.stapler.stelekit", + testonly = True, + kotlinc_opts = "//:kmp_android_kotlinc_opts", + associates = ["//kmp/src/androidMain/kotlin:android_main"], + deps = [ + "@maven//:junit_junit", + "@maven//:org_jetbrains_kotlin_kotlin_test_junit", + "@maven//:org_robolectric_robolectric", + "@maven//:androidx_test_core", + "@maven//:androidx_test_ext_junit", + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_test_jvm", + "@maven//:androidx_arch_core_core_testing", + "@maven//:androidx_glance_glance_appwidget_testing", + "@maven//:org_jetbrains_kotlin_kotlin_stdlib", + ], +) + +android_local_test( + name = "android_unit_tests", + manifest = "//androidApp:BazelAndroidManifest.xml", + test_class = "dev.stapler.stelekit.AllAndroidUnitTests", + # android-all provides robolectric-deps.properties in the test's runfiles so that + # android_local_test can find the Android SDK JARs when running offline (-Drobolectric.offline=true). + data = ["@rules_robolectric//bazel:android-all"], + deps = [ + ":android_unit_test_lib", + "@maven//:org_robolectric_robolectric", + ], + visibility = ["//visibility:public"], +) diff --git a/kmp/src/androidUnitTest/kotlin/dev/stapler/stelekit/AllAndroidUnitTests.kt b/kmp/src/androidUnitTest/kotlin/dev/stapler/stelekit/AllAndroidUnitTests.kt new file mode 100644 index 00000000..619c0dfd --- /dev/null +++ b/kmp/src/androidUnitTest/kotlin/dev/stapler/stelekit/AllAndroidUnitTests.kt @@ -0,0 +1,33 @@ +package dev.stapler.stelekit + +import dev.stapler.stelekit.db.WalConfiguredCallbackTest +import dev.stapler.stelekit.platform.LegacyPathValidationTest +import dev.stapler.stelekit.platform.PlatformFileSystemPickerTest +import dev.stapler.stelekit.platform.PlatformFileSystemSafTest +import dev.stapler.stelekit.platform.PlatformFileSystemUriLogicTest +import dev.stapler.stelekit.platform.SafPermissionPersistenceTest +import dev.stapler.stelekit.platform.SafPermissionStateTransitionTest +import dev.stapler.stelekit.platform.ShadowFileCacheTest +import dev.stapler.stelekit.platform.UpgradePathTest +import dev.stapler.stelekit.platform.sensor.ExifOrientationFixerTest +import dev.stapler.stelekit.ui.LoadingStateTest +import dev.stapler.stelekit.voice.AndroidSpeechRecognizerPermissionTest +import org.junit.runner.RunWith +import org.junit.runners.Suite + +@RunWith(Suite::class) +@Suite.SuiteClasses( + WalConfiguredCallbackTest::class, + LegacyPathValidationTest::class, + PlatformFileSystemPickerTest::class, + PlatformFileSystemSafTest::class, + PlatformFileSystemUriLogicTest::class, + SafPermissionPersistenceTest::class, + SafPermissionStateTransitionTest::class, + ShadowFileCacheTest::class, + UpgradePathTest::class, + ExifOrientationFixerTest::class, + LoadingStateTest::class, + AndroidSpeechRecognizerPermissionTest::class, +) +class AllAndroidUnitTests diff --git a/kmp/src/businessTest/kotlin/BUILD.bazel b/kmp/src/businessTest/kotlin/BUILD.bazel new file mode 100644 index 00000000..3ff10145 --- /dev/null +++ b/kmp/src/businessTest/kotlin/BUILD.bazel @@ -0,0 +1,24 @@ +""" +businessTest — business logic tests (no UI dependencies). + +This source set compiles against jvm_main_lib; it has no Compose or platform +dependencies, making it fast to run in CI. +""" + +load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library", "kt_jvm_test") + +# Runnable test target — bazel test //kmp:business_tests +kt_jvm_test( + name = "business_tests", + srcs = glob(["**/*.kt"]), + test_class = "dev.stapler.stelekit.AllBusinessTests", + kotlinc_opts = "//:kmp_jvm_kotlinc_opts", + associates = ["//kmp/src/jvmMain/kotlin:jvm_main_lib"], + deps = [ + "@maven//:org_jetbrains_kotlin_kotlin_test_junit", + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_test_jvm", + "@maven//:org_jetbrains_kotlinx_kotlinx_serialization_json_jvm", + "@maven//:org_jetbrains_kotlin_kotlin_stdlib", + ], + visibility = ["//kmp:__subpackages__"], +) diff --git a/kmp/src/businessTest/kotlin/dev/stapler/stelekit/AllBusinessTests.kt b/kmp/src/businessTest/kotlin/dev/stapler/stelekit/AllBusinessTests.kt new file mode 100644 index 00000000..81d0389b --- /dev/null +++ b/kmp/src/businessTest/kotlin/dev/stapler/stelekit/AllBusinessTests.kt @@ -0,0 +1,37 @@ +package dev.stapler.stelekit + +import dev.stapler.stelekit.clipboard.BlockClipboardTest +import dev.stapler.stelekit.domain.ImportServiceTest +import dev.stapler.stelekit.editor.LinkInsertionTest +import dev.stapler.stelekit.flashcard.FlashcardPropertiesTest +import dev.stapler.stelekit.flashcard.FlashcardReviewTest +import dev.stapler.stelekit.performance.HistogramRegressionTest +import dev.stapler.stelekit.performance.HistogramWriterTest +import dev.stapler.stelekit.performance.PerfExporterPickerTest +import dev.stapler.stelekit.repository.BacklinkRepositoryTest +import dev.stapler.stelekit.ui.ToolbarActionTest +import dev.stapler.stelekit.voice.VoiceCaptureViewModelTest +import dev.stapler.stelekit.voice.VoiceNoteBlockFormatTest +import dev.stapler.stelekit.voice.VoicePipelineFactoryTest +import dev.stapler.stelekit.voice.VoiceSettingsTest +import org.junit.runner.RunWith +import org.junit.runners.Suite + +@RunWith(Suite::class) +@Suite.SuiteClasses( + BlockClipboardTest::class, + ImportServiceTest::class, + LinkInsertionTest::class, + FlashcardPropertiesTest::class, + FlashcardReviewTest::class, + HistogramRegressionTest::class, + HistogramWriterTest::class, + PerfExporterPickerTest::class, + BacklinkRepositoryTest::class, + ToolbarActionTest::class, + VoiceCaptureViewModelTest::class, + VoiceNoteBlockFormatTest::class, + VoicePipelineFactoryTest::class, + VoiceSettingsTest::class, +) +class AllBusinessTests diff --git a/kmp/src/commonMain/kotlin/BUILD.bazel b/kmp/src/commonMain/kotlin/BUILD.bazel new file mode 100644 index 00000000..d39eea72 --- /dev/null +++ b/kmp/src/commonMain/kotlin/BUILD.bazel @@ -0,0 +1,26 @@ +""" +commonMain sources for JVM and Android compilation. + +JVM: sources are exported via the kt_srcs filegroup and compiled together with +jvmCommonMain and jvmMain sources in //kmp/src/jvmMain/kotlin:jvm_main_lib. +Compiling commonMain alone for JVM is not possible because expect declarations +require their actual implementations to be present in the same compilation unit. + +Android: sources are exported via the kt_srcs filegroup and compiled together with +jvmCommonMain and androidMain sources in //kmp/src/androidMain/kotlin:android_main. +This mirrors the JVM pattern so expect/actual resolution works under Bazel. + +See ADR-005 for the double-compilation trade-off. +""" + +# ── JVM and Android flavor ──────────────────────────────────────────────────── +# Sources exported for inclusion in: +# - //kmp/src/jvmMain/kotlin:jvm_main_lib (JVM) +# - //kmp/src/androidMain/kotlin:android_main (Android) +# Both combine commonMain + jvmCommonMain + platform-specific sources into a +# single compilation unit so expect/actual declarations resolve correctly. +filegroup( + name = "kt_srcs", + srcs = glob(["**/*.kt"]), + visibility = ["//kmp:__subpackages__"], +) diff --git a/kmp/src/commonMain/kotlin/dev/stapler/stelekit/db/GraphLoader.kt b/kmp/src/commonMain/kotlin/dev/stapler/stelekit/db/GraphLoader.kt index 4d41be3b..e98e941d 100644 --- a/kmp/src/commonMain/kotlin/dev/stapler/stelekit/db/GraphLoader.kt +++ b/kmp/src/commonMain/kotlin/dev/stapler/stelekit/db/GraphLoader.kt @@ -698,6 +698,14 @@ class GraphLoader( } } logger.info("Background indexing complete.") + // One controlled FTS merge pass after the full batch, not per-page-save. + // saveBlocks intentionally skips ftsMerge to avoid reading a large index on every + // navigation; bulk callers compact once here when all inserts are done. + @OptIn(DirectRepositoryWrite::class) + writeActor.execute(DatabaseWriteActor.Priority.LOW) { + blockRepository.compactFtsIndex() + Unit.right() + } } finally { backgroundIndexJob = null PerformanceMonitor.endTrace("indexRemainingPages") diff --git a/kmp/src/commonMain/kotlin/dev/stapler/stelekit/repository/BlockWriteRepository.kt b/kmp/src/commonMain/kotlin/dev/stapler/stelekit/repository/BlockWriteRepository.kt index 4a6e2cc0..c6aacb24 100644 --- a/kmp/src/commonMain/kotlin/dev/stapler/stelekit/repository/BlockWriteRepository.kt +++ b/kmp/src/commonMain/kotlin/dev/stapler/stelekit/repository/BlockWriteRepository.kt @@ -51,6 +51,13 @@ interface BlockWriteRepository { @DirectRepositoryWrite suspend fun walCheckpoint() {} + /** + * Compact the FTS index with a single controlled merge pass. Call once after bulk + * indexing completes — not during incremental saves. No-op by default (non-SQLite backends). + */ + @DirectRepositoryWrite + suspend fun compactFtsIndex() {} + /** * Update only the content of a block. Does NOT touch structural fields * (parentUuid, position, level, leftUuid), eliminating the race condition diff --git a/kmp/src/commonMain/kotlin/dev/stapler/stelekit/repository/SqlDelightBlockRepository.kt b/kmp/src/commonMain/kotlin/dev/stapler/stelekit/repository/SqlDelightBlockRepository.kt index da4b16f4..f3d15287 100644 --- a/kmp/src/commonMain/kotlin/dev/stapler/stelekit/repository/SqlDelightBlockRepository.kt +++ b/kmp/src/commonMain/kotlin/dev/stapler/stelekit/repository/SqlDelightBlockRepository.kt @@ -193,10 +193,11 @@ class SqlDelightBlockRepository( override fun getBlockParent(blockUuid: BlockUuid): Flow> = flow { try { val block = queries.selectBlockByUuid(blockUuid.value).executeAsOneOrNull() - if (block == null || block.parent_uuid == null) { + val parentUuid = block?.parent_uuid + if (block == null || parentUuid == null) { emit(null.right()) } else { - val parent = queries.selectBlockByUuid(block.parent_uuid).executeAsOneOrNull() + val parent = queries.selectBlockByUuid(parentUuid).executeAsOneOrNull() emit(parent?.toBlockModel().right()) } } catch (e: CancellationException) { @@ -281,7 +282,10 @@ class SqlDelightBlockRepository( } } ftsAutomergeDefault() - ftsMerge() + // ftsMerge() is intentionally NOT called here. Calling merge=-200 on an already-large + // FTS index (e.g. after 500+ pages are indexed) adds hundreds of ms per navigation. + // Callers that do bulk indexing must invoke compactFtsIndex() once after the full + // batch is complete. Per-save compaction is handled by automerge=8. Unit.right() } catch (e: CancellationException) { runCatching { ftsAutomergeDefault() } @@ -386,6 +390,10 @@ class SqlDelightBlockRepository( } } + override suspend fun compactFtsIndex(): Unit = withContext(PlatformDispatcher.DB) { + ftsMerge() + } + override suspend fun saveBlocksUpdate(blocks: List): Either = withContext(PlatformDispatcher.DB) { try { blocks.chunked(WRITE_CHUNK_SIZE).forEach { chunk -> diff --git a/kmp/src/commonMain/kotlin/dev/stapler/stelekit/ui/components/SearchDialog.kt b/kmp/src/commonMain/kotlin/dev/stapler/stelekit/ui/components/SearchDialog.kt index 65e9a670..f50d4962 100644 --- a/kmp/src/commonMain/kotlin/dev/stapler/stelekit/ui/components/SearchDialog.kt +++ b/kmp/src/commonMain/kotlin/dev/stapler/stelekit/ui/components/SearchDialog.kt @@ -580,6 +580,7 @@ fun SearchResultRow( subtitle: String, isSelected: Boolean, onClick: () -> Unit, + modifier: Modifier = Modifier, snippet: String? = null ) = SearchResultRow( title = title, @@ -588,7 +589,8 @@ fun SearchResultRow( inlineTags = emptyList(), snippet = snippet, isSelected = isSelected, - onClick = onClick + onClick = onClick, + modifier = modifier, ) /** diff --git a/kmp/src/commonMain/resources/BUILD.bazel b/kmp/src/commonMain/resources/BUILD.bazel new file mode 100644 index 00000000..0f47df27 --- /dev/null +++ b/kmp/src/commonMain/resources/BUILD.bazel @@ -0,0 +1,11 @@ +load("@rules_java//java:defs.bzl", "java_library") + +# Classpath resources for commonMain — demo-graph and icons. +# resource_strip_prefix strips the path down to the resource roots +# so tests find resources as "demo-graph/..." not full package paths. +java_library( + name = "common_resources", + resources = glob(["demo-graph/**/*"]), + resource_strip_prefix = "kmp/src/commonMain/resources", + visibility = ["//kmp:__subpackages__"], +) diff --git a/kmp/src/commonTest/kotlin/BUILD.bazel b/kmp/src/commonTest/kotlin/BUILD.bazel new file mode 100644 index 00000000..d9bffa1e --- /dev/null +++ b/kmp/src/commonTest/kotlin/BUILD.bazel @@ -0,0 +1,21 @@ +""" +common_test_fixtures — shared test utilities compiled for JVM. + +FakeFileSystem lives in commonTest/ so it compiles on all KMP platforms, but it +is also referenced by jvmTest sources (e.g. ImageAnnotationOfflineTest). This +kt_jvm_library exposes just the fixture files needed by jvmTest without pulling +in the full commonTest suite. Add files here as jvmTest grows its cross-source- +set fixture usage. +""" + +load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") + +kt_jvm_library( + name = "common_test_fixtures", + srcs = ["dev/stapler/stelekit/db/sidecar/FakeFileSystem.kt"], + deps = [ + "//kmp/src/jvmMain/kotlin:jvm_main_lib", + "@maven//:org_jetbrains_kotlin_kotlin_stdlib", + ], + visibility = ["//kmp/src:__subpackages__"], +) diff --git a/kmp/src/generated/sqldelight/BUILD.bazel b/kmp/src/generated/sqldelight/BUILD.bazel new file mode 100644 index 00000000..e4fddf16 --- /dev/null +++ b/kmp/src/generated/sqldelight/BUILD.bazel @@ -0,0 +1,24 @@ +""" +Checked-in SQLDelight generated sources. + +Regeneration: run `./gradlew :kmp:generateCommonMainSteleDatabase` then + rsync -a kmp/build/generated/sqldelight/code/SteleDatabase/commonMain/ kmp/src/generated/sqldelight/ +after any change to kmp/src/commonMain/sqldelight/*.sq files. + +See ADR-001 for rationale on checked-in vs. rule-generated strategy. +""" + +load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") + +# JVM target for desktop/tests +kt_jvm_library( + name = "sqldelight_generated_jvm", + srcs = glob(["**/*.kt"]), + deps = [ + "@maven//:app_cash_sqldelight_runtime_jvm", + "@maven//:app_cash_sqldelight_coroutines_extensions_jvm", + "@maven//:app_cash_sqldelight_async_extensions_jvm", + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_core_jvm", + ], + visibility = ["//kmp:__subpackages__"], +) diff --git a/kmp/src/generated/sqldelight/README_REGEN.md b/kmp/src/generated/sqldelight/README_REGEN.md new file mode 100644 index 00000000..a4694544 --- /dev/null +++ b/kmp/src/generated/sqldelight/README_REGEN.md @@ -0,0 +1,21 @@ +# SQLDelight Generated Sources + +These files are checked in (not generated at build time by Bazel). + +## When to re-generate + +Re-run whenever you change any `.sq` file under `kmp/src/commonMain/sqldelight/`. + +## Regeneration command + +```bash +./gradlew :kmp:generateCommonMainSteleDatabase +rsync -a kmp/build/generated/sqldelight/code/SteleDatabase/commonMain/ kmp/src/generated/sqldelight/ +git add kmp/src/generated/sqldelight/ +``` + +## Rationale + +See `project_plans/stelekit-bazel/decisions/ADR-003-checkin-sqldelight-generated.md`: +checked-in sources are simpler and avoid a complex code-generation Bazel rule that would +require Kotlin scripting support not yet stable in `rules_kotlin`. diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Asset_index.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Asset_index.kt new file mode 100644 index 00000000..d3c35b87 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Asset_index.kt @@ -0,0 +1,25 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class Asset_index( + public val uuid: String, + public val file_path: String, + public val relative_path: String, + public val media_type: String, + public val subfolder: String, + public val tags: String, + public val auto_labels: String, + public val ocr_text: String?, + public val cloud_description: String?, + public val page_uuids: String, + public val size_bytes: Long, + public val imported_at_ms: Long, + public val ml_processed: Long, + public val ml_attempted_at: Long?, + public val ml_failed: Long, + public val content_hash: String?, + public val is_orphan: Long, + public val ml_tags_source: String, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Block_references.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Block_references.kt new file mode 100644 index 00000000..025fedb1 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Block_references.kt @@ -0,0 +1,11 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class Block_references( + public val id: Long, + public val from_block_uuid: String, + public val to_block_uuid: String, + public val created_at: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Blocks.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Blocks.kt new file mode 100644 index 00000000..926dd822 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Blocks.kt @@ -0,0 +1,21 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class Blocks( + public val id: Long, + public val uuid: String, + public val page_uuid: String, + public val parent_uuid: String?, + public val left_uuid: String?, + public val content: String, + public val level: Long, + public val position: Long, + public val created_at: Long, + public val updated_at: Long, + public val properties: String?, + public val version: Long, + public val content_hash: String?, + public val block_type: String, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/CountOperationPayloadSize.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/CountOperationPayloadSize.kt new file mode 100644 index 00000000..ba6f0e7b --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/CountOperationPayloadSize.kt @@ -0,0 +1,7 @@ +package dev.stapler.stelekit.db + +import kotlin.Long + +public data class CountOperationPayloadSize( + public val SUM: Long?, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Debug_flags.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Debug_flags.kt new file mode 100644 index 00000000..e559e3f5 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Debug_flags.kt @@ -0,0 +1,10 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class Debug_flags( + public val key: String, + public val value_: Long, + public val updated_at: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Git_config.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Git_config.kt new file mode 100644 index 00000000..c777a570 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Git_config.kt @@ -0,0 +1,19 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class Git_config( + public val graph_id: String, + public val repo_root: String, + public val wiki_subdir: String, + public val remote_name: String, + public val remote_branch: String, + public val auth_type: String, + public val ssh_key_path: String?, + public val ssh_key_passphrase_key: String?, + public val https_token_key: String?, + public val poll_interval_minutes: Long, + public val auto_commit: Long, + public val commit_message_template: String, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Image_annotations.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Image_annotations.kt new file mode 100644 index 00000000..a470d377 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Image_annotations.kt @@ -0,0 +1,32 @@ +package dev.stapler.stelekit.db + +import kotlin.Double +import kotlin.Long +import kotlin.String + +public data class Image_annotations( + public val uuid: String, + public val block_uuid: String, + public val page_uuid: String, + public val graph_path: String, + public val file_path: String, + public val thumbnail_path: String?, + public val source: String, + public val source_uri: String?, + public val captured_at_ms: Long?, + public val imported_at_ms: Long, + public val calibration_method: String, + public val pixels_per_meter: Double, + public val calibration_confidence_pct: Long, + public val unit: String, + public val tags: String, + public val lat_lng: String?, + public val altitude_m: Double?, + public val bearing_deg: Double?, + public val pitch_deg: Double?, + public val roll_deg: Double?, + public val focal_length_mm: Double?, + public val focal_length_35mm_eq: Double?, + public val camera_make: String?, + public val camera_model: String?, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Logical_clock.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Logical_clock.kt new file mode 100644 index 00000000..375ffa71 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Logical_clock.kt @@ -0,0 +1,9 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class Logical_clock( + public val session_id: String, + public val seq: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Measurement_annotations.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Measurement_annotations.kt new file mode 100644 index 00000000..7a0d6ed4 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Measurement_annotations.kt @@ -0,0 +1,16 @@ +package dev.stapler.stelekit.db + +import kotlin.Double +import kotlin.String + +public data class Measurement_annotations( + public val uuid: String, + public val image_uuid: String, + public val annotation_type: String, + public val normalized_points: String, + public val value_meters: Double?, + public val value_display: String?, + public val label: String?, + public val color_hex: String, + public val ble_device_id: String?, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Metadata.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Metadata.kt new file mode 100644 index 00000000..f63571e5 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Metadata.kt @@ -0,0 +1,8 @@ +package dev.stapler.stelekit.db + +import kotlin.String + +public data class Metadata( + public val key: String, + public val value_: String, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Migration_changelog.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Migration_changelog.kt new file mode 100644 index 00000000..53f09546 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Migration_changelog.kt @@ -0,0 +1,18 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class Migration_changelog( + public val id: String, + public val graph_id: String, + public val description: String, + public val checksum: String, + public val applied_at: Long, + public val execution_ms: Long, + public val status: String, + public val applied_by: String, + public val execution_order: Long, + public val changes_applied: Long, + public val error_message: String?, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Operations.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Operations.kt new file mode 100644 index 00000000..d5005bb7 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Operations.kt @@ -0,0 +1,15 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class Operations( + public val op_id: String, + public val session_id: String, + public val seq: Long, + public val op_type: String, + public val entity_uuid: String?, + public val page_uuid: String?, + public val payload: String, + public val created_at: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Page_visits.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Page_visits.kt new file mode 100644 index 00000000..2adc7ff5 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Page_visits.kt @@ -0,0 +1,10 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class Page_visits( + public val page_uuid: String, + public val visit_count: Long, + public val last_visited_at: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Pages.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Pages.kt new file mode 100644 index 00000000..9cdc3470 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Pages.kt @@ -0,0 +1,20 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class Pages( + public val uuid: String, + public val name: String, + public val namespace: String?, + public val file_path: String?, + public val created_at: Long, + public val updated_at: Long, + public val properties: String?, + public val version: Long, + public val is_favorite: Long?, + public val is_journal: Long?, + public val journal_date: String?, + public val is_content_loaded: Long, + public val backlink_count: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Pending_asset_moves.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Pending_asset_moves.kt new file mode 100644 index 00000000..9eaacbd4 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Pending_asset_moves.kt @@ -0,0 +1,14 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class Pending_asset_moves( + public val id: Long, + public val asset_uuid: String, + public val old_file_path: String, + public val new_file_path: String, + public val old_relative_path: String, + public val new_relative_path: String, + public val created_at_ms: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Perf_histogram_buckets.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Perf_histogram_buckets.kt new file mode 100644 index 00000000..a073186b --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Perf_histogram_buckets.kt @@ -0,0 +1,12 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class Perf_histogram_buckets( + public val id: Long, + public val operation_name: String, + public val bucket_ms: Long, + public val count: Long, + public val recorded_at: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Plugin_data.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Plugin_data.kt new file mode 100644 index 00000000..00b5f697 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Plugin_data.kt @@ -0,0 +1,15 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class Plugin_data( + public val id: Long, + public val plugin_id: String, + public val entity_type: String, + public val entity_uuid: String, + public val key: String, + public val value_: String, + public val created_at: Long, + public val updated_at: Long?, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Properties.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Properties.kt new file mode 100644 index 00000000..549bb5c7 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Properties.kt @@ -0,0 +1,12 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class Properties( + public val uuid: String, + public val block_uuid: String, + public val key: String, + public val value_: String, + public val created_at: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Query_stats.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Query_stats.kt new file mode 100644 index 00000000..8546675a --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Query_stats.kt @@ -0,0 +1,24 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class Query_stats( + public val app_version: String, + public val table_name: String, + public val operation: String, + public val calls: Long, + public val errors: Long, + public val total_ms: Long, + public val min_ms: Long, + public val max_ms: Long, + public val b1: Long, + public val b5: Long, + public val b16: Long, + public val b50: Long, + public val b100: Long, + public val b500: Long, + public val b_inf: Long, + public val first_seen: Long, + public val last_seen: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SearchBlocksByContentFts.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SearchBlocksByContentFts.kt new file mode 100644 index 00000000..1b2e5038 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SearchBlocksByContentFts.kt @@ -0,0 +1,21 @@ +package dev.stapler.stelekit.db + +import kotlin.Double +import kotlin.Long +import kotlin.String + +public data class SearchBlocksByContentFts( + public val uuid: String, + public val page_uuid: String, + public val parent_uuid: String?, + public val left_uuid: String?, + public val content: String, + public val level: Long, + public val position: Long, + public val created_at: Long, + public val updated_at: Long, + public val properties: String?, + public val version: Long, + public val highlight: String?, + public val bm25_score: Double, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SearchBlocksByContentFtsInDateRange.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SearchBlocksByContentFtsInDateRange.kt new file mode 100644 index 00000000..86c7a4aa --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SearchBlocksByContentFtsInDateRange.kt @@ -0,0 +1,21 @@ +package dev.stapler.stelekit.db + +import kotlin.Double +import kotlin.Long +import kotlin.String + +public data class SearchBlocksByContentFtsInDateRange( + public val uuid: String, + public val page_uuid: String, + public val parent_uuid: String?, + public val left_uuid: String?, + public val content: String, + public val level: Long, + public val position: Long, + public val created_at: Long, + public val updated_at: Long, + public val properties: String?, + public val version: Long, + public val highlight: String?, + public val bm25_score: Double, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SearchBlocksByContentFtsInPage.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SearchBlocksByContentFtsInPage.kt new file mode 100644 index 00000000..d2633e29 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SearchBlocksByContentFtsInPage.kt @@ -0,0 +1,21 @@ +package dev.stapler.stelekit.db + +import kotlin.Double +import kotlin.Long +import kotlin.String + +public data class SearchBlocksByContentFtsInPage( + public val uuid: String, + public val page_uuid: String, + public val parent_uuid: String?, + public val left_uuid: String?, + public val content: String, + public val level: Long, + public val position: Long, + public val created_at: Long, + public val updated_at: Long, + public val properties: String?, + public val version: Long, + public val highlight: String?, + public val bm25_score: Double, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SearchPagesByNameFts.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SearchPagesByNameFts.kt new file mode 100644 index 00000000..22c2f937 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SearchPagesByNameFts.kt @@ -0,0 +1,22 @@ +package dev.stapler.stelekit.db + +import kotlin.Double +import kotlin.Long +import kotlin.String + +public data class SearchPagesByNameFts( + public val uuid: String, + public val name: String, + public val namespace: String?, + public val file_path: String?, + public val created_at: Long, + public val updated_at: Long, + public val properties: String?, + public val version: Long, + public val is_favorite: Long?, + public val is_journal: Long?, + public val journal_date: String?, + public val is_content_loaded: Long, + public val highlight: String?, + public val bm25_score: Double, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SearchPagesByNameFtsInDateRange.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SearchPagesByNameFtsInDateRange.kt new file mode 100644 index 00000000..cf600187 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SearchPagesByNameFtsInDateRange.kt @@ -0,0 +1,22 @@ +package dev.stapler.stelekit.db + +import kotlin.Double +import kotlin.Long +import kotlin.String + +public data class SearchPagesByNameFtsInDateRange( + public val uuid: String, + public val name: String, + public val namespace: String?, + public val file_path: String?, + public val created_at: Long, + public val updated_at: Long, + public val properties: String?, + public val version: Long, + public val is_favorite: Long?, + public val is_journal: Long?, + public val journal_date: String?, + public val is_content_loaded: Long, + public val highlight: String?, + public val bm25_score: Double, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectAllBlocksWithPagePath.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectAllBlocksWithPagePath.kt new file mode 100644 index 00000000..6bb65570 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectAllBlocksWithPagePath.kt @@ -0,0 +1,12 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class SelectAllBlocksWithPagePath( + public val uuid: String, + public val parent_uuid: String?, + public val position: Long, + public val content: String, + public val file_path: String, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectAllDebugFlags.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectAllDebugFlags.kt new file mode 100644 index 00000000..97597083 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectAllDebugFlags.kt @@ -0,0 +1,9 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class SelectAllDebugFlags( + public val key: String, + public val value_: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectAllHistogramBuckets.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectAllHistogramBuckets.kt new file mode 100644 index 00000000..dea9979c --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectAllHistogramBuckets.kt @@ -0,0 +1,10 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class SelectAllHistogramBuckets( + public val operation_name: String, + public val bucket_ms: Long, + public val count: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectAppliedMigrations.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectAppliedMigrations.kt new file mode 100644 index 00000000..ac7fb641 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectAppliedMigrations.kt @@ -0,0 +1,9 @@ +package dev.stapler.stelekit.db + +import kotlin.String + +public data class SelectAppliedMigrations( + public val id: String, + public val checksum: String, + public val status: String, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectBacklinkCountsForPages.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectBacklinkCountsForPages.kt new file mode 100644 index 00000000..0c5e46c4 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectBacklinkCountsForPages.kt @@ -0,0 +1,9 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class SelectBacklinkCountsForPages( + public val page_name: String, + public val backlink_count: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectBlocksHashByPageUuid.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectBlocksHashByPageUuid.kt new file mode 100644 index 00000000..7c1de1b5 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectBlocksHashByPageUuid.kt @@ -0,0 +1,8 @@ +package dev.stapler.stelekit.db + +import kotlin.String + +public data class SelectBlocksHashByPageUuid( + public val uuid: String, + public val content_hash: String?, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectDuplicateBlockHashes.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectDuplicateBlockHashes.kt new file mode 100644 index 00000000..8a87f5e6 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectDuplicateBlockHashes.kt @@ -0,0 +1,9 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class SelectDuplicateBlockHashes( + public val content_hash: String, + public val cnt: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectHistogramForOperation.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectHistogramForOperation.kt new file mode 100644 index 00000000..e62f78e2 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectHistogramForOperation.kt @@ -0,0 +1,8 @@ +package dev.stapler.stelekit.db + +import kotlin.Long + +public data class SelectHistogramForOperation( + public val bucket_ms: Long, + public val count: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectJournalPages.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectJournalPages.kt new file mode 100644 index 00000000..6530cfaf --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectJournalPages.kt @@ -0,0 +1,20 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class SelectJournalPages( + public val uuid: String, + public val name: String, + public val namespace: String?, + public val file_path: String?, + public val created_at: Long, + public val updated_at: Long, + public val properties: String?, + public val version: Long, + public val is_favorite: Long?, + public val is_journal: Long?, + public val journal_date: String, + public val is_content_loaded: Long, + public val backlink_count: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectMostConnectedBlocks.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectMostConnectedBlocks.kt new file mode 100644 index 00000000..45fba132 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectMostConnectedBlocks.kt @@ -0,0 +1,22 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class SelectMostConnectedBlocks( + public val id: Long, + public val uuid: String, + public val page_uuid: String, + public val parent_uuid: String?, + public val left_uuid: String?, + public val content: String, + public val level: Long, + public val position: Long, + public val created_at: Long, + public val updated_at: Long, + public val properties: String?, + public val version: Long, + public val content_hash: String?, + public val block_type: String, + public val reference_count: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectPageNameEntries.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectPageNameEntries.kt new file mode 100644 index 00000000..949e90ec --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectPageNameEntries.kt @@ -0,0 +1,9 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class SelectPageNameEntries( + public val name: String, + public val is_journal: Long?, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectPageVisitByUuid.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectPageVisitByUuid.kt new file mode 100644 index 00000000..daa54337 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectPageVisitByUuid.kt @@ -0,0 +1,10 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class SelectPageVisitByUuid( + public val page_uuid: String, + public val last_visited_at: Long, + public val visit_count: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectPageVisitsByUuids.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectPageVisitsByUuids.kt new file mode 100644 index 00000000..abe47827 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SelectPageVisitsByUuids.kt @@ -0,0 +1,10 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class SelectPageVisitsByUuids( + public val page_uuid: String, + public val last_visited_at: Long, + public val visit_count: Long, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Spans.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Spans.kt new file mode 100644 index 00000000..6ae84abb --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/Spans.kt @@ -0,0 +1,19 @@ +package dev.stapler.stelekit.db + +import kotlin.Long +import kotlin.String + +public data class Spans( + public val id: Long, + public val trace_id: String, + public val span_id: String, + public val parent_span_id: String, + public val name: String, + public val start_epoch_ms: Long, + public val end_epoch_ms: Long, + public val duration_ms: Long, + public val attributes_json: String, + public val status_code: String, + public val app_version: String, + public val commit_hash: String, +) diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SteleDatabase.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SteleDatabase.kt new file mode 100644 index 00000000..c1212370 --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SteleDatabase.kt @@ -0,0 +1,20 @@ +package dev.stapler.stelekit.db + +import app.cash.sqldelight.SuspendingTransacter +import app.cash.sqldelight.db.QueryResult +import app.cash.sqldelight.db.SqlDriver +import app.cash.sqldelight.db.SqlSchema +import dev.stapler.stelekit.db.kmp.newInstance +import dev.stapler.stelekit.db.kmp.schema +import kotlin.Unit + +public interface SteleDatabase : SuspendingTransacter { + public val steleDatabaseQueries: SteleDatabaseQueries + + public companion object { + public val Schema: SqlSchema> + get() = SteleDatabase::class.schema + + public operator fun invoke(driver: SqlDriver): SteleDatabase = SteleDatabase::class.newInstance(driver) + } +} diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SteleDatabaseQueries.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SteleDatabaseQueries.kt new file mode 100644 index 00000000..be3e953a --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SteleDatabaseQueries.kt @@ -0,0 +1,7071 @@ +package dev.stapler.stelekit.db + +import app.cash.sqldelight.ExecutableQuery +import app.cash.sqldelight.Query +import app.cash.sqldelight.SuspendingTransacterImpl +import app.cash.sqldelight.db.QueryResult +import app.cash.sqldelight.db.SqlCursor +import app.cash.sqldelight.db.SqlDriver +import kotlin.Any +import kotlin.Double +import kotlin.Long +import kotlin.String +import kotlin.collections.Collection + +public class SteleDatabaseQueries( + driver: SqlDriver, +) : SuspendingTransacterImpl(driver) { + public fun selectBlockByUuid(uuid: String, mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T): Query = SelectBlockByUuidQuery(uuid) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectBlockByUuid(uuid: String): Query = selectBlockByUuid(uuid, ::Blocks) + + public fun selectBlocksByUuids(uuid: Collection, mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T): Query = SelectBlocksByUuidsQuery(uuid) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectBlocksByUuids(uuid: Collection): Query = selectBlocksByUuids(uuid, ::Blocks) + + public fun existsBlockByUuid(uuid: String): Query = ExistsBlockByUuidQuery(uuid) { cursor -> + cursor.getLong(0)!! + } + + public fun selectAllBlocks(mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T): Query = Query(1_803_430_346, arrayOf("blocks"), driver, "SteleDatabase.sq", "selectAllBlocks", "SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks ORDER BY uuid") { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectAllBlocks(): Query = selectAllBlocks(::Blocks) + + public fun selectAllBlocksPaginated( + `value`: Long, + value_: Long, + mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T, + ): Query = SelectAllBlocksPaginatedQuery(value, value_) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectAllBlocksPaginated(value_: Long, value__: Long): Query = selectAllBlocksPaginated(value_, value__, ::Blocks) + + public fun selectAllBlocksPaginatedAfterUuid( + uuid: String, + `value`: Long, + mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T, + ): Query = SelectAllBlocksPaginatedAfterUuidQuery(uuid, value) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectAllBlocksPaginatedAfterUuid(uuid: String, value_: Long): Query = selectAllBlocksPaginatedAfterUuid(uuid, value_, ::Blocks) + + public fun selectBlockChildren( + parent_uuid: String?, + `value`: Long, + value_: Long, + mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T, + ): Query = SelectBlockChildrenQuery(parent_uuid, value, value_) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectBlockChildren( + parent_uuid: String?, + value_: Long, + value__: Long, + ): Query = selectBlockChildren(parent_uuid, value_, value__, ::Blocks) + + public fun countBlockChildren(parent_uuid: String?): Query = CountBlockChildrenQuery(parent_uuid) { cursor -> + cursor.getLong(0)!! + } + + public fun selectBlockSiblings( + uuid: String, + uuid_: String, + uuid__: String, + mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T, + ): Query = SelectBlockSiblingsQuery(uuid, uuid_, uuid__) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectBlockSiblings( + uuid: String, + uuid_: String, + uuid__: String, + ): Query = selectBlockSiblings(uuid, uuid_, uuid__, ::Blocks) + + public fun selectRootBlocks( + page_uuid: String, + `value`: Long, + value_: Long, + mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T, + ): Query = SelectRootBlocksQuery(page_uuid, value, value_) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectRootBlocks( + page_uuid: String, + value_: Long, + value__: Long, + ): Query = selectRootBlocks(page_uuid, value_, value__, ::Blocks) + + public fun countRootBlocks(page_uuid: String): Query = CountRootBlocksQuery(page_uuid) { cursor -> + cursor.getLong(0)!! + } + + public fun selectBlocksByPageUuid( + page_uuid: String, + `value`: Long, + value_: Long, + mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T, + ): Query = SelectBlocksByPageUuidQuery(page_uuid, value, value_) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectBlocksByPageUuid( + page_uuid: String, + value_: Long, + value__: Long, + ): Query = selectBlocksByPageUuid(page_uuid, value_, value__, ::Blocks) + + public fun selectBlocksByPageUuidUnpaginated(page_uuid: String, mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T): Query = SelectBlocksByPageUuidUnpaginatedQuery(page_uuid) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectBlocksByPageUuidUnpaginated(page_uuid: String): Query = selectBlocksByPageUuidUnpaginated(page_uuid, ::Blocks) + + public fun selectBlocksWithContentLike(content: String, mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T): Query = SelectBlocksWithContentLikeQuery(content) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectBlocksWithContentLike(content: String): Query = selectBlocksWithContentLike(content, ::Blocks) + + public fun selectBlocksWithContentLikePaginated( + content: String, + `value`: Long, + value_: Long, + mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T, + ): Query = SelectBlocksWithContentLikePaginatedQuery(content, value, value_) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectBlocksWithContentLikePaginated( + content: String, + value_: Long, + value__: Long, + ): Query = selectBlocksWithContentLikePaginated(content, value_, value__, ::Blocks) + + public fun countBlocksByPageUuid(page_uuid: String): Query = CountBlocksByPageUuidQuery(page_uuid) { cursor -> + cursor.getLong(0)!! + } + + public fun selectBlocksByParentUuidOrdered(parent_uuid: String?, mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T): Query = SelectBlocksByParentUuidOrderedQuery(parent_uuid) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectBlocksByParentUuidOrdered(parent_uuid: String?): Query = selectBlocksByParentUuidOrdered(parent_uuid, ::Blocks) + + public fun selectBlocksByParentUuids(parent_uuid: Collection, mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T): Query = SelectBlocksByParentUuidsQuery(parent_uuid) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectBlocksByParentUuids(parent_uuid: Collection): Query = selectBlocksByParentUuids(parent_uuid, ::Blocks) + + public fun selectRootBlocksByPageUuidOrdered(page_uuid: String, mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T): Query = SelectRootBlocksByPageUuidOrderedQuery(page_uuid) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectRootBlocksByPageUuidOrdered(page_uuid: String): Query = selectRootBlocksByPageUuidOrdered(page_uuid, ::Blocks) + + public fun selectBlockByLeftUuid(left_uuid: String?, mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T): Query = SelectBlockByLeftUuidQuery(left_uuid) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectBlockByLeftUuid(left_uuid: String?): Query = selectBlockByLeftUuid(left_uuid, ::Blocks) + + public fun selectLastChild(parent_uuid: String?, mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T): Query = SelectLastChildQuery(parent_uuid) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectLastChild(parent_uuid: String?): Query = selectLastChild(parent_uuid, ::Blocks) + + public fun countBlocks(): Query = Query(-589_645_868, arrayOf("blocks"), driver, "SteleDatabase.sq", "countBlocks", "SELECT COUNT(*) FROM blocks") { cursor -> + cursor.getLong(0)!! + } + + public fun selectBlocksHashByPageUuid(page_uuid: String, mapper: (uuid: String, content_hash: String?) -> T): Query = SelectBlocksHashByPageUuidQuery(page_uuid) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1) + ) + } + + public fun selectBlocksHashByPageUuid(page_uuid: String): Query = selectBlocksHashByPageUuid(page_uuid, ::SelectBlocksHashByPageUuid) + + public fun selectBlocksByContentHash(content_hash: String?, mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T): Query = SelectBlocksByContentHashQuery(content_hash) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectBlocksByContentHash(content_hash: String?): Query = selectBlocksByContentHash(content_hash, ::Blocks) + + public fun selectDuplicateBlockHashes(`value`: Long, mapper: (content_hash: String, cnt: Long) -> T): Query = SelectDuplicateBlockHashesQuery(value) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getLong(1)!! + ) + } + + public fun selectDuplicateBlockHashes(value_: Long): Query = selectDuplicateBlockHashes(value_, ::SelectDuplicateBlockHashes) + + public fun selectPageByUuid(uuid: String, mapper: ( + uuid: String, + name: String, + namespace: String?, + file_path: String?, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String?, + is_content_loaded: Long, + backlink_count: Long, + ) -> T): Query = SelectPageByUuidQuery(uuid) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6), + cursor.getLong(7)!!, + cursor.getLong(8), + cursor.getLong(9), + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getLong(12)!! + ) + } + + public fun selectPageByUuid(uuid: String): Query = selectPageByUuid(uuid, ::Pages) + + public fun selectPageByName(name: String, mapper: ( + uuid: String, + name: String, + namespace: String?, + file_path: String?, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String?, + is_content_loaded: Long, + backlink_count: Long, + ) -> T): Query = SelectPageByNameQuery(name) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6), + cursor.getLong(7)!!, + cursor.getLong(8), + cursor.getLong(9), + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getLong(12)!! + ) + } + + public fun selectPageByName(name: String): Query = selectPageByName(name, ::Pages) + + public fun existsPageByUuid(uuid: String): Query = ExistsPageByUuidQuery(uuid) { cursor -> + cursor.getLong(0)!! + } + + public fun existsPageByName(name: String): Query = ExistsPageByNameQuery(name) { cursor -> + cursor.getLong(0)!! + } + + public fun selectAllPagesPaginated( + `value`: Long, + value_: Long, + mapper: ( + uuid: String, + name: String, + namespace: String?, + file_path: String?, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String?, + is_content_loaded: Long, + backlink_count: Long, + ) -> T, + ): Query = SelectAllPagesPaginatedQuery(value, value_) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6), + cursor.getLong(7)!!, + cursor.getLong(8), + cursor.getLong(9), + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getLong(12)!! + ) + } + + public fun selectAllPagesPaginated(value_: Long, value__: Long): Query = selectAllPagesPaginated(value_, value__, ::Pages) + + public fun selectUnloadedPagesPaginated( + `value`: Long, + value_: Long, + mapper: ( + uuid: String, + name: String, + namespace: String?, + file_path: String?, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String?, + is_content_loaded: Long, + backlink_count: Long, + ) -> T, + ): Query = SelectUnloadedPagesPaginatedQuery(value, value_) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6), + cursor.getLong(7)!!, + cursor.getLong(8), + cursor.getLong(9), + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getLong(12)!! + ) + } + + public fun selectUnloadedPagesPaginated(value_: Long, value__: Long): Query = selectUnloadedPagesPaginated(value_, value__, ::Pages) + + public fun countUnloadedPages(): Query = Query(-58_485_640, arrayOf("pages"), driver, "SteleDatabase.sq", "countUnloadedPages", "SELECT COUNT(*) FROM pages WHERE is_content_loaded = 0") { cursor -> + cursor.getLong(0)!! + } + + public fun selectPageNameEntries(mapper: (name: String, is_journal: Long?) -> T): Query = Query(-1_279_862_151, arrayOf("pages"), driver, "SteleDatabase.sq", "selectPageNameEntries", "SELECT name, is_journal FROM pages") { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getLong(1) + ) + } + + public fun selectPageNameEntries(): Query = selectPageNameEntries(::SelectPageNameEntries) + + public fun selectPagesByNames(name: Collection, mapper: ( + uuid: String, + name: String, + namespace: String?, + file_path: String?, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String?, + is_content_loaded: Long, + backlink_count: Long, + ) -> T): Query = SelectPagesByNamesQuery(name) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6), + cursor.getLong(7)!!, + cursor.getLong(8), + cursor.getLong(9), + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getLong(12)!! + ) + } + + public fun selectPagesByNames(name: Collection): Query = selectPagesByNames(name, ::Pages) + + public fun selectJournalPagesByDates(journal_date: Collection, mapper: ( + uuid: String, + name: String, + namespace: String?, + file_path: String?, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String?, + is_content_loaded: Long, + backlink_count: Long, + ) -> T): Query = SelectJournalPagesByDatesQuery(journal_date) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6), + cursor.getLong(7)!!, + cursor.getLong(8), + cursor.getLong(9), + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getLong(12)!! + ) + } + + public fun selectJournalPagesByDates(journal_date: Collection): Query = selectJournalPagesByDates(journal_date, ::Pages) + + public fun selectFavoritePages(mapper: ( + uuid: String, + name: String, + namespace: String?, + file_path: String?, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String?, + is_content_loaded: Long, + backlink_count: Long, + ) -> T): Query = Query(1_623_585_099, arrayOf("pages"), driver, "SteleDatabase.sq", "selectFavoritePages", "SELECT pages.uuid, pages.name, pages.namespace, pages.file_path, pages.created_at, pages.updated_at, pages.properties, pages.version, pages.is_favorite, pages.is_journal, pages.journal_date, pages.is_content_loaded, pages.backlink_count FROM pages WHERE is_favorite = 1 ORDER BY name") { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6), + cursor.getLong(7)!!, + cursor.getLong(8), + cursor.getLong(9), + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getLong(12)!! + ) + } + + public fun selectFavoritePages(): Query = selectFavoritePages(::Pages) + + public fun selectPagesByNamespace( + namespace: String?, + `value`: Long, + value_: Long, + mapper: ( + uuid: String, + name: String, + namespace: String?, + file_path: String?, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String?, + is_content_loaded: Long, + backlink_count: Long, + ) -> T, + ): Query = SelectPagesByNamespaceQuery(namespace, value, value_) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6), + cursor.getLong(7)!!, + cursor.getLong(8), + cursor.getLong(9), + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getLong(12)!! + ) + } + + public fun selectPagesByNamespace( + namespace: String?, + value_: Long, + value__: Long, + ): Query = selectPagesByNamespace(namespace, value_, value__, ::Pages) + + public fun selectPagesByNamespaceUnpaginated(namespace: String?, mapper: ( + uuid: String, + name: String, + namespace: String?, + file_path: String?, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String?, + is_content_loaded: Long, + backlink_count: Long, + ) -> T): Query = SelectPagesByNamespaceUnpaginatedQuery(namespace) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6), + cursor.getLong(7)!!, + cursor.getLong(8), + cursor.getLong(9), + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getLong(12)!! + ) + } + + public fun selectPagesByNamespaceUnpaginated(namespace: String?): Query = selectPagesByNamespaceUnpaginated(namespace, ::Pages) + + public fun countPagesByNamespace(namespace: String?): Query = CountPagesByNamespaceQuery(namespace) { cursor -> + cursor.getLong(0)!! + } + + public fun selectRecentlyUpdatedPages(`value`: Long, mapper: ( + uuid: String, + name: String, + namespace: String?, + file_path: String?, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String?, + is_content_loaded: Long, + backlink_count: Long, + ) -> T): Query = SelectRecentlyUpdatedPagesQuery(value) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6), + cursor.getLong(7)!!, + cursor.getLong(8), + cursor.getLong(9), + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getLong(12)!! + ) + } + + public fun selectRecentlyUpdatedPages(value_: Long): Query = selectRecentlyUpdatedPages(value_, ::Pages) + + public fun selectRecentlyCreatedPages(`value`: Long, mapper: ( + uuid: String, + name: String, + namespace: String?, + file_path: String?, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String?, + is_content_loaded: Long, + backlink_count: Long, + ) -> T): Query = SelectRecentlyCreatedPagesQuery(value) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6), + cursor.getLong(7)!!, + cursor.getLong(8), + cursor.getLong(9), + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getLong(12)!! + ) + } + + public fun selectRecentlyCreatedPages(value_: Long): Query = selectRecentlyCreatedPages(value_, ::Pages) + + public fun countPages(): Query = Query(1_240_499_126, arrayOf("pages"), driver, "SteleDatabase.sq", "countPages", "SELECT COUNT(*) FROM pages") { cursor -> + cursor.getLong(0)!! + } + + public fun selectJournalPages( + `value`: Long, + value_: Long, + mapper: ( + uuid: String, + name: String, + namespace: String?, + file_path: String?, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String, + is_content_loaded: Long, + backlink_count: Long, + ) -> T, + ): Query = SelectJournalPagesQuery(value, value_) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6), + cursor.getLong(7)!!, + cursor.getLong(8), + cursor.getLong(9), + cursor.getString(10)!!, + cursor.getLong(11)!!, + cursor.getLong(12)!! + ) + } + + public fun selectJournalPages(value_: Long, value__: Long): Query = selectJournalPages(value_, value__, ::SelectJournalPages) + + public fun selectJournalPageByDate(journal_date: String?, mapper: ( + uuid: String, + name: String, + namespace: String?, + file_path: String?, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String?, + is_content_loaded: Long, + backlink_count: Long, + ) -> T): Query = SelectJournalPageByDateQuery(journal_date) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6), + cursor.getLong(7)!!, + cursor.getLong(8), + cursor.getLong(9), + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getLong(12)!! + ) + } + + public fun selectJournalPageByDate(journal_date: String?): Query = selectJournalPageByDate(journal_date, ::Pages) + + public fun selectNeighbourPageUuids(pageUuid: String): Query = SelectNeighbourPageUuidsQuery(pageUuid) { cursor -> + cursor.getString(0)!! + } + + public fun selectOutgoingReferences(from_block_uuid: String, mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T): Query = SelectOutgoingReferencesQuery(from_block_uuid) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectOutgoingReferences(from_block_uuid: String): Query = selectOutgoingReferences(from_block_uuid, ::Blocks) + + public fun selectIncomingReferences(to_block_uuid: String, mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T): Query = SelectIncomingReferencesQuery(to_block_uuid) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectIncomingReferences(to_block_uuid: String): Query = selectIncomingReferences(to_block_uuid, ::Blocks) + + public fun selectOrphanedBlocks(mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T): Query = Query(-1_994_028_502, arrayOf("blocks", "block_references"), driver, "SteleDatabase.sq", "selectOrphanedBlocks", """ + |SELECT b.id, b.uuid, b.page_uuid, b.parent_uuid, b.left_uuid, b.content, b.level, b.position, b.created_at, b.updated_at, b.properties, b.version, b.content_hash, b.block_type FROM blocks b + |LEFT JOIN block_references br ON b.uuid = br.to_block_uuid + |WHERE br.id IS NULL + """.trimMargin()) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectOrphanedBlocks(): Query = selectOrphanedBlocks(::Blocks) + + public fun selectMostConnectedBlocks(`value`: Long, mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + reference_count: Long, + ) -> T): Query = SelectMostConnectedBlocksQuery(value) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!!, + cursor.getLong(14)!! + ) + } + + public fun selectMostConnectedBlocks(value_: Long): Query = selectMostConnectedBlocks(value_, ::SelectMostConnectedBlocks) + + public fun selectPagesByNameLike(name: String, mapper: ( + uuid: String, + name: String, + namespace: String?, + file_path: String?, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String?, + is_content_loaded: Long, + backlink_count: Long, + ) -> T): Query = SelectPagesByNameLikeQuery(name) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6), + cursor.getLong(7)!!, + cursor.getLong(8), + cursor.getLong(9), + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getLong(12)!! + ) + } + + public fun selectPagesByNameLike(name: String): Query = selectPagesByNameLike(name, ::Pages) + + public fun selectPagesByNameLikePaginated( + name: String, + `value`: Long, + value_: Long, + mapper: ( + uuid: String, + name: String, + namespace: String?, + file_path: String?, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String?, + is_content_loaded: Long, + backlink_count: Long, + ) -> T, + ): Query = SelectPagesByNameLikePaginatedQuery(name, value, value_) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6), + cursor.getLong(7)!!, + cursor.getLong(8), + cursor.getLong(9), + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getLong(12)!! + ) + } + + public fun selectPagesByNameLikePaginated( + name: String, + value_: Long, + value__: Long, + ): Query = selectPagesByNameLikePaginated(name, value_, value__, ::Pages) + + public fun selectBlocksReferencing(to_block_uuid: String, mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T): Query = SelectBlocksReferencingQuery(to_block_uuid) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectBlocksReferencing(to_block_uuid: String): Query = selectBlocksReferencing(to_block_uuid, ::Blocks) + + public fun selectPluginDataById(id: Long, mapper: ( + id: Long, + plugin_id: String, + entity_type: String, + entity_uuid: String, + key: String, + value_: String, + created_at: Long, + updated_at: Long?, + ) -> T): Query = SelectPluginDataByIdQuery(id) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!!, + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7) + ) + } + + public fun selectPluginDataById(id: Long): Query = selectPluginDataById(id, ::Plugin_data) + + public fun selectPluginDataByPlugin(plugin_id: String, mapper: ( + id: Long, + plugin_id: String, + entity_type: String, + entity_uuid: String, + key: String, + value_: String, + created_at: Long, + updated_at: Long?, + ) -> T): Query = SelectPluginDataByPluginQuery(plugin_id) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!!, + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7) + ) + } + + public fun selectPluginDataByPlugin(plugin_id: String): Query = selectPluginDataByPlugin(plugin_id, ::Plugin_data) + + public fun selectPluginDataByEntity( + entity_type: String, + entity_uuid: String, + mapper: ( + id: Long, + plugin_id: String, + entity_type: String, + entity_uuid: String, + key: String, + value_: String, + created_at: Long, + updated_at: Long?, + ) -> T, + ): Query = SelectPluginDataByEntityQuery(entity_type, entity_uuid) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!!, + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7) + ) + } + + public fun selectPluginDataByEntity(entity_type: String, entity_uuid: String): Query = selectPluginDataByEntity(entity_type, entity_uuid, ::Plugin_data) + + public fun selectPluginDataByKey( + plugin_id: String, + key: String, + mapper: ( + id: Long, + plugin_id: String, + entity_type: String, + entity_uuid: String, + key: String, + value_: String, + created_at: Long, + updated_at: Long?, + ) -> T, + ): Query = SelectPluginDataByKeyQuery(plugin_id, key) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!!, + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7) + ) + } + + public fun selectPluginDataByKey(plugin_id: String, key: String): Query = selectPluginDataByKey(plugin_id, key, ::Plugin_data) + + public fun selectPluginDataByPluginAndEntity( + plugin_id: String, + entity_type: String, + entity_uuid: String, + mapper: ( + id: Long, + plugin_id: String, + entity_type: String, + entity_uuid: String, + key: String, + value_: String, + created_at: Long, + updated_at: Long?, + ) -> T, + ): Query = SelectPluginDataByPluginAndEntityQuery(plugin_id, entity_type, entity_uuid) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!!, + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7) + ) + } + + public fun selectPluginDataByPluginAndEntity( + plugin_id: String, + entity_type: String, + entity_uuid: String, + ): Query = selectPluginDataByPluginAndEntity(plugin_id, entity_type, entity_uuid, ::Plugin_data) + + public fun countPluginDataByPlugin(plugin_id: String): Query = CountPluginDataByPluginQuery(plugin_id) { cursor -> + cursor.getLong(0)!! + } + + public fun countPluginDataByEntity(entity_type: String, entity_uuid: String): Query = CountPluginDataByEntityQuery(entity_type, entity_uuid) { cursor -> + cursor.getLong(0)!! + } + + public fun existsPluginData( + plugin_id: String, + entity_type: String, + entity_uuid: String, + key: String, + ): Query = ExistsPluginDataQuery(plugin_id, entity_type, entity_uuid, key) { cursor -> + cursor.getLong(0)!! + } + + public fun searchBlocksByContentFts( + query: String, + limit: Long, + offset: Long, + mapper: ( + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + highlight: String?, + bm25_score: Double, + ) -> T, + ): Query = SearchBlocksByContentFtsQuery(query, limit, offset) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getString(4)!!, + cursor.getLong(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getString(9), + cursor.getLong(10)!!, + cursor.getString(11), + cursor.getDouble(12)!! + ) + } + + public fun searchBlocksByContentFts( + query: String, + limit: Long, + offset: Long, + ): Query = searchBlocksByContentFts(query, limit, offset, ::SearchBlocksByContentFts) + + public fun searchBlocksByContentFtsInPage( + query: String, + pageUuid: String, + limit: Long, + offset: Long, + mapper: ( + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + highlight: String?, + bm25_score: Double, + ) -> T, + ): Query = SearchBlocksByContentFtsInPageQuery(query, pageUuid, limit, offset) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getString(4)!!, + cursor.getLong(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getString(9), + cursor.getLong(10)!!, + cursor.getString(11), + cursor.getDouble(12)!! + ) + } + + public fun searchBlocksByContentFtsInPage( + query: String, + pageUuid: String, + limit: Long, + offset: Long, + ): Query = searchBlocksByContentFtsInPage(query, pageUuid, limit, offset, ::SearchBlocksByContentFtsInPage) + + public fun searchBlocksCountFts(query: String): Query = SearchBlocksCountFtsQuery(query) { cursor -> + cursor.getLong(0)!! + } + + public fun searchPagesByNameFts( + query: String, + limit: Long, + mapper: ( + uuid: String, + name: String, + namespace: String?, + file_path: String?, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String?, + is_content_loaded: Long, + highlight: String?, + bm25_score: Double, + ) -> T, + ): Query = SearchPagesByNameFtsQuery(query, limit) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6), + cursor.getLong(7)!!, + cursor.getLong(8), + cursor.getLong(9), + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getDouble(13)!! + ) + } + + public fun searchPagesByNameFts(query: String, limit: Long): Query = searchPagesByNameFts(query, limit, ::SearchPagesByNameFts) + + public fun searchPagesByNameFtsInDateRange( + query: String, + startMs: Long, + endMs: Long, + limit: Long, + mapper: ( + uuid: String, + name: String, + namespace: String?, + file_path: String?, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String?, + is_content_loaded: Long, + highlight: String?, + bm25_score: Double, + ) -> T, + ): Query = SearchPagesByNameFtsInDateRangeQuery(query, startMs, endMs, limit) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6), + cursor.getLong(7)!!, + cursor.getLong(8), + cursor.getLong(9), + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getDouble(13)!! + ) + } + + public fun searchPagesByNameFtsInDateRange( + query: String, + startMs: Long, + endMs: Long, + limit: Long, + ): Query = searchPagesByNameFtsInDateRange(query, startMs, endMs, limit, ::SearchPagesByNameFtsInDateRange) + + public fun searchBlocksByContentFtsInDateRange( + query: String, + startMs: Long, + endMs: Long, + limit: Long, + offset: Long, + mapper: ( + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + highlight: String?, + bm25_score: Double, + ) -> T, + ): Query = SearchBlocksByContentFtsInDateRangeQuery(query, startMs, endMs, limit, offset) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2), + cursor.getString(3), + cursor.getString(4)!!, + cursor.getLong(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getString(9), + cursor.getLong(10)!!, + cursor.getString(11), + cursor.getDouble(12)!! + ) + } + + public fun searchBlocksByContentFtsInDateRange( + query: String, + startMs: Long, + endMs: Long, + limit: Long, + offset: Long, + ): Query = searchBlocksByContentFtsInDateRange(query, startMs, endMs, limit, offset, ::SearchBlocksByContentFtsInDateRange) + + public fun selectPageVisitsByUuids(page_uuid: Collection, mapper: ( + page_uuid: String, + last_visited_at: Long, + visit_count: Long, + ) -> T): Query = SelectPageVisitsByUuidsQuery(page_uuid) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getLong(1)!!, + cursor.getLong(2)!! + ) + } + + public fun selectPageVisitsByUuids(page_uuid: Collection): Query = selectPageVisitsByUuids(page_uuid, ::SelectPageVisitsByUuids) + + public fun selectPageVisitByUuid(page_uuid: String, mapper: ( + page_uuid: String, + last_visited_at: Long, + visit_count: Long, + ) -> T): Query = SelectPageVisitByUuidQuery(page_uuid) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getLong(1)!!, + cursor.getLong(2)!! + ) + } + + public fun selectPageVisitByUuid(page_uuid: String): Query = selectPageVisitByUuid(page_uuid, ::SelectPageVisitByUuid) + + public fun selectHistogramForOperation(operation_name: String, mapper: (bucket_ms: Long, count: Long) -> T): Query = SelectHistogramForOperationQuery(operation_name) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getLong(1)!! + ) + } + + public fun selectHistogramForOperation(operation_name: String): Query = selectHistogramForOperation(operation_name, ::SelectHistogramForOperation) + + public fun selectAllHistogramOperations(): Query = Query(-11_535_700, arrayOf("perf_histogram_buckets"), driver, "SteleDatabase.sq", "selectAllHistogramOperations", "SELECT DISTINCT operation_name FROM perf_histogram_buckets ORDER BY operation_name") { cursor -> + cursor.getString(0)!! + } + + public fun selectAllHistogramBuckets(mapper: ( + operation_name: String, + bucket_ms: Long, + count: Long, + ) -> T): Query = Query(592_431_369, arrayOf("perf_histogram_buckets"), driver, "SteleDatabase.sq", "selectAllHistogramBuckets", "SELECT operation_name, bucket_ms, count FROM perf_histogram_buckets ORDER BY operation_name, bucket_ms") { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getLong(1)!!, + cursor.getLong(2)!! + ) + } + + public fun selectAllHistogramBuckets(): Query = selectAllHistogramBuckets(::SelectAllHistogramBuckets) + + public fun selectDebugFlag(key: String): Query = SelectDebugFlagQuery(key) { cursor -> + cursor.getLong(0)!! + } + + public fun selectAllDebugFlags(mapper: (key: String, value_: Long) -> T): Query = Query(213_515_832, arrayOf("debug_flags"), driver, "SteleDatabase.sq", "selectAllDebugFlags", "SELECT key, value FROM debug_flags ORDER BY key") { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getLong(1)!! + ) + } + + public fun selectAllDebugFlags(): Query = selectAllDebugFlags(::SelectAllDebugFlags) + + public fun countBlocksWithWikilink(pageName: String): Query = CountBlocksWithWikilinkQuery(pageName) { cursor -> + cursor.getLong(0)!! + } + + public fun selectBlocksWithWikilink(pageName: String, mapper: ( + id: Long, + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ) -> T): Query = SelectBlocksWithWikilinkQuery(pageName) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10), + cursor.getLong(11)!!, + cursor.getString(12), + cursor.getString(13)!! + ) + } + + public fun selectBlocksWithWikilink(pageName: String): Query = selectBlocksWithWikilink(pageName, ::Blocks) + + public fun countLinkedReferencesForPage(pageName: String): Query = CountLinkedReferencesForPageQuery(pageName) { cursor -> + cursor.getLong(0)!! + } + + public fun selectBacklinkCountsForPages(uuid: Collection, mapper: (page_name: String, backlink_count: Long) -> T): Query = SelectBacklinkCountsForPagesQuery(uuid) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getLong(1)!! + ) + } + + public fun selectBacklinkCountsForPages(uuid: Collection): Query = selectBacklinkCountsForPages(uuid, ::SelectBacklinkCountsForPages) + + public fun selectPageBacklinkCount(name: String): Query = SelectPageBacklinkCountQuery(name) { cursor -> + cursor.getLong(0)!! + } + + public fun selectMetadata(key: String): Query = SelectMetadataQuery(key) { cursor -> + cursor.getString(0)!! + } + + public fun selectAllMetadata(mapper: (key: String, value_: String) -> T): Query = Query(-1_855_662_477, arrayOf("metadata"), driver, "SteleDatabase.sq", "selectAllMetadata", "SELECT key, value FROM metadata") { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!! + ) + } + + public fun selectAllMetadata(): Query = selectAllMetadata(::Metadata) + + public fun selectAllBlocksWithPagePath(mapper: ( + uuid: String, + parent_uuid: String?, + position: Long, + content: String, + file_path: String, + ) -> T): Query = Query(557_803_812, arrayOf("blocks", "pages"), driver, "SteleDatabase.sq", "selectAllBlocksWithPagePath", """ + |SELECT b.uuid, b.parent_uuid, b.position, b.content, p.file_path + |FROM blocks b + |JOIN pages p ON b.page_uuid = p.uuid + |WHERE p.file_path IS NOT NULL + """.trimMargin()) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1), + cursor.getLong(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!! + ) + } + + public fun selectAllBlocksWithPagePath(): Query = selectAllBlocksWithPagePath(::SelectAllBlocksWithPagePath) + + public fun selectOperationsBySessionDesc( + session_id: String, + `value`: Long, + mapper: ( + op_id: String, + session_id: String, + seq: Long, + op_type: String, + entity_uuid: String?, + page_uuid: String?, + payload: String, + created_at: Long, + ) -> T, + ): Query = SelectOperationsBySessionDescQuery(session_id, value) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getLong(2)!!, + cursor.getString(3)!!, + cursor.getString(4), + cursor.getString(5), + cursor.getString(6)!!, + cursor.getLong(7)!! + ) + } + + public fun selectOperationsBySessionDesc(session_id: String, value_: Long): Query = selectOperationsBySessionDesc(session_id, value_, ::Operations) + + public fun selectOperationsByPageUuid(page_uuid: String?, mapper: ( + op_id: String, + session_id: String, + seq: Long, + op_type: String, + entity_uuid: String?, + page_uuid: String?, + payload: String, + created_at: Long, + ) -> T): Query = SelectOperationsByPageUuidQuery(page_uuid) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getLong(2)!!, + cursor.getString(3)!!, + cursor.getString(4), + cursor.getString(5), + cursor.getString(6)!!, + cursor.getLong(7)!! + ) + } + + public fun selectOperationsByPageUuid(page_uuid: String?): Query = selectOperationsByPageUuid(page_uuid, ::Operations) + + public fun selectOperationsSince( + session_id: String, + seq: Long, + mapper: ( + op_id: String, + session_id: String, + seq: Long, + op_type: String, + entity_uuid: String?, + page_uuid: String?, + payload: String, + created_at: Long, + ) -> T, + ): Query = SelectOperationsSinceQuery(session_id, seq) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getLong(2)!!, + cursor.getString(3)!!, + cursor.getString(4), + cursor.getString(5), + cursor.getString(6)!!, + cursor.getLong(7)!! + ) + } + + public fun selectOperationsSince(session_id: String, seq: Long): Query = selectOperationsSince(session_id, seq, ::Operations) + + public fun countOperationPayloadSize(session_id: String, mapper: (SUM: Long?) -> T): Query = CountOperationPayloadSizeQuery(session_id) { cursor -> + mapper( + cursor.getLong(0) + ) + } + + public fun countOperationPayloadSize(session_id: String): Query = countOperationPayloadSize(session_id, ::CountOperationPayloadSize) + + public fun selectLogicalClock(session_id: String): Query = SelectLogicalClockQuery(session_id) { cursor -> + cursor.getLong(0)!! + } + + public fun selectAppliedMigrations(graph_id: String, mapper: ( + id: String, + checksum: String, + status: String, + ) -> T): Query = SelectAppliedMigrationsQuery(graph_id) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!! + ) + } + + public fun selectAppliedMigrations(graph_id: String): Query = selectAppliedMigrations(graph_id, ::SelectAppliedMigrations) + + public fun selectMigrationById( + id: String, + graph_id: String, + mapper: ( + id: String, + graph_id: String, + description: String, + checksum: String, + applied_at: Long, + execution_ms: Long, + status: String, + applied_by: String, + execution_order: Long, + changes_applied: Long, + error_message: String?, + ) -> T, + ): Query = SelectMigrationByIdQuery(id, graph_id) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6)!!, + cursor.getString(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10) + ) + } + + public fun selectMigrationById(id: String, graph_id: String): Query = selectMigrationById(id, graph_id, ::Migration_changelog) + + public fun selectRunningMigrations(graph_id: String, mapper: ( + id: String, + graph_id: String, + description: String, + checksum: String, + applied_at: Long, + execution_ms: Long, + status: String, + applied_by: String, + execution_order: Long, + changes_applied: Long, + error_message: String?, + ) -> T): Query = SelectRunningMigrationsQuery(graph_id) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6)!!, + cursor.getString(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10) + ) + } + + public fun selectRunningMigrations(graph_id: String): Query = selectRunningMigrations(graph_id, ::Migration_changelog) + + public fun selectAllMigrationsForGraph(graph_id: String, mapper: ( + id: String, + graph_id: String, + description: String, + checksum: String, + applied_at: Long, + execution_ms: Long, + status: String, + applied_by: String, + execution_order: Long, + changes_applied: Long, + error_message: String?, + ) -> T): Query = SelectAllMigrationsForGraphQuery(graph_id) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getString(6)!!, + cursor.getString(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getString(10) + ) + } + + public fun selectAllMigrationsForGraph(graph_id: String): Query = selectAllMigrationsForGraph(graph_id, ::Migration_changelog) + + public fun selectRecentSpans(`value`: Long, mapper: ( + id: Long, + trace_id: String, + span_id: String, + parent_span_id: String, + name: String, + start_epoch_ms: Long, + end_epoch_ms: Long, + duration_ms: Long, + attributes_json: String, + status_code: String, + app_version: String, + commit_hash: String, + ) -> T): Query = SelectRecentSpansQuery(value) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!!, + cursor.getLong(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getString(8)!!, + cursor.getString(9)!!, + cursor.getString(10)!!, + cursor.getString(11)!! + ) + } + + public fun selectRecentSpans(value_: Long): Query = selectRecentSpans(value_, ::Spans) + + public fun selectSlowSpansByVersionAndName( + app_version: String, + name: String, + `value`: Long, + mapper: ( + id: Long, + trace_id: String, + span_id: String, + parent_span_id: String, + name: String, + start_epoch_ms: Long, + end_epoch_ms: Long, + duration_ms: Long, + attributes_json: String, + status_code: String, + app_version: String, + commit_hash: String, + ) -> T, + ): Query = SelectSlowSpansByVersionAndNameQuery(app_version, name, value) { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!!, + cursor.getLong(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getString(8)!!, + cursor.getString(9)!!, + cursor.getString(10)!!, + cursor.getString(11)!! + ) + } + + public fun selectSlowSpansByVersionAndName( + app_version: String, + name: String, + value_: Long, + ): Query = selectSlowSpansByVersionAndName(app_version, name, value_, ::Spans) + + public fun selectDistinctVersionsWithSpans(): Query = Query(799_650_447, arrayOf("spans"), driver, "SteleDatabase.sq", "selectDistinctVersionsWithSpans", "SELECT DISTINCT app_version FROM spans WHERE app_version != '' ORDER BY app_version DESC") { cursor -> + cursor.getString(0)!! + } + + public fun selectQueryStatsByVersion(app_version: String, mapper: ( + app_version: String, + table_name: String, + operation: String, + calls: Long, + errors: Long, + total_ms: Long, + min_ms: Long, + max_ms: Long, + b1: Long, + b5: Long, + b16: Long, + b50: Long, + b100: Long, + b500: Long, + b_inf: Long, + first_seen: Long, + last_seen: Long, + ) -> T): Query = SelectQueryStatsByVersionQuery(app_version) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getLong(3)!!, + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getLong(10)!!, + cursor.getLong(11)!!, + cursor.getLong(12)!!, + cursor.getLong(13)!!, + cursor.getLong(14)!!, + cursor.getLong(15)!!, + cursor.getLong(16)!! + ) + } + + public fun selectQueryStatsByVersion(app_version: String): Query = selectQueryStatsByVersion(app_version, ::Query_stats) + + public fun selectTopQueryStatsByTotalMs( + app_version: String, + `value`: Long, + mapper: ( + app_version: String, + table_name: String, + operation: String, + calls: Long, + errors: Long, + total_ms: Long, + min_ms: Long, + max_ms: Long, + b1: Long, + b5: Long, + b16: Long, + b50: Long, + b100: Long, + b500: Long, + b_inf: Long, + first_seen: Long, + last_seen: Long, + ) -> T, + ): Query = SelectTopQueryStatsByTotalMsQuery(app_version, value) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getLong(3)!!, + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getLong(10)!!, + cursor.getLong(11)!!, + cursor.getLong(12)!!, + cursor.getLong(13)!!, + cursor.getLong(14)!!, + cursor.getLong(15)!!, + cursor.getLong(16)!! + ) + } + + public fun selectTopQueryStatsByTotalMs(app_version: String, value_: Long): Query = selectTopQueryStatsByTotalMs(app_version, value_, ::Query_stats) + + public fun selectTopQueryStatsByCalls( + app_version: String, + `value`: Long, + mapper: ( + app_version: String, + table_name: String, + operation: String, + calls: Long, + errors: Long, + total_ms: Long, + min_ms: Long, + max_ms: Long, + b1: Long, + b5: Long, + b16: Long, + b50: Long, + b100: Long, + b500: Long, + b_inf: Long, + first_seen: Long, + last_seen: Long, + ) -> T, + ): Query = SelectTopQueryStatsByCallsQuery(app_version, value) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getLong(3)!!, + cursor.getLong(4)!!, + cursor.getLong(5)!!, + cursor.getLong(6)!!, + cursor.getLong(7)!!, + cursor.getLong(8)!!, + cursor.getLong(9)!!, + cursor.getLong(10)!!, + cursor.getLong(11)!!, + cursor.getLong(12)!!, + cursor.getLong(13)!!, + cursor.getLong(14)!!, + cursor.getLong(15)!!, + cursor.getLong(16)!! + ) + } + + public fun selectTopQueryStatsByCalls(app_version: String, value_: Long): Query = selectTopQueryStatsByCalls(app_version, value_, ::Query_stats) + + public fun selectAllQueryStatVersions(): Query = Query(-639_506_637, arrayOf("query_stats"), driver, "SteleDatabase.sq", "selectAllQueryStatVersions", "SELECT DISTINCT app_version FROM query_stats ORDER BY app_version DESC") { cursor -> + cursor.getString(0)!! + } + + public fun selectGitConfig(graph_id: String, mapper: ( + graph_id: String, + repo_root: String, + wiki_subdir: String, + remote_name: String, + remote_branch: String, + auth_type: String, + ssh_key_path: String?, + ssh_key_passphrase_key: String?, + https_token_key: String?, + poll_interval_minutes: Long, + auto_commit: Long, + commit_message_template: String, + ) -> T): Query = SelectGitConfigQuery(graph_id) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!!, + cursor.getString(5)!!, + cursor.getString(6), + cursor.getString(7), + cursor.getString(8), + cursor.getLong(9)!!, + cursor.getLong(10)!!, + cursor.getString(11)!! + ) + } + + public fun selectGitConfig(graph_id: String): Query = selectGitConfig(graph_id, ::Git_config) + + public fun selectAllImageAnnotations(mapper: ( + uuid: String, + block_uuid: String, + page_uuid: String, + graph_path: String, + file_path: String, + thumbnail_path: String?, + source: String, + source_uri: String?, + captured_at_ms: Long?, + imported_at_ms: Long, + calibration_method: String, + pixels_per_meter: Double, + calibration_confidence_pct: Long, + unit: String, + tags: String, + lat_lng: String?, + altitude_m: Double?, + bearing_deg: Double?, + pitch_deg: Double?, + roll_deg: Double?, + focal_length_mm: Double?, + focal_length_35mm_eq: Double?, + camera_make: String?, + camera_model: String?, + ) -> T): Query = Query(-1_056_409_075, arrayOf("image_annotations"), driver, "SteleDatabase.sq", "selectAllImageAnnotations", "SELECT image_annotations.uuid, image_annotations.block_uuid, image_annotations.page_uuid, image_annotations.graph_path, image_annotations.file_path, image_annotations.thumbnail_path, image_annotations.source, image_annotations.source_uri, image_annotations.captured_at_ms, image_annotations.imported_at_ms, image_annotations.calibration_method, image_annotations.pixels_per_meter, image_annotations.calibration_confidence_pct, image_annotations.unit, image_annotations.tags, image_annotations.lat_lng, image_annotations.altitude_m, image_annotations.bearing_deg, image_annotations.pitch_deg, image_annotations.roll_deg, image_annotations.focal_length_mm, image_annotations.focal_length_35mm_eq, image_annotations.camera_make, image_annotations.camera_model FROM image_annotations ORDER BY imported_at_ms DESC") { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!!, + cursor.getString(5), + cursor.getString(6)!!, + cursor.getString(7), + cursor.getLong(8), + cursor.getLong(9)!!, + cursor.getString(10)!!, + cursor.getDouble(11)!!, + cursor.getLong(12)!!, + cursor.getString(13)!!, + cursor.getString(14)!!, + cursor.getString(15), + cursor.getDouble(16), + cursor.getDouble(17), + cursor.getDouble(18), + cursor.getDouble(19), + cursor.getDouble(20), + cursor.getDouble(21), + cursor.getString(22), + cursor.getString(23) + ) + } + + public fun selectAllImageAnnotations(): Query = selectAllImageAnnotations(::Image_annotations) + + public fun selectImageAnnotationByUuid(uuid: String, mapper: ( + uuid: String, + block_uuid: String, + page_uuid: String, + graph_path: String, + file_path: String, + thumbnail_path: String?, + source: String, + source_uri: String?, + captured_at_ms: Long?, + imported_at_ms: Long, + calibration_method: String, + pixels_per_meter: Double, + calibration_confidence_pct: Long, + unit: String, + tags: String, + lat_lng: String?, + altitude_m: Double?, + bearing_deg: Double?, + pitch_deg: Double?, + roll_deg: Double?, + focal_length_mm: Double?, + focal_length_35mm_eq: Double?, + camera_make: String?, + camera_model: String?, + ) -> T): Query = SelectImageAnnotationByUuidQuery(uuid) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!!, + cursor.getString(5), + cursor.getString(6)!!, + cursor.getString(7), + cursor.getLong(8), + cursor.getLong(9)!!, + cursor.getString(10)!!, + cursor.getDouble(11)!!, + cursor.getLong(12)!!, + cursor.getString(13)!!, + cursor.getString(14)!!, + cursor.getString(15), + cursor.getDouble(16), + cursor.getDouble(17), + cursor.getDouble(18), + cursor.getDouble(19), + cursor.getDouble(20), + cursor.getDouble(21), + cursor.getString(22), + cursor.getString(23) + ) + } + + public fun selectImageAnnotationByUuid(uuid: String): Query = selectImageAnnotationByUuid(uuid, ::Image_annotations) + + public fun selectImageAnnotationsByPage(page_uuid: String, mapper: ( + uuid: String, + block_uuid: String, + page_uuid: String, + graph_path: String, + file_path: String, + thumbnail_path: String?, + source: String, + source_uri: String?, + captured_at_ms: Long?, + imported_at_ms: Long, + calibration_method: String, + pixels_per_meter: Double, + calibration_confidence_pct: Long, + unit: String, + tags: String, + lat_lng: String?, + altitude_m: Double?, + bearing_deg: Double?, + pitch_deg: Double?, + roll_deg: Double?, + focal_length_mm: Double?, + focal_length_35mm_eq: Double?, + camera_make: String?, + camera_model: String?, + ) -> T): Query = SelectImageAnnotationsByPageQuery(page_uuid) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!!, + cursor.getString(5), + cursor.getString(6)!!, + cursor.getString(7), + cursor.getLong(8), + cursor.getLong(9)!!, + cursor.getString(10)!!, + cursor.getDouble(11)!!, + cursor.getLong(12)!!, + cursor.getString(13)!!, + cursor.getString(14)!!, + cursor.getString(15), + cursor.getDouble(16), + cursor.getDouble(17), + cursor.getDouble(18), + cursor.getDouble(19), + cursor.getDouble(20), + cursor.getDouble(21), + cursor.getString(22), + cursor.getString(23) + ) + } + + public fun selectImageAnnotationsByPage(page_uuid: String): Query = selectImageAnnotationsByPage(page_uuid, ::Image_annotations) + + public fun selectImageAnnotationsByTag(`value`: String, mapper: ( + uuid: String, + block_uuid: String, + page_uuid: String, + graph_path: String, + file_path: String, + thumbnail_path: String?, + source: String, + source_uri: String?, + captured_at_ms: Long?, + imported_at_ms: Long, + calibration_method: String, + pixels_per_meter: Double, + calibration_confidence_pct: Long, + unit: String, + tags: String, + lat_lng: String?, + altitude_m: Double?, + bearing_deg: Double?, + pitch_deg: Double?, + roll_deg: Double?, + focal_length_mm: Double?, + focal_length_35mm_eq: Double?, + camera_make: String?, + camera_model: String?, + ) -> T): Query = SelectImageAnnotationsByTagQuery(value) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!!, + cursor.getString(5), + cursor.getString(6)!!, + cursor.getString(7), + cursor.getLong(8), + cursor.getLong(9)!!, + cursor.getString(10)!!, + cursor.getDouble(11)!!, + cursor.getLong(12)!!, + cursor.getString(13)!!, + cursor.getString(14)!!, + cursor.getString(15), + cursor.getDouble(16), + cursor.getDouble(17), + cursor.getDouble(18), + cursor.getDouble(19), + cursor.getDouble(20), + cursor.getDouble(21), + cursor.getString(22), + cursor.getString(23) + ) + } + + public fun selectImageAnnotationsByTag(value_: String): Query = selectImageAnnotationsByTag(value_, ::Image_annotations) + + public fun selectMeasurementsForImage(image_uuid: String, mapper: ( + uuid: String, + image_uuid: String, + annotation_type: String, + normalized_points: String, + value_meters: Double?, + value_display: String?, + label: String?, + color_hex: String, + ble_device_id: String?, + ) -> T): Query = SelectMeasurementsForImageQuery(image_uuid) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getDouble(4), + cursor.getString(5), + cursor.getString(6), + cursor.getString(7)!!, + cursor.getString(8) + ) + } + + public fun selectMeasurementsForImage(image_uuid: String): Query = selectMeasurementsForImage(image_uuid, ::Measurement_annotations) + + public fun selectAssetByUuid(uuid: String, mapper: ( + uuid: String, + file_path: String, + relative_path: String, + media_type: String, + subfolder: String, + tags: String, + auto_labels: String, + ocr_text: String?, + cloud_description: String?, + page_uuids: String, + size_bytes: Long, + imported_at_ms: Long, + ml_processed: Long, + ml_attempted_at: Long?, + ml_failed: Long, + content_hash: String?, + is_orphan: Long, + ml_tags_source: String, + ) -> T): Query = SelectAssetByUuidQuery(uuid) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!!, + cursor.getString(5)!!, + cursor.getString(6)!!, + cursor.getString(7), + cursor.getString(8), + cursor.getString(9)!!, + cursor.getLong(10)!!, + cursor.getLong(11)!!, + cursor.getLong(12)!!, + cursor.getLong(13), + cursor.getLong(14)!!, + cursor.getString(15), + cursor.getLong(16)!!, + cursor.getString(17)!! + ) + } + + public fun selectAssetByUuid(uuid: String): Query = selectAssetByUuid(uuid, ::Asset_index) + + public fun selectAssets( + limit: Long, + offset: Long, + mapper: ( + uuid: String, + file_path: String, + relative_path: String, + media_type: String, + subfolder: String, + tags: String, + auto_labels: String, + ocr_text: String?, + cloud_description: String?, + page_uuids: String, + size_bytes: Long, + imported_at_ms: Long, + ml_processed: Long, + ml_attempted_at: Long?, + ml_failed: Long, + content_hash: String?, + is_orphan: Long, + ml_tags_source: String, + ) -> T, + ): Query = SelectAssetsQuery(limit, offset) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!!, + cursor.getString(5)!!, + cursor.getString(6)!!, + cursor.getString(7), + cursor.getString(8), + cursor.getString(9)!!, + cursor.getLong(10)!!, + cursor.getLong(11)!!, + cursor.getLong(12)!!, + cursor.getLong(13), + cursor.getLong(14)!!, + cursor.getString(15), + cursor.getLong(16)!!, + cursor.getString(17)!! + ) + } + + public fun selectAssets(limit: Long, offset: Long): Query = selectAssets(limit, offset, ::Asset_index) + + public fun selectAssetsByMediaType( + media_type: String, + limit: Long, + offset: Long, + mapper: ( + uuid: String, + file_path: String, + relative_path: String, + media_type: String, + subfolder: String, + tags: String, + auto_labels: String, + ocr_text: String?, + cloud_description: String?, + page_uuids: String, + size_bytes: Long, + imported_at_ms: Long, + ml_processed: Long, + ml_attempted_at: Long?, + ml_failed: Long, + content_hash: String?, + is_orphan: Long, + ml_tags_source: String, + ) -> T, + ): Query = SelectAssetsByMediaTypeQuery(media_type, limit, offset) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!!, + cursor.getString(5)!!, + cursor.getString(6)!!, + cursor.getString(7), + cursor.getString(8), + cursor.getString(9)!!, + cursor.getLong(10)!!, + cursor.getLong(11)!!, + cursor.getLong(12)!!, + cursor.getLong(13), + cursor.getLong(14)!!, + cursor.getString(15), + cursor.getLong(16)!!, + cursor.getString(17)!! + ) + } + + public fun selectAssetsByMediaType( + media_type: String, + limit: Long, + offset: Long, + ): Query = selectAssetsByMediaType(media_type, limit, offset, ::Asset_index) + + public fun searchAssets( + query: String, + limit: Long, + offset: Long, + mapper: ( + uuid: String, + file_path: String, + relative_path: String, + media_type: String, + subfolder: String, + tags: String, + auto_labels: String, + ocr_text: String?, + cloud_description: String?, + page_uuids: String, + size_bytes: Long, + imported_at_ms: Long, + ml_processed: Long, + ml_attempted_at: Long?, + ml_failed: Long, + content_hash: String?, + is_orphan: Long, + ml_tags_source: String, + ) -> T, + ): Query = SearchAssetsQuery(query, limit, offset) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!!, + cursor.getString(5)!!, + cursor.getString(6)!!, + cursor.getString(7), + cursor.getString(8), + cursor.getString(9)!!, + cursor.getLong(10)!!, + cursor.getLong(11)!!, + cursor.getLong(12)!!, + cursor.getLong(13), + cursor.getLong(14)!!, + cursor.getString(15), + cursor.getLong(16)!!, + cursor.getString(17)!! + ) + } + + public fun searchAssets( + query: String, + limit: Long, + offset: Long, + ): Query = searchAssets(query, limit, offset, ::Asset_index) + + public fun selectUnprocessedAssets( + limit: Long, + offset: Long, + mapper: ( + uuid: String, + file_path: String, + relative_path: String, + media_type: String, + subfolder: String, + tags: String, + auto_labels: String, + ocr_text: String?, + cloud_description: String?, + page_uuids: String, + size_bytes: Long, + imported_at_ms: Long, + ml_processed: Long, + ml_attempted_at: Long?, + ml_failed: Long, + content_hash: String?, + is_orphan: Long, + ml_tags_source: String, + ) -> T, + ): Query = SelectUnprocessedAssetsQuery(limit, offset) { cursor -> + mapper( + cursor.getString(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!!, + cursor.getString(5)!!, + cursor.getString(6)!!, + cursor.getString(7), + cursor.getString(8), + cursor.getString(9)!!, + cursor.getLong(10)!!, + cursor.getLong(11)!!, + cursor.getLong(12)!!, + cursor.getLong(13), + cursor.getLong(14)!!, + cursor.getString(15), + cursor.getLong(16)!!, + cursor.getString(17)!! + ) + } + + public fun selectUnprocessedAssets(limit: Long, offset: Long): Query = selectUnprocessedAssets(limit, offset, ::Asset_index) + + public fun countUnprocessedAssets(): Query = Query(-1_728_676_438, arrayOf("asset_index"), driver, "SteleDatabase.sq", "countUnprocessedAssets", "SELECT COUNT(*) FROM asset_index WHERE ml_processed = 0 AND ml_failed = 0") { cursor -> + cursor.getLong(0)!! + } + + public fun countAssets(): Query = Query(-611_689_007, arrayOf("asset_index"), driver, "SteleDatabase.sq", "countAssets", "SELECT COUNT(*) FROM asset_index") { cursor -> + cursor.getLong(0)!! + } + + public fun selectAllPendingMoves(mapper: ( + id: Long, + asset_uuid: String, + old_file_path: String, + new_file_path: String, + old_relative_path: String, + new_relative_path: String, + created_at_ms: Long, + ) -> T): Query = Query(-947_239_761, arrayOf("pending_asset_moves"), driver, "SteleDatabase.sq", "selectAllPendingMoves", "SELECT pending_asset_moves.id, pending_asset_moves.asset_uuid, pending_asset_moves.old_file_path, pending_asset_moves.new_file_path, pending_asset_moves.old_relative_path, pending_asset_moves.new_relative_path, pending_asset_moves.created_at_ms FROM pending_asset_moves") { cursor -> + mapper( + cursor.getLong(0)!!, + cursor.getString(1)!!, + cursor.getString(2)!!, + cursor.getString(3)!!, + cursor.getString(4)!!, + cursor.getString(5)!!, + cursor.getLong(6)!! + ) + } + + public fun selectAllPendingMoves(): Query = selectAllPendingMoves(::Pending_asset_moves) + + public fun selectLastInsertRowId(): ExecutableQuery = Query(998_850_025, driver, "SteleDatabase.sq", "selectLastInsertRowId", "SELECT last_insert_rowid()") { cursor -> + cursor.getLong(0)!! + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateBlockParent(parent_uuid: String?, uuid: String): Long { + val result = driver.execute(805_213_229, """UPDATE blocks SET parent_uuid = ? WHERE uuid = ?""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, parent_uuid) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(805_213_229) { emit -> + emit("blocks") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateBlockParentPositionAndLevel( + parent_uuid: String?, + position: Long, + level: Long, + uuid: String, + ): Long { + val result = driver.execute(-1_913_429_373, """UPDATE blocks SET parent_uuid = ?, position = ?, level = ? WHERE uuid = ?""", 4) { + var parameterIndex = 0 + bindString(parameterIndex++, parent_uuid) + bindLong(parameterIndex++, position) + bindLong(parameterIndex++, level) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(-1_913_429_373) { emit -> + emit("blocks") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateBlockHierarchy( + parent_uuid: String?, + left_uuid: String?, + position: Long, + level: Long, + uuid: String, + ): Long { + val result = driver.execute(759_870_418, """UPDATE blocks SET parent_uuid = ?, left_uuid = ?, position = ?, level = ? WHERE uuid = ?""", 5) { + var parameterIndex = 0 + bindString(parameterIndex++, parent_uuid) + bindString(parameterIndex++, left_uuid) + bindLong(parameterIndex++, position) + bindLong(parameterIndex++, level) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(759_870_418) { emit -> + emit("blocks") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateBlockPositionOnly(position: Long, uuid: String): Long { + val result = driver.execute(1_997_868_472, """UPDATE blocks SET position = ? WHERE uuid = ?""", 2) { + var parameterIndex = 0 + bindLong(parameterIndex++, position) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(1_997_868_472) { emit -> + emit("blocks") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateBlockContent( + content: String, + updated_at: Long, + content_hash: String?, + uuid: String, + ): Long { + val result = driver.execute(936_712_534, """UPDATE blocks SET content = ?, updated_at = ?, version = version + 1, content_hash = ? WHERE uuid = ?""", 4) { + var parameterIndex = 0 + bindString(parameterIndex++, content) + bindLong(parameterIndex++, updated_at) + bindString(parameterIndex++, content_hash) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(936_712_534) { emit -> + emit("blocks") + emit("blocks_fts") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateBlockFull( + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + updated_at: Long, + properties: String?, + content_hash: String?, + block_type: String, + uuid: String, + ): Long { + val result = driver.execute(1_055_306_450, """ + |UPDATE blocks SET + | page_uuid = ?, parent_uuid = ?, left_uuid = ?, content = ?, + | level = ?, position = ?, updated_at = ?, properties = ?, + | version = version + 1, content_hash = ?, block_type = ? + |WHERE uuid = ? + """.trimMargin(), 11) { + var parameterIndex = 0 + bindString(parameterIndex++, page_uuid) + bindString(parameterIndex++, parent_uuid) + bindString(parameterIndex++, left_uuid) + bindString(parameterIndex++, content) + bindLong(parameterIndex++, level) + bindLong(parameterIndex++, position) + bindLong(parameterIndex++, updated_at) + bindString(parameterIndex++, properties) + bindString(parameterIndex++, content_hash) + bindString(parameterIndex++, block_type) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(1_055_306_450) { emit -> + emit("blocks") + emit("blocks_fts") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateBlockLevelOnly(level: Long, uuid: String): Long { + val result = driver.execute(1_283_321_581, """UPDATE blocks SET level = ? WHERE uuid = ?""", 2) { + var parameterIndex = 0 + bindLong(parameterIndex++, level) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(1_283_321_581) { emit -> + emit("blocks") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateBlockLeftUuid(left_uuid: String?, uuid: String): Long { + val result = driver.execute(1_259_103_013, """UPDATE blocks SET left_uuid = ? WHERE uuid = ?""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, left_uuid) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(1_259_103_013) { emit -> + emit("blocks") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateBlockProperties(properties: String?, uuid: String): Long { + val result = driver.execute(10_067_766, """UPDATE blocks SET properties = ? WHERE uuid = ?""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, properties) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(10_067_766) { emit -> + emit("blocks") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteBlockByUuid(uuid: String): Long { + val result = driver.execute(1_663_446_547, """DELETE FROM blocks WHERE uuid = ?""", 1) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(1_663_446_547) { emit -> + emit("block_references") + emit("blocks") + emit("blocks_fts") + emit("properties") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteBlockChildren(parent_uuid: String?): Long { + val result = driver.execute(null, """DELETE FROM blocks WHERE parent_uuid ${ if (parent_uuid == null) "IS" else "=" } ?""", 1) { + var parameterIndex = 0 + bindString(parameterIndex++, parent_uuid) + }.await() + notifyQueries(948_586_272) { emit -> + emit("block_references") + emit("blocks") + emit("blocks_fts") + emit("properties") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteAllBlocks(): Long { + val result = driver.execute(-1_165_677_061, """DELETE FROM blocks""", 0).await() + notifyQueries(-1_165_677_061) { emit -> + emit("block_references") + emit("blocks") + emit("blocks_fts") + emit("properties") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteBlocksByPageUuid(page_uuid: String): Long { + val result = driver.execute(-2_119_562_093, """DELETE FROM blocks WHERE page_uuid = ?""", 1) { + var parameterIndex = 0 + bindString(parameterIndex++, page_uuid) + }.await() + notifyQueries(-2_119_562_093) { emit -> + emit("block_references") + emit("blocks") + emit("blocks_fts") + emit("properties") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteBlocksByPageUuids(page_uuid: Collection): Long { + val page_uuidIndexes = createArguments(count = page_uuid.size) + val result = driver.execute(null, """DELETE FROM blocks WHERE page_uuid IN $page_uuidIndexes""", page_uuid.size) { + var parameterIndex = 0 + page_uuid.forEach { page_uuid_ -> + bindString(parameterIndex++, page_uuid_) + } + }.await() + notifyQueries(-1_281_915_328) { emit -> + emit("block_references") + emit("blocks") + emit("blocks_fts") + emit("properties") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun insertBlock( + uuid: String, + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + ): Long { + val result = driver.execute(2_142_163_379, """ + |INSERT OR REPLACE INTO blocks (uuid, page_uuid, parent_uuid, left_uuid, content, level, position, created_at, updated_at, properties, version, content_hash, block_type) + |VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """.trimMargin(), 13) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + bindString(parameterIndex++, page_uuid) + bindString(parameterIndex++, parent_uuid) + bindString(parameterIndex++, left_uuid) + bindString(parameterIndex++, content) + bindLong(parameterIndex++, level) + bindLong(parameterIndex++, position) + bindLong(parameterIndex++, created_at) + bindLong(parameterIndex++, updated_at) + bindString(parameterIndex++, properties) + bindLong(parameterIndex++, version) + bindString(parameterIndex++, content_hash) + bindString(parameterIndex++, block_type) + }.await() + notifyQueries(2_142_163_379) { emit -> + emit("blocks") + emit("blocks_fts") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateBlockForSave( + page_uuid: String, + parent_uuid: String?, + left_uuid: String?, + content: String, + level: Long, + position: Long, + updated_at: Long, + properties: String?, + version: Long, + content_hash: String?, + block_type: String, + uuid: String, + ): Long { + val result = driver.execute(-693_036_349, """ + |UPDATE blocks + |SET page_uuid = ?, parent_uuid = ?, left_uuid = ?, content = ?, level = ?, + | position = ?, updated_at = ?, properties = ?, version = ?, content_hash = ?, block_type = ? + |WHERE uuid = ? + """.trimMargin(), 12) { + var parameterIndex = 0 + bindString(parameterIndex++, page_uuid) + bindString(parameterIndex++, parent_uuid) + bindString(parameterIndex++, left_uuid) + bindString(parameterIndex++, content) + bindLong(parameterIndex++, level) + bindLong(parameterIndex++, position) + bindLong(parameterIndex++, updated_at) + bindString(parameterIndex++, properties) + bindLong(parameterIndex++, version) + bindString(parameterIndex++, content_hash) + bindString(parameterIndex++, block_type) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(-693_036_349) { emit -> + emit("blocks") + emit("blocks_fts") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updatePageProperties(properties: String?, uuid: String): Long { + val result = driver.execute(1_668_226_252, """UPDATE pages SET properties = ? WHERE uuid = ?""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, properties) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(1_668_226_252) { emit -> + emit("pages") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updatePageName(name: String, uuid: String): Long { + val result = driver.execute(-658_837_276, """UPDATE pages SET name = ? WHERE uuid = ?""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, name) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(-658_837_276) { emit -> + emit("pages") + emit("pages_fts") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updatePage( + namespace: String?, + file_path: String?, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String?, + is_content_loaded: Long, + uuid: String, + ): Long { + val result = driver.execute(1_994_000_057, """ + |UPDATE pages SET + | namespace = ?, + | file_path = ?, + | updated_at = ?, + | properties = ?, + | version = ?, + | is_favorite = ?, + | is_journal = ?, + | journal_date = ?, + | is_content_loaded = ? + |WHERE uuid = ? + """.trimMargin(), 10) { + var parameterIndex = 0 + bindString(parameterIndex++, namespace) + bindString(parameterIndex++, file_path) + bindLong(parameterIndex++, updated_at) + bindString(parameterIndex++, properties) + bindLong(parameterIndex++, version) + bindLong(parameterIndex++, is_favorite) + bindLong(parameterIndex++, is_journal) + bindString(parameterIndex++, journal_date) + bindLong(parameterIndex++, is_content_loaded) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(1_994_000_057) { emit -> + emit("pages") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deletePageByUuid(uuid: String): Long { + val result = driver.execute(1_953_287_981, """DELETE FROM pages WHERE uuid = ?""", 1) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(1_953_287_981) { emit -> + emit("blocks") + emit("pages") + emit("pages_fts") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun insertPage( + uuid: String, + name: String, + namespace: String?, + file_path: String?, + created_at: Long, + updated_at: Long, + properties: String?, + version: Long, + is_favorite: Long?, + is_journal: Long?, + journal_date: String?, + is_content_loaded: Long, + ): Long { + val result = driver.execute(-1_038_870_359, """ + |INSERT OR IGNORE INTO pages (uuid, name, namespace, file_path, created_at, updated_at, properties, version, is_favorite, is_journal, journal_date, is_content_loaded) + |VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """.trimMargin(), 12) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + bindString(parameterIndex++, name) + bindString(parameterIndex++, namespace) + bindString(parameterIndex++, file_path) + bindLong(parameterIndex++, created_at) + bindLong(parameterIndex++, updated_at) + bindString(parameterIndex++, properties) + bindLong(parameterIndex++, version) + bindLong(parameterIndex++, is_favorite) + bindLong(parameterIndex++, is_journal) + bindString(parameterIndex++, journal_date) + bindLong(parameterIndex++, is_content_loaded) + }.await() + notifyQueries(-1_038_870_359) { emit -> + emit("pages") + emit("pages_fts") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updatePageFavorite(is_favorite: Long?, uuid: String): Long { + val result = driver.execute(-10_196_107, """UPDATE pages SET is_favorite = ? WHERE uuid = ?""", 2) { + var parameterIndex = 0 + bindLong(parameterIndex++, is_favorite) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(-10_196_107) { emit -> + emit("pages") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteAllPages(): Long { + val result = driver.execute(1_637_559_471, """DELETE FROM pages""", 0).await() + notifyQueries(1_637_559_471) { emit -> + emit("blocks") + emit("pages") + emit("pages_fts") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun insertBlockReference( + from_block_uuid: String, + to_block_uuid: String, + created_at: Long, + ): Long { + val result = driver.execute(1_226_032_856, """ + |INSERT OR REPLACE INTO block_references (from_block_uuid, to_block_uuid, created_at) + |VALUES (?, ?, ?) + """.trimMargin(), 3) { + var parameterIndex = 0 + bindString(parameterIndex++, from_block_uuid) + bindString(parameterIndex++, to_block_uuid) + bindLong(parameterIndex++, created_at) + }.await() + notifyQueries(1_226_032_856) { emit -> + emit("block_references") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteBlockReference(from_block_uuid: String, to_block_uuid: String): Long { + val result = driver.execute(-1_489_470_902, """DELETE FROM block_references WHERE from_block_uuid = ? AND to_block_uuid = ?""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, from_block_uuid) + bindString(parameterIndex++, to_block_uuid) + }.await() + notifyQueries(-1_489_470_902) { emit -> + emit("block_references") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun insertPluginData( + plugin_id: String, + entity_type: String, + entity_uuid: String, + key: String, + value_: String, + created_at: Long, + updated_at: Long?, + ): Long { + val result = driver.execute(-1_794_622_441, """ + |INSERT INTO plugin_data (plugin_id, entity_type, entity_uuid, key, value, created_at, updated_at) + |VALUES (?, ?, ?, ?, ?, ?, ?) + """.trimMargin(), 7) { + var parameterIndex = 0 + bindString(parameterIndex++, plugin_id) + bindString(parameterIndex++, entity_type) + bindString(parameterIndex++, entity_uuid) + bindString(parameterIndex++, key) + bindString(parameterIndex++, value_) + bindLong(parameterIndex++, created_at) + bindLong(parameterIndex++, updated_at) + }.await() + notifyQueries(-1_794_622_441) { emit -> + emit("plugin_data") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updatePluginData( + value_: String, + updated_at: Long?, + plugin_id: String, + entity_type: String, + entity_uuid: String, + key: String, + ): Long { + val result = driver.execute(998_727_207, """UPDATE plugin_data SET value = ?, updated_at = ? WHERE plugin_id = ? AND entity_type = ? AND entity_uuid = ? AND key = ?""", 6) { + var parameterIndex = 0 + bindString(parameterIndex++, value_) + bindLong(parameterIndex++, updated_at) + bindString(parameterIndex++, plugin_id) + bindString(parameterIndex++, entity_type) + bindString(parameterIndex++, entity_uuid) + bindString(parameterIndex++, key) + }.await() + notifyQueries(998_727_207) { emit -> + emit("plugin_data") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun upsertPluginData( + plugin_id: String, + entity_type: String, + entity_uuid: String, + key: String, + value_: String, + created_at: Long, + updated_at: Long?, + ): Long { + val result = driver.execute(-610_961_651, """ + |INSERT OR REPLACE INTO plugin_data (plugin_id, entity_type, entity_uuid, key, value, created_at, updated_at) + |VALUES (?, ?, ?, ?, ?, ?, ?) + """.trimMargin(), 7) { + var parameterIndex = 0 + bindString(parameterIndex++, plugin_id) + bindString(parameterIndex++, entity_type) + bindString(parameterIndex++, entity_uuid) + bindString(parameterIndex++, key) + bindString(parameterIndex++, value_) + bindLong(parameterIndex++, created_at) + bindLong(parameterIndex++, updated_at) + }.await() + notifyQueries(-610_961_651) { emit -> + emit("plugin_data") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deletePluginData( + plugin_id: String, + entity_type: String, + entity_uuid: String, + key: String, + ): Long { + val result = driver.execute(761_559_177, """DELETE FROM plugin_data WHERE plugin_id = ? AND entity_type = ? AND entity_uuid = ? AND key = ?""", 4) { + var parameterIndex = 0 + bindString(parameterIndex++, plugin_id) + bindString(parameterIndex++, entity_type) + bindString(parameterIndex++, entity_uuid) + bindString(parameterIndex++, key) + }.await() + notifyQueries(761_559_177) { emit -> + emit("plugin_data") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deletePluginDataByPlugin(plugin_id: String): Long { + val result = driver.execute(1_301_794_323, """DELETE FROM plugin_data WHERE plugin_id = ?""", 1) { + var parameterIndex = 0 + bindString(parameterIndex++, plugin_id) + }.await() + notifyQueries(1_301_794_323) { emit -> + emit("plugin_data") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deletePluginDataByEntity(entity_type: String, entity_uuid: String): Long { + val result = driver.execute(988_693_187, """DELETE FROM plugin_data WHERE entity_type = ? AND entity_uuid = ?""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, entity_type) + bindString(parameterIndex++, entity_uuid) + }.await() + notifyQueries(988_693_187) { emit -> + emit("plugin_data") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun insertPageVisitIfAbsent(page_uuid: String, last_visited_at: Long): Long { + val result = driver.execute(-671_925_512, """ + |INSERT OR IGNORE INTO page_visits (page_uuid, visit_count, last_visited_at) + |VALUES (?, 0, ?) + """.trimMargin(), 2) { + var parameterIndex = 0 + bindString(parameterIndex++, page_uuid) + bindLong(parameterIndex++, last_visited_at) + }.await() + notifyQueries(-671_925_512) { emit -> + emit("page_visits") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updatePageVisit(last_visited_at: Long, page_uuid: String): Long { + val result = driver.execute(1_058_513_426, """ + |UPDATE page_visits + |SET visit_count = visit_count + 1, last_visited_at = ? + |WHERE page_uuid = ? + """.trimMargin(), 2) { + var parameterIndex = 0 + bindLong(parameterIndex++, last_visited_at) + bindString(parameterIndex++, page_uuid) + }.await() + notifyQueries(1_058_513_426) { emit -> + emit("page_visits") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun insertHistogramBucketIfAbsent( + operation_name: String, + bucket_ms: Long, + recorded_at: Long, + ): Long { + val result = driver.execute(-212_282_134, """ + |INSERT OR IGNORE INTO perf_histogram_buckets (operation_name, bucket_ms, count, recorded_at) + |VALUES (?, ?, 0, ?) + """.trimMargin(), 3) { + var parameterIndex = 0 + bindString(parameterIndex++, operation_name) + bindLong(parameterIndex++, bucket_ms) + bindLong(parameterIndex++, recorded_at) + }.await() + notifyQueries(-212_282_134) { emit -> + emit("perf_histogram_buckets") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun incrementHistogramBucketCount( + recorded_at: Long, + operation_name: String, + bucket_ms: Long, + ): Long { + val result = driver.execute(-438_417_937, """ + |UPDATE perf_histogram_buckets + |SET count = count + 1, recorded_at = ? + |WHERE operation_name = ? AND bucket_ms = ? + """.trimMargin(), 3) { + var parameterIndex = 0 + bindLong(parameterIndex++, recorded_at) + bindString(parameterIndex++, operation_name) + bindLong(parameterIndex++, bucket_ms) + }.await() + notifyQueries(-438_417_937) { emit -> + emit("perf_histogram_buckets") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteOldHistogramRows(recorded_at: Long): Long { + val result = driver.execute(-994_534_270, """DELETE FROM perf_histogram_buckets WHERE recorded_at < ?""", 1) { + var parameterIndex = 0 + bindLong(parameterIndex++, recorded_at) + }.await() + notifyQueries(-994_534_270) { emit -> + emit("perf_histogram_buckets") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun upsertDebugFlag( + key: String, + value_: Long, + updated_at: Long, + ): Long { + val result = driver.execute(1_041_055_951, """ + |INSERT OR REPLACE INTO debug_flags (key, value, updated_at) + |VALUES (?, ?, ?) + """.trimMargin(), 3) { + var parameterIndex = 0 + bindString(parameterIndex++, key) + bindLong(parameterIndex++, value_) + bindLong(parameterIndex++, updated_at) + }.await() + notifyQueries(1_041_055_951) { emit -> + emit("debug_flags") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun recomputeBacklinkCountForPage(name: String): Long { + val result = driver.execute(1_594_896_973, """ + |UPDATE pages SET backlink_count = ( + | SELECT COUNT(*) FROM blocks + | WHERE blocks.content LIKE '%[[' || pages.name || ']]%' + |) WHERE pages.name = ? + """.trimMargin(), 1) { + var parameterIndex = 0 + bindString(parameterIndex++, name) + }.await() + notifyQueries(1_594_896_973) { emit -> + emit("pages") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun setPageBacklinkCount(backlink_count: Long, name: String): Long { + val result = driver.execute(1_739_125_790, """UPDATE pages SET backlink_count = ? WHERE name = ?""", 2) { + var parameterIndex = 0 + bindLong(parameterIndex++, backlink_count) + bindString(parameterIndex++, name) + }.await() + notifyQueries(1_739_125_790) { emit -> + emit("pages") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun upsertMetadata(key: String, value_: String): Long { + val result = driver.execute(421_270_719, """INSERT OR REPLACE INTO metadata (key, value) VALUES (?, ?)""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, key) + bindString(parameterIndex++, value_) + }.await() + notifyQueries(421_270_719) { emit -> + emit("metadata") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateBlockUuidForMigration(uuid: String, uuid_: String): Long { + val result = driver.execute(-1_394_940_893, """UPDATE blocks SET uuid = ? WHERE uuid = ?""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + bindString(parameterIndex++, uuid_) + }.await() + notifyQueries(-1_394_940_893) { emit -> + emit("blocks") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateParentUuidForMigration(parent_uuid: String?, parent_uuid_: String?): Long { + val result = driver.execute(null, """UPDATE blocks SET parent_uuid = ? WHERE parent_uuid ${ if (parent_uuid_ == null) "IS" else "=" } ?""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, parent_uuid) + bindString(parameterIndex++, parent_uuid_) + }.await() + notifyQueries(1_196_885_716) { emit -> + emit("blocks") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateLeftUuidForMigration(left_uuid: String?, left_uuid_: String?): Long { + val result = driver.execute(null, """UPDATE blocks SET left_uuid = ? WHERE left_uuid ${ if (left_uuid_ == null) "IS" else "=" } ?""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, left_uuid) + bindString(parameterIndex++, left_uuid_) + }.await() + notifyQueries(-750_147_919) { emit -> + emit("blocks") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateBlockReferencesFromForMigration(from_block_uuid: String, from_block_uuid_: String): Long { + val result = driver.execute(1_262_608_506, """UPDATE block_references SET from_block_uuid = ? WHERE from_block_uuid = ?""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, from_block_uuid) + bindString(parameterIndex++, from_block_uuid_) + }.await() + notifyQueries(1_262_608_506) { emit -> + emit("block_references") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateBlockReferencesToForMigration(to_block_uuid: String, to_block_uuid_: String): Long { + val result = driver.execute(-1_154_362_229, """UPDATE block_references SET to_block_uuid = ? WHERE to_block_uuid = ?""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, to_block_uuid) + bindString(parameterIndex++, to_block_uuid_) + }.await() + notifyQueries(-1_154_362_229) { emit -> + emit("block_references") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updatePropertiesBlockUuidForMigration(block_uuid: String, block_uuid_: String): Long { + val result = driver.execute(1_878_397_232, """UPDATE properties SET block_uuid = ? WHERE block_uuid = ?""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, block_uuid) + bindString(parameterIndex++, block_uuid_) + }.await() + notifyQueries(1_878_397_232) { emit -> + emit("properties") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun insertOperation( + op_id: String, + session_id: String, + seq: Long, + op_type: String, + entity_uuid: String?, + page_uuid: String?, + payload: String, + created_at: Long, + ): Long { + val result = driver.execute(-1_292_181_619, """ + |INSERT INTO operations (op_id, session_id, seq, op_type, entity_uuid, page_uuid, payload, created_at) + |VALUES (?, ?, ?, ?, ?, ?, ?, ?) + """.trimMargin(), 8) { + var parameterIndex = 0 + bindString(parameterIndex++, op_id) + bindString(parameterIndex++, session_id) + bindLong(parameterIndex++, seq) + bindString(parameterIndex++, op_type) + bindString(parameterIndex++, entity_uuid) + bindString(parameterIndex++, page_uuid) + bindString(parameterIndex++, payload) + bindLong(parameterIndex++, created_at) + }.await() + notifyQueries(-1_292_181_619) { emit -> + emit("operations") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteOperationsBefore(session_id: String, seq: Long): Long { + val result = driver.execute(-562_863_977, """DELETE FROM operations WHERE session_id = ? AND seq < ?""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, session_id) + bindLong(parameterIndex++, seq) + }.await() + notifyQueries(-562_863_977) { emit -> + emit("operations") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun upsertLogicalClock(session_id: String, seq: Long): Long { + val result = driver.execute(-601_899_243, """INSERT OR REPLACE INTO logical_clock (session_id, seq) VALUES (?, ?)""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, session_id) + bindLong(parameterIndex++, seq) + }.await() + notifyQueries(-601_899_243) { emit -> + emit("logical_clock") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun insertMigrationRecord( + id: String, + graph_id: String, + description: String, + checksum: String, + applied_at: Long, + execution_ms: Long, + status: String, + applied_by: String, + execution_order: Long, + changes_applied: Long, + error_message: String?, + ): Long { + val result = driver.execute(1_305_497_445, """ + |INSERT INTO migration_changelog + | (id, graph_id, description, checksum, applied_at, execution_ms, status, applied_by, execution_order, changes_applied, error_message) + |VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """.trimMargin(), 11) { + var parameterIndex = 0 + bindString(parameterIndex++, id) + bindString(parameterIndex++, graph_id) + bindString(parameterIndex++, description) + bindString(parameterIndex++, checksum) + bindLong(parameterIndex++, applied_at) + bindLong(parameterIndex++, execution_ms) + bindString(parameterIndex++, status) + bindString(parameterIndex++, applied_by) + bindLong(parameterIndex++, execution_order) + bindLong(parameterIndex++, changes_applied) + bindString(parameterIndex++, error_message) + }.await() + notifyQueries(1_305_497_445) { emit -> + emit("migration_changelog") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateMigrationStatus( + status: String, + error_message: String?, + execution_ms: Long, + changes_applied: Long, + id: String, + graph_id: String, + ): Long { + val result = driver.execute(21_715_702, """ + |UPDATE migration_changelog SET status = ?, error_message = ?, execution_ms = ?, changes_applied = ? + |WHERE id = ? AND graph_id = ? + """.trimMargin(), 6) { + var parameterIndex = 0 + bindString(parameterIndex++, status) + bindString(parameterIndex++, error_message) + bindLong(parameterIndex++, execution_ms) + bindLong(parameterIndex++, changes_applied) + bindString(parameterIndex++, id) + bindString(parameterIndex++, graph_id) + }.await() + notifyQueries(21_715_702) { emit -> + emit("migration_changelog") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteMigrationRecord(id: String, graph_id: String): Long { + val result = driver.execute(-1_270_740_429, """DELETE FROM migration_changelog WHERE id = ? AND graph_id = ?""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, id) + bindString(parameterIndex++, graph_id) + }.await() + notifyQueries(-1_270_740_429) { emit -> + emit("migration_changelog") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateMigrationChecksum( + checksum: String, + id: String, + graph_id: String, + ): Long { + val result = driver.execute(-387_828_153, """UPDATE migration_changelog SET checksum = ? WHERE id = ? AND graph_id = ?""", 3) { + var parameterIndex = 0 + bindString(parameterIndex++, checksum) + bindString(parameterIndex++, id) + bindString(parameterIndex++, graph_id) + }.await() + notifyQueries(-387_828_153) { emit -> + emit("migration_changelog") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun insertSpan( + trace_id: String, + span_id: String, + parent_span_id: String, + name: String, + start_epoch_ms: Long, + end_epoch_ms: Long, + duration_ms: Long, + attributes_json: String, + status_code: String, + app_version: String, + commit_hash: String, + ): Long { + val result = driver.execute(-1_038_766_748, """ + |INSERT INTO spans (trace_id, span_id, parent_span_id, name, start_epoch_ms, end_epoch_ms, duration_ms, attributes_json, status_code, app_version, commit_hash) + |VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """.trimMargin(), 11) { + var parameterIndex = 0 + bindString(parameterIndex++, trace_id) + bindString(parameterIndex++, span_id) + bindString(parameterIndex++, parent_span_id) + bindString(parameterIndex++, name) + bindLong(parameterIndex++, start_epoch_ms) + bindLong(parameterIndex++, end_epoch_ms) + bindLong(parameterIndex++, duration_ms) + bindString(parameterIndex++, attributes_json) + bindString(parameterIndex++, status_code) + bindString(parameterIndex++, app_version) + bindString(parameterIndex++, commit_hash) + }.await() + notifyQueries(-1_038_766_748) { emit -> + emit("spans") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteSpansOlderThan(end_epoch_ms: Long): Long { + val result = driver.execute(-1_376_925_320, """DELETE FROM spans WHERE end_epoch_ms < ?""", 1) { + var parameterIndex = 0 + bindLong(parameterIndex++, end_epoch_ms) + }.await() + notifyQueries(-1_376_925_320) { emit -> + emit("spans") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteExcessSpans(`value`: Long): Long { + val result = driver.execute(1_788_250_216, """DELETE FROM spans WHERE id NOT IN (SELECT id FROM spans ORDER BY start_epoch_ms DESC LIMIT ?)""", 1) { + var parameterIndex = 0 + bindLong(parameterIndex++, value) + }.await() + notifyQueries(1_788_250_216) { emit -> + emit("spans") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteAllSpans(): Long { + val result = driver.execute(1_640_771_412, """DELETE FROM spans""", 0).await() + notifyQueries(1_640_771_412) { emit -> + emit("spans") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun insertQueryStatIfAbsent( + app_version: String, + table_name: String, + operation: String, + first_seen: Long, + last_seen: Long, + ): Long { + val result = driver.execute(1_909_304_888, """ + |INSERT OR IGNORE INTO query_stats (app_version, table_name, operation, calls, errors, total_ms, min_ms, max_ms, b1, b5, b16, b50, b100, b500, b_inf, first_seen, last_seen) + |VALUES (?, ?, ?, 0, 0, 0, 9999999, 0, 0, 0, 0, 0, 0, 0, 0, ?, ?) + """.trimMargin(), 5) { + var parameterIndex = 0 + bindString(parameterIndex++, app_version) + bindString(parameterIndex++, table_name) + bindString(parameterIndex++, operation) + bindLong(parameterIndex++, first_seen) + bindLong(parameterIndex++, last_seen) + }.await() + notifyQueries(1_909_304_888) { emit -> + emit("query_stats") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun mergeQueryStat( + calls: Long, + errors: Long, + total_ms: Long, + `value`: Long?, + value_: Long?, + b1: Long, + b5: Long, + b16: Long, + b50: Long, + b100: Long, + b500: Long, + b_inf: Long, + value__: Long?, + app_version: String, + table_name: String, + operation: String, + ): Long { + val result = driver.execute(2_023_646_501, """ + |UPDATE query_stats SET + | calls = calls + ?, + | errors = errors + ?, + | total_ms = total_ms + ?, + | min_ms = MIN(min_ms, ?), + | max_ms = MAX(max_ms, ?), + | b1 = b1 + ?, + | b5 = b5 + ?, + | b16 = b16 + ?, + | b50 = b50 + ?, + | b100 = b100 + ?, + | b500 = b500 + ?, + | b_inf = b_inf + ?, + | last_seen = MAX(last_seen, ?) + |WHERE app_version = ? AND table_name = ? AND operation = ? + """.trimMargin(), 16) { + var parameterIndex = 0 + bindLong(parameterIndex++, calls) + bindLong(parameterIndex++, errors) + bindLong(parameterIndex++, total_ms) + bindLong(parameterIndex++, value) + bindLong(parameterIndex++, value_) + bindLong(parameterIndex++, b1) + bindLong(parameterIndex++, b5) + bindLong(parameterIndex++, b16) + bindLong(parameterIndex++, b50) + bindLong(parameterIndex++, b100) + bindLong(parameterIndex++, b500) + bindLong(parameterIndex++, b_inf) + bindLong(parameterIndex++, value__) + bindString(parameterIndex++, app_version) + bindString(parameterIndex++, table_name) + bindString(parameterIndex++, operation) + }.await() + notifyQueries(2_023_646_501) { emit -> + emit("query_stats") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteQueryStatsForVersion(app_version: String): Long { + val result = driver.execute(876_124_146, """DELETE FROM query_stats WHERE app_version = ?""", 1) { + var parameterIndex = 0 + bindString(parameterIndex++, app_version) + }.await() + notifyQueries(876_124_146) { emit -> + emit("query_stats") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun insertOrReplaceGitConfig( + graph_id: String, + repo_root: String, + wiki_subdir: String, + remote_name: String, + remote_branch: String, + auth_type: String, + ssh_key_path: String?, + ssh_key_passphrase_key: String?, + https_token_key: String?, + poll_interval_minutes: Long, + auto_commit: Long, + commit_message_template: String, + ): Long { + val result = driver.execute(66_633_213, """ + |INSERT OR REPLACE INTO git_config( + | graph_id, repo_root, wiki_subdir, remote_name, remote_branch, + | auth_type, ssh_key_path, ssh_key_passphrase_key, https_token_key, + | poll_interval_minutes, auto_commit, commit_message_template + |) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """.trimMargin(), 12) { + var parameterIndex = 0 + bindString(parameterIndex++, graph_id) + bindString(parameterIndex++, repo_root) + bindString(parameterIndex++, wiki_subdir) + bindString(parameterIndex++, remote_name) + bindString(parameterIndex++, remote_branch) + bindString(parameterIndex++, auth_type) + bindString(parameterIndex++, ssh_key_path) + bindString(parameterIndex++, ssh_key_passphrase_key) + bindString(parameterIndex++, https_token_key) + bindLong(parameterIndex++, poll_interval_minutes) + bindLong(parameterIndex++, auto_commit) + bindString(parameterIndex++, commit_message_template) + }.await() + notifyQueries(66_633_213) { emit -> + emit("git_config") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteGitConfig(graph_id: String): Long { + val result = driver.execute(-1_517_498_072, """DELETE FROM git_config WHERE graph_id = ?""", 1) { + var parameterIndex = 0 + bindString(parameterIndex++, graph_id) + }.await() + notifyQueries(-1_517_498_072) { emit -> + emit("git_config") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun insertImageAnnotation( + uuid: String, + block_uuid: String, + page_uuid: String, + graph_path: String, + file_path: String, + thumbnail_path: String?, + source: String, + source_uri: String?, + captured_at_ms: Long?, + imported_at_ms: Long, + calibration_method: String, + pixels_per_meter: Double, + calibration_confidence_pct: Long, + unit: String, + tags: String, + lat_lng: String?, + altitude_m: Double?, + bearing_deg: Double?, + pitch_deg: Double?, + roll_deg: Double?, + focal_length_mm: Double?, + focal_length_35mm_eq: Double?, + camera_make: String?, + camera_model: String?, + ): Long { + val result = driver.execute(390_467_728, """ + |INSERT OR REPLACE INTO image_annotations ( + | uuid, block_uuid, page_uuid, graph_path, file_path, thumbnail_path, + | source, source_uri, captured_at_ms, imported_at_ms, + | calibration_method, pixels_per_meter, calibration_confidence_pct, + | unit, tags, lat_lng, altitude_m, bearing_deg, pitch_deg, roll_deg, + | focal_length_mm, focal_length_35mm_eq, camera_make, camera_model + |) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """.trimMargin(), 24) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + bindString(parameterIndex++, block_uuid) + bindString(parameterIndex++, page_uuid) + bindString(parameterIndex++, graph_path) + bindString(parameterIndex++, file_path) + bindString(parameterIndex++, thumbnail_path) + bindString(parameterIndex++, source) + bindString(parameterIndex++, source_uri) + bindLong(parameterIndex++, captured_at_ms) + bindLong(parameterIndex++, imported_at_ms) + bindString(parameterIndex++, calibration_method) + bindDouble(parameterIndex++, pixels_per_meter) + bindLong(parameterIndex++, calibration_confidence_pct) + bindString(parameterIndex++, unit) + bindString(parameterIndex++, tags) + bindString(parameterIndex++, lat_lng) + bindDouble(parameterIndex++, altitude_m) + bindDouble(parameterIndex++, bearing_deg) + bindDouble(parameterIndex++, pitch_deg) + bindDouble(parameterIndex++, roll_deg) + bindDouble(parameterIndex++, focal_length_mm) + bindDouble(parameterIndex++, focal_length_35mm_eq) + bindString(parameterIndex++, camera_make) + bindString(parameterIndex++, camera_model) + }.await() + notifyQueries(390_467_728) { emit -> + emit("image_annotations") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateImageAnnotation( + block_uuid: String, + page_uuid: String, + graph_path: String, + file_path: String, + thumbnail_path: String?, + source: String, + source_uri: String?, + captured_at_ms: Long?, + imported_at_ms: Long, + calibration_method: String, + pixels_per_meter: Double, + calibration_confidence_pct: Long, + unit: String, + tags: String, + lat_lng: String?, + altitude_m: Double?, + bearing_deg: Double?, + pitch_deg: Double?, + roll_deg: Double?, + focal_length_mm: Double?, + focal_length_35mm_eq: Double?, + camera_make: String?, + camera_model: String?, + uuid: String, + ): Long { + val result = driver.execute(-935_741_312, """ + |UPDATE image_annotations SET + | block_uuid = ?, + | page_uuid = ?, + | graph_path = ?, + | file_path = ?, + | thumbnail_path = ?, + | source = ?, + | source_uri = ?, + | captured_at_ms = ?, + | imported_at_ms = ?, + | calibration_method = ?, + | pixels_per_meter = ?, + | calibration_confidence_pct = ?, + | unit = ?, + | tags = ?, + | lat_lng = ?, + | altitude_m = ?, + | bearing_deg = ?, + | pitch_deg = ?, + | roll_deg = ?, + | focal_length_mm = ?, + | focal_length_35mm_eq = ?, + | camera_make = ?, + | camera_model = ? + |WHERE uuid = ? + """.trimMargin(), 24) { + var parameterIndex = 0 + bindString(parameterIndex++, block_uuid) + bindString(parameterIndex++, page_uuid) + bindString(parameterIndex++, graph_path) + bindString(parameterIndex++, file_path) + bindString(parameterIndex++, thumbnail_path) + bindString(parameterIndex++, source) + bindString(parameterIndex++, source_uri) + bindLong(parameterIndex++, captured_at_ms) + bindLong(parameterIndex++, imported_at_ms) + bindString(parameterIndex++, calibration_method) + bindDouble(parameterIndex++, pixels_per_meter) + bindLong(parameterIndex++, calibration_confidence_pct) + bindString(parameterIndex++, unit) + bindString(parameterIndex++, tags) + bindString(parameterIndex++, lat_lng) + bindDouble(parameterIndex++, altitude_m) + bindDouble(parameterIndex++, bearing_deg) + bindDouble(parameterIndex++, pitch_deg) + bindDouble(parameterIndex++, roll_deg) + bindDouble(parameterIndex++, focal_length_mm) + bindDouble(parameterIndex++, focal_length_35mm_eq) + bindString(parameterIndex++, camera_make) + bindString(parameterIndex++, camera_model) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(-935_741_312) { emit -> + emit("image_annotations") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteImageAnnotation(uuid: String): Long { + val result = driver.execute(2_109_197_150, """DELETE FROM image_annotations WHERE uuid = ?""", 1) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(2_109_197_150) { emit -> + emit("image_annotations") + emit("measurement_annotations") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun insertMeasurementAnnotation( + uuid: String, + image_uuid: String, + annotation_type: String, + normalized_points: String, + value_meters: Double?, + value_display: String?, + label: String?, + color_hex: String, + ble_device_id: String?, + ): Long { + val result = driver.execute(-368_694_991, """ + |INSERT OR REPLACE INTO measurement_annotations ( + | uuid, image_uuid, annotation_type, normalized_points, + | value_meters, value_display, label, color_hex, ble_device_id + |) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) + """.trimMargin(), 9) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + bindString(parameterIndex++, image_uuid) + bindString(parameterIndex++, annotation_type) + bindString(parameterIndex++, normalized_points) + bindDouble(parameterIndex++, value_meters) + bindString(parameterIndex++, value_display) + bindString(parameterIndex++, label) + bindString(parameterIndex++, color_hex) + bindString(parameterIndex++, ble_device_id) + }.await() + notifyQueries(-368_694_991) { emit -> + emit("measurement_annotations") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteMeasurementsForImage(image_uuid: String): Long { + val result = driver.execute(-2_064_403_595, """DELETE FROM measurement_annotations WHERE image_uuid = ?""", 1) { + var parameterIndex = 0 + bindString(parameterIndex++, image_uuid) + }.await() + notifyQueries(-2_064_403_595) { emit -> + emit("measurement_annotations") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteMeasurementAnnotation(uuid: String): Long { + val result = driver.execute(-804_777_601, """DELETE FROM measurement_annotations WHERE uuid = ?""", 1) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(-804_777_601) { emit -> + emit("measurement_annotations") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun insertAsset( + uuid: String, + file_path: String, + relative_path: String, + media_type: String, + subfolder: String, + tags: String, + auto_labels: String, + ocr_text: String?, + cloud_description: String?, + page_uuids: String, + size_bytes: Long, + imported_at_ms: Long, + content_hash: String?, + ): Long { + val result = driver.execute(2_141_452_310, """ + |INSERT INTO asset_index(uuid, file_path, relative_path, media_type, subfolder, tags, auto_labels, ocr_text, cloud_description, page_uuids, size_bytes, imported_at_ms, ml_processed, ml_failed, content_hash, is_orphan, ml_tags_source) + |VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 0, ?, 0, 'NONE') + """.trimMargin(), 13) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + bindString(parameterIndex++, file_path) + bindString(parameterIndex++, relative_path) + bindString(parameterIndex++, media_type) + bindString(parameterIndex++, subfolder) + bindString(parameterIndex++, tags) + bindString(parameterIndex++, auto_labels) + bindString(parameterIndex++, ocr_text) + bindString(parameterIndex++, cloud_description) + bindString(parameterIndex++, page_uuids) + bindLong(parameterIndex++, size_bytes) + bindLong(parameterIndex++, imported_at_ms) + bindString(parameterIndex++, content_hash) + }.await() + notifyQueries(2_141_452_310) { emit -> + emit("asset_index") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun insertAssetOrIgnore( + uuid: String, + file_path: String, + relative_path: String, + media_type: String, + subfolder: String, + tags: String, + auto_labels: String, + ocr_text: String?, + cloud_description: String?, + page_uuids: String, + size_bytes: Long, + imported_at_ms: Long, + content_hash: String?, + ): Long { + val result = driver.execute(1_434_560_459, """ + |INSERT OR IGNORE INTO asset_index(uuid, file_path, relative_path, media_type, subfolder, tags, auto_labels, ocr_text, cloud_description, page_uuids, size_bytes, imported_at_ms, ml_processed, ml_failed, content_hash, is_orphan, ml_tags_source) + |VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 0, ?, 0, 'NONE') + """.trimMargin(), 13) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + bindString(parameterIndex++, file_path) + bindString(parameterIndex++, relative_path) + bindString(parameterIndex++, media_type) + bindString(parameterIndex++, subfolder) + bindString(parameterIndex++, tags) + bindString(parameterIndex++, auto_labels) + bindString(parameterIndex++, ocr_text) + bindString(parameterIndex++, cloud_description) + bindString(parameterIndex++, page_uuids) + bindLong(parameterIndex++, size_bytes) + bindLong(parameterIndex++, imported_at_ms) + bindString(parameterIndex++, content_hash) + }.await() + notifyQueries(1_434_560_459) { emit -> + emit("asset_index") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateAssetFilePath( + filePath: String, + relativePath: String, + uuid: String, + ): Long { + val result = driver.execute(1_923_840_487, """UPDATE asset_index SET file_path = ?, relative_path = ? WHERE uuid = ?""", 3) { + var parameterIndex = 0 + bindString(parameterIndex++, filePath) + bindString(parameterIndex++, relativePath) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(1_923_840_487) { emit -> + emit("asset_index") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateAssetTags(tags: String, uuid: String): Long { + val result = driver.execute(1_498_546_495, """UPDATE asset_index SET tags = ? WHERE uuid = ?""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, tags) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(1_498_546_495) { emit -> + emit("asset_index") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateAssetAutoLabels( + autoLabels: String, + mlTagsSource: String, + uuid: String, + ): Long { + val result = driver.execute(-324_615_372, """UPDATE asset_index SET auto_labels = ?, ml_tags_source = ? WHERE uuid = ?""", 3) { + var parameterIndex = 0 + bindString(parameterIndex++, autoLabels) + bindString(parameterIndex++, mlTagsSource) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(-324_615_372) { emit -> + emit("asset_index") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateAssetOcrText(ocrText: String?, uuid: String): Long { + val result = driver.execute(1_232_601_221, """UPDATE asset_index SET ocr_text = ? WHERE uuid = ?""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, ocrText) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(1_232_601_221) { emit -> + emit("asset_index") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateAssetCloudDescription( + cloudDescription: String?, + mlTagsSource: String, + uuid: String, + ): Long { + val result = driver.execute(-280_162_643, """UPDATE asset_index SET cloud_description = ?, ml_tags_source = ? WHERE uuid = ?""", 3) { + var parameterIndex = 0 + bindString(parameterIndex++, cloudDescription) + bindString(parameterIndex++, mlTagsSource) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(-280_162_643) { emit -> + emit("asset_index") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun markAssetMlProcessed(attemptedAt: Long?, uuid: String): Long { + val result = driver.execute(158_555_853, """UPDATE asset_index SET ml_processed = 1, ml_attempted_at = ? WHERE uuid = ?""", 2) { + var parameterIndex = 0 + bindLong(parameterIndex++, attemptedAt) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(158_555_853) { emit -> + emit("asset_index") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun markAssetMlFailed(attemptedAt: Long?, uuid: String): Long { + val result = driver.execute(83_642_654, """UPDATE asset_index SET ml_failed = 1, ml_attempted_at = ? WHERE uuid = ?""", 2) { + var parameterIndex = 0 + bindLong(parameterIndex++, attemptedAt) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(83_642_654) { emit -> + emit("asset_index") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun updateAssetPageUuids(pageUuids: String, uuid: String): Long { + val result = driver.execute(1_714_875_747, """UPDATE asset_index SET page_uuids = ? WHERE uuid = ?""", 2) { + var parameterIndex = 0 + bindString(parameterIndex++, pageUuids) + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(1_714_875_747) { emit -> + emit("asset_index") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deleteAsset(uuid: String): Long { + val result = driver.execute(1_122_778_212, """DELETE FROM asset_index WHERE uuid = ?""", 1) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + }.await() + notifyQueries(1_122_778_212) { emit -> + emit("asset_index") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun insertPendingMove( + asset_uuid: String, + old_file_path: String, + new_file_path: String, + old_relative_path: String, + new_relative_path: String, + created_at_ms: Long, + ): Long { + val result = driver.execute(442_412_718, """ + |INSERT INTO pending_asset_moves(asset_uuid, old_file_path, new_file_path, old_relative_path, new_relative_path, created_at_ms) + |VALUES (?, ?, ?, ?, ?, ?) + """.trimMargin(), 6) { + var parameterIndex = 0 + bindString(parameterIndex++, asset_uuid) + bindString(parameterIndex++, old_file_path) + bindString(parameterIndex++, new_file_path) + bindString(parameterIndex++, old_relative_path) + bindString(parameterIndex++, new_relative_path) + bindLong(parameterIndex++, created_at_ms) + }.await() + notifyQueries(442_412_718) { emit -> + emit("pending_asset_moves") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun deletePendingMove(id: Long): Long { + val result = driver.execute(-1_920_335_748, """DELETE FROM pending_asset_moves WHERE id = ?""", 1) { + var parameterIndex = 0 + bindLong(parameterIndex++, id) + }.await() + notifyQueries(-1_920_335_748) { emit -> + emit("pending_asset_moves") + } + return result + } + + /** + * @return The number of rows updated. + */ + public suspend fun pragmaWalCheckpointTruncate(): Long { + val result = driver.execute(-158_994_413, """PRAGMA wal_checkpoint(TRUNCATE)""", 0).await() + return result + } + + private inner class SelectBlockByUuidQuery( + public val uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_177_587_166, """SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks WHERE uuid = ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectBlockByUuid" + } + + private inner class SelectBlocksByUuidsQuery( + public val uuid: Collection, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult { + val uuidIndexes = createArguments(count = uuid.size) + return driver.executeQuery(null, """SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks WHERE uuid IN $uuidIndexes""", mapper, uuid.size) { + var parameterIndex = 0 + uuid.forEach { uuid_ -> + bindString(parameterIndex++, uuid_) + } + } + } + + override fun toString(): String = "SteleDatabase.sq:selectBlocksByUuids" + } + + private inner class ExistsBlockByUuidQuery( + public val uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(703_157_954, """SELECT COUNT(*) FROM blocks WHERE uuid = ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + } + + override fun toString(): String = "SteleDatabase.sq:existsBlockByUuid" + } + + private inner class SelectAllBlocksPaginatedQuery( + public val `value`: Long, + public val value_: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-619_541_469, """SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks ORDER BY uuid LIMIT ? OFFSET ?""", mapper, 2) { + var parameterIndex = 0 + bindLong(parameterIndex++, value) + bindLong(parameterIndex++, value_) + } + + override fun toString(): String = "SteleDatabase.sq:selectAllBlocksPaginated" + } + + private inner class SelectAllBlocksPaginatedAfterUuidQuery( + public val uuid: String, + public val `value`: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_119_311_148, """SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks WHERE uuid > ? ORDER BY uuid LIMIT ?""", mapper, 2) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + bindLong(parameterIndex++, value) + } + + override fun toString(): String = "SteleDatabase.sq:selectAllBlocksPaginatedAfterUuid" + } + + private inner class SelectBlockChildrenQuery( + public val parent_uuid: String?, + public val `value`: Long, + public val value_: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(null, """SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks WHERE parent_uuid ${ if (parent_uuid == null) "IS" else "=" } ? ORDER BY position LIMIT ? OFFSET ?""", mapper, 3) { + var parameterIndex = 0 + bindString(parameterIndex++, parent_uuid) + bindLong(parameterIndex++, value) + bindLong(parameterIndex++, value_) + } + + override fun toString(): String = "SteleDatabase.sq:selectBlockChildren" + } + + private inner class CountBlockChildrenQuery( + public val parent_uuid: String?, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(null, """SELECT COUNT(*) FROM blocks WHERE parent_uuid ${ if (parent_uuid == null) "IS" else "=" } ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, parent_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:countBlockChildren" + } + + private inner class SelectBlockSiblingsQuery( + public val uuid: String, + public val uuid_: String, + public val uuid__: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(821_827_425, """ + |SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks + |WHERE parent_uuid IS (SELECT parent_uuid FROM blocks WHERE uuid = ?) + |AND page_uuid = (SELECT page_uuid FROM blocks WHERE uuid = ?) + |AND uuid != ? + |ORDER BY position + """.trimMargin(), mapper, 3) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + bindString(parameterIndex++, uuid_) + bindString(parameterIndex++, uuid__) + } + + override fun toString(): String = "SteleDatabase.sq:selectBlockSiblings" + } + + private inner class SelectRootBlocksQuery( + public val page_uuid: String, + public val `value`: Long, + public val value_: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(1_052_737_061, """SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks WHERE parent_uuid IS NULL AND page_uuid = ? ORDER BY position LIMIT ? OFFSET ?""", mapper, 3) { + var parameterIndex = 0 + bindString(parameterIndex++, page_uuid) + bindLong(parameterIndex++, value) + bindLong(parameterIndex++, value_) + } + + override fun toString(): String = "SteleDatabase.sq:selectRootBlocks" + } + + private inner class CountRootBlocksQuery( + public val page_uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(1_021_025_366, """SELECT COUNT(*) FROM blocks WHERE parent_uuid IS NULL AND page_uuid = ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, page_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:countRootBlocks" + } + + private inner class SelectBlocksByPageUuidQuery( + public val page_uuid: String, + public val `value`: Long, + public val value_: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(264_501_732, """SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks WHERE page_uuid = ? ORDER BY position LIMIT ? OFFSET ?""", mapper, 3) { + var parameterIndex = 0 + bindString(parameterIndex++, page_uuid) + bindLong(parameterIndex++, value) + bindLong(parameterIndex++, value_) + } + + override fun toString(): String = "SteleDatabase.sq:selectBlocksByPageUuid" + } + + private inner class SelectBlocksByPageUuidUnpaginatedQuery( + public val page_uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-801_581_104, """SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks WHERE page_uuid = ? ORDER BY position""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, page_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectBlocksByPageUuidUnpaginated" + } + + private inner class SelectBlocksWithContentLikeQuery( + public val content: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_328_715_929, """SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks WHERE content LIKE ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, content) + } + + override fun toString(): String = "SteleDatabase.sq:selectBlocksWithContentLike" + } + + private inner class SelectBlocksWithContentLikePaginatedQuery( + public val content: String, + public val `value`: Long, + public val value_: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(1_872_908_070, """SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks WHERE content LIKE ? ORDER BY created_at DESC LIMIT ? OFFSET ?""", mapper, 3) { + var parameterIndex = 0 + bindString(parameterIndex++, content) + bindLong(parameterIndex++, value) + bindLong(parameterIndex++, value_) + } + + override fun toString(): String = "SteleDatabase.sq:selectBlocksWithContentLikePaginated" + } + + private inner class CountBlocksByPageUuidQuery( + public val page_uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(602_074_965, """SELECT COUNT(*) FROM blocks WHERE page_uuid = ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, page_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:countBlocksByPageUuid" + } + + private inner class SelectBlocksByParentUuidOrderedQuery( + public val parent_uuid: String?, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(null, """SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks WHERE parent_uuid ${ if (parent_uuid == null) "IS" else "=" } ? ORDER BY position""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, parent_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectBlocksByParentUuidOrdered" + } + + private inner class SelectBlocksByParentUuidsQuery( + public val parent_uuid: Collection, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult { + val parent_uuidIndexes = createArguments(count = parent_uuid.size) + return driver.executeQuery(null, """SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks WHERE parent_uuid IN $parent_uuidIndexes ORDER BY parent_uuid, position""", mapper, parent_uuid.size) { + var parameterIndex = 0 + parent_uuid.forEach { parent_uuid_ -> + bindString(parameterIndex++, parent_uuid_) + } + } + } + + override fun toString(): String = "SteleDatabase.sq:selectBlocksByParentUuids" + } + + private inner class SelectRootBlocksByPageUuidOrderedQuery( + public val page_uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(359_935_271, """SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks WHERE parent_uuid IS NULL AND page_uuid = ? ORDER BY position""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, page_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectRootBlocksByPageUuidOrdered" + } + + private inner class SelectBlockByLeftUuidQuery( + public val left_uuid: String?, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(null, """SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks WHERE left_uuid ${ if (left_uuid == null) "IS" else "=" } ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, left_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectBlockByLeftUuid" + } + + private inner class SelectLastChildQuery( + public val parent_uuid: String?, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(null, """SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks WHERE parent_uuid ${ if (parent_uuid == null) "IS" else "=" } ? ORDER BY position DESC LIMIT 1""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, parent_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectLastChild" + } + + private inner class SelectBlocksHashByPageUuidQuery( + public val page_uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(1_615_242_258, """SELECT uuid, content_hash FROM blocks WHERE page_uuid = ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, page_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectBlocksHashByPageUuid" + } + + private inner class SelectBlocksByContentHashQuery( + public val content_hash: String?, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(null, """SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks WHERE content_hash ${ if (content_hash == null) "IS" else "=" } ? ORDER BY created_at""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, content_hash) + } + + override fun toString(): String = "SteleDatabase.sq:selectBlocksByContentHash" + } + + private inner class SelectDuplicateBlockHashesQuery( + public val `value`: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_141_612_549, """ + |SELECT content_hash, COUNT(*) AS cnt + |FROM blocks + |WHERE content_hash IS NOT NULL + |GROUP BY content_hash + |HAVING COUNT(*) > 1 + |ORDER BY cnt DESC + |LIMIT ? + """.trimMargin(), mapper, 1) { + var parameterIndex = 0 + bindLong(parameterIndex++, value) + } + + override fun toString(): String = "SteleDatabase.sq:selectDuplicateBlockHashes" + } + + private inner class SelectPageByUuidQuery( + public val uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-493_662_914, """SELECT pages.uuid, pages.name, pages.namespace, pages.file_path, pages.created_at, pages.updated_at, pages.properties, pages.version, pages.is_favorite, pages.is_journal, pages.journal_date, pages.is_content_loaded, pages.backlink_count FROM pages WHERE uuid = ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectPageByUuid" + } + + private inner class SelectPageByNameQuery( + public val name: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-493_890_546, """SELECT pages.uuid, pages.name, pages.namespace, pages.file_path, pages.created_at, pages.updated_at, pages.properties, pages.version, pages.is_favorite, pages.is_journal, pages.journal_date, pages.is_content_loaded, pages.backlink_count FROM pages WHERE name = ? LIMIT 1""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, name) + } + + override fun toString(): String = "SteleDatabase.sq:selectPageByName" + } + + private inner class ExistsPageByUuidQuery( + public val uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_957_014_370, """SELECT COUNT(*) FROM pages WHERE uuid = ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + } + + override fun toString(): String = "SteleDatabase.sq:existsPageByUuid" + } + + private inner class ExistsPageByNameQuery( + public val name: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_957_242_002, """SELECT COUNT(*) FROM pages WHERE name = ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, name) + } + + override fun toString(): String = "SteleDatabase.sq:existsPageByName" + } + + private inner class SelectAllPagesPaginatedQuery( + public val `value`: Long, + public val value_: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_018_316_883, """SELECT pages.uuid, pages.name, pages.namespace, pages.file_path, pages.created_at, pages.updated_at, pages.properties, pages.version, pages.is_favorite, pages.is_journal, pages.journal_date, pages.is_content_loaded, pages.backlink_count FROM pages ORDER BY name LIMIT ? OFFSET ?""", mapper, 2) { + var parameterIndex = 0 + bindLong(parameterIndex++, value) + bindLong(parameterIndex++, value_) + } + + override fun toString(): String = "SteleDatabase.sq:selectAllPagesPaginated" + } + + private inner class SelectUnloadedPagesPaginatedQuery( + public val `value`: Long, + public val value_: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(1_551_624_324, """SELECT pages.uuid, pages.name, pages.namespace, pages.file_path, pages.created_at, pages.updated_at, pages.properties, pages.version, pages.is_favorite, pages.is_journal, pages.journal_date, pages.is_content_loaded, pages.backlink_count FROM pages WHERE is_content_loaded = 0 ORDER BY uuid LIMIT ? OFFSET ?""", mapper, 2) { + var parameterIndex = 0 + bindLong(parameterIndex++, value) + bindLong(parameterIndex++, value_) + } + + override fun toString(): String = "SteleDatabase.sq:selectUnloadedPagesPaginated" + } + + private inner class SelectPagesByNamesQuery( + public val name: Collection, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult { + val nameIndexes = createArguments(count = name.size) + return driver.executeQuery(null, """SELECT pages.uuid, pages.name, pages.namespace, pages.file_path, pages.created_at, pages.updated_at, pages.properties, pages.version, pages.is_favorite, pages.is_journal, pages.journal_date, pages.is_content_loaded, pages.backlink_count FROM pages WHERE name IN $nameIndexes""", mapper, name.size) { + var parameterIndex = 0 + name.forEach { name_ -> + bindString(parameterIndex++, name_) + } + } + } + + override fun toString(): String = "SteleDatabase.sq:selectPagesByNames" + } + + private inner class SelectJournalPagesByDatesQuery( + public val journal_date: Collection, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult { + val journal_dateIndexes = createArguments(count = journal_date.size) + return driver.executeQuery(null, """SELECT pages.uuid, pages.name, pages.namespace, pages.file_path, pages.created_at, pages.updated_at, pages.properties, pages.version, pages.is_favorite, pages.is_journal, pages.journal_date, pages.is_content_loaded, pages.backlink_count FROM pages WHERE is_journal = 1 AND journal_date IN $journal_dateIndexes""", mapper, journal_date.size) { + var parameterIndex = 0 + journal_date.forEach { journal_date_ -> + bindString(parameterIndex++, journal_date_) + } + } + } + + override fun toString(): String = "SteleDatabase.sq:selectJournalPagesByDates" + } + + private inner class SelectPagesByNamespaceQuery( + public val namespace: String?, + public val `value`: Long, + public val value_: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(null, """SELECT pages.uuid, pages.name, pages.namespace, pages.file_path, pages.created_at, pages.updated_at, pages.properties, pages.version, pages.is_favorite, pages.is_journal, pages.journal_date, pages.is_content_loaded, pages.backlink_count FROM pages WHERE namespace ${ if (namespace == null) "IS" else "=" } ? ORDER BY name LIMIT ? OFFSET ?""", mapper, 3) { + var parameterIndex = 0 + bindString(parameterIndex++, namespace) + bindLong(parameterIndex++, value) + bindLong(parameterIndex++, value_) + } + + override fun toString(): String = "SteleDatabase.sq:selectPagesByNamespace" + } + + private inner class SelectPagesByNamespaceUnpaginatedQuery( + public val namespace: String?, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(null, """SELECT pages.uuid, pages.name, pages.namespace, pages.file_path, pages.created_at, pages.updated_at, pages.properties, pages.version, pages.is_favorite, pages.is_journal, pages.journal_date, pages.is_content_loaded, pages.backlink_count FROM pages WHERE namespace ${ if (namespace == null) "IS" else "=" } ? ORDER BY name""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, namespace) + } + + override fun toString(): String = "SteleDatabase.sq:selectPagesByNamespaceUnpaginated" + } + + private inner class CountPagesByNamespaceQuery( + public val namespace: String?, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(null, """SELECT COUNT(*) FROM pages WHERE namespace ${ if (namespace == null) "IS" else "=" } ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, namespace) + } + + override fun toString(): String = "SteleDatabase.sq:countPagesByNamespace" + } + + private inner class SelectRecentlyUpdatedPagesQuery( + public val `value`: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(2_012_172_782, """SELECT pages.uuid, pages.name, pages.namespace, pages.file_path, pages.created_at, pages.updated_at, pages.properties, pages.version, pages.is_favorite, pages.is_journal, pages.journal_date, pages.is_content_loaded, pages.backlink_count FROM pages ORDER BY updated_at DESC LIMIT ?""", mapper, 1) { + var parameterIndex = 0 + bindLong(parameterIndex++, value) + } + + override fun toString(): String = "SteleDatabase.sq:selectRecentlyUpdatedPages" + } + + private inner class SelectRecentlyCreatedPagesQuery( + public val `value`: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(193_234_913, """SELECT pages.uuid, pages.name, pages.namespace, pages.file_path, pages.created_at, pages.updated_at, pages.properties, pages.version, pages.is_favorite, pages.is_journal, pages.journal_date, pages.is_content_loaded, pages.backlink_count FROM pages ORDER BY created_at DESC LIMIT ?""", mapper, 1) { + var parameterIndex = 0 + bindLong(parameterIndex++, value) + } + + override fun toString(): String = "SteleDatabase.sq:selectRecentlyCreatedPages" + } + + private inner class SelectJournalPagesQuery( + public val `value`: Long, + public val value_: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(1_864_064_170, """SELECT pages.uuid, pages.name, pages.namespace, pages.file_path, pages.created_at, pages.updated_at, pages.properties, pages.version, pages.is_favorite, pages.is_journal, pages.journal_date, pages.is_content_loaded, pages.backlink_count FROM pages WHERE is_journal = 1 AND journal_date IS NOT NULL ORDER BY journal_date DESC LIMIT ? OFFSET ?""", mapper, 2) { + var parameterIndex = 0 + bindLong(parameterIndex++, value) + bindLong(parameterIndex++, value_) + } + + override fun toString(): String = "SteleDatabase.sq:selectJournalPages" + } + + private inner class SelectJournalPageByDateQuery( + public val journal_date: String?, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(null, """SELECT pages.uuid, pages.name, pages.namespace, pages.file_path, pages.created_at, pages.updated_at, pages.properties, pages.version, pages.is_favorite, pages.is_journal, pages.journal_date, pages.is_content_loaded, pages.backlink_count FROM pages WHERE is_journal = 1 AND journal_date ${ if (journal_date == null) "IS" else "=" } ? LIMIT 1""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, journal_date) + } + + override fun toString(): String = "SteleDatabase.sq:selectJournalPageByDate" + } + + private inner class SelectNeighbourPageUuidsQuery( + public val pageUuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", "block_references", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", "block_references", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-2_037_987_511, """ + |SELECT DISTINCT to_b.page_uuid AS page_uuid + |FROM block_references br + |JOIN blocks from_b ON from_b.uuid = br.from_block_uuid + |JOIN blocks to_b ON to_b.uuid = br.to_block_uuid + |WHERE from_b.page_uuid = ? AND to_b.page_uuid != ? + |UNION + |SELECT DISTINCT from_b.page_uuid AS page_uuid + |FROM block_references br + |JOIN blocks from_b ON from_b.uuid = br.from_block_uuid + |JOIN blocks to_b ON to_b.uuid = br.to_block_uuid + |WHERE to_b.page_uuid = ? AND from_b.page_uuid != ? + """.trimMargin(), mapper, 4) { + var parameterIndex = 0 + bindString(parameterIndex++, pageUuid) + bindString(parameterIndex++, pageUuid) + bindString(parameterIndex++, pageUuid) + bindString(parameterIndex++, pageUuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectNeighbourPageUuids" + } + + private inner class SelectOutgoingReferencesQuery( + public val from_block_uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", "block_references", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", "block_references", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-494_736_591, """ + |SELECT b.id, b.uuid, b.page_uuid, b.parent_uuid, b.left_uuid, b.content, b.level, b.position, b.created_at, b.updated_at, b.properties, b.version, b.content_hash, b.block_type FROM blocks b + |INNER JOIN block_references br ON b.uuid = br.to_block_uuid + |WHERE br.from_block_uuid = ? + """.trimMargin(), mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, from_block_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectOutgoingReferences" + } + + private inner class SelectIncomingReferencesQuery( + public val to_block_uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", "block_references", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", "block_references", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(585_273_195, """ + |SELECT b.id, b.uuid, b.page_uuid, b.parent_uuid, b.left_uuid, b.content, b.level, b.position, b.created_at, b.updated_at, b.properties, b.version, b.content_hash, b.block_type FROM blocks b + |INNER JOIN block_references br ON b.uuid = br.from_block_uuid + |WHERE br.to_block_uuid = ? + """.trimMargin(), mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, to_block_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectIncomingReferences" + } + + private inner class SelectMostConnectedBlocksQuery( + public val `value`: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", "block_references", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", "block_references", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_980_914_833, """ + |SELECT b.id, b.uuid, b.page_uuid, b.parent_uuid, b.left_uuid, b.content, b.level, b.position, b.created_at, b.updated_at, b.properties, b.version, b.content_hash, b.block_type, COUNT(br.id) AS reference_count + |FROM blocks b + |LEFT JOIN block_references br ON b.uuid = br.to_block_uuid OR b.uuid = br.from_block_uuid + |GROUP BY b.uuid + |ORDER BY reference_count DESC + |LIMIT ? + """.trimMargin(), mapper, 1) { + var parameterIndex = 0 + bindLong(parameterIndex++, value) + } + + override fun toString(): String = "SteleDatabase.sq:selectMostConnectedBlocks" + } + + private inner class SelectPagesByNameLikeQuery( + public val name: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(141_501_984, """SELECT pages.uuid, pages.name, pages.namespace, pages.file_path, pages.created_at, pages.updated_at, pages.properties, pages.version, pages.is_favorite, pages.is_journal, pages.journal_date, pages.is_content_loaded, pages.backlink_count FROM pages WHERE name LIKE ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, name) + } + + override fun toString(): String = "SteleDatabase.sq:selectPagesByNameLike" + } + + private inner class SelectPagesByNameLikePaginatedQuery( + public val name: String, + public val `value`: Long, + public val value_: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(673_779_853, """SELECT pages.uuid, pages.name, pages.namespace, pages.file_path, pages.created_at, pages.updated_at, pages.properties, pages.version, pages.is_favorite, pages.is_journal, pages.journal_date, pages.is_content_loaded, pages.backlink_count FROM pages WHERE name LIKE ? ORDER BY name LIMIT ? OFFSET ?""", mapper, 3) { + var parameterIndex = 0 + bindString(parameterIndex++, name) + bindLong(parameterIndex++, value) + bindLong(parameterIndex++, value_) + } + + override fun toString(): String = "SteleDatabase.sq:selectPagesByNameLikePaginated" + } + + private inner class SelectBlocksReferencingQuery( + public val to_block_uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", "block_references", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", "block_references", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-974_356_443, """ + |SELECT DISTINCT b.id, b.uuid, b.page_uuid, b.parent_uuid, b.left_uuid, b.content, b.level, b.position, b.created_at, b.updated_at, b.properties, b.version, b.content_hash, b.block_type FROM blocks b + |INNER JOIN block_references br ON b.uuid = br.from_block_uuid + |WHERE br.to_block_uuid = ? + """.trimMargin(), mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, to_block_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectBlocksReferencing" + } + + private inner class SelectPluginDataByIdQuery( + public val id: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("plugin_data", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("plugin_data", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(1_505_356_172, """SELECT plugin_data.id, plugin_data.plugin_id, plugin_data.entity_type, plugin_data.entity_uuid, plugin_data.key, plugin_data.value, plugin_data.created_at, plugin_data.updated_at FROM plugin_data WHERE id = ?""", mapper, 1) { + var parameterIndex = 0 + bindLong(parameterIndex++, id) + } + + override fun toString(): String = "SteleDatabase.sq:selectPluginDataById" + } + + private inner class SelectPluginDataByPluginQuery( + public val plugin_id: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("plugin_data", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("plugin_data", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_125_405_916, """SELECT plugin_data.id, plugin_data.plugin_id, plugin_data.entity_type, plugin_data.entity_uuid, plugin_data.key, plugin_data.value, plugin_data.created_at, plugin_data.updated_at FROM plugin_data WHERE plugin_id = ? ORDER BY created_at""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, plugin_id) + } + + override fun toString(): String = "SteleDatabase.sq:selectPluginDataByPlugin" + } + + private inner class SelectPluginDataByEntityQuery( + public val entity_type: String, + public val entity_uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("plugin_data", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("plugin_data", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_438_507_052, """SELECT plugin_data.id, plugin_data.plugin_id, plugin_data.entity_type, plugin_data.entity_uuid, plugin_data.key, plugin_data.value, plugin_data.created_at, plugin_data.updated_at FROM plugin_data WHERE entity_type = ? AND entity_uuid = ? ORDER BY key""", mapper, 2) { + var parameterIndex = 0 + bindString(parameterIndex++, entity_type) + bindString(parameterIndex++, entity_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectPluginDataByEntity" + } + + private inner class SelectPluginDataByKeyQuery( + public val plugin_id: String, + public val key: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("plugin_data", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("plugin_data", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-578_596_850, """SELECT plugin_data.id, plugin_data.plugin_id, plugin_data.entity_type, plugin_data.entity_uuid, plugin_data.key, plugin_data.value, plugin_data.created_at, plugin_data.updated_at FROM plugin_data WHERE plugin_id = ? AND key = ? ORDER BY entity_type, entity_uuid""", mapper, 2) { + var parameterIndex = 0 + bindString(parameterIndex++, plugin_id) + bindString(parameterIndex++, key) + } + + override fun toString(): String = "SteleDatabase.sq:selectPluginDataByKey" + } + + private inner class SelectPluginDataByPluginAndEntityQuery( + public val plugin_id: String, + public val entity_type: String, + public val entity_uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("plugin_data", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("plugin_data", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(1_919_683_030, """SELECT plugin_data.id, plugin_data.plugin_id, plugin_data.entity_type, plugin_data.entity_uuid, plugin_data.key, plugin_data.value, plugin_data.created_at, plugin_data.updated_at FROM plugin_data WHERE plugin_id = ? AND entity_type = ? AND entity_uuid = ? ORDER BY key""", mapper, 3) { + var parameterIndex = 0 + bindString(parameterIndex++, plugin_id) + bindString(parameterIndex++, entity_type) + bindString(parameterIndex++, entity_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectPluginDataByPluginAndEntity" + } + + private inner class CountPluginDataByPluginQuery( + public val plugin_id: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("plugin_data", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("plugin_data", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(1_159_923_797, """SELECT COUNT(*) FROM plugin_data WHERE plugin_id = ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, plugin_id) + } + + override fun toString(): String = "SteleDatabase.sq:countPluginDataByPlugin" + } + + private inner class CountPluginDataByEntityQuery( + public val entity_type: String, + public val entity_uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("plugin_data", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("plugin_data", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(846_822_661, """SELECT COUNT(*) FROM plugin_data WHERE entity_type = ? AND entity_uuid = ?""", mapper, 2) { + var parameterIndex = 0 + bindString(parameterIndex++, entity_type) + bindString(parameterIndex++, entity_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:countPluginDataByEntity" + } + + private inner class ExistsPluginDataQuery( + public val plugin_id: String, + public val entity_type: String, + public val entity_uuid: String, + public val key: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("plugin_data", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("plugin_data", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(1_146_224_122, """SELECT COUNT(*) FROM plugin_data WHERE plugin_id = ? AND entity_type = ? AND entity_uuid = ? AND key = ?""", mapper, 4) { + var parameterIndex = 0 + bindString(parameterIndex++, plugin_id) + bindString(parameterIndex++, entity_type) + bindString(parameterIndex++, entity_uuid) + bindString(parameterIndex++, key) + } + + override fun toString(): String = "SteleDatabase.sq:existsPluginData" + } + + private inner class SearchBlocksByContentFtsQuery( + public val query: String, + public val limit: Long, + public val offset: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", "blocks_fts", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", "blocks_fts", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(642_676_818, """ + |SELECT + | b.uuid, + | b.page_uuid, + | b.parent_uuid, + | b.left_uuid, + | b.content, + | b.level, + | b.position, + | b.created_at, + | b.updated_at, + | b.properties, + | b.version, + | highlight(blocks_fts, 0, '', '') AS highlight, + | bm25(blocks_fts) AS bm25_score + |FROM blocks_fts bm + |JOIN blocks b ON b.id = bm.rowid + |WHERE blocks_fts MATCH ? + |ORDER BY bm25(blocks_fts) + |LIMIT ? OFFSET ? + """.trimMargin(), mapper, 3) { + var parameterIndex = 0 + bindString(parameterIndex++, query) + bindLong(parameterIndex++, limit) + bindLong(parameterIndex++, offset) + } + + override fun toString(): String = "SteleDatabase.sq:searchBlocksByContentFts" + } + + private inner class SearchBlocksByContentFtsInPageQuery( + public val query: String, + public val pageUuid: String, + public val limit: Long, + public val offset: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", "blocks_fts", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", "blocks_fts", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(337_193_030, """ + |SELECT + | b.uuid, + | b.page_uuid, + | b.parent_uuid, + | b.left_uuid, + | b.content, + | b.level, + | b.position, + | b.created_at, + | b.updated_at, + | b.properties, + | b.version, + | highlight(blocks_fts, 0, '', '') AS highlight, + | bm25(blocks_fts) AS bm25_score + |FROM blocks_fts bm + |JOIN blocks b ON b.id = bm.rowid + |WHERE blocks_fts MATCH ? + |AND b.page_uuid = ? + |ORDER BY bm25(blocks_fts) + |LIMIT ? OFFSET ? + """.trimMargin(), mapper, 4) { + var parameterIndex = 0 + bindString(parameterIndex++, query) + bindString(parameterIndex++, pageUuid) + bindLong(parameterIndex++, limit) + bindLong(parameterIndex++, offset) + } + + override fun toString(): String = "SteleDatabase.sq:searchBlocksByContentFtsInPage" + } + + private inner class SearchBlocksCountFtsQuery( + public val query: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks_fts", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks_fts", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(990_901_189, """ + |SELECT COUNT(*) AS result_count + |FROM blocks_fts bm + |WHERE blocks_fts MATCH ? + """.trimMargin(), mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, query) + } + + override fun toString(): String = "SteleDatabase.sq:searchBlocksCountFts" + } + + private inner class SearchPagesByNameFtsQuery( + public val query: String, + public val limit: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", "pages_fts", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", "pages_fts", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(2_023_372_136, """ + |SELECT + | p.uuid, + | p.name, + | p.namespace, + | p.file_path, + | p.created_at, + | p.updated_at, + | p.properties, + | p.version, + | p.is_favorite, + | p.is_journal, + | p.journal_date, + | p.is_content_loaded, + | highlight(pages_fts, 0, '', '') AS highlight, + | bm25(pages_fts) AS bm25_score + |FROM pages_fts pf + |JOIN pages p ON p.rowid = pf.rowid + |WHERE pages_fts MATCH ? + |ORDER BY bm25(pages_fts) + |LIMIT ? + """.trimMargin(), mapper, 2) { + var parameterIndex = 0 + bindString(parameterIndex++, query) + bindLong(parameterIndex++, limit) + } + + override fun toString(): String = "SteleDatabase.sq:searchPagesByNameFts" + } + + private inner class SearchPagesByNameFtsInDateRangeQuery( + public val query: String, + public val startMs: Long, + public val endMs: Long, + public val limit: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", "pages_fts", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", "pages_fts", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_087_339_518, """ + |SELECT p.uuid, p.name, p.namespace, p.file_path, p.created_at, p.updated_at, + | p.properties, p.version, p.is_favorite, p.is_journal, p.journal_date, + | p.is_content_loaded, + | highlight(pages_fts, 0, '', '') AS highlight, + | bm25(pages_fts) AS bm25_score + |FROM pages_fts pf + |JOIN pages p ON p.rowid = pf.rowid + |WHERE pages_fts MATCH ? + |AND p.updated_at >= ? AND p.updated_at <= ? + |ORDER BY bm25(pages_fts) + |LIMIT ? + """.trimMargin(), mapper, 4) { + var parameterIndex = 0 + bindString(parameterIndex++, query) + bindLong(parameterIndex++, startMs) + bindLong(parameterIndex++, endMs) + bindLong(parameterIndex++, limit) + } + + override fun toString(): String = "SteleDatabase.sq:searchPagesByNameFtsInDateRange" + } + + private inner class SearchBlocksByContentFtsInDateRangeQuery( + public val query: String, + public val startMs: Long, + public val endMs: Long, + public val limit: Long, + public val offset: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", "blocks_fts", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", "blocks_fts", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(234_891_992, """ + |SELECT b.uuid, b.page_uuid, b.parent_uuid, b.left_uuid, b.content, b.level, + | b.position, b.created_at, b.updated_at, b.properties, b.version, + | highlight(blocks_fts, 0, '', '') AS highlight, + | bm25(blocks_fts) AS bm25_score + |FROM blocks_fts bm + |JOIN blocks b ON b.id = bm.rowid + |WHERE blocks_fts MATCH ? + |AND b.updated_at >= ? AND b.updated_at <= ? + |ORDER BY bm25(blocks_fts) + |LIMIT ? OFFSET ? + """.trimMargin(), mapper, 5) { + var parameterIndex = 0 + bindString(parameterIndex++, query) + bindLong(parameterIndex++, startMs) + bindLong(parameterIndex++, endMs) + bindLong(parameterIndex++, limit) + bindLong(parameterIndex++, offset) + } + + override fun toString(): String = "SteleDatabase.sq:searchBlocksByContentFtsInDateRange" + } + + private inner class SelectPageVisitsByUuidsQuery( + public val page_uuid: Collection, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("page_visits", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("page_visits", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult { + val page_uuidIndexes = createArguments(count = page_uuid.size) + return driver.executeQuery(null, """ + |SELECT page_uuid, last_visited_at, visit_count + |FROM page_visits + |WHERE page_uuid IN $page_uuidIndexes + """.trimMargin(), mapper, page_uuid.size) { + var parameterIndex = 0 + page_uuid.forEach { page_uuid_ -> + bindString(parameterIndex++, page_uuid_) + } + } + } + + override fun toString(): String = "SteleDatabase.sq:selectPageVisitsByUuids" + } + + private inner class SelectPageVisitByUuidQuery( + public val page_uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("page_visits", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("page_visits", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-2_119_147_311, """ + |SELECT page_uuid, last_visited_at, visit_count + |FROM page_visits + |WHERE page_uuid = ? + """.trimMargin(), mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, page_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectPageVisitByUuid" + } + + private inner class SelectHistogramForOperationQuery( + public val operation_name: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("perf_histogram_buckets", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("perf_histogram_buckets", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_589_019, """SELECT bucket_ms, count FROM perf_histogram_buckets WHERE operation_name = ? ORDER BY bucket_ms""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, operation_name) + } + + override fun toString(): String = "SteleDatabase.sq:selectHistogramForOperation" + } + + private inner class SelectDebugFlagQuery( + public val key: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("debug_flags", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("debug_flags", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_764_549_726, """SELECT value FROM debug_flags WHERE key = ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, key) + } + + override fun toString(): String = "SteleDatabase.sq:selectDebugFlag" + } + + private inner class CountBlocksWithWikilinkQuery( + public val pageName: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-322_444_156, """SELECT COUNT(*) FROM blocks WHERE content LIKE '%[[' || ? || ']]%'""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, pageName) + } + + override fun toString(): String = "SteleDatabase.sq:countBlocksWithWikilink" + } + + private inner class SelectBlocksWithWikilinkQuery( + public val pageName: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(1_687_193_427, """SELECT blocks.id, blocks.uuid, blocks.page_uuid, blocks.parent_uuid, blocks.left_uuid, blocks.content, blocks.level, blocks.position, blocks.created_at, blocks.updated_at, blocks.properties, blocks.version, blocks.content_hash, blocks.block_type FROM blocks WHERE content LIKE '%[[' || ? || ']]%' ORDER BY page_uuid, position""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, pageName) + } + + override fun toString(): String = "SteleDatabase.sq:selectBlocksWithWikilink" + } + + private inner class CountLinkedReferencesForPageQuery( + public val pageName: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("blocks", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("blocks", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(1_158_809_001, """SELECT COUNT(*) FROM blocks WHERE content LIKE '%[[' || ? || ']]%'""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, pageName) + } + + override fun toString(): String = "SteleDatabase.sq:countLinkedReferencesForPage" + } + + private inner class SelectBacklinkCountsForPagesQuery( + public val uuid: Collection, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult { + val uuidIndexes = createArguments(count = uuid.size) + return driver.executeQuery(null, """ + |SELECT name AS page_name, backlink_count + |FROM pages + |WHERE uuid IN $uuidIndexes + """.trimMargin(), mapper, uuid.size) { + var parameterIndex = 0 + uuid.forEach { uuid_ -> + bindString(parameterIndex++, uuid_) + } + } + } + + override fun toString(): String = "SteleDatabase.sq:selectBacklinkCountsForPages" + } + + private inner class SelectPageBacklinkCountQuery( + public val name: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("pages", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("pages", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_616_094_686, """SELECT backlink_count FROM pages WHERE name = ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, name) + } + + override fun toString(): String = "SteleDatabase.sq:selectPageBacklinkCount" + } + + private inner class SelectMetadataQuery( + public val key: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("metadata", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("metadata", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_885_990_004, """SELECT value FROM metadata WHERE key = ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, key) + } + + override fun toString(): String = "SteleDatabase.sq:selectMetadata" + } + + private inner class SelectOperationsBySessionDescQuery( + public val session_id: String, + public val `value`: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("operations", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("operations", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(1_678_222_055, """SELECT operations.op_id, operations.session_id, operations.seq, operations.op_type, operations.entity_uuid, operations.page_uuid, operations.payload, operations.created_at FROM operations WHERE session_id = ? ORDER BY seq DESC LIMIT ?""", mapper, 2) { + var parameterIndex = 0 + bindString(parameterIndex++, session_id) + bindLong(parameterIndex++, value) + } + + override fun toString(): String = "SteleDatabase.sq:selectOperationsBySessionDesc" + } + + private inner class SelectOperationsByPageUuidQuery( + public val page_uuid: String?, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("operations", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("operations", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(null, """SELECT operations.op_id, operations.session_id, operations.seq, operations.op_type, operations.entity_uuid, operations.page_uuid, operations.payload, operations.created_at FROM operations WHERE page_uuid ${ if (page_uuid == null) "IS" else "=" } ? ORDER BY seq ASC""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, page_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectOperationsByPageUuid" + } + + private inner class SelectOperationsSinceQuery( + public val session_id: String, + public val seq: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("operations", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("operations", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-2_003_635_279, """SELECT operations.op_id, operations.session_id, operations.seq, operations.op_type, operations.entity_uuid, operations.page_uuid, operations.payload, operations.created_at FROM operations WHERE session_id = ? AND seq > ? ORDER BY seq ASC""", mapper, 2) { + var parameterIndex = 0 + bindString(parameterIndex++, session_id) + bindLong(parameterIndex++, seq) + } + + override fun toString(): String = "SteleDatabase.sq:selectOperationsSince" + } + + private inner class CountOperationPayloadSizeQuery( + public val session_id: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("operations", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("operations", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(554_681_494, """SELECT SUM(LENGTH(payload)) FROM operations WHERE session_id = ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, session_id) + } + + override fun toString(): String = "SteleDatabase.sq:countOperationPayloadSize" + } + + private inner class SelectLogicalClockQuery( + public val session_id: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("logical_clock", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("logical_clock", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(1_957_924_706, """SELECT seq FROM logical_clock WHERE session_id = ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, session_id) + } + + override fun toString(): String = "SteleDatabase.sq:selectLogicalClock" + } + + private inner class SelectAppliedMigrationsQuery( + public val graph_id: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("migration_changelog", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("migration_changelog", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(347_740_933, """SELECT id, checksum, status FROM migration_changelog WHERE graph_id = ? AND status = 'APPLIED' ORDER BY execution_order""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, graph_id) + } + + override fun toString(): String = "SteleDatabase.sq:selectAppliedMigrations" + } + + private inner class SelectMigrationByIdQuery( + public val id: String, + public val graph_id: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("migration_changelog", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("migration_changelog", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_304_131_965, """SELECT migration_changelog.id, migration_changelog.graph_id, migration_changelog.description, migration_changelog.checksum, migration_changelog.applied_at, migration_changelog.execution_ms, migration_changelog.status, migration_changelog.applied_by, migration_changelog.execution_order, migration_changelog.changes_applied, migration_changelog.error_message FROM migration_changelog WHERE id = ? AND graph_id = ?""", mapper, 2) { + var parameterIndex = 0 + bindString(parameterIndex++, id) + bindString(parameterIndex++, graph_id) + } + + override fun toString(): String = "SteleDatabase.sq:selectMigrationById" + } + + private inner class SelectRunningMigrationsQuery( + public val graph_id: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("migration_changelog", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("migration_changelog", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-338_897_465, """SELECT migration_changelog.id, migration_changelog.graph_id, migration_changelog.description, migration_changelog.checksum, migration_changelog.applied_at, migration_changelog.execution_ms, migration_changelog.status, migration_changelog.applied_by, migration_changelog.execution_order, migration_changelog.changes_applied, migration_changelog.error_message FROM migration_changelog WHERE graph_id = ? AND status = 'RUNNING'""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, graph_id) + } + + override fun toString(): String = "SteleDatabase.sq:selectRunningMigrations" + } + + private inner class SelectAllMigrationsForGraphQuery( + public val graph_id: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("migration_changelog", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("migration_changelog", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-2_001_246_770, """SELECT migration_changelog.id, migration_changelog.graph_id, migration_changelog.description, migration_changelog.checksum, migration_changelog.applied_at, migration_changelog.execution_ms, migration_changelog.status, migration_changelog.applied_by, migration_changelog.execution_order, migration_changelog.changes_applied, migration_changelog.error_message FROM migration_changelog WHERE graph_id = ? ORDER BY execution_order""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, graph_id) + } + + override fun toString(): String = "SteleDatabase.sq:selectAllMigrationsForGraph" + } + + private inner class SelectRecentSpansQuery( + public val `value`: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("spans", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("spans", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(681_519_953, """SELECT spans.id, spans.trace_id, spans.span_id, spans.parent_span_id, spans.name, spans.start_epoch_ms, spans.end_epoch_ms, spans.duration_ms, spans.attributes_json, spans.status_code, spans.app_version, spans.commit_hash FROM spans ORDER BY start_epoch_ms DESC LIMIT ?""", mapper, 1) { + var parameterIndex = 0 + bindLong(parameterIndex++, value) + } + + override fun toString(): String = "SteleDatabase.sq:selectRecentSpans" + } + + private inner class SelectSlowSpansByVersionAndNameQuery( + public val app_version: String, + public val name: String, + public val `value`: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("spans", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("spans", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(629_842_828, """SELECT spans.id, spans.trace_id, spans.span_id, spans.parent_span_id, spans.name, spans.start_epoch_ms, spans.end_epoch_ms, spans.duration_ms, spans.attributes_json, spans.status_code, spans.app_version, spans.commit_hash FROM spans WHERE app_version = ? AND name = ? ORDER BY duration_ms DESC LIMIT ?""", mapper, 3) { + var parameterIndex = 0 + bindString(parameterIndex++, app_version) + bindString(parameterIndex++, name) + bindLong(parameterIndex++, value) + } + + override fun toString(): String = "SteleDatabase.sq:selectSlowSpansByVersionAndName" + } + + private inner class SelectQueryStatsByVersionQuery( + public val app_version: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("query_stats", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("query_stats", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(542_632_205, """SELECT query_stats.app_version, query_stats.table_name, query_stats.operation, query_stats.calls, query_stats.errors, query_stats.total_ms, query_stats.min_ms, query_stats.max_ms, query_stats.b1, query_stats.b5, query_stats.b16, query_stats.b50, query_stats.b100, query_stats.b500, query_stats.b_inf, query_stats.first_seen, query_stats.last_seen FROM query_stats WHERE app_version = ? ORDER BY total_ms DESC""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, app_version) + } + + override fun toString(): String = "SteleDatabase.sq:selectQueryStatsByVersion" + } + + private inner class SelectTopQueryStatsByTotalMsQuery( + public val app_version: String, + public val `value`: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("query_stats", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("query_stats", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_979_761_980, """SELECT query_stats.app_version, query_stats.table_name, query_stats.operation, query_stats.calls, query_stats.errors, query_stats.total_ms, query_stats.min_ms, query_stats.max_ms, query_stats.b1, query_stats.b5, query_stats.b16, query_stats.b50, query_stats.b100, query_stats.b500, query_stats.b_inf, query_stats.first_seen, query_stats.last_seen FROM query_stats WHERE app_version = ? ORDER BY total_ms DESC LIMIT ?""", mapper, 2) { + var parameterIndex = 0 + bindString(parameterIndex++, app_version) + bindLong(parameterIndex++, value) + } + + override fun toString(): String = "SteleDatabase.sq:selectTopQueryStatsByTotalMs" + } + + private inner class SelectTopQueryStatsByCallsQuery( + public val app_version: String, + public val `value`: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("query_stats", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("query_stats", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(410_865_423, """SELECT query_stats.app_version, query_stats.table_name, query_stats.operation, query_stats.calls, query_stats.errors, query_stats.total_ms, query_stats.min_ms, query_stats.max_ms, query_stats.b1, query_stats.b5, query_stats.b16, query_stats.b50, query_stats.b100, query_stats.b500, query_stats.b_inf, query_stats.first_seen, query_stats.last_seen FROM query_stats WHERE app_version = ? ORDER BY calls DESC LIMIT ?""", mapper, 2) { + var parameterIndex = 0 + bindString(parameterIndex++, app_version) + bindLong(parameterIndex++, value) + } + + override fun toString(): String = "SteleDatabase.sq:selectTopQueryStatsByCalls" + } + + private inner class SelectGitConfigQuery( + public val graph_id: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("git_config", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("git_config", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(1_451_609_335, """SELECT git_config.graph_id, git_config.repo_root, git_config.wiki_subdir, git_config.remote_name, git_config.remote_branch, git_config.auth_type, git_config.ssh_key_path, git_config.ssh_key_passphrase_key, git_config.https_token_key, git_config.poll_interval_minutes, git_config.auto_commit, git_config.commit_message_template FROM git_config WHERE graph_id = ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, graph_id) + } + + override fun toString(): String = "SteleDatabase.sq:selectGitConfig" + } + + private inner class SelectImageAnnotationByUuidQuery( + public val uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("image_annotations", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("image_annotations", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-575_052_033, """SELECT image_annotations.uuid, image_annotations.block_uuid, image_annotations.page_uuid, image_annotations.graph_path, image_annotations.file_path, image_annotations.thumbnail_path, image_annotations.source, image_annotations.source_uri, image_annotations.captured_at_ms, image_annotations.imported_at_ms, image_annotations.calibration_method, image_annotations.pixels_per_meter, image_annotations.calibration_confidence_pct, image_annotations.unit, image_annotations.tags, image_annotations.lat_lng, image_annotations.altitude_m, image_annotations.bearing_deg, image_annotations.pitch_deg, image_annotations.roll_deg, image_annotations.focal_length_mm, image_annotations.focal_length_35mm_eq, image_annotations.camera_make, image_annotations.camera_model FROM image_annotations WHERE uuid = ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectImageAnnotationByUuid" + } + + private inner class SelectImageAnnotationsByPageQuery( + public val page_uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("image_annotations", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("image_annotations", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_651_202_740, """SELECT image_annotations.uuid, image_annotations.block_uuid, image_annotations.page_uuid, image_annotations.graph_path, image_annotations.file_path, image_annotations.thumbnail_path, image_annotations.source, image_annotations.source_uri, image_annotations.captured_at_ms, image_annotations.imported_at_ms, image_annotations.calibration_method, image_annotations.pixels_per_meter, image_annotations.calibration_confidence_pct, image_annotations.unit, image_annotations.tags, image_annotations.lat_lng, image_annotations.altitude_m, image_annotations.bearing_deg, image_annotations.pitch_deg, image_annotations.roll_deg, image_annotations.focal_length_mm, image_annotations.focal_length_35mm_eq, image_annotations.camera_make, image_annotations.camera_model FROM image_annotations WHERE page_uuid = ? ORDER BY imported_at_ms DESC""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, page_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectImageAnnotationsByPage" + } + + private inner class SelectImageAnnotationsByTagQuery( + public val `value`: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("image_annotations", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("image_annotations", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(778_023_229, """SELECT image_annotations.uuid, image_annotations.block_uuid, image_annotations.page_uuid, image_annotations.graph_path, image_annotations.file_path, image_annotations.thumbnail_path, image_annotations.source, image_annotations.source_uri, image_annotations.captured_at_ms, image_annotations.imported_at_ms, image_annotations.calibration_method, image_annotations.pixels_per_meter, image_annotations.calibration_confidence_pct, image_annotations.unit, image_annotations.tags, image_annotations.lat_lng, image_annotations.altitude_m, image_annotations.bearing_deg, image_annotations.pitch_deg, image_annotations.roll_deg, image_annotations.focal_length_mm, image_annotations.focal_length_35mm_eq, image_annotations.camera_make, image_annotations.camera_model FROM image_annotations WHERE tags LIKE '%"' || ? || '"%' ORDER BY imported_at_ms DESC""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, value) + } + + override fun toString(): String = "SteleDatabase.sq:selectImageAnnotationsByTag" + } + + private inner class SelectMeasurementsForImageQuery( + public val image_uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("measurement_annotations", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("measurement_annotations", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(1_858_375_750, """SELECT measurement_annotations.uuid, measurement_annotations.image_uuid, measurement_annotations.annotation_type, measurement_annotations.normalized_points, measurement_annotations.value_meters, measurement_annotations.value_display, measurement_annotations.label, measurement_annotations.color_hex, measurement_annotations.ble_device_id FROM measurement_annotations WHERE image_uuid = ? ORDER BY rowid""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, image_uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectMeasurementsForImage" + } + + private inner class SelectAssetByUuidQuery( + public val uuid: String, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("asset_index", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("asset_index", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-807_861_691, """SELECT asset_index.uuid, asset_index.file_path, asset_index.relative_path, asset_index.media_type, asset_index.subfolder, asset_index.tags, asset_index.auto_labels, asset_index.ocr_text, asset_index.cloud_description, asset_index.page_uuids, asset_index.size_bytes, asset_index.imported_at_ms, asset_index.ml_processed, asset_index.ml_attempted_at, asset_index.ml_failed, asset_index.content_hash, asset_index.is_orphan, asset_index.ml_tags_source FROM asset_index WHERE uuid = ?""", mapper, 1) { + var parameterIndex = 0 + bindString(parameterIndex++, uuid) + } + + override fun toString(): String = "SteleDatabase.sq:selectAssetByUuid" + } + + private inner class SelectAssetsQuery( + public val limit: Long, + public val offset: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("asset_index", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("asset_index", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_047_691_488, """SELECT asset_index.uuid, asset_index.file_path, asset_index.relative_path, asset_index.media_type, asset_index.subfolder, asset_index.tags, asset_index.auto_labels, asset_index.ocr_text, asset_index.cloud_description, asset_index.page_uuids, asset_index.size_bytes, asset_index.imported_at_ms, asset_index.ml_processed, asset_index.ml_attempted_at, asset_index.ml_failed, asset_index.content_hash, asset_index.is_orphan, asset_index.ml_tags_source FROM asset_index ORDER BY imported_at_ms DESC LIMIT ? OFFSET ?""", mapper, 2) { + var parameterIndex = 0 + bindLong(parameterIndex++, limit) + bindLong(parameterIndex++, offset) + } + + override fun toString(): String = "SteleDatabase.sq:selectAssets" + } + + private inner class SelectAssetsByMediaTypeQuery( + public val media_type: String, + public val limit: Long, + public val offset: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("asset_index", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("asset_index", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(-1_673_176_217, """SELECT asset_index.uuid, asset_index.file_path, asset_index.relative_path, asset_index.media_type, asset_index.subfolder, asset_index.tags, asset_index.auto_labels, asset_index.ocr_text, asset_index.cloud_description, asset_index.page_uuids, asset_index.size_bytes, asset_index.imported_at_ms, asset_index.ml_processed, asset_index.ml_attempted_at, asset_index.ml_failed, asset_index.content_hash, asset_index.is_orphan, asset_index.ml_tags_source FROM asset_index WHERE media_type = ? ORDER BY imported_at_ms DESC LIMIT ? OFFSET ?""", mapper, 3) { + var parameterIndex = 0 + bindString(parameterIndex++, media_type) + bindLong(parameterIndex++, limit) + bindLong(parameterIndex++, offset) + } + + override fun toString(): String = "SteleDatabase.sq:selectAssetsByMediaType" + } + + private inner class SearchAssetsQuery( + public val query: String, + public val limit: Long, + public val offset: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("asset_index", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("asset_index", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(1_326_743_244, """SELECT asset_index.uuid, asset_index.file_path, asset_index.relative_path, asset_index.media_type, asset_index.subfolder, asset_index.tags, asset_index.auto_labels, asset_index.ocr_text, asset_index.cloud_description, asset_index.page_uuids, asset_index.size_bytes, asset_index.imported_at_ms, asset_index.ml_processed, asset_index.ml_attempted_at, asset_index.ml_failed, asset_index.content_hash, asset_index.is_orphan, asset_index.ml_tags_source FROM asset_index WHERE (file_path LIKE ? ESCAPE '\' OR tags LIKE ? ESCAPE '\' OR auto_labels LIKE ? ESCAPE '\' OR ocr_text LIKE ? ESCAPE '\') ORDER BY imported_at_ms DESC LIMIT ? OFFSET ?""", mapper, 6) { + var parameterIndex = 0 + bindString(parameterIndex++, query) + bindString(parameterIndex++, query) + bindString(parameterIndex++, query) + bindString(parameterIndex++, query) + bindLong(parameterIndex++, limit) + bindLong(parameterIndex++, offset) + } + + override fun toString(): String = "SteleDatabase.sq:searchAssets" + } + + private inner class SelectUnprocessedAssetsQuery( + public val limit: Long, + public val offset: Long, + mapper: (SqlCursor) -> T, + ) : Query(mapper) { + override fun addListener(listener: Query.Listener) { + driver.addListener("asset_index", listener = listener) + } + + override fun removeListener(listener: Query.Listener) { + driver.removeListener("asset_index", listener = listener) + } + + override fun execute(mapper: (SqlCursor) -> QueryResult): QueryResult = driver.executeQuery(691_455_227, """SELECT asset_index.uuid, asset_index.file_path, asset_index.relative_path, asset_index.media_type, asset_index.subfolder, asset_index.tags, asset_index.auto_labels, asset_index.ocr_text, asset_index.cloud_description, asset_index.page_uuids, asset_index.size_bytes, asset_index.imported_at_ms, asset_index.ml_processed, asset_index.ml_attempted_at, asset_index.ml_failed, asset_index.content_hash, asset_index.is_orphan, asset_index.ml_tags_source FROM asset_index WHERE ml_processed = 0 AND ml_failed = 0 ORDER BY imported_at_ms ASC LIMIT ? OFFSET ?""", mapper, 2) { + var parameterIndex = 0 + bindLong(parameterIndex++, limit) + bindLong(parameterIndex++, offset) + } + + override fun toString(): String = "SteleDatabase.sq:selectUnprocessedAssets" + } +} diff --git a/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/kmp/SteleDatabaseImpl.kt b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/kmp/SteleDatabaseImpl.kt new file mode 100644 index 00000000..6f1b51af --- /dev/null +++ b/kmp/src/generated/sqldelight/dev/stapler/stelekit/db/kmp/SteleDatabaseImpl.kt @@ -0,0 +1,525 @@ +package dev.stapler.stelekit.db.kmp + +import app.cash.sqldelight.SuspendingTransacterImpl +import app.cash.sqldelight.db.AfterVersion +import app.cash.sqldelight.db.QueryResult +import app.cash.sqldelight.db.SqlDriver +import app.cash.sqldelight.db.SqlSchema +import dev.stapler.stelekit.db.SteleDatabase +import dev.stapler.stelekit.db.SteleDatabaseQueries +import kotlin.Long +import kotlin.Unit +import kotlin.reflect.KClass + +internal val KClass.schema: SqlSchema> + get() = SteleDatabaseImpl.Schema + +internal fun KClass.newInstance(driver: SqlDriver): SteleDatabase = SteleDatabaseImpl(driver) + +private class SteleDatabaseImpl( + driver: SqlDriver, +) : SuspendingTransacterImpl(driver), + SteleDatabase { + override val steleDatabaseQueries: SteleDatabaseQueries = SteleDatabaseQueries(driver) + + public object Schema : SqlSchema> { + override val version: Long + get() = 7 + + override fun create(driver: SqlDriver): QueryResult.AsyncValue = QueryResult.AsyncValue { + driver.execute(null, """ + |CREATE TABLE pages ( + | uuid TEXT NOT NULL PRIMARY KEY, + | name TEXT NOT NULL UNIQUE COLLATE NOCASE, + | namespace TEXT, + | file_path TEXT, + | created_at INTEGER NOT NULL, + | updated_at INTEGER NOT NULL, + | properties TEXT, -- JSON string for page properties + | version INTEGER NOT NULL DEFAULT 0, + | is_favorite INTEGER DEFAULT 0, + | is_journal INTEGER DEFAULT 0, + | journal_date TEXT, + | is_content_loaded INTEGER NOT NULL DEFAULT 1, + | backlink_count INTEGER NOT NULL DEFAULT 0 + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TABLE blocks ( + | id INTEGER PRIMARY KEY AUTOINCREMENT, -- Hidden numeric ID for FTS5 internal use + | uuid TEXT NOT NULL UNIQUE, + | page_uuid TEXT NOT NULL, + | parent_uuid TEXT, + | left_uuid TEXT, + | content TEXT NOT NULL, + | level INTEGER NOT NULL DEFAULT 0, + | position INTEGER NOT NULL, + | created_at INTEGER NOT NULL, + | updated_at INTEGER NOT NULL, + | properties TEXT, -- JSON string for block properties + | version INTEGER NOT NULL DEFAULT 0, + | content_hash TEXT, -- SHA-256 hex digest of normalised content (used for deduplication) + | block_type TEXT NOT NULL DEFAULT 'bullet', -- Structural discriminator (bullet, paragraph, heading, etc.) — excluded from FTS intentionally + | FOREIGN KEY (page_uuid) REFERENCES pages(uuid) ON DELETE CASCADE, + | FOREIGN KEY (parent_uuid) REFERENCES blocks(uuid) ON DELETE CASCADE, + | FOREIGN KEY (left_uuid) REFERENCES blocks(uuid) ON DELETE SET NULL + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TABLE properties ( + | uuid TEXT NOT NULL PRIMARY KEY, + | block_uuid TEXT NOT NULL, + | key TEXT NOT NULL, + | value TEXT NOT NULL, + | created_at INTEGER NOT NULL, + | FOREIGN KEY (block_uuid) REFERENCES blocks(uuid) ON DELETE CASCADE + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TABLE plugin_data ( + | id INTEGER PRIMARY KEY AUTOINCREMENT, + | plugin_id TEXT NOT NULL, + | entity_type TEXT NOT NULL, + | entity_uuid TEXT NOT NULL, + | key TEXT NOT NULL, + | value TEXT NOT NULL, + | created_at INTEGER NOT NULL, + | updated_at INTEGER, + | UNIQUE(plugin_id, entity_type, entity_uuid, key) + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TABLE block_references ( + | id INTEGER PRIMARY KEY AUTOINCREMENT, + | from_block_uuid TEXT NOT NULL, + | to_block_uuid TEXT NOT NULL, + | created_at INTEGER NOT NULL, + | UNIQUE(from_block_uuid, to_block_uuid), + | FOREIGN KEY (from_block_uuid) REFERENCES blocks(uuid) ON DELETE CASCADE, + | FOREIGN KEY (to_block_uuid) REFERENCES blocks(uuid) ON DELETE CASCADE + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TABLE migration_changelog ( + | id TEXT NOT NULL, + | graph_id TEXT NOT NULL, + | description TEXT NOT NULL, + | checksum TEXT NOT NULL, + | applied_at INTEGER NOT NULL, + | execution_ms INTEGER NOT NULL DEFAULT 0, + | status TEXT NOT NULL DEFAULT 'APPLIED', + | applied_by TEXT NOT NULL DEFAULT '', + | execution_order INTEGER NOT NULL DEFAULT 0, + | changes_applied INTEGER NOT NULL DEFAULT 0, + | error_message TEXT, + | PRIMARY KEY (id, graph_id) + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TABLE IF NOT EXISTS page_visits ( + | page_uuid TEXT NOT NULL PRIMARY KEY, + | visit_count INTEGER NOT NULL DEFAULT 0, + | last_visited_at INTEGER NOT NULL -- epoch milliseconds (Unix) + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TABLE IF NOT EXISTS perf_histogram_buckets ( + | id INTEGER PRIMARY KEY AUTOINCREMENT, + | operation_name TEXT NOT NULL, + | bucket_ms INTEGER NOT NULL, + | count INTEGER NOT NULL DEFAULT 0, + | recorded_at INTEGER NOT NULL + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TABLE IF NOT EXISTS debug_flags ( + | key TEXT NOT NULL PRIMARY KEY, + | value INTEGER NOT NULL DEFAULT 0, + | updated_at INTEGER NOT NULL + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TABLE metadata ( + | key TEXT NOT NULL PRIMARY KEY, + | value TEXT NOT NULL + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TABLE operations ( + | op_id TEXT NOT NULL PRIMARY KEY, -- UUID v7 (time-ordered for efficient range scans) + | session_id TEXT NOT NULL, + | seq INTEGER NOT NULL, -- Lamport clock value (monotonically increasing per session) + | op_type TEXT NOT NULL, -- INSERT_BLOCK | UPDATE_BLOCK | DELETE_BLOCK | MOVE_BLOCK | BATCH_START | BATCH_END | SYNC_BARRIER + | entity_uuid TEXT, -- block UUID affected (NULL for BATCH_START/END and SYNC_BARRIER) + | page_uuid TEXT, -- page context (NULL for BATCH_START/END and SYNC_BARRIER) + | payload TEXT NOT NULL DEFAULT '{}', -- JSON: {"before": {...}, "after": {...}} + | created_at INTEGER NOT NULL + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TABLE logical_clock ( + | session_id TEXT NOT NULL PRIMARY KEY, + | seq INTEGER NOT NULL DEFAULT 0 + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TABLE IF NOT EXISTS spans ( + | id INTEGER PRIMARY KEY AUTOINCREMENT, + | trace_id TEXT NOT NULL DEFAULT '', + | span_id TEXT NOT NULL DEFAULT '', + | parent_span_id TEXT NOT NULL DEFAULT '', + | name TEXT NOT NULL, + | start_epoch_ms INTEGER NOT NULL, + | end_epoch_ms INTEGER NOT NULL, + | duration_ms INTEGER NOT NULL, + | attributes_json TEXT NOT NULL DEFAULT '{}', + | status_code TEXT NOT NULL DEFAULT 'OK', + | app_version TEXT NOT NULL DEFAULT '', + | commit_hash TEXT NOT NULL DEFAULT '' + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TABLE IF NOT EXISTS query_stats ( + | app_version TEXT NOT NULL, + | table_name TEXT NOT NULL, + | operation TEXT NOT NULL, + | calls INTEGER NOT NULL DEFAULT 0, + | errors INTEGER NOT NULL DEFAULT 0, + | total_ms INTEGER NOT NULL DEFAULT 0, + | min_ms INTEGER NOT NULL DEFAULT 9999999, + | max_ms INTEGER NOT NULL DEFAULT 0, + | b1 INTEGER NOT NULL DEFAULT 0, -- ≤ 1 ms + | b5 INTEGER NOT NULL DEFAULT 0, -- ≤ 5 ms + | b16 INTEGER NOT NULL DEFAULT 0, -- ≤ 16 ms + | b50 INTEGER NOT NULL DEFAULT 0, -- ≤ 50 ms + | b100 INTEGER NOT NULL DEFAULT 0, -- ≤ 100 ms + | b500 INTEGER NOT NULL DEFAULT 0, -- ≤ 500 ms + | b_inf INTEGER NOT NULL DEFAULT 0, -- > 500 ms + | first_seen INTEGER NOT NULL, + | last_seen INTEGER NOT NULL, + | PRIMARY KEY (app_version, table_name, operation) + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TABLE IF NOT EXISTS git_config ( + | graph_id TEXT NOT NULL PRIMARY KEY, + | repo_root TEXT NOT NULL, + | wiki_subdir TEXT NOT NULL DEFAULT '', + | remote_name TEXT NOT NULL DEFAULT 'origin', + | remote_branch TEXT NOT NULL DEFAULT 'main', + | auth_type TEXT NOT NULL DEFAULT 'NONE', + | ssh_key_path TEXT, + | ssh_key_passphrase_key TEXT, + | https_token_key TEXT, + | poll_interval_minutes INTEGER NOT NULL DEFAULT 5, + | auto_commit INTEGER NOT NULL DEFAULT 1, + | commit_message_template TEXT NOT NULL DEFAULT 'SteleKit: {date}' + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TABLE IF NOT EXISTS image_annotations ( + | uuid TEXT NOT NULL PRIMARY KEY, + | block_uuid TEXT NOT NULL, + | page_uuid TEXT NOT NULL, + | graph_path TEXT NOT NULL, + | file_path TEXT NOT NULL, + | thumbnail_path TEXT, + | source TEXT NOT NULL DEFAULT 'FILE', + | source_uri TEXT, + | captured_at_ms INTEGER, + | imported_at_ms INTEGER NOT NULL DEFAULT 0, + | calibration_method TEXT NOT NULL DEFAULT 'NONE', + | pixels_per_meter REAL NOT NULL DEFAULT 0.0, + | calibration_confidence_pct INTEGER NOT NULL DEFAULT 0, + | unit TEXT NOT NULL DEFAULT 'METERS', + | tags TEXT NOT NULL DEFAULT '[]', + | lat_lng TEXT, + | altitude_m REAL, + | bearing_deg REAL, + | pitch_deg REAL, + | roll_deg REAL, + | focal_length_mm REAL, + | focal_length_35mm_eq REAL, + | camera_make TEXT, + | camera_model TEXT + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TABLE IF NOT EXISTS measurement_annotations ( + | uuid TEXT NOT NULL PRIMARY KEY, + | image_uuid TEXT NOT NULL, + | annotation_type TEXT NOT NULL, + | normalized_points TEXT NOT NULL DEFAULT '[]', + | value_meters REAL, + | value_display TEXT, + | label TEXT, + | color_hex TEXT NOT NULL DEFAULT '#FF0000', + | ble_device_id TEXT, + | FOREIGN KEY (image_uuid) REFERENCES image_annotations(uuid) ON DELETE CASCADE + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TABLE IF NOT EXISTS asset_index ( + | uuid TEXT NOT NULL PRIMARY KEY, + | file_path TEXT NOT NULL, + | relative_path TEXT NOT NULL, + | media_type TEXT NOT NULL, + | subfolder TEXT NOT NULL DEFAULT 'files', + | tags TEXT NOT NULL DEFAULT '[]', + | auto_labels TEXT NOT NULL DEFAULT '[]', + | ocr_text TEXT, + | cloud_description TEXT, + | page_uuids TEXT NOT NULL DEFAULT '[]', + | size_bytes INTEGER NOT NULL DEFAULT 0, + | imported_at_ms INTEGER NOT NULL, + | ml_processed INTEGER NOT NULL DEFAULT 0, + | ml_attempted_at INTEGER, + | ml_failed INTEGER NOT NULL DEFAULT 0, + | content_hash TEXT, + | is_orphan INTEGER NOT NULL DEFAULT 0, + | ml_tags_source TEXT NOT NULL DEFAULT 'NONE' + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TABLE IF NOT EXISTS pending_asset_moves ( + | id INTEGER PRIMARY KEY AUTOINCREMENT, + | asset_uuid TEXT NOT NULL, + | old_file_path TEXT NOT NULL, + | new_file_path TEXT NOT NULL, + | old_relative_path TEXT NOT NULL, + | new_relative_path TEXT NOT NULL, + | created_at_ms INTEGER NOT NULL + |) + """.trimMargin(), 0).await() + driver.execute(null, "CREATE INDEX idx_pages_namespace ON pages(namespace)", 0).await() + driver.execute(null, "CREATE INDEX idx_blocks_page_position ON blocks(page_uuid, position)", 0).await() + driver.execute(null, "CREATE INDEX idx_blocks_parent_position ON blocks(parent_uuid, position)", 0).await() + driver.execute(null, "CREATE INDEX idx_blocks_page_hash ON blocks(page_uuid, uuid, content_hash)", 0).await() + driver.execute(null, "CREATE INDEX idx_blocks_left_uuid ON blocks(left_uuid)", 0).await() + driver.execute(null, "CREATE INDEX idx_blocks_content_hash ON blocks(content_hash)", 0).await() + driver.execute(null, "CREATE INDEX idx_properties_block_uuid ON properties(block_uuid)", 0).await() + driver.execute(null, "CREATE INDEX idx_properties_key ON properties(key)", 0).await() + driver.execute(null, "CREATE INDEX idx_plugin_data_plugin_id ON plugin_data(plugin_id)", 0).await() + driver.execute(null, "CREATE INDEX idx_plugin_data_entity ON plugin_data(entity_type, entity_uuid)", 0).await() + driver.execute(null, "CREATE INDEX idx_plugin_data_key ON plugin_data(key)", 0).await() + driver.execute(null, "CREATE INDEX idx_references_from ON block_references(from_block_uuid)", 0).await() + driver.execute(null, "CREATE INDEX idx_references_to ON block_references(to_block_uuid)", 0).await() + driver.execute(null, "CREATE INDEX idx_pages_journal ON pages(is_journal, journal_date DESC)", 0).await() + driver.execute(null, "CREATE INDEX idx_pages_updated_at ON pages(updated_at DESC)", 0).await() + driver.execute(null, "CREATE INDEX idx_pages_created_at ON pages(created_at DESC)", 0).await() + driver.execute(null, "CREATE INDEX idx_pages_favorite ON pages(name) WHERE is_favorite = 1", 0).await() + driver.execute(null, "CREATE INDEX idx_changelog_graph_status ON migration_changelog(graph_id, status)", 0).await() + driver.execute(null, "CREATE INDEX idx_changelog_applied_at ON migration_changelog(graph_id, applied_at)", 0).await() + driver.execute(null, """ + |CREATE TRIGGER blocks_ai AFTER INSERT ON blocks BEGIN + | INSERT INTO blocks_fts(rowid, content) VALUES (new.id, new.content); + |END + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TRIGGER blocks_ad AFTER DELETE ON blocks BEGIN + | INSERT INTO blocks_fts(blocks_fts, rowid, content) + | VALUES('delete', old.id, old.content); + |END + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TRIGGER blocks_au AFTER UPDATE OF content ON blocks BEGIN + | INSERT INTO blocks_fts(blocks_fts, rowid, content) + | VALUES('delete', old.id, old.content); + | INSERT INTO blocks_fts(rowid, content) VALUES (new.id, new.content); + |END + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TRIGGER pages_ai AFTER INSERT ON pages BEGIN + | INSERT INTO pages_fts(rowid, name) VALUES (new.rowid, new.name); + |END + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TRIGGER pages_ad AFTER DELETE ON pages BEGIN + | INSERT INTO pages_fts(pages_fts, rowid, name) VALUES('delete', old.rowid, old.name); + |END + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE TRIGGER pages_au AFTER UPDATE OF name ON pages BEGIN + | INSERT INTO pages_fts(pages_fts, rowid, name) VALUES('delete', old.rowid, old.name); + | INSERT INTO pages_fts(rowid, name) VALUES (new.rowid, new.name); + |END + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE UNIQUE INDEX IF NOT EXISTS idx_perf_hist_op_bucket + | ON perf_histogram_buckets(operation_name, bucket_ms) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE INDEX IF NOT EXISTS idx_perf_hist_recorded_at + | ON perf_histogram_buckets(recorded_at) + """.trimMargin(), 0).await() + driver.execute(null, "CREATE INDEX idx_operations_session_seq ON operations(session_id, seq)", 0).await() + driver.execute(null, "CREATE INDEX idx_operations_page ON operations(page_uuid)", 0).await() + driver.execute(null, "CREATE INDEX idx_operations_entity ON operations(entity_uuid)", 0).await() + driver.execute(null, "CREATE INDEX IF NOT EXISTS spans_start_epoch_ms_idx ON spans(start_epoch_ms DESC)", 0).await() + driver.execute(null, "CREATE INDEX IF NOT EXISTS spans_trace_id_idx ON spans(trace_id)", 0).await() + driver.execute(null, "CREATE INDEX IF NOT EXISTS idx_spans_version_name_duration ON spans(app_version, name, duration_ms DESC)", 0).await() + driver.execute(null, "CREATE INDEX IF NOT EXISTS idx_spans_end_epoch_ms ON spans(end_epoch_ms)", 0).await() + driver.execute(null, """ + |CREATE INDEX IF NOT EXISTS idx_query_stats_version_ms + | ON query_stats(app_version, total_ms DESC) + """.trimMargin(), 0).await() + driver.execute(null, "CREATE INDEX IF NOT EXISTS idx_image_annotations_block_uuid ON image_annotations(block_uuid)", 0).await() + driver.execute(null, "CREATE INDEX IF NOT EXISTS idx_image_annotations_page_uuid ON image_annotations(page_uuid)", 0).await() + driver.execute(null, "CREATE INDEX IF NOT EXISTS idx_image_annotations_graph_path ON image_annotations(graph_path)", 0).await() + driver.execute(null, "CREATE INDEX IF NOT EXISTS idx_image_annotations_imported_at ON image_annotations(imported_at_ms DESC)", 0).await() + driver.execute(null, "CREATE INDEX IF NOT EXISTS idx_measurement_annotations_image_uuid ON measurement_annotations(image_uuid)", 0).await() + driver.execute(null, "CREATE UNIQUE INDEX IF NOT EXISTS idx_asset_file_path_unique ON asset_index(file_path)", 0).await() + driver.execute(null, "CREATE INDEX IF NOT EXISTS idx_asset_unprocessed ON asset_index(ml_processed, ml_failed, imported_at_ms)", 0).await() + driver.execute(null, "CREATE INDEX IF NOT EXISTS idx_asset_media_type ON asset_index(media_type)", 0).await() + driver.execute(null, "CREATE INDEX IF NOT EXISTS idx_asset_imported_at ON asset_index(imported_at_ms DESC)", 0).await() + driver.execute(null, """ + |CREATE VIRTUAL TABLE blocks_fts USING fts5( + | content, + | content=blocks, + | content_rowid=id, + | tokenize='porter unicode61' + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE VIRTUAL TABLE pages_fts USING fts5( + | name, + | content=pages, + | content_rowid=rowid, + | tokenize='porter unicode61' + |) + """.trimMargin(), 0).await() + } + + private fun migrateInternal( + driver: SqlDriver, + oldVersion: Long, + newVersion: Long, + ): QueryResult.AsyncValue = QueryResult.AsyncValue { + if (oldVersion <= 2 && newVersion > 2) { + driver.execute(null, "ALTER TABLE blocks ADD COLUMN block_type TEXT NOT NULL DEFAULT 'bullet'", 0).await() + } + if (oldVersion <= 3 && newVersion > 3) { + driver.execute(null, """ + |CREATE TABLE IF NOT EXISTS migration_changelog ( + | id TEXT NOT NULL, + | graph_id TEXT NOT NULL, + | description TEXT NOT NULL, + | checksum TEXT NOT NULL, + | applied_at INTEGER NOT NULL, + | execution_ms INTEGER NOT NULL DEFAULT 0, + | status TEXT NOT NULL DEFAULT 'APPLIED', + | applied_by TEXT NOT NULL DEFAULT '', + | execution_order INTEGER NOT NULL DEFAULT 0, + | changes_applied INTEGER NOT NULL DEFAULT 0, + | error_message TEXT, + | PRIMARY KEY (id, graph_id) + |) + """.trimMargin(), 0).await() + driver.execute(null, "CREATE INDEX IF NOT EXISTS idx_changelog_graph_status ON migration_changelog(graph_id, status)", 0).await() + driver.execute(null, "CREATE INDEX IF NOT EXISTS idx_changelog_applied_at ON migration_changelog(graph_id, applied_at)", 0).await() + } + if (oldVersion <= 4 && newVersion > 4) { + driver.execute(null, """ + |CREATE TABLE IF NOT EXISTS image_annotations ( + | uuid TEXT NOT NULL PRIMARY KEY, + | block_uuid TEXT NOT NULL, + | page_uuid TEXT NOT NULL, + | graph_path TEXT NOT NULL, + | file_path TEXT NOT NULL, + | thumbnail_path TEXT, + | source TEXT NOT NULL DEFAULT 'FILE', + | source_uri TEXT, + | captured_at_ms INTEGER, + | imported_at_ms INTEGER NOT NULL DEFAULT 0, + | calibration_method TEXT NOT NULL DEFAULT 'NONE', + | pixels_per_meter REAL NOT NULL DEFAULT 0.0, + | calibration_confidence_pct INTEGER NOT NULL DEFAULT 0, + | unit TEXT NOT NULL DEFAULT 'METERS', + | tags TEXT NOT NULL DEFAULT '[]', + | lat_lng TEXT, + | altitude_m REAL, + | bearing_deg REAL, + | pitch_deg REAL, + | roll_deg REAL, + | focal_length_mm REAL, + | focal_length_35mm_eq REAL, + | camera_make TEXT, + | camera_model TEXT + |) + """.trimMargin(), 0).await() + driver.execute(null, "CREATE INDEX IF NOT EXISTS idx_image_annotations_block_uuid ON image_annotations(block_uuid)", 0).await() + driver.execute(null, "CREATE INDEX IF NOT EXISTS idx_image_annotations_page_uuid ON image_annotations(page_uuid)", 0).await() + driver.execute(null, "CREATE INDEX IF NOT EXISTS idx_image_annotations_graph_path ON image_annotations(graph_path)", 0).await() + driver.execute(null, """ + |CREATE TABLE IF NOT EXISTS measurement_annotations ( + | uuid TEXT NOT NULL PRIMARY KEY, + | image_uuid TEXT NOT NULL, + | annotation_type TEXT NOT NULL, + | normalized_points TEXT NOT NULL DEFAULT '[]', + | value_meters REAL, + | value_display TEXT, + | label TEXT, + | color_hex TEXT NOT NULL DEFAULT '#FF0000', + | ble_device_id TEXT, + | FOREIGN KEY (image_uuid) REFERENCES image_annotations(uuid) ON DELETE CASCADE + |) + """.trimMargin(), 0).await() + driver.execute(null, "CREATE INDEX IF NOT EXISTS idx_measurement_annotations_image_uuid ON measurement_annotations(image_uuid)", 0).await() + } + if (oldVersion <= 5 && newVersion > 5) { + driver.execute(null, """ + |CREATE TABLE IF NOT EXISTS query_stats ( + | app_version TEXT NOT NULL, + | table_name TEXT NOT NULL, + | operation TEXT NOT NULL, + | calls INTEGER NOT NULL DEFAULT 0, + | errors INTEGER NOT NULL DEFAULT 0, + | total_ms INTEGER NOT NULL DEFAULT 0, + | min_ms INTEGER NOT NULL DEFAULT 9999999, + | max_ms INTEGER NOT NULL DEFAULT 0, + | b1 INTEGER NOT NULL DEFAULT 0, + | b5 INTEGER NOT NULL DEFAULT 0, + | b16 INTEGER NOT NULL DEFAULT 0, + | b50 INTEGER NOT NULL DEFAULT 0, + | b100 INTEGER NOT NULL DEFAULT 0, + | b500 INTEGER NOT NULL DEFAULT 0, + | b_inf INTEGER NOT NULL DEFAULT 0, + | first_seen INTEGER NOT NULL, + | last_seen INTEGER NOT NULL, + | PRIMARY KEY (app_version, table_name, operation) + |) + """.trimMargin(), 0).await() + driver.execute(null, """ + |CREATE INDEX IF NOT EXISTS idx_query_stats_version_ms + | ON query_stats(app_version, total_ms DESC) + """.trimMargin(), 0).await() + } + if (oldVersion <= 6 && newVersion > 6) { + driver.execute(null, "CREATE INDEX IF NOT EXISTS idx_blocks_page_uuid_position ON blocks(page_uuid, position)", 0).await() + driver.execute(null, "DROP INDEX IF EXISTS idx_blocks_page_uuid", 0).await() + driver.execute(null, "ANALYZE blocks", 0).await() + } + } + + override fun migrate( + driver: SqlDriver, + oldVersion: Long, + newVersion: Long, + vararg callbacks: AfterVersion, + ): QueryResult.AsyncValue = QueryResult.AsyncValue { + var lastVersion = oldVersion + + callbacks.filter { it.afterVersion in oldVersion until newVersion } + .sortedBy { it.afterVersion } + .forEach { callback -> + migrateInternal(driver, oldVersion = lastVersion, newVersion = callback.afterVersion + 1).await() + callback.block(driver) + lastVersion = callback.afterVersion + 1 + } + + if (lastVersion < newVersion) { + migrateInternal(driver, lastVersion, newVersion).await() + } + } + } +} diff --git a/kmp/src/jvmCommonMain/kotlin/BUILD.bazel b/kmp/src/jvmCommonMain/kotlin/BUILD.bazel new file mode 100644 index 00000000..26517e19 --- /dev/null +++ b/kmp/src/jvmCommonMain/kotlin/BUILD.bazel @@ -0,0 +1,22 @@ +""" +jvmCommonMain — shared JVM/Android sources (OpenTelemetry API layer). + +This source set is shared between Desktop (JVM) and Android targets. + +JVM: sources exported via kt_srcs filegroup for inclusion in the combined +jvm_main_lib compilation at //kmp/src/jvmMain/kotlin:jvm_main_lib. + +Android: sources exported via kt_srcs filegroup for inclusion in the combined +android_main compilation at //kmp/src/androidMain/kotlin:android_main. +This mirrors the JVM pattern so expect/actual resolution works under Bazel. +""" + +# ── JVM and Android flavor ──────────────────────────────────────────────────── +# Sources exported for inclusion in: +# - //kmp/src/jvmMain/kotlin:jvm_main_lib (JVM) +# - //kmp/src/androidMain/kotlin:android_main (Android) +filegroup( + name = "kt_srcs", + srcs = glob(["**/*.kt"]), + visibility = ["//kmp:__subpackages__"], +) diff --git a/kmp/src/jvmMain/kotlin/BUILD.bazel b/kmp/src/jvmMain/kotlin/BUILD.bazel new file mode 100644 index 00000000..adc0b43a --- /dev/null +++ b/kmp/src/jvmMain/kotlin/BUILD.bazel @@ -0,0 +1,120 @@ +""" +jvmMain — Desktop entry point library and runnable binary. + +jvm_main_lib compiles commonMain + jvmCommonMain + jvmMain sources in a single +compilation unit, which is required for Kotlin Multiplatform expect/actual +resolution under Bazel. Gradle does the same by combining all three source sets +into one kotlinc invocation when targeting JVM. +""" + +load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_binary", "kt_jvm_library") + +# Desktop library — all JVM sources compiled together (commonMain + jvmCommonMain + jvmMain). +# common_srcs marks the commonMain sources as KMP common (containing expect declarations). +# The compiler receives -Xcommon-sources for these files and resolves actual implementations +# from jvmCommonMain and jvmMain sources in the same compilation. +kt_jvm_library( + name = "jvm_main_lib", + srcs = [ + "//kmp/src/commonMain/kotlin:kt_srcs", + "//kmp/src/jvmCommonMain/kotlin:kt_srcs", + ] + glob( + ["**/*.kt"], + exclude = ["**/benchmarks/**"], # JMH benchmarks — Gradle-only (jmh plugin) + ), + common_srcs = ["//kmp/src/commonMain/kotlin:kt_srcs"], + kotlinc_opts = "//:kmp_jvm_kotlinc_opts", + plugins = [ + "//:compose_compiler_plugin", + "//:serialization_compiler_plugin", + ], + deps = [ + # Resources (demo-graph, icons) from commonMain/resources + "//kmp/src/commonMain/resources:common_resources", + + # SQLDelight generated code + runtime (from commonMain) + "//kmp/src/generated/sqldelight:sqldelight_generated_jvm", + "@maven//:app_cash_sqldelight_runtime_jvm", + "@maven//:app_cash_sqldelight_coroutines_extensions_jvm", + "@maven//:app_cash_sqldelight_async_extensions_jvm", + "@maven//:app_cash_sqldelight_sqlite_driver", + + # Arrow (from commonMain) + "@maven//:io_arrow_kt_arrow_core_jvm", + "@maven//:io_arrow_kt_arrow_optics_jvm", + "@maven//:io_arrow_kt_arrow_fx_coroutines_jvm", + "@maven//:io_arrow_kt_arrow_resilience_jvm", + + # Kotlinx (from commonMain) + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_core_jvm", + "@maven//:org_jetbrains_kotlinx_kotlinx_datetime_jvm", + "@maven//:org_jetbrains_kotlinx_kotlinx_serialization_json_jvm", + + # Markdown (from commonMain) + "@maven//:org_jetbrains_markdown_jvm", + + # Compose Desktop (from commonMain + jvmMain) + "@maven//:org_jetbrains_compose_runtime_runtime_desktop", + "@maven//:org_jetbrains_compose_foundation_foundation_desktop", + "@maven//:org_jetbrains_compose_material3_material3_desktop", + "@maven//:org_jetbrains_compose_material_material_icons_extended_desktop", + "@maven//:org_jetbrains_compose_components_components_resources_desktop", + "@maven//:org_jetbrains_compose_desktop_desktop_jvm_linux_x64", + + # Lifecycle (from commonMain) + "@maven//:org_jetbrains_androidx_lifecycle_lifecycle_runtime_compose", + "@maven//:org_jetbrains_androidx_lifecycle_lifecycle_viewmodel_compose", + + # Coil (from commonMain) + "@maven//:io_coil_kt_coil3_coil_compose_jvm", + "@maven//:io_coil_kt_coil3_coil_network_ktor3_jvm", + + # Ktor (from commonMain + jvmMain) + "@maven//:io_ktor_ktor_client_core_jvm", + "@maven//:io_ktor_ktor_client_content_negotiation_jvm", + "@maven//:io_ktor_ktor_serialization_kotlinx_json_jvm", + "@maven//:io_ktor_ktor_client_okhttp_jvm", + + # Ksoup (from commonMain) + "@maven//:com_fleeksoft_ksoup_ksoup_jvm", + + # Kotlin Multiplatform Diff (from commonMain) + "@maven//:io_github_petertrr_kotlin_multiplatform_diff_jvm", + + # OpenTelemetry API (from jvmCommonMain) + SDK (from jvmMain) + "@maven//:io_opentelemetry_opentelemetry_api", + "@maven//:io_opentelemetry_opentelemetry_sdk", + "@maven//:io_opentelemetry_opentelemetry_exporter_logging", + + # Kotlinx Swing dispatcher (from jvmMain) + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_swing", + + # JGit 7.x (from jvmMain) + "@maven//:org_eclipse_jgit_org_eclipse_jgit", + "@maven//:org_eclipse_jgit_org_eclipse_jgit_ssh_apache", + + # BouncyCastle (from jvmMain) + "@maven//:org_bouncycastle_bcprov_jdk18on", + + # PDFBox — PDF text extraction for asset OCR pipeline (from jvmMain) + "@maven//:org_apache_pdfbox_pdfbox", + + # Kotlin stdlib + "@maven//:org_jetbrains_kotlin_kotlin_stdlib", + ], + visibility = ["//kmp:__subpackages__"], +) + +# Desktop application binary +kt_jvm_binary( + name = "desktop_app", + main_class = "dev.stapler.stelekit.desktop.MainKt", + runtime_deps = [":jvm_main_lib"], + jvm_flags = [ + # Required for JVM attach (async-profiler + JFR) + "-Djdk.attach.allowAttachSelf=true", + # Required by Compose Desktop for reflection into java.lang + "--add-opens=java.base/java.lang=ALL-UNNAMED", + ], + visibility = ["//visibility:public"], +) diff --git a/kmp/src/jvmTest/kotlin/BUILD.bazel b/kmp/src/jvmTest/kotlin/BUILD.bazel new file mode 100644 index 00000000..c421630d --- /dev/null +++ b/kmp/src/jvmTest/kotlin/BUILD.bazel @@ -0,0 +1,61 @@ +""" +jvmTest — JVM/Desktop test suite (minus screenshot/Roborazzi tests). + +Screenshot tests (*Screenshot*.kt, ui/screenshots/**) are excluded because they +require Roborazzi which has no Bazel integration (kept in Gradle only). + +Test framework: JUnit 4 via kotlin-test-junit (run by kt_jvm_test runner). + +To run: bazel test //kmp/src/jvmTest/kotlin:jvm_tests +Or via alias: bazel test //kmp:jvm_tests +""" + +load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_test") + +kt_jvm_test( + name = "jvm_tests", + srcs = glob( + ["**/*.kt"], + exclude = [ + # Roborazzi screenshot tests — no Bazel integration; kept in Gradle + "**/*Screenshot*.kt", + "**/*Roborazzi*.kt", + "**/screenshots/**", + ], + ), + test_class = "dev.stapler.stelekit.AllJvmTests", + kotlinc_opts = "//:kmp_jvm_kotlinc_opts", + plugins = [ + "//:compose_compiler_plugin", + "//:serialization_compiler_plugin", + ], + associates = ["//kmp/src/jvmMain/kotlin:jvm_main_lib"], + deps = [ + "//kmp/src/commonMain/resources:common_resources", + "//kmp/src/commonTest/kotlin:common_test_fixtures", + "@maven//:org_jetbrains_kotlin_kotlin_test_junit", + "@maven//:org_jetbrains_compose_ui_ui_test_junit4_desktop", + "@maven//:io_ktor_ktor_client_mock_jvm", + "@maven//:io_projectreactor_tools_blockhound", + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_test_jvm", + "@maven//:org_jetbrains_kotlin_kotlin_stdlib", + ], + jvm_flags = [ + # Required for JVM attach (BlockHound, async-profiler) + "-Djdk.attach.allowAttachSelf=true", + # Required by Compose Desktop test infrastructure + "--add-opens=java.base/java.lang=ALL-UNNAMED", + # Software rendering for CI (no GPU required) + "-Djava.awt.headless=false", + ], + env = { + # Force software OpenGL for Compose Desktop tests on headless CI + "LIBGL_ALWAYS_SOFTWARE": "1", + }, + env_inherit = ["DISPLAY", "XAUTHORITY"], + visibility = ["//visibility:public"], + tags = [ + # Some tests open a Compose window — requires an X display on Linux CI + "requires-display", + ], +) diff --git a/kmp/src/jvmTest/kotlin/dev/stapler/stelekit/AllJvmTests.kt b/kmp/src/jvmTest/kotlin/dev/stapler/stelekit/AllJvmTests.kt new file mode 100644 index 00000000..9c6e9357 --- /dev/null +++ b/kmp/src/jvmTest/kotlin/dev/stapler/stelekit/AllJvmTests.kt @@ -0,0 +1,182 @@ +package dev.stapler.stelekit + +import dev.stapler.stelekit.benchmark.GraphLoadJankTest +import dev.stapler.stelekit.benchmark.GraphLoadTimingTest +import dev.stapler.stelekit.benchmark.RepositoryBenchmarkRunnerTest +import dev.stapler.stelekit.benchmark.RepositoryBenchmarkTest +import dev.stapler.stelekit.cache.CacheHitBenchmarkTest +import dev.stapler.stelekit.db.AppLoadJournalIntegrationTest +import dev.stapler.stelekit.db.BacklinkRenamerTest +import dev.stapler.stelekit.db.BlocksFtsTriggerTest +import dev.stapler.stelekit.db.ConflictMarkerDetectorTest +import dev.stapler.stelekit.db.DatabaseWriteActorTest +import dev.stapler.stelekit.db.DemoGraphIntegrationTest +import dev.stapler.stelekit.db.DiffMergeTest +import dev.stapler.stelekit.db.ExternalChangeConflictTest +import dev.stapler.stelekit.db.FileRegistryTest +import dev.stapler.stelekit.db.GraphLoaderIntegrationTest +import dev.stapler.stelekit.db.GraphLoaderProgressiveTest +import dev.stapler.stelekit.db.GraphLoaderTest +import dev.stapler.stelekit.db.GraphLoaderWatcherTest +import dev.stapler.stelekit.db.GraphWriterTest +import dev.stapler.stelekit.db.MigrationRunnerApplyAllTest +import dev.stapler.stelekit.db.PooledJdbcSqliteDriverTest +import dev.stapler.stelekit.db.QueryPlanAuditTest +import dev.stapler.stelekit.db.SanitizationTest +import dev.stapler.stelekit.docs.DemoGraphCoverageTest +import dev.stapler.stelekit.docs.FeatureDocRegistryTest +import dev.stapler.stelekit.domain.ClaudeTopicEnricherTest +import dev.stapler.stelekit.domain.UrlFetcherJvmTest +import dev.stapler.stelekit.export.ExportIntegrationTest +import dev.stapler.stelekit.export.HtmlExporterTest +import dev.stapler.stelekit.integration.JournalParseReproTest +import dev.stapler.stelekit.integration.PipelineReproductionTest +import dev.stapler.stelekit.migration.ChangeApplierTest +import dev.stapler.stelekit.migration.DagValidatorTest +import dev.stapler.stelekit.migration.DryRunTest +import dev.stapler.stelekit.migration.DslEvaluatorTest +import dev.stapler.stelekit.migration.MigrationDslTest +import dev.stapler.stelekit.migration.MigrationRegressionTest +import dev.stapler.stelekit.migration.MigrationRunnerTest +import dev.stapler.stelekit.migration.MigrationsTest +import dev.stapler.stelekit.migration.NormalizeJournalNamesMigrationTest +import dev.stapler.stelekit.migration.RepairTest +import dev.stapler.stelekit.repository.CacheInvalidationTest +import dev.stapler.stelekit.repository.ExactTitleMatchTest +import dev.stapler.stelekit.repository.FtsRebuildTest +import dev.stapler.stelekit.repository.SaveBlocksChunkingTest +import dev.stapler.stelekit.repository.SearchLatencyTest +import dev.stapler.stelekit.repository.SearchRepositoryIntegrationTests +import dev.stapler.stelekit.repository.VisitRecencyMultiplierTest +import dev.stapler.stelekit.search.FtsQueryBuilderTest +import dev.stapler.stelekit.stats.LibraryWrappedTest +import dev.stapler.stelekit.testing.OutlinerMonkeyTest +import dev.stapler.stelekit.ui.DiskConflictResolutionTest +import dev.stapler.stelekit.ui.DragDropReorderTest +import dev.stapler.stelekit.ui.KeyboardShortcutTest +import dev.stapler.stelekit.ui.MigrationReadyLoadingTest +import dev.stapler.stelekit.ui.OutlinerRegressionTest +import dev.stapler.stelekit.ui.RecentPagesTest +import dev.stapler.stelekit.ui.StelekitViewModelLoadingTest +import dev.stapler.stelekit.ui.components.ApplyAutocompleteSelectionTest +import dev.stapler.stelekit.ui.components.ParseMarkdownWithStylingTest +import dev.stapler.stelekit.ui.components.SearchDialogTest +import dev.stapler.stelekit.ui.components.SuggestionContextMenuTest +import dev.stapler.stelekit.ui.components.SuggestionNavigatorPanelTest +import dev.stapler.stelekit.ui.components.SuggestionRenderBenchmarkTest +import dev.stapler.stelekit.ui.components.TopBarTest +import dev.stapler.stelekit.ui.layout.DesktopLayoutTest +import dev.stapler.stelekit.ui.layout.MobileLayoutTest +import dev.stapler.stelekit.ui.layout.SidebarLoadingStateTest +import dev.stapler.stelekit.ui.screens.AllPagesViewModelTest +import dev.stapler.stelekit.ui.screens.JournalsViewSqlDelightTest +import dev.stapler.stelekit.ui.screens.JournalsViewUITest +import dev.stapler.stelekit.ui.screens.PageViewUITest +import dev.stapler.stelekit.vault.crypto.CryptoEngineTest +import dev.stapler.stelekit.vault.integration.GraphLayerCryptoTest +import dev.stapler.stelekit.vault.integration.VaultRoundTripTest +import dev.stapler.stelekit.vault.layer.CryptoLayerTest +import dev.stapler.stelekit.vault.perf.VaultPerformanceTest +import dev.stapler.stelekit.vault.property.VaultPropertyTest +import dev.stapler.stelekit.vault.security.AdversarialTest +import dev.stapler.stelekit.vault.security.KeyslotIntegrityTest +import dev.stapler.stelekit.vault.security.NoncePropertyTest +import dev.stapler.stelekit.vault.vault.VaultHeaderSerializerTest +import dev.stapler.stelekit.vault.vault.VaultManagerTest +import dev.stapler.stelekit.voice.ClaudeLlmFormatterProviderTest +import dev.stapler.stelekit.voice.OpenAiLlmFormatterProviderTest +import dev.stapler.stelekit.voice.WhisperSpeechToTextProviderTest +import org.junit.runner.RunWith +import org.junit.runners.Suite + +@RunWith(Suite::class) +@Suite.SuiteClasses( + GraphLoadJankTest::class, + GraphLoadTimingTest::class, + RepositoryBenchmarkRunnerTest::class, + RepositoryBenchmarkTest::class, + CacheHitBenchmarkTest::class, + DatabaseIntegrationTest::class, + AppLoadJournalIntegrationTest::class, + BacklinkRenamerTest::class, + BlocksFtsTriggerTest::class, + ConflictMarkerDetectorTest::class, + DatabaseWriteActorTest::class, + DemoGraphIntegrationTest::class, + DiffMergeTest::class, + ExternalChangeConflictTest::class, + FileRegistryTest::class, + GraphLoaderIntegrationTest::class, + GraphLoaderProgressiveTest::class, + GraphLoaderTest::class, + GraphLoaderWatcherTest::class, + GraphWriterTest::class, + MigrationRunnerApplyAllTest::class, + PooledJdbcSqliteDriverTest::class, + QueryPlanAuditTest::class, + SanitizationTest::class, + DemoGraphCoverageTest::class, + FeatureDocRegistryTest::class, + ClaudeTopicEnricherTest::class, + UrlFetcherJvmTest::class, + ExportIntegrationTest::class, + HtmlExporterTest::class, + JournalParseReproTest::class, + PipelineReproductionTest::class, + ChangeApplierTest::class, + DagValidatorTest::class, + DryRunTest::class, + DslEvaluatorTest::class, + MigrationDslTest::class, + MigrationRegressionTest::class, + MigrationRunnerTest::class, + MigrationsTest::class, + NormalizeJournalNamesMigrationTest::class, + RepairTest::class, + CacheInvalidationTest::class, + ExactTitleMatchTest::class, + FtsRebuildTest::class, + SaveBlocksChunkingTest::class, + SearchLatencyTest::class, + SearchRepositoryIntegrationTests::class, + VisitRecencyMultiplierTest::class, + FtsQueryBuilderTest::class, + LibraryWrappedTest::class, + OutlinerMonkeyTest::class, + ApplyAutocompleteSelectionTest::class, + ParseMarkdownWithStylingTest::class, + SearchDialogTest::class, + SuggestionContextMenuTest::class, + SuggestionNavigatorPanelTest::class, + SuggestionRenderBenchmarkTest::class, + TopBarTest::class, + DiskConflictResolutionTest::class, + DragDropReorderTest::class, + KeyboardShortcutTest::class, + DesktopLayoutTest::class, + MobileLayoutTest::class, + SidebarLoadingStateTest::class, + MigrationReadyLoadingTest::class, + OutlinerRegressionTest::class, + RecentPagesTest::class, + AllPagesViewModelTest::class, + JournalsViewSqlDelightTest::class, + JournalsViewUITest::class, + PageViewUITest::class, + StelekitViewModelLoadingTest::class, + CryptoEngineTest::class, + GraphLayerCryptoTest::class, + VaultRoundTripTest::class, + CryptoLayerTest::class, + VaultPerformanceTest::class, + VaultPropertyTest::class, + AdversarialTest::class, + KeyslotIntegrityTest::class, + NoncePropertyTest::class, + VaultHeaderSerializerTest::class, + VaultManagerTest::class, + ClaudeLlmFormatterProviderTest::class, + OpenAiLlmFormatterProviderTest::class, + WhisperSpeechToTextProviderTest::class, +) +class AllJvmTests diff --git a/kmp/src/jvmTest/kotlin/dev/stapler/stelekit/db/DemoGraphIntegrationTest.kt b/kmp/src/jvmTest/kotlin/dev/stapler/stelekit/db/DemoGraphIntegrationTest.kt index b73c4213..3cc801b1 100644 --- a/kmp/src/jvmTest/kotlin/dev/stapler/stelekit/db/DemoGraphIntegrationTest.kt +++ b/kmp/src/jvmTest/kotlin/dev/stapler/stelekit/db/DemoGraphIntegrationTest.kt @@ -3,12 +3,12 @@ package dev.stapler.stelekit.db import dev.stapler.stelekit.platform.PlatformFileSystem import dev.stapler.stelekit.repository.DatalogBlockRepository import dev.stapler.stelekit.repository.InMemoryPageRepository +import dev.stapler.stelekit.testing.getClasspathDirectory import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking import java.io.File import kotlin.test.Test import kotlin.test.assertTrue -import kotlin.test.fail /** * Integration tests for the bundled demo graph. Loads the demo graph from the @@ -22,9 +22,7 @@ class DemoGraphIntegrationTest { private fun loadDemoGraph(): Triple, InMemoryPageRepository, DatalogBlockRepository> = runBlocking { - val url = javaClass.classLoader.getResource("demo-graph") - ?: fail("demo-graph not found in classpath") - val graphDir = File(url.toURI()) + val graphDir = getClasspathDirectory(javaClass.classLoader, "demo-graph") val fileSystem = PlatformFileSystem() val pageRepository = InMemoryPageRepository() @@ -105,13 +103,9 @@ class DemoGraphIntegrationTest { @Test fun `demo graph has expected page count`() = runBlocking { - val pagesUrl = javaClass.classLoader.getResource("demo-graph/pages") - ?: fail("demo-graph/pages not found in classpath") - val journalsUrl = javaClass.classLoader.getResource("demo-graph/journals") - ?: fail("demo-graph/journals not found in classpath") - - val pagesDir = File(pagesUrl.toURI()) - val journalsDir = File(journalsUrl.toURI()) + val demoGraph = getClasspathDirectory(javaClass.classLoader, "demo-graph") + val pagesDir = File(demoGraph, "pages") + val journalsDir = File(demoGraph, "journals") val onDiskCount = (pagesDir.listFiles { f -> f.name.endsWith(".md") && f.name != ".gitkeep" }?.size ?: 0) + (journalsDir.listFiles { f -> f.name.endsWith(".md") && f.name != ".gitkeep" }?.size ?: 0) diff --git a/kmp/src/jvmTest/kotlin/dev/stapler/stelekit/db/GraphWriterTest.kt b/kmp/src/jvmTest/kotlin/dev/stapler/stelekit/db/GraphWriterTest.kt index b37bb810..356443b4 100644 --- a/kmp/src/jvmTest/kotlin/dev/stapler/stelekit/db/GraphWriterTest.kt +++ b/kmp/src/jvmTest/kotlin/dev/stapler/stelekit/db/GraphWriterTest.kt @@ -26,13 +26,13 @@ class GraphWriterTest { val fileSystem = PlatformFileSystem() val writer = GraphWriter(fileSystem) - // createTempDirectory inside user.home so the path falls inside JvmFileSystemBase's whitelist. val tempDir = java.nio.file.Files.createTempDirectory( - java.nio.file.Paths.get(System.getProperty("user.home")), + java.nio.file.Paths.get(System.getProperty("java.io.tmpdir")), "stelekit_test_", ).toFile() val graphPath = tempDir.absolutePath - + fileSystem.registerGraphRoot(graphPath) + val now = Clock.System.now() try { @@ -178,7 +178,7 @@ class GraphWriterTest { @Test fun `PlatformFileSystem writeFile logs exception when write fails`() { val tempDir = java.nio.file.Files.createTempDirectory( - java.nio.file.Paths.get(System.getProperty("user.home")), + java.nio.file.Paths.get(System.getProperty("java.io.tmpdir")), "stelekit_test_fs_", ).toFile() // Create a directory with the same name as the target file — forces an IOException @@ -188,6 +188,7 @@ class GraphWriterTest { try { val fileSystem = PlatformFileSystem() + fileSystem.registerGraphRoot(tempDir.absolutePath) LogManager.clearLogs() diff --git a/kmp/src/jvmTest/kotlin/dev/stapler/stelekit/docs/DemoGraphCoverageTest.kt b/kmp/src/jvmTest/kotlin/dev/stapler/stelekit/docs/DemoGraphCoverageTest.kt index c4089c35..07d22d48 100644 --- a/kmp/src/jvmTest/kotlin/dev/stapler/stelekit/docs/DemoGraphCoverageTest.kt +++ b/kmp/src/jvmTest/kotlin/dev/stapler/stelekit/docs/DemoGraphCoverageTest.kt @@ -1,17 +1,15 @@ package dev.stapler.stelekit.docs +import dev.stapler.stelekit.testing.getClasspathDirectory import dev.stapler.stelekit.ui.Screen import java.io.File import kotlin.test.Test import kotlin.test.assertTrue -import kotlin.test.fail class DemoGraphCoverageTest { private val demoGraphPagesDir: File by lazy { - val url = javaClass.classLoader.getResource("demo-graph/pages") - ?: fail("demo-graph/pages not found in classpath") - File(url.toURI()) + File(getClasspathDirectory(javaClass.classLoader, "demo-graph"), "pages") } private fun pageExists(title: String): Boolean = diff --git a/kmp/src/jvmTest/kotlin/dev/stapler/stelekit/testing/ClasspathUtils.kt b/kmp/src/jvmTest/kotlin/dev/stapler/stelekit/testing/ClasspathUtils.kt new file mode 100644 index 00000000..9cf81084 --- /dev/null +++ b/kmp/src/jvmTest/kotlin/dev/stapler/stelekit/testing/ClasspathUtils.kt @@ -0,0 +1,52 @@ +package dev.stapler.stelekit.testing + +import java.io.File +import java.net.JarURLConnection +import java.net.URL + +/** + * Resolves a classpath resource as a real File, handling both filesystem (Gradle) + * and JAR-packed (Bazel) resource layouts. + * + * In Gradle, resources are real directories on disk. In Bazel, they are packed into + * JARs. When the resource is inside a JAR, this function extracts it to a temp + * directory so tests can access it via the normal File API. + */ + +private val extractionLock = Any() + +fun getClasspathDirectory(loader: ClassLoader, resourceName: String): File { + val url: URL = loader.getResource(resourceName) + ?: error("$resourceName not found in classpath") + if (url.protocol == "file") return File(url.toURI()) + // JAR resource (Bazel packs resources into JARs): extract to temp dir. + val dest = File( + System.getenv("TEST_TMPDIR") ?: System.getProperty("java.io.tmpdir"), + resourceName.replace('/', '_'), + ) + synchronized(extractionLock) { + if (!dest.exists()) { + val tmp = File(dest.parent, dest.name + ".tmp") + tmp.deleteRecursively() + tmp.mkdirs() + try { + val conn = url.openConnection() as JarURLConnection + conn.jarFile.use { jar -> + val prefix = conn.entryName + "/" + jar.entries().asSequence() + .filter { !it.isDirectory && it.name.startsWith(prefix) } + .forEach { entry -> + val target = File(tmp, entry.name.removePrefix(prefix)) + target.parentFile?.mkdirs() + jar.getInputStream(entry).use { input -> input.copyTo(target.outputStream()) } + } + } + tmp.renameTo(dest) + } catch (e: Exception) { + tmp.deleteRecursively() + throw e + } + } + } + return dest +} diff --git a/project_plans/stelekit-bazel/decisions/ADR-001-scope-jvm-android-only.md b/project_plans/stelekit-bazel/decisions/ADR-001-scope-jvm-android-only.md new file mode 100644 index 00000000..315cb63e --- /dev/null +++ b/project_plans/stelekit-bazel/decisions/ADR-001-scope-jvm-android-only.md @@ -0,0 +1,88 @@ +# ADR-001: Scope Bazel Migration to JVM + Android Only (Phase 1) + +## Status +Accepted + +## Date +2026-05-17 + +## Context + +SteleKit targets four platforms from a single KMP codebase: Desktop (JVM), Android, iOS +(Kotlin/Native), and Web (Kotlin/WASM). The goal of the Bazel migration is faster +incremental builds and a remote-cache-backed CI pipeline. + +Two hard constraints prevent a full cross-platform Bazel migration: + +1. **No `rules_kmp` exists.** The `rules_kotlin` ruleset (v2.3.20, the current stable + release on the Bazel Central Registry) provides `kt_jvm_*` and `kt_android_*` rules + only. There are no `kt_multiplatform_*` rules, no `expect`/`actual` dispatch, and no + source-set hierarchy support. GitHub issue #567 ("Kotlin Bazel Cross-Platform Roadmap") + has been open since 2021 with no concrete implementation shipped. + +2. **iOS and WASM/JS targets cannot be compiled in Bazel.** Kotlin/Native iOS compilation + requires a macOS host and the Kotlin/Native toolchain distribution (`~/.konan/`). Bazel + forbids network downloads during sandboxed builds, and no stable Bazel ruleset can + declare the Kotlin/Native toolchain as a hermetic repository dependency. Similarly, + Kotlin/WASM has no Bazel support. `rules_kotlin`'s `kt_js_library` is limited and does + not cover the `wasm-js` target. + +3. **Compose Multiplatform K2 wiring is actively broken in Bazel.** `rules_kotlin` issue + #1388 (filed October 2025) documents that Compose BOM 2025.x + Kotlin 2.x fails to + activate the Compose compiler plugin when using `kt_compiler_plugin`. This affects + Desktop and iOS Compose targets. Jetpack Compose on Android (non-multiplatform) works + with a `suppressKotlinVersionCompatibilityCheck` workaround, but the multiplatform + variant does not. + +The JVM (Desktop) and Android source sets — `commonMain`, `jvmMain`, `androidMain` — are +pure JVM bytecode targets. They compile correctly today with `kt_jvm_library` and +`kt_android_library`. These source sets represent approximately 80% of the SteleKit +codebase by line count and are the primary targets for incremental-build improvement. + +## Decision + +Phase 1 of the Bazel migration covers **JVM and Android targets only**: +- `commonMain` compiled as `kt_jvm_library` (JVM flavor) and `kt_android_library` + (Android flavor) +- `jvmMain` compiled as `kt_jvm_library`; desktop binary as `kt_jvm_binary` +- `androidMain` compiled as `kt_android_library`; APK via `android_binary` +- `jvmTest` and `businessTest` compiled as `kt_jvm_test` +- `androidUnitTest` compiled as `android_local_test` with Robolectric + +**iOS (`iosMain`) and WASM (`wasmJsMain`) targets remain in Gradle for Phase 1.** + +Phase 2 (future, no committed timeline) will reassess iOS/WASM once a usable KMP Bazel +ruleset or JetBrains Build Tools API (KEEP-421) integration is available. + +## Consequences + +**Positive:** +- Unblocks the migration immediately using only stable, production-ready rulesets. +- The JVM and Android targets gain Bazel's incremental build graph, remote caching, and + parallel action execution. +- Reduces the blast radius of migration risk; iOS/WASM developers are not disrupted. + +**Negative:** +- CI must run two build systems in parallel: Bazel for JVM/Android, Gradle for iOS/WASM. + This increases CI complexity and job count. +- Developers must understand which targets belong to which system, creating a split mental + model. +- Gradle must be kept healthy for iOS/WASM even after JVM/Android are migrated; Gradle + cannot be retired until Phase 2 is complete. +- `commonMain` sources are compiled twice by Bazel (once per platform flavor), slightly + increasing JVM/Android build time compared to a single KMP compilation. + +## Alternatives Considered + +**Full KMP migration now**: Infeasible. No stable Bazel ruleset supports Kotlin/Native or +WASM. Custom Starlark rules for the Kotlin/Native toolchain are a multi-month engineering +effort with high maintenance burden. + +**Keep everything in Gradle**: Viable but foregoes the incremental build and remote-cache +benefits that motivated this migration. Does not address the CI speed goals in the +requirements. + +**Migrate to Buck2 instead of Bazel**: Buck2 (Meta) has stronger Kotlin incremental +compilation via KEEP-421 (announced August 2025), but shares the same fundamental gap: +no KMP Native/WASM support. Switching to Buck2 would incur the same Phase 1 scope and +add a steeper learning curve with a smaller community than Bazel. diff --git a/project_plans/stelekit-bazel/decisions/ADR-002-bzlmod-over-workspace.md b/project_plans/stelekit-bazel/decisions/ADR-002-bzlmod-over-workspace.md new file mode 100644 index 00000000..1251b154 --- /dev/null +++ b/project_plans/stelekit-bazel/decisions/ADR-002-bzlmod-over-workspace.md @@ -0,0 +1,92 @@ +# ADR-002: Use MODULE.bazel (Bzlmod) Over WORKSPACE + +## Status +Accepted + +## Date +2026-05-17 + +## Context + +Bazel supports two external-dependency management systems: + +- **WORKSPACE** (legacy): a single file at the repository root that calls repository rules + (`http_archive`, `maven_install`, etc.) to fetch external dependencies. Transitive + dependencies must be fetched manually or via `*_repositories()` macro calls, which are + opaque and conflict-prone. + +- **MODULE.bazel / Bzlmod** (current): a module-based system introduced in Bazel 5.2 and + stabilized in Bazel 6. Each Bazel module declares direct dependencies; Bazel resolves the + full transitive graph automatically via the Bazel Central Registry (BCR). + +The version trajectory is unambiguous: + +| Bazel version | WORKSPACE status | MODULE.bazel status | +|---|---|---| +| 7.x | Enabled by default (with flag) | Recommended | +| 8.x (Dec 2024 LTS) | **Disabled by default** | Default | +| 9.x (planned) | **Removed** | Only supported mode | + +All rulesets needed for Phase 1 are available on the BCR under Bzlmod: +- `rules_kotlin` v2.3.20 +- `rules_android` v0.6.6 +- `rules_jvm_external` v6.6+ (includes `maven.from_toml` for Gradle version catalog import) +- `bazel_skylib` v1.7.1 +- `robolectric` v4.14.1 + +Starting with WORKSPACE would require migrating to Bzlmod before Bazel 9 is released +anyway, making it a one-time cost that should be paid upfront. + +## Decision + +SteleKit's Bazel integration uses **`MODULE.bazel` (Bzlmod) from the first commit**. +No `WORKSPACE` file will be created. The `.bazelrc` will not set +`--noenable_bzlmod` or any flag that re-enables WORKSPACE semantics. + +The `MODULE.bazel` will declare: +```python +module(name = "stelekit", version = "0.0.0") + +bazel_dep(name = "rules_kotlin", version = "2.3.20") +bazel_dep(name = "rules_android", version = "0.6.6") +bazel_dep(name = "rules_jvm_external", version = "6.6") +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "robolectric", version = "4.14.1") +``` + +Maven dependencies will be declared via the `maven` extension from `rules_jvm_external`, +using `maven.from_toml` to import from the existing `gradle/libs.versions.toml` version +catalog where coordinates align, supplemented by inline `maven.install` calls for +Bazel-specific artifact overrides (e.g., explicit `-jvm` classifier variants for KMP +libraries). + +## Consequences + +**Positive:** +- The project is forward-compatible with Bazel 8 and 9 without any migration work. +- Transitive dependency version resolution is automatic; no manual `*_repositories()` macro + chains to maintain. +- The BCR provides checksum verification for all declared modules, improving supply-chain + security. +- `maven.from_toml` keeps Maven artifact versions in a single source of truth + (`gradle/libs.versions.toml`), shared between Gradle (Gradle builds) and Bazel (JVM/Android builds). + +**Negative:** +- Any third-party Bazel rule not yet published to the BCR cannot be referenced without a + manual `archive_override` or `git_override`, which partially reintroduces WORKSPACE-style + complexity for those rules. +- Bzlmod's stricter module graph rules (a module can only see its direct deps' repos) + occasionally require `use_repo` declarations that were implicit under WORKSPACE. This + adds verbosity when integrating less-mature rulesets. +- Team members unfamiliar with Bzlmod will need to learn its concepts (module extensions, + `use_repo`, `inject_repo`) rather than the older, more widely documented WORKSPACE + patterns. + +## Alternatives Considered + +**Start with WORKSPACE, migrate later**: Avoids Bzlmod learning curve now but guarantees a +forced migration before Bazel 9. Given that the project is starting fresh, paying the +migration cost upfront avoids a second disruption later. Rejected. + +**Use Bazel 7.x to retain WORKSPACE as default**: Pins the project to an older LTS that +will lose support before Bazel 9 ships. Creates technical debt from day one. Rejected. diff --git a/project_plans/stelekit-bazel/decisions/ADR-003-checkin-sqldelight-generated.md b/project_plans/stelekit-bazel/decisions/ADR-003-checkin-sqldelight-generated.md new file mode 100644 index 00000000..df435e14 --- /dev/null +++ b/project_plans/stelekit-bazel/decisions/ADR-003-checkin-sqldelight-generated.md @@ -0,0 +1,101 @@ +# ADR-003: Check In SQLDelight Generated Sources + +## Status +Accepted + +## Date +2026-05-17 + +## Context + +SteleKit uses SQLDelight 2.3.2 (`app.cash.sqldelight`) to generate type-safe Kotlin from +`.sq` schema files located at `kmp/src/commonMain/sqldelight/`. In a Gradle build, +SQLDelight's Gradle plugin runs automatically during compilation and emits generated Kotlin +into `kmp/build/generated/`. + +Bazel requires that all build inputs be declared in the action graph before the build runs +(hermetic, sandboxed execution). There are two problems with the current Gradle-driven +code generation: + +1. **`square/sqldelight_bazel_rules` is SQLDelight 1.x only.** The official Bazel rule + (`sqldelight_codegen`) was written against `com.squareup.sqldelight` (the 1.x Maven + group). SQLDelight 2.0 changed the group ID to `app.cash.sqldelight` — a breaking + change. The `sqldelight_bazel_rules` repository has received no substantive commits + after the 2.0 release and has no 2.x-compatible release. Using the 1.x rule against + SteleKit's 2.3.2 schema would require forking the rule and porting it, which is + significant engineering work. + +2. **SQLDelight has no standalone CLI.** The SQLDelight code generator is tightly coupled + to the Gradle plugin. A custom Bazel `genrule` invoking it would need to shell out to + Gradle, defeating the purpose of a hermetic Bazel build. The README for + `sqldelight_bazel_rules` acknowledges this: "SQLDelight doesn't presently have a CLI or + non-Gradle entry point, so the Bazel tooling provides this front-end until it can be + upgraded." + +The practical alternative is to treat generated sources as committed source files that +Bazel builds as an ordinary `kt_jvm_library`, with Gradle responsible for regenerating +them when the schema changes. + +## Decision + +SQLDelight-generated Kotlin sources will be **checked into version control** under +`kmp/src/commonMain/generated/sqldelight/` and included in the `commonMain` BUILD +target's `srcs` glob. + +**Workflow for schema changes:** +1. Developer modifies `.sq` files under `kmp/src/commonMain/sqldelight/`. +2. Developer runs `./gradlew generateCommonMainSteleDatabaseInterface` (or the equivalent + Gradle task) to regenerate the Kotlin. +3. Developer copies the output from `kmp/build/generated/` into + `kmp/src/commonMain/generated/sqldelight/` and commits both the schema change and the + generated code. + +**CI enforcement** (schema/code divergence prevention): A CI check runs +`./gradlew generateCommonMainSteleDatabaseInterface` and diffs the output against the +committed generated sources. If they differ, the check fails. This mirrors the existing +README sync check (`bash scripts/generate-readme.sh && git diff --exit-code README.md`). + +**Pre-commit hook (optional, recommended)**: A pre-commit hook can run the same diff +check to catch divergence before push. + +The `.gitignore` entry for `kmp/src/commonMain/generated/` must be removed (or the +directory must be explicitly un-ignored) so that generated sources are tracked by git. + +## Consequences + +**Positive:** +- Zero new Bazel rule complexity: the generated files are plain Kotlin source files + compiled by the existing `kt_jvm_library` / `kt_android_library` rules. +- Bazel builds are fully hermetic — no network access or Gradle subprocess invocation + during `bazel build`. +- Unblocks Phase 1 immediately without depending on a future SQLDelight 2.x Bazel rule. +- Code review sees both the `.sq` schema change and the resulting generated Kotlin in the + same PR, which is useful for reviewers. + +**Negative:** +- Generated source files live in version control, which is generally considered an + anti-pattern. The repository size grows slightly with each schema change (though + SQLDelight output is compact text). +- There is a risk of schema/generated-code divergence if a developer forgets to regenerate + after a schema change. CI enforcement mitigates but does not eliminate this risk. +- The generation step requires Gradle and a local JVM to be available on the developer's + machine even if they only use Bazel for building. This is not a new requirement (Gradle + is already required for iOS/WASM builds), but it is worth documenting. +- If SQLDelight releases a 2.x-compatible Bazel rule in the future, migrating away from + checked-in sources requires removing the generated directory, adding the Bazel rule, and + cleaning up CI. This is straightforward work but adds a future migration step. + +## Alternatives Considered + +**Fork `sqldelight_bazel_rules` and port to 2.x**: Technically possible but requires +reverse-engineering how the Gradle plugin invokes the SQLDelight compiler, writing a +hermetic Bazel wrapper, and maintaining the fork across SQLDelight releases. Estimated +effort: 2–4 weeks. Not justified for Phase 1. Revisit if SQLDelight ships an official CLI. + +**Custom `genrule` invoking the SQLDelight Gradle task**: Breaks Bazel's hermetic sandbox +model. Gradle runs Maven resolution at configure time, which violates the no-network-in-build +constraint. Rejected. + +**Run Gradle entirely for commonMain sources and only use Bazel for jvmMain/androidMain**: +Overly complex split; Bazel's incremental graph benefits are maximized when `commonMain` +is also a Bazel target. Rejected. diff --git a/project_plans/stelekit-bazel/decisions/ADR-004-buildbuddy-remote-cache.md b/project_plans/stelekit-bazel/decisions/ADR-004-buildbuddy-remote-cache.md new file mode 100644 index 00000000..c74d0330 --- /dev/null +++ b/project_plans/stelekit-bazel/decisions/ADR-004-buildbuddy-remote-cache.md @@ -0,0 +1,115 @@ +# ADR-004: Remote Cache via BuildBuddy Free Tier + +## Status +Accepted + +## Date +2026-05-17 + +## Context + +Bazel's value proposition in CI depends heavily on a shared remote cache. Without it, +every CI job starts cold and rebuilds all targets from scratch, negating incremental-build +benefits. + +Two remote-cache options are commonly evaluated for open or small-team projects: + +### GitHub Actions Cache + +GitHub Actions provides a built-in cache (`actions/cache`) with these properties: +- **10 GB total limit** shared across all branches and workflows in a repository. +- **HTTP REST API only** — not gRPC. Bazel's native remote cache protocol is gRPC; using + it with GitHub's REST cache requires wrapping with a local proxy (e.g., `bazel-remote` + running as a sidecar in the workflow) or a compatibility layer. +- **No build event visibility** — GitHub's cache is opaque; there is no UI to inspect what + was cached, hit rates, or per-target timing. +- **Branch scoping** — cache entries from a branch are not visible to other branches unless + the base branch was cached first. This means PR builds often miss the cache entirely on + the first run. +- **Cache eviction is unpredictable** — GitHub evicts entries after 7 days of inactivity + and when the 10 GB limit is reached, with no control over which entries are evicted. + +### BuildBuddy Free Tier + +BuildBuddy (buildbuddy.io) is a cloud Bazel build platform with a free tier offering: +- **Native gRPC remote cache** — Bazel connects directly via `--remote_cache=grpcs://...` + with no proxy required. +- **Build Event Protocol (BEP) viewer** — a web UI showing per-action timing, cache hit + rates, test results, and build logs, accessible at `app.buildbuddy.io`. +- **No branch scoping** — all CI jobs share the same cache namespace, so PR builds + immediately benefit from cache entries populated by `main` branch builds. +- **Larger effective cache** — the free tier does not publish a hard cache size limit + comparable to GitHub's 10 GB; in practice, BuildBuddy's cache is substantially larger + for typical project sizes. +- **Authentication via API key** — a single `BUILDBUDDY_API_KEY` GitHub secret is required. + +The free tier has no SLA and no guaranteed uptime, but cache misses are graceful: Bazel +falls back to a full local build if the remote cache is unavailable. This is an acceptable +failure mode for CI. + +## Decision + +SteleKit's Bazel CI will use **BuildBuddy free tier** for remote caching. + +The `.bazelrc` will include: + +``` +# Remote cache (BuildBuddy) +build:ci --remote_cache=grpcs://remote.buildbuddy.io +build:ci --remote_header=x-buildbuddy-api-key=${BUILDBUDDY_API_KEY} +build:ci --remote_upload_local_results=true +build:ci --bes_backend=grpcs://remote.buildbuddy.io +build:ci --bes_results_url=https://app.buildbuddy.io/invocation/ +``` + +CI workflows will pass `--config=ci` when running `bazel build` or `bazel test`. + +A `BUILDBUDDY_API_KEY` secret must be configured in the GitHub repository settings +(Settings → Secrets → Actions). The key is obtained from the BuildBuddy free-tier +dashboard at `app.buildbuddy.io`. + +Local developer builds do **not** use the remote cache by default (no `--config=ci` in +the local `.bazelrc.user` template), preventing accidental cache poisoning from +non-hermetic local environments. + +## Consequences + +**Positive:** +- Native gRPC protocol — no proxy sidecar, no extra CI step, no compatibility workarounds. +- Build Event Protocol viewer gives immediate visibility into cache hit rates and per-target + timing, making it easy to identify BUILD file changes that break caching. +- Cross-branch cache sharing means PR builds benefit from cache entries built on `main`. +- Zero cost for the project's scale; free tier is sufficient for a single-team project. + +**Negative:** +- **No SLA on the free tier.** If BuildBuddy's free cache is unavailable, CI falls back to + a full cold build (slower but not broken). Teams should not depend on the free tier for + latency-sensitive release pipelines. +- **`BUILDBUDDY_API_KEY` GitHub secret is required.** New repository forks and contributor + CI runs on forks will not have the secret and will build without the remote cache (cold + builds). This is acceptable for external contributors but means their CI runs will be + slower. +- **Dependency on a third-party service.** If BuildBuddy discontinues the free tier, + migration to an alternative (self-hosted `bazel-remote`, GitHub Actions cache with proxy, + or a paid BuildBuddy/EngFlow plan) is required. The `.bazelrc` configuration is + standardized Bazel remote-cache flags, so migration is low-friction. + +## Alternatives Considered + +**GitHub Actions cache with `bazel-remote` sidecar**: Viable but adds operational +complexity (running a sidecar service in the workflow, managing its lifecycle and port). +The 10 GB limit is likely insufficient once Bazel's action cache is populated with JVM +and Android build artifacts. The lack of a build event UI makes cache performance opaque. +Rejected in favor of BuildBuddy's simpler integration. + +**Self-hosted `bazel-remote` on a VPS**: Full control over cache size and no third-party +dependency, but requires infrastructure provisioning, maintenance, and cost. Appropriate +for larger teams; overkill for the current project scale. Rejected for Phase 1. + +**No remote cache**: Simpler setup but defeats a primary motivation for adopting Bazel in +CI. Cold builds of the JVM + Android targets are expected to take 8–15 minutes; a warm +remote cache should reduce this to 2–4 minutes. Rejected. + +**BuildBuddy paid tier / EngFlow**: Provides SLAs, remote execution, and enterprise +features. Appropriate if the project grows or if remote execution (not just caching) is +needed. Revisit in Phase 2. diff --git a/project_plans/stelekit-bazel/implementation/plan.md b/project_plans/stelekit-bazel/implementation/plan.md new file mode 100644 index 00000000..40d972cc --- /dev/null +++ b/project_plans/stelekit-bazel/implementation/plan.md @@ -0,0 +1,776 @@ +# SteleKit Bazel Migration — Implementation Plan + +_Authored: 2026-05-17_ + +--- + +## Scope + +### In Scope + +- **JVM/Desktop target**: `commonMain` (JVM flavor) + `jvmCommonMain` + `jvmMain` compiled via `kt_jvm_library` / `kt_jvm_binary` +- **Android target**: `commonMain` (Android flavor) + `jvmCommonMain` + `androidMain` compiled via `kt_android_library` / `android_binary` +- **JVM tests**: `businessTest` + `jvmTest` via `kt_jvm_test` +- **Android unit tests**: `androidUnitTest` via `android_local_test` + Robolectric +- **SQLDelight codegen**: checked-in generated sources strategy (re-generated from Gradle when `.sq` files change) +- **Compose compiler plugin**: wired via `kt_compiler_plugin` for JVM and Android targets +- **Detekt**: run as a `genrule` or standalone CI step (no Bazel caching benefit; outside the action graph) +- **Remote caching**: BuildBuddy free tier on GitHub Actions CI +- **MODULE.bazel (Bzlmod)**: mandatory; no WORKSPACE + +### Out of Scope (future epics — see section below) + +- iOS / Kotlin Native targets (`iosMain`, `iosX64`, `iosArm64`, `iosSimulatorArm64`) +- WASM/JS target (`wasmJsMain`) and all npm/webpack concerns +- Roborazzi screenshot tests (kept in Gradle) +- `kotlinx-benchmark` integration (kept in Gradle) +- Full Gradle removal (Gradle stays as a code-generator for SQLDelight and for iOS/WASM/screenshot until those phases are complete) + +--- + +## Dependency Notes (from build.gradle.kts analysis) + +Key versions to pin in Bazel: + +| Artifact | Version | +|---|---| +| Kotlin | 2.3.21 | +| Compose Multiplatform | 1.10.3 | +| SQLDelight | 2.3.2 | +| Arrow | 2.2.1.1 | +| Coroutines | 1.10.2 | +| AGP (Android Gradle Plugin) | 8.13.2 | +| Android compileSdk | 36, minSdk 26 | +| JVM target | 21 | + +The project has **no `gradle/libs.versions.toml`** — all dependency versions are declared inline in `kmp/build.gradle.kts` and `settings.gradle.kts`. The `maven.from_toml()` shortcut is therefore not applicable; artifacts must be declared inline in `MODULE.bazel`. + +--- + +## Epic 1: Bazel Scaffolding + +_Goal: A working, empty Bazel workspace that resolves Maven dependencies and has toolchains registered. No source compilation yet._ + +### Story 1.1: Bootstrap MODULE.bazel and .bazelrc + +#### Task 1.1.1: Create `MODULE.bazel` at repo root + +**File**: `MODULE.bazel` + +Content must declare: +- `module(name = "stelekit", version = "0.0.0")` +- `bazel_dep(name = "rules_kotlin", version = "2.3.20")` +- `bazel_dep(name = "rules_android", version = "0.6.6")` +- `bazel_dep(name = "rules_jvm_external", version = "6.6")` +- `bazel_dep(name = "bazel_skylib", version = "1.7.1")` +- `bazel_dep(name = "rules_java", version = "8.3.2")` +- `bazel_dep(name = "robolectric", version = "4.14.1")` +- `maven` extension with all artifacts from `commonMain`, `jvmMain`, `androidMain`, `jvmTest`, `androidUnitTest` declared explicitly with `-jvm` / `-android` classifiers where KMP variants exist (e.g., `app.cash.sqldelight:runtime-jvm:2.3.2`, `app.cash.sqldelight:android-driver:2.3.2`) +- `android_sdk_repository_extension` with `api_level = 36, build_tools_version = "35.0.0"` +- `use_repo(maven, "maven")` + +**Acceptance criterion**: `bazel mod graph` runs without error; `bazel fetch //...` resolves all Maven artifacts with no network failures. + +**Complexity**: M + +#### Task 1.1.2: Create `.bazelrc` + +**File**: `.bazelrc` + +Required flags: +``` +build --java_runtime_version=21 +build --tool_java_runtime_version=21 +build --android_sdk=@androidsdk//:sdk +build --incompatible_enable_android_toolchain_resolution + +# CI config +build:ci --remote_cache=grpcs://remote.buildbuddy.io +build:ci --remote_header=x-buildbuddy-api-key=$BUILDBUDDY_API_KEY +build:ci --noremote_upload_local_results # only seed cache from main branch pushes +build:ci --build_event_log_file=build_events.json + +# Correctness +build --sandbox_default_allow_network=false +build --incompatible_strict_action_env +``` + +**Acceptance criterion**: `bazel info` runs cleanly on a developer machine; `.bazelrc` is recognized by `bazel build //...`. + +**Complexity**: S + +#### Task 1.1.3: Create root `BUILD.bazel` with Kotlin toolchain + +**File**: `BUILD.bazel` + +Define the Kotlin toolchain: +```python +load("@rules_kotlin//kotlin:core.bzl", "define_kt_toolchain") + +define_kt_toolchain( + name = "kotlin_toolchain", + api_version = "2.1", + jvm_target = "21", + language_version = "2.1", +) +``` + +Also declare the Compose compiler plugin here (shared by all targets): +```python +load("@rules_kotlin//kotlin:core.bzl", "kt_compiler_plugin") + +kt_compiler_plugin( + name = "compose_compiler_plugin", + id = "androidx.compose.compiler.plugins.kotlin", + target_embedded_compiler = True, + visibility = ["//visibility:public"], + options = { + "suppressKotlinVersionCompatibilityCheck": "2.3.21", + "sourceInformation": "true", + }, + deps = ["@maven//:org_jetbrains_kotlin_kotlin_compose_compiler_plugin_embeddable"], +) +``` + +**Acceptance criterion**: `bazel build //:kotlin_toolchain` succeeds; toolchain is discoverable by `bazel query`. + +**Complexity**: S + +#### Task 1.1.4: Pin Maven lockfile + +**File**: `maven_install.json` (auto-generated) + +Run `bazel run @maven//:pin` after artifact list is complete to generate the lockfile. Commit it. + +**Acceptance criterion**: `maven_install.json` exists and is referenced by `MODULE.bazel` (`lock_file = "//:maven_install.json"`). A fresh `bazel build //...` after deleting `~/.cache/bazel` does not perform any Maven resolution (all artifacts served from lockfile + local cache). + +**Complexity**: S + +### Story 1.2: Resolve KMP Maven variant disambiguation + +#### Task 1.2.1: Audit all KMP dependencies for JVM/Android classifier requirements + +All KMP libraries in `commonMain` that publish platform variants need explicit classifiers. Known cases: +- `app.cash.sqldelight:runtime` → `runtime-jvm` (JVM), `android-driver` (Android) +- `io.arrow-kt:arrow-core` → check if `-jvm` suffix is needed +- `org.jetbrains.kotlinx:kotlinx-coroutines-core` → usually JVM artifact available without classifier +- `io.ktor:ktor-client-core` → check KMP variant; use `ktor-client-core-jvm` if needed +- `io.coil-kt.coil3:coil-compose` → KMP library; check variant requirements +- `io.github.petertrr:kotlin-multiplatform-diff` → likely needs `-jvm` classifier +- `com.fleeksoft.ksoup:ksoup` → check classifier + +Create a tracking table in a comment at the top of the `maven.install` block in `MODULE.bazel` documenting which classifier was chosen and why for each KMP artifact. + +**Acceptance criterion**: `bazel build @maven//:pin` completes; no "artifact not found" errors for any dependency. `rules_jvm_external` lock file resolves all artifacts to concrete JARs. + +**Complexity**: M + +--- + +## Epic 2: JVM/Desktop Target + +_Goal: `bazel build //kmp:desktop_app` produces a runnable JVM binary; `bazel run //kmp:desktop_app` launches the desktop UI._ + +### Story 2.1: Generate and check in SQLDelight sources + +#### Task 2.1.1: Run Gradle code generator and commit generated sources + +**Files**: Create directory `kmp/src/generated/sqldelight/` and populate from Gradle output. + +Steps: +1. Run `./gradlew :kmp:generateCommonMainSteleDatabase` (or the equivalent task that outputs to `kmp/build/generated/sqldelight/`) +2. Copy generated Kotlin files from `kmp/build/generated/sqldelight/commonMain/kotlin/` to `kmp/src/generated/sqldelight/` +3. Add a `.gitkeep` and update `.gitignore` to ensure the directory is tracked +4. Document the regeneration command in a `kmp/src/generated/sqldelight/README_REGEN.md` (one-liner: when to re-run, what command) + +**Acceptance criterion**: `kmp/src/generated/sqldelight/dev/stapler/stelekit/db/SteleDatabase.kt` (and peers) exist in the repo as committed source files. `git diff --stat HEAD` shows them tracked. + +**Complexity**: S + +#### Task 2.1.2: Create `kmp/src/generated/sqldelight/BUILD.bazel` + +**File**: `kmp/src/generated/sqldelight/BUILD.bazel` + +```python +load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") + +kt_jvm_library( + name = "sqldelight_generated_jvm", + srcs = glob(["**/*.kt"]), + deps = [ + "@maven//:app_cash_sqldelight_runtime_jvm", + "@maven//:app_cash_sqldelight_coroutines_extensions_jvm", + "@maven//:app_cash_sqldelight_async_extensions_jvm", + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_core_jvm", + ], + visibility = ["//kmp:__subpackages__"], +) + +load("@rules_kotlin//kotlin:android.bzl", "kt_android_library") + +kt_android_library( + name = "sqldelight_generated_android", + srcs = glob(["**/*.kt"]), + custom_package = "dev.stapler.stelekit.db", + deps = [ + "@maven//:app_cash_sqldelight_runtime_jvm", + "@maven//:app_cash_sqldelight_coroutines_extensions_jvm", + "@maven//:app_cash_sqldelight_async_extensions_jvm", + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_core_jvm", + ], + visibility = ["//kmp:__subpackages__"], +) +``` + +**Acceptance criterion**: `bazel build //kmp/src/generated/sqldelight:sqldelight_generated_jvm` succeeds. + +**Complexity**: S + +### Story 2.2: commonMain JVM library target + +#### Task 2.2.1: Create `kmp/src/commonMain/kotlin/BUILD.bazel` (JVM flavor) + +**File**: `kmp/src/commonMain/kotlin/BUILD.bazel` + +Define `kt_jvm_library(name = "common_jvm", ...)` with: +- `srcs = glob(["**/*.kt"])` +- `plugins = ["//:compose_compiler_plugin"]` +- `deps` covering all `commonMain` Maven artifacts (Arrow, coroutines, datetime, serialization, markdown, SQLDelight runtime, Compose runtime JARs, lifecycle, Coil, Ktor core, Ksoup, multiplatform-diff) +- `deps` also including `//kmp/src/generated/sqldelight:sqldelight_generated_jvm` +- `visibility = ["//kmp:__subpackages__"]` + +Note: `compose.runtime`, `compose.foundation`, `compose.material3`, `compose.materialIconsExtended`, `compose.components.resources` must map to concrete Maven coordinates for Compose Multiplatform 1.10.3 JVM artifacts. These must be declared in `maven.install`. + +**Acceptance criterion**: `bazel build //kmp/src/commonMain/kotlin:common_jvm` succeeds (zero compilation errors). + +**Complexity**: L + +#### Task 2.2.2: Create `kmp/src/jvmCommonMain/kotlin/BUILD.bazel` + +**File**: `kmp/src/jvmCommonMain/kotlin/BUILD.bazel` + +Define `kt_jvm_library(name = "jvm_common_main", ...)` with: +- `deps = ["//kmp/src/commonMain/kotlin:common_jvm", "@maven//:io_opentelemetry_opentelemetry_api"]` + +**Acceptance criterion**: `bazel build //kmp/src/jvmCommonMain/kotlin:jvm_common_main` succeeds. + +**Complexity**: S + +### Story 2.3: jvmMain binary target + +#### Task 2.3.1: Create `kmp/src/jvmMain/kotlin/BUILD.bazel` + +**File**: `kmp/src/jvmMain/kotlin/BUILD.bazel` + +Define: +```python +kt_jvm_library( + name = "jvm_main_lib", + srcs = glob(["**/*.kt"]), + plugins = ["//:compose_compiler_plugin"], + deps = [ + "//kmp/src/jvmCommonMain/kotlin:jvm_common_main", + "@maven//:app_cash_sqldelight_sqlite_driver", + "@maven//:org_jetbrains_compose_desktop_currentOs", # Compose Desktop + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_swing", + "@maven//:org_eclipse_jgit_org_eclipse_jgit", # JGit 7.x + "@maven//:org_eclipse_jgit_org_eclipse_jgit_ssh_apache", + "@maven//:io_opentelemetry_opentelemetry_sdk", + "@maven//:io_opentelemetry_opentelemetry_exporter_logging", + "@maven//:org_bouncycastle_bcprov_jdk18on", + "@maven//:io_ktor_ktor_client_okhttp_jvm", + ], + visibility = ["//kmp:__subpackages__"], +) + +kt_jvm_binary( + name = "desktop_app", + main_class = "dev.stapler.stelekit.desktop.MainKt", + runtime_deps = [":jvm_main_lib"], + jvm_flags = [ + "-Djdk.attach.allowAttachSelf=true", + "--add-opens=java.base/java.lang=ALL-UNNAMED", + ], + visibility = ["//visibility:public"], +) +``` + +Also add a `skiko` version-pinning mechanism. In `MODULE.bazel`, add `override_target` or `exclusion` rules for Skiko AWT runtime variants to force `0.9.37.4` (matching Gradle's `resolutionStrategy.force`). Document the exact Bazel equivalent approach (likely `artifact()` with explicit version in `maven.install` with `override_targets`). + +**Acceptance criterion**: `bazel run //kmp/src/jvmMain/kotlin:desktop_app` launches the SteleKit desktop application. App window appears. + +**Complexity**: L + +#### Task 2.3.2: Add top-level aliases to `kmp/BUILD.bazel` + +**File**: `kmp/BUILD.bazel` + +```python +alias(name = "desktop_app", actual = "//kmp/src/jvmMain/kotlin:desktop_app", visibility = ["//visibility:public"]) +``` + +Developer command becomes: `bazel run //kmp:desktop_app` + +**Acceptance criterion**: `bazel run //kmp:desktop_app` works as an alias. + +**Complexity**: S + +--- + +## Epic 3: Android Target + +_Goal: `bazel build //kmp:android_app` produces a valid debug APK; `bazel mobile-install //kmp:android_app` installs on a connected device._ + +### Story 3.1: commonMain Android library target + +#### Task 3.1.1: Create `kt_android_library` target in `kmp/src/commonMain/kotlin/BUILD.bazel` + +**File**: `kmp/src/commonMain/kotlin/BUILD.bazel` (add to existing file from Task 2.2.1) + +Define `kt_android_library(name = "common_android", ...)` with: +- Same `srcs` glob as `common_jvm` +- `plugins = ["//:compose_compiler_plugin"]` +- `custom_package = "dev.stapler.stelekit"` +- `manifest = "//kmp:AndroidManifest.xml"` (or `//androidApp:AndroidManifest.xml`) +- `deps` using Android-specific Maven coordinates (Jetpack Compose, AndroidX, etc.) +- `deps` including `//kmp/src/generated/sqldelight:sqldelight_generated_android` + +**Acceptance criterion**: `bazel build //kmp/src/commonMain/kotlin:common_android` succeeds. + +**Complexity**: L + +### Story 3.2: jvmCommonMain Android flavor + +#### Task 3.2.1: Add `kt_android_library` to `kmp/src/jvmCommonMain/kotlin/BUILD.bazel` + +**File**: `kmp/src/jvmCommonMain/kotlin/BUILD.bazel` (add to existing file from Task 2.2.2) + +```python +kt_android_library( + name = "jvm_common_main_android", + srcs = glob(["**/*.kt"]), + deps = [ + "//kmp/src/commonMain/kotlin:common_android", + "@maven//:io_opentelemetry_opentelemetry_api", + ], + custom_package = "dev.stapler.stelekit", + visibility = ["//kmp:__subpackages__"], +) +``` + +**Acceptance criterion**: `bazel build //kmp/src/jvmCommonMain/kotlin:jvm_common_main_android` succeeds. + +**Complexity**: S + +### Story 3.3: androidMain library and app binary + +#### Task 3.3.1: Create `kmp/src/androidMain/kotlin/BUILD.bazel` + +**File**: `kmp/src/androidMain/kotlin/BUILD.bazel` + +Define `kt_android_library(name = "android_main", ...)` with: +- `srcs = glob(["**/*.kt"])` +- `plugins = ["//:compose_compiler_plugin"]` +- `deps` including `jvm_common_main_android`, all `androidMain` Maven artifacts (AndroidX Activity, AppCompat, Core KTX, coroutines-android, SQLDelight android-driver, sqlite-android, Ktor OkHttp, DocumentFile, Jetpack Compose UI/Material3, OpenTelemetry SDK, JankStats, security-crypto, mlkit-genai, Glance, WorkManager, JGit 5.13.x, jsch) +- `custom_package = "dev.stapler.stelekit"` + +**Acceptance criterion**: `bazel build //kmp/src/androidMain/kotlin:android_main` succeeds. + +**Complexity**: L + +#### Task 3.3.2: Create `androidApp/BUILD.bazel` with `android_binary` + +**File**: `androidApp/BUILD.bazel` + +```python +load("@rules_android//rules:rules.bzl", "android_binary") + +android_binary( + name = "android_app", + manifest = "src/main/AndroidManifest.xml", + custom_package = "dev.stapler.stelekit.android", + deps = ["//kmp/src/androidMain/kotlin:android_main"], + multidex = "native", + # Core library desugaring + desugar_java8_libs = True, + visibility = ["//visibility:public"], +) +``` + +Wire `coreLibraryDesugaring` via `desugar_java8_libs` or equivalent `rules_android` mechanism. Declare `com.android.tools:desugar_jdk_libs:2.1.4` in `maven.install`. + +Note: `packaging { resources { excludes += "plugin.properties" } }` must be replicated as a resource strip rule or `nocompress_extensions` attribute. + +**Acceptance criterion**: `bazel build //androidApp:android_app` produces an APK. `bazel mobile-install //androidApp:android_app` installs on a connected Android 8+ device. + +**Complexity**: L + +#### Task 3.3.3: Add top-level alias for Android app + +**File**: `kmp/BUILD.bazel` + +```python +alias(name = "android_app", actual = "//androidApp:android_app", visibility = ["//visibility:public"]) +``` + +**Acceptance criterion**: `bazel build //kmp:android_app` works. + +**Complexity**: S + +--- + +## Epic 4: Test Targets + +_Goal: `bazel test //...` runs all JVM and Android unit tests. All existing `./gradlew jvmTest` tests pass._ + +### Story 4.1: businessTest library + +#### Task 4.1.1: Create `kmp/src/businessTest/kotlin/BUILD.bazel` + +**File**: `kmp/src/businessTest/kotlin/BUILD.bazel` + +```python +kt_jvm_library( + name = "business_tests", + srcs = glob(["**/*.kt"]), + testonly = True, + deps = [ + "//kmp/src/commonMain/kotlin:common_jvm", + "@maven//:org_jetbrains_kotlin_kotlin_test_junit", + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_test_jvm", + "@maven//:org_jetbrains_kotlinx_kotlinx_serialization_json_jvm", + ], + visibility = ["//kmp:__subpackages__"], +) +``` + +**Acceptance criterion**: `bazel build //kmp/src/businessTest/kotlin:business_tests` succeeds. + +**Complexity**: S + +### Story 4.2: jvmTest target + +#### Task 4.2.1: Create `kmp/src/jvmTest/kotlin/BUILD.bazel` + +**File**: `kmp/src/jvmTest/kotlin/BUILD.bazel` + +```python +kt_jvm_test( + name = "jvm_tests", + srcs = glob(["**/*.kt"], exclude = ["**/*Screenshot*", "**/*Roborazzi*"]), + test_class = "dev.stapler.stelekit.JvmTestSuite", # adjust to actual suite class or use junit runner + deps = [ + "//kmp/src/jvmMain/kotlin:jvm_main_lib", + "//kmp/src/businessTest/kotlin:business_tests", + "@maven//:org_jetbrains_kotlin_kotlin_test_junit", + "@maven//:org_jetbrains_compose_desktop_ui_test_junit4", + "@maven//:io_ktor_ktor_client_mock_jvm", + "@maven//:io_projectreactor_tools_blockhound", + ], + jvm_flags = [ + "-Djdk.attach.allowAttachSelf=true", + "--add-opens=java.base/java.lang=ALL-UNNAMED", + "-Djava.awt.headless=false", + ], + env = { + "LIBGL_ALWAYS_SOFTWARE": "1", + }, + visibility = ["//visibility:public"], + tags = ["requires-display"], # some tests need display server +) +``` + +Roborazzi screenshot tests (`**/*Screenshot*`, `**/*Roborazzi*`) are excluded via glob `exclude` — they remain Gradle-only. + +**Acceptance criterion**: `bazel test //kmp/src/jvmTest/kotlin:jvm_tests` runs; all non-screenshot tests pass. Test count matches `./gradlew jvmTest` minus screenshot tests. + +**Complexity**: M + +#### Task 4.2.2: Add top-level test alias + +**File**: `kmp/BUILD.bazel` + +```python +alias(name = "jvm_tests", actual = "//kmp/src/jvmTest/kotlin:jvm_tests", visibility = ["//visibility:public"]) +``` + +Developer command: `bazel test //kmp:jvm_tests` + +**Acceptance criterion**: `bazel test //kmp:jvm_tests` passes. + +**Complexity**: S + +### Story 4.3: Android unit tests (Robolectric) + +#### Task 4.3.1: Create `kmp/src/androidUnitTest/kotlin/BUILD.bazel` + +**File**: `kmp/src/androidUnitTest/kotlin/BUILD.bazel` + +```python +load("@rules_android//rules:rules.bzl", "android_local_test") +load("@rules_kotlin//kotlin:android.bzl", "kt_android_library") + +kt_android_library( + name = "android_unit_test_lib", + srcs = glob(["**/*.kt"]), + custom_package = "dev.stapler.stelekit", + testonly = True, + deps = [ + "//kmp/src/androidMain/kotlin:android_main", + "@maven//:junit_junit", + "@maven//:org_robolectric_robolectric", + "@maven//:androidx_test_core", + "@maven//:androidx_test_ext_junit", + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_test_jvm", + "@maven//:androidx_arch_core_core_testing", + "@maven//:androidx_glance_glance_appwidget_testing", + ], +) + +android_local_test( + name = "android_unit_tests", + manifest = "//androidApp:src/main/AndroidManifest.xml", + deps = [ + ":android_unit_test_lib", + "@robolectric//bazel:android-all", + "@maven//:org_robolectric_robolectric", + ], + visibility = ["//visibility:public"], +) +``` + +Note: Roborazzi Android screenshot tests (`roborazzi`, `roborazzi-compose`) are declared as deps but the screenshot test classes themselves are excluded via a glob or `tags = ["manual"]`. + +**Acceptance criterion**: `bazel test //kmp/src/androidUnitTest/kotlin:android_unit_tests` passes. Test count matches `./gradlew testDebugUnitTest` minus screenshot tests. + +**Complexity**: M + +--- + +## Epic 5: CI Integration and Remote Caching + +_Goal: GitHub Actions CI runs `bazel test //...` instead of `./gradlew ciCheck`. Remote cache seeded from main-branch builds. CI green._ + +### Story 5.1: GitHub Actions workflow + +#### Task 5.1.1: Create `.github/workflows/bazel-ci.yml` + +**File**: `.github/workflows/bazel-ci.yml` + +Jobs: +- `bazel-jvm`: `bazel test //kmp:jvm_tests --config=ci` on `ubuntu-latest` with xvfb-run for display-requiring tests +- `bazel-android`: `bazel build //kmp:android_app --config=ci` on `ubuntu-latest` +- `bazel-android-tests`: `bazel test //kmp/src/androidUnitTest/kotlin:android_unit_tests --config=ci` on `ubuntu-latest` + +Each job: +1. Installs Bazel via `bazel-contrib/setup-bazel` action +2. Sets `BUILDBUDDY_API_KEY` from GitHub Secrets +3. Caches `~/.cache/bazel` using `actions/cache` keyed on `hashFiles('MODULE.bazel', 'maven_install.json')` + +Maintain existing Gradle jobs (`gradle-jvm`, `gradle-android`, `detekt`) in parallel during transition. They run the screenshot tests and Roborazzi checks that remain Gradle-only. + +**Acceptance criterion**: Bazel CI jobs pass on a PR. Build event stream visible in BuildBuddy dashboard. + +**Complexity**: M + +#### Task 5.1.2: Register BuildBuddy and configure remote cache seeding + +**File**: `.bazelrc` (update from Task 1.1.2) + +Add: +``` +# Only upload cache results from main branch (not PRs, to avoid cache poisoning) +build:ci-main --remote_upload_local_results +build:ci-pr --noremote_upload_local_results +``` + +In `bazel-ci.yml`: +- Main branch pushes use `--config=ci --config=ci-main` +- PR builds use `--config=ci --config=ci-pr` + +**Acceptance criterion**: After a main-branch push, a subsequent PR build shows >50% remote cache hit rate in BuildBuddy dashboard for the incremental build scenario. + +**Complexity**: S + +#### Task 5.1.3: Add `bazel-diff` for affected-target detection (optional / stretch) + +**File**: `.github/workflows/bazel-ci.yml` (update) + +Add a pre-step that runs `bazel-diff` to compute affected targets between PR HEAD and merge base. Pass the affected set to `bazel test` instead of `//...`. + +**Acceptance criterion**: PRs that touch only `androidMain` sources skip `//kmp:jvm_tests` entirely. CI wall-clock time drops measurably. + +**Complexity**: M + +### Story 5.2: Developer documentation + +#### Task 5.2.1: Update `CLAUDE.md` with Bazel command equivalents + +**File**: `CLAUDE.md` + +Add a "Bazel Build Commands" section alongside the existing Gradle section: + +| Gradle | Bazel | +|--------|-------| +| `./gradlew run` | `bazel run //kmp:desktop_app` | +| `./gradlew jvmTest` | `bazel test //kmp:jvm_tests` | +| `./gradlew allTests` | `bazel test //...` | +| `./gradlew ciCheck` | `bazel test //... --config=ci` | +| `./gradlew installAndroid` | `bazel mobile-install //kmp:android_app` | +| `./gradlew packageDistributionForCurrentOS` | (Gradle only — see Epic 6) | + +**Acceptance criterion**: Docs reflect accurate commands. A new developer can run the app using only Bazel after following the README. + +**Complexity**: S + +--- + +## Epic 6: Detekt and Linting Integration + +_Goal: Detekt runs in CI without Gradle. `bazel test //...:detekt` enforces style._ + +### Story 6.1: Detekt as a Bazel genrule + +#### Task 6.1.1: Add Detekt as a `sh_binary` / `genrule` Bazel target + +**File**: `kmp/BUILD.bazel` (add to existing) + +Detekt has no official Bazel rule. Two options: + +**Option A (simpler)**: Keep Detekt as a standalone CI step that invokes the Detekt CLI JAR directly via `java -jar` — not a Bazel target. Add it as a separate GitHub Actions job step that runs after `bazel build`. + +**Option B (Bazel-native)**: Declare a `genrule` that downloads the Detekt CLI JAR (via `rules_jvm_external`) and runs it against source directories. Mark it `tags = ["manual"]` so it doesn't run in `//...`. + +Recommendation: Option A for initial migration (simpler, no caching loss for a fast linter step). Option B if Detekt becomes a bottleneck. + +**Acceptance criterion**: Detekt runs in CI and blocks merges on linting failures. The custom buildSrc ruleset (`buildSrc.jar`) is still invoked. + +**Complexity**: M + +--- + +## Epic 7: Gradle Removal + +_Goal: No `gradlew`, `build.gradle.kts`, or `settings.gradle.kts` remain in the repository. All functionality is handled by Bazel or has been intentionally deferred._ + +**Prerequisite**: Epics 1–6 are complete and CI is fully green on Bazel. iOS and WASM targets have been either migrated or formally deferred to a separate track. + +### Story 7.1: Audit remaining Gradle-only functionality + +#### Task 7.1.1: Inventory all Gradle tasks not yet in Bazel + +**Files**: `kmp/build.gradle.kts`, `settings.gradle.kts`, `androidApp/build.gradle.kts`, `macrobenchmark/build.gradle.kts` + +Produce a checklist of: +- `packageDistributionForCurrentOS` (Compose Desktop packaging) → needs `rules_pkg` or stays external +- `jvmTestProfile` (JFR profiling task) → express as a `sh_binary` wrapper around `bazel run` +- `graphStats` (library stats test) → migrate to Bazel test target with `tags = ["manual"]` +- `jvmBenchmark` (kotlinx-benchmark) → no Bazel equivalent; document as manually run via Gradle +- Screenshot test tasks → remain Gradle for now; document in CLAUDE.md + +**Acceptance criterion**: Checklist exists with disposition (Bazel, manual script, or deferred) for each Gradle task. + +**Complexity**: S + +#### Task 7.1.2: Migrate `packageDistributionForCurrentOS` to `rules_pkg` + +**Files**: `kmp/BUILD.bazel` (add `pkg_zip` or `pkg_deb` targets) + +Use `rules_pkg` to package the JVM binary into platform-specific distributions. This partially replaces the Compose Desktop packaging but does not produce `.dmg`/`.msi` installers — those require platform-specific tooling. + +Alternatively: create a `sh_binary` wrapper that invokes the Bazel-built `desktop_app` JAR with `jpackage` for native installers. + +**Acceptance criterion**: `bazel build //kmp:desktop_dist` produces a `.deb` on Linux and a `.tar.gz` on macOS with the app binary and JVM bundled. + +**Complexity**: L + +#### Task 7.1.3: Remove Gradle files + +**Files to delete**: +- `gradlew`, `gradlew.bat`, `gradle/` directory (wrapper) +- `settings.gradle.kts` +- `kmp/build.gradle.kts` +- `androidApp/build.gradle.kts` +- `macrobenchmark/build.gradle.kts` +- `tools/flamegraph/build.gradle.kts` +- `buildSrc/` (custom Detekt rules — migrate to a `kt_jvm_library` Bazel target or standalone JAR) +- `gradle.properties` + +**Acceptance criterion**: `find . -name "*.gradle.kts"` returns zero results. `find . -name "gradlew"` returns zero results. `bazel build //...` still passes. + +**Complexity**: M + +--- + +## Out of Scope (Future Epics) + +### Future Epic A: iOS / Kotlin Native Migration + +Blocked on `rules_kotlin` adding Kotlin/Native support (tracked in rules_kotlin issue #567). No ETA as of May 2026. Requires: +- Custom Kotlin/Native toolchain declaration (pre-fetched `~/.konan/` compiler distribution as `http_archive`) +- `rules_apple` / `rules_ios` for `.framework` / `.xcframework` bundling +- macOS-only CI runner for final binary production +- SQLDelight native driver (`app.cash.sqldelight:native-driver`) Bazel compilation + +### Future Epic B: WASM/JS Migration + +Blocked on `rules_kotlin` Kotlin/WASM support (none exists as of May 2026). Requires: +- WASM toolchain integration +- `npm` dependency resolution (currently via yarn/webpack in Gradle) +- sqlite-wasm OPFS runtime packaging + +### Future Epic C: Roborazzi Screenshot Tests in Bazel + +Blocked on Roborazzi Bazel support. Requires manual wiring of Compose UI test infrastructure for `android_local_test`. No community examples exist. + +### Future Epic D: kotlinx-benchmark in Bazel + +JMH / kotlinx-benchmark has no Bazel rule. Would require a custom `genrule` that invokes the benchmark runner JAR. Low priority — benchmarks run infrequently. + +--- + +## ADR Candidates + +The following decisions should be documented as Architecture Decision Records before or during implementation: + +| # | Decision | Why It Needs an ADR | +|---|----------|---------------------| +| ADR-001 | SQLDelight: checked-in generated sources vs custom `sqldelight_codegen` rule | Checked-in sources are pragmatic but create a schema/code drift risk; the trade-off should be explicit and the regeneration process formally documented | +| ADR-002 | KMP scope: JVM + Android only in Bazel (iOS and WASM remain Gradle) | Deviates from the original G1 requirement ("all KMP targets"); stakeholder alignment required | +| ADR-003 | Remote caching: BuildBuddy free tier vs bazel-github-actions-cache | BuildBuddy requires an external account and API key; `bazel-github-actions-cache` uses GHA-native storage but hits a 10 GB cap. Cost/risk trade-off. | +| ADR-004 | Compose compiler plugin K2 wiring: `kt_compiler_plugin` + `suppressKotlinVersionCompatibilityCheck` | Active open bug (rules_kotlin #1388) means this workaround may break on Compose BOM upgrades. Document the known risk and the version pins required. | +| ADR-005 | `commonMain` compiled twice (JVM + Android flavors) vs single-flavor approach | Duplicating compile work has a real cost. The decision to use two separate targets vs. flattening should be explicit. | +| ADR-006 | Gradle removal timing: parallel vs immediate | Keeping Gradle for iOS/WASM/screenshots means two build systems co-exist indefinitely. Define the condition under which Gradle is removed. | + +--- + +## Summary + +| Metric | Count | +|---|---| +| Epics | 7 (5 in-scope + 2 support) | +| Stories | 14 | +| Tasks | 27 | +| ADRs flagged | 6 | + +### Epic Summary + +| Epic | Goal | Complexity | Blocking? | +|---|---|---|---| +| 1: Bazel Scaffolding | MODULE.bazel, toolchains, Maven resolution | M | All others | +| 2: JVM/Desktop Target | `bazel run //kmp:desktop_app` working | L | Epic 4 (jvmTest) | +| 3: Android Target | `bazel build //kmp:android_app` working | L | Epic 4 (android tests) | +| 4: Test Targets | All non-screenshot tests pass under Bazel | M | Epic 5 (CI) | +| 5: CI Integration | GitHub Actions green on Bazel | M | Epic 7 | +| 6: Detekt / Linting | Linting in CI without Gradle | S | Epic 7 | +| 7: Gradle Removal | No `gradlew` in repo | L | Epics 1–6 complete | + +### Recommended sequencing + +1. Epic 1 (scaffolding) — unblocks everything +2. Epic 2 story 2.1 (SQLDelight gen) — low risk, needed by both JVM and Android +3. Epic 2 stories 2.2–2.3 and Epic 3 in parallel — JVM and Android can be developed concurrently +4. Epic 4 (tests) — depends on Epics 2 and 3 +5. Epic 6 (Detekt) — can proceed in parallel with Epics 2–4 +6. Epic 5 (CI) — after Epics 2–4 pass locally +7. Epic 7 (Gradle removal) — last step, after CI is confirmed green diff --git a/project_plans/stelekit-bazel/implementation/validation.md b/project_plans/stelekit-bazel/implementation/validation.md new file mode 100644 index 00000000..71cca1c3 --- /dev/null +++ b/project_plans/stelekit-bazel/implementation/validation.md @@ -0,0 +1,346 @@ +# Validation Plan: stelekit-bazel + +**Date**: 2026-05-17 + +--- + +## Overview + +This document maps every requirement from `requirements.md` to concrete test cases. Tests are organized into four categories: Build Validation, Test Migration, Correctness, and CI Integration. Each test carries a unique ID, the requirement(s) it covers, the pass criterion, and whether it is automated or manual. + +--- + +## Requirement → Test Mapping + +| Requirement | Test ID | Test Name | Type | Scenario | +|---|---|---|---|---| +| G1: All KMP targets build | BV-01 | `bazel build //kmp:desktop_app` succeeds on clean checkout | Build | Happy path — JVM/Desktop | +| G1: All KMP targets build | BV-02 | `bazel build //kmp:android_app` succeeds on clean checkout | Build | Happy path — Android APK | +| G1: All KMP targets build | BV-03 | `bazel build //kmp:desktop_app` fails with informative error when Kotlin toolchain missing | Build | Error path — misconfigured toolchain | +| G1: All KMP targets build | BV-04 | `bazel build //kmp/src/generated/sqldelight:sqldelight_generated_jvm` succeeds | Build | SQLDelight generated sources visible to Bazel | +| G2: Full Gradle replacement | CV-01 | `find . -name "*.gradle.kts"` returns zero results after Epic 7 | Correctness | Happy path — Gradle files removed | +| G2: Full Gradle replacement | CV-02 | `find . -name "gradlew"` returns zero results after Epic 7 | Correctness | Happy path — wrapper removed | +| G2: Full Gradle replacement | CV-03 | `bazel build //...` passes with no Gradle fallback step in CI after Epic 7 | Correctness | Error path — no hidden Gradle dependency | +| G3: Incremental builds < 5s | BV-05 | Touch single `.kt` file; measure `bazel build //kmp:desktop_app` wall time | Build | Happy path — incremental rebuild | +| G3: Incremental builds < 5s | BV-06 | Touch multiple `.kt` files in unrelated package; verify only affected actions re-run | Build | Happy path — action graph correctness | +| G3: Incremental builds < 5s | BV-07 | Touch a `.kt` file in `androidMain`; verify `//kmp:desktop_app` action graph is unaffected | Build | Error path — no cross-target invalidation | +| G4: Remote caching via GHA | CI-01 | Second CI run on identical commit shows >50% cache hit rate in BuildBuddy dashboard | CI | Happy path — remote cache hit | +| G4: Remote caching via GHA | CI-02 | PR build with `--noremote_upload_local_results` does not poison main-branch cache | CI | Error path — cache isolation | +| G4: Remote caching via GHA | CI-03 | `maven_install.json` lock file present; `bazel build //...` succeeds without network after cold start | Build | Happy path — hermetic Maven resolution | +| G5: CI passes on Bazel | CI-04 | `bazel-ci.yml` `bazel-jvm` job passes on PR push | CI | Happy path — JVM CI job green | +| G5: CI passes on Bazel | CI-05 | `bazel-ci.yml` `bazel-android` job passes on PR push | CI | Happy path — Android CI job green | +| G5: CI passes on Bazel | CI-06 | `bazel-ci.yml` `bazel-android-tests` job passes on PR push | CI | Happy path — Android unit test CI job green | +| G5: CI passes on Bazel | CI-07 | Detekt CI job still runs and blocks merge on linting failures | CI | Error path — lint gate enforced | +| G5: CI passes on Bazel | CI-08 | Existing Gradle screenshot/Roborazzi CI jobs still pass (no regression) | CI | Error path — no Gradle regression | +| G6: Developer experience | BV-08 | `bazel run //kmp:desktop_app` launches the application window | Build | Happy path — run alias works | +| G6: Developer experience | TM-01 | `bazel test //kmp:jvm_tests` runs and all non-screenshot tests pass | Test Migration | Happy path — jvmTest suite | +| G6: Developer experience | TM-02 | `bazel test //kmp:business_tests` (or `//kmp/src/businessTest/kotlin:business_tests`) passes | Test Migration | Happy path — businessTest suite | +| G6: Developer experience | TM-03 | `bazel test //kmp/src/androidUnitTest/kotlin:android_unit_tests` passes | Test Migration | Happy path — Android unit tests | +| G6: Developer experience | TM-04 | `bazel mobile-install //kmp:android_app` installs APK on a connected device | Test Migration | Happy path — install alias | + +--- + +## Test Cases — Detailed Specifications + +### Category 1: Build Validation (BV) + +#### BV-01: Clean JVM/Desktop build +- **ID**: BV-01 +- **Description**: From a clean workspace with no prior Bazel output, `bazel build //kmp:desktop_app` (or equivalent alias) completes without error and produces a runnable JAR/binary. +- **Requirements covered**: G1, G6 +- **Pass criteria**: Exit code 0; output artifact exists at `bazel-bin/kmp/src/jvmMain/kotlin/desktop_app`. +- **Automated/Manual**: Automated (CI job `bazel-jvm`) +- **Test command**: `bazel clean --expunge && bazel build //kmp:desktop_app` +- **Epic**: 2 (Story 2.3, Task 2.3.1) + +#### BV-02: Clean Android build +- **ID**: BV-02 +- **Description**: From a clean workspace, `bazel build //kmp:android_app` completes without error and produces a valid debug APK. +- **Requirements covered**: G1, G6 +- **Pass criteria**: Exit code 0; `bazel-bin/androidApp/android_app.apk` exists and is a valid ZIP with `classes.dex`. +- **Automated/Manual**: Automated (CI job `bazel-android`) +- **Test command**: `bazel clean --expunge && bazel build //kmp:android_app` +- **Epic**: 3 (Story 3.3, Task 3.3.2) + +#### BV-03: Toolchain misconfiguration error path +- **ID**: BV-03 +- **Description**: If `MODULE.bazel` references a non-existent Kotlin toolchain version, `bazel build //kmp:desktop_app` fails with a clear, actionable error message (not a cryptic Starlark traceback). +- **Requirements covered**: G1 +- **Pass criteria**: Exit code non-zero; error message references toolchain or `rules_kotlin` module, not an internal Bazel crash. +- **Automated/Manual**: Manual (one-time verification during scaffolding) +- **Epic**: 1 (Story 1.1, Task 1.1.3) + +#### BV-04: SQLDelight generated sources compile +- **ID**: BV-04 +- **Description**: `bazel build //kmp/src/generated/sqldelight:sqldelight_generated_jvm` and `:sqldelight_generated_android` succeed, confirming checked-in generated sources are recognized by Bazel. +- **Requirements covered**: G1 +- **Pass criteria**: Exit code 0 for both targets; no "unresolved reference" errors in downstream builds. +- **Automated/Manual**: Automated (included in `bazel build //...`) +- **Test command**: `bazel build //kmp/src/generated/sqldelight:sqldelight_generated_jvm //kmp/src/generated/sqldelight:sqldelight_generated_android` +- **Epic**: 2 (Story 2.1, Task 2.1.2) + +#### BV-05: Incremental rebuild < 5s after single file change +- **ID**: BV-05 +- **Description**: After a successful cold build, touch a single `.kt` file in `commonMain` and re-run `bazel build //kmp:desktop_app`. The wall-clock time must be under 5 seconds. +- **Requirements covered**: G3 +- **Pass criteria**: `time bazel build //kmp:desktop_app` reports real elapsed time < 5s on developer machine (Linux or macOS, 8+ cores). Must also be < 5s on the CI runner. +- **Automated/Manual**: Manual (benchmarked once per major Bazel rule version upgrade; optionally automated via a timing script in CI) +- **Measurement script**: `touch kmp/src/commonMain/kotlin/dev/stapler/stelekit/model/Models.kt && time bazel build //kmp:desktop_app` +- **Epic**: Spans Epics 1–2 + +#### BV-06: Action-graph correctness — only affected actions re-run +- **ID**: BV-06 +- **Description**: After touching a file in `commonMain`, `bazel build //kmp:desktop_app --explain=/tmp/bazel_explain.txt` shows that only the affected `KotlinCompile` action and its dependents are re-executed, not the full graph. +- **Requirements covered**: G3 +- **Pass criteria**: `grep "^ Executing" /tmp/bazel_explain.txt | wc -l` returns a number significantly less than the total action count from a clean build. +- **Automated/Manual**: Manual (reviewed once during Epic 2 validation) +- **Epic**: 1–2 + +#### BV-07: Cross-target isolation — androidMain change does not invalidate JVM build +- **ID**: BV-07 +- **Description**: Touch a `.kt` file in `kmp/src/androidMain/`. `bazel build //kmp:desktop_app` reports all actions cached (no re-execution). +- **Requirements covered**: G3 +- **Pass criteria**: `bazel build //kmp:desktop_app 2>&1 | grep "INFO: Build completed"` includes "0 actions executed" or all actions shown as "(cached)". +- **Automated/Manual**: Manual (one-time verification during Epic 3) +- **Epic**: 3 + +#### BV-08: `bazel run //kmp:desktop_app` launches application +- **ID**: BV-08 +- **Description**: `bazel run //kmp:desktop_app` starts the SteleKit desktop application. The main window appears within 10 seconds. +- **Requirements covered**: G6 +- **Pass criteria**: Application process starts; desktop window visible; no immediate crash or `ClassNotFoundException`. Verified manually. +- **Automated/Manual**: Manual +- **Epic**: 2 (Task 2.3.1) + +--- + +### Category 2: Test Migration (TM) + +#### TM-01: JVM test suite parity +- **ID**: TM-01 +- **Description**: `bazel test //kmp:jvm_tests` runs the same set of tests as `./gradlew jvmTest` (minus screenshot/Roborazzi tests which are excluded). All must pass. +- **Requirements covered**: G5, G6 +- **Pass criteria**: Exit code 0; test count in Bazel output matches Gradle jvmTest count minus Roborazzi-excluded count (verified by comparing `Tests run` totals). Zero failures. +- **Automated/Manual**: Automated (CI job `bazel-jvm`) +- **Test command**: `bazel test //kmp:jvm_tests --test_output=summary` +- **Epic**: 4 (Story 4.2, Task 4.2.1) + +#### TM-02: Business test suite parity +- **ID**: TM-02 +- **Description**: `bazel test //kmp/src/businessTest/kotlin:business_tests` (or top-level alias if added) runs and all business-logic tests pass. +- **Requirements covered**: G5, G6 +- **Pass criteria**: Exit code 0; all tests pass; count matches Gradle `businessTest` output. +- **Automated/Manual**: Automated (included in `bazel test //...`) +- **Test command**: `bazel test //kmp/src/businessTest/kotlin:business_tests --test_output=summary` +- **Epic**: 4 (Story 4.1, Task 4.1.1) + +#### TM-03: Android unit test suite parity +- **ID**: TM-03 +- **Description**: `bazel test //kmp/src/androidUnitTest/kotlin:android_unit_tests` runs and all non-screenshot Android tests pass. +- **Requirements covered**: G5, G6 +- **Pass criteria**: Exit code 0; test count matches `./gradlew testDebugUnitTest` count minus Roborazzi-excluded count. +- **Automated/Manual**: Automated (CI job `bazel-android-tests`) +- **Test command**: `bazel test //kmp/src/androidUnitTest/kotlin:android_unit_tests --test_output=summary` +- **Epic**: 4 (Story 4.3, Task 4.3.1) + +#### TM-04: Arrow Either types compile and function correctly +- **ID**: TM-04 +- **Description**: At least one existing test that exercises Arrow `Either` (happy path + error path) passes under Bazel, confirming Arrow 2.2.1.1 resolves correctly with the JVM classifier. +- **Requirements covered**: G1, G5 +- **Pass criteria**: No `ClassNotFoundException` or `NoClassDefFoundError` for `arrow.core.Either`; the test passes. +- **Automated/Manual**: Automated (covered by TM-01/TM-02 if Arrow tests exist in those suites) +- **Note**: Identify a specific existing Arrow test (e.g., in `repository/` tests) during Epic 4 and verify it is included in the Bazel test run. +- **Epic**: 4 + +#### TM-05: Coroutines and `kotlinx-coroutines-test` available in test scope +- **ID**: TM-05 +- **Description**: Tests using `runTest {}` from `kotlinx-coroutines-test` compile and run correctly under Bazel. +- **Requirements covered**: G5 +- **Pass criteria**: No missing-symbol compile errors for `kotlinx.coroutines.test.*`; tests using `runTest {}` pass. +- **Automated/Manual**: Automated (covered by TM-01/TM-02) +- **Epic**: 4 + +#### TM-06: `bazel test //...` — full suite run +- **ID**: TM-06 +- **Description**: `bazel test //...` runs all test targets (jvm_tests, business_tests, android_unit_tests) in a single invocation and all pass. +- **Requirements covered**: G5, G6 +- **Pass criteria**: Exit code 0; all three test targets appear in summary output; zero failures. +- **Automated/Manual**: Automated (CI) +- **Test command**: `bazel test //... --test_output=summary` +- **Epic**: 4 + +--- + +### Category 3: Correctness (CV) + +#### CV-01: SQLDelight generated code matches Gradle output +- **ID**: CV-01 +- **Description**: Run `./gradlew :kmp:generateCommonMainSteleDatabase`, then `diff -r kmp/build/generated/sqldelight/commonMain/kotlin/ kmp/src/generated/sqldelight/`. The diff must be empty (or only contain documented intentional differences). +- **Requirements covered**: G1, G2 +- **Pass criteria**: `diff` exits 0, or any differences are explained and accepted in a comment in the generated file header. +- **Automated/Manual**: Manual (run after any `.sq` schema change) +- **Regeneration command**: `./gradlew :kmp:generateCommonMainSteleDatabase && rsync -a kmp/build/generated/sqldelight/commonMain/kotlin/ kmp/src/generated/sqldelight/` +- **Epic**: 2 (Story 2.1) + +#### CV-02: Compose UI smoke test — desktop app renders +- **ID**: CV-02 +- **Description**: After `bazel run //kmp:desktop_app`, open a graph directory. Verify the page list renders and a page opens without Compose runtime errors. +- **Requirements covered**: G1, G6 +- **Pass criteria**: No `ComposeRuntimeError` or `IllegalStateException` from Compose; UI is interactive. +- **Automated/Manual**: Manual +- **Epic**: 2 (Task 2.3.1) + +#### CV-03: No Gradle fallback in CI after Gradle removal (Epic 7) +- **ID**: CV-03 +- **Description**: After Epic 7, the CI workflow file contains no `gradle` or `gradlew` commands (verified by grep). +- **Requirements covered**: G2 +- **Pass criteria**: `grep -r "gradlew\|gradle " .github/workflows/` returns zero results. +- **Automated/Manual**: Automated (CI lint step or pre-commit hook) +- **Epic**: 7 + +#### CV-04: `bazel mod graph` and `bazel fetch //...` succeed hermeticity check +- **ID**: CV-04 +- **Description**: From a clean checkout with network access disabled (e.g., `--sandbox_default_allow_network=false` in `.bazelrc`), `bazel build //kmp:desktop_app` succeeds using only the locked Maven artifacts. +- **Requirements covered**: G1, G4 +- **Pass criteria**: Build completes without any "network not allowed" or "could not download" errors. Lockfile `maven_install.json` satisfies all dependencies. +- **Automated/Manual**: Automated (`.bazelrc` sets `--sandbox_default_allow_network=false` globally) +- **Epic**: 1 (Story 1.1, Task 1.1.4) + +#### CV-05: KMP classifier audit — no ambiguous artifact resolution +- **ID**: CV-05 +- **Description**: `bazel build @maven//:pin` (i.e., `bazel run @maven//:pin`) completes without "multiple artifacts matching" warnings. The tracking table in `MODULE.bazel` comments documents classifier choices for all KMP libraries. +- **Requirements covered**: G1 +- **Pass criteria**: Zero "ambiguous artifact" warnings from `rules_jvm_external`; lock file committed. +- **Automated/Manual**: Automated (Maven pin step in CI or local setup) +- **Epic**: 1 (Story 1.2, Task 1.2.1) + +--- + +### Category 4: CI Integration (CI) + +#### CI-01: Remote cache hit on second CI run +- **ID**: CI-01 +- **Description**: After a main-branch push seeds the BuildBuddy remote cache, a subsequent CI run on the same commit (or a PR touching unrelated files) shows >50% action cache hit rate. +- **Requirements covered**: G4 +- **Pass criteria**: BuildBuddy dashboard for the second run shows `Cache hit rate: >50%`. Measured via `--build_event_log_file=build_events.json` parsed in CI or viewed in BuildBuddy UI. +- **Automated/Manual**: Manual (inspected in BuildBuddy after first two CI runs) +- **Epic**: 5 (Story 5.1, Task 5.1.2) + +#### CI-02: PR builds do not upload to cache +- **ID**: CI-02 +- **Description**: PR CI jobs run with `--config=ci-pr` (`--noremote_upload_local_results`). Verify that PR artifacts do not appear as new entries in BuildBuddy cache viewer. +- **Requirements covered**: G4 +- **Pass criteria**: After a PR build, no new cache entries are visible in BuildBuddy that did not already exist from main-branch runs. +- **Automated/Manual**: Manual (inspected in BuildBuddy) +- **Epic**: 5 (Story 5.1, Task 5.1.2) + +#### CI-03: Hermetic build — no Maven network calls during build +- **ID**: CI-03 +- **Description**: `maven_install.json` lock file is committed. In CI, `bazel build //...` does not make outbound Maven Central requests during compilation (only during `bazel fetch` pre-step). +- **Requirements covered**: G4 +- **Pass criteria**: CI network log (or `--sandbox_default_allow_network=false` enforcement) shows no Maven Central connections during `bazel build`. +- **Automated/Manual**: Automated (`--sandbox_default_allow_network=false` in `.bazelrc` enforces this) +- **Epic**: 1 (Task 1.1.4) and 5 (Task 5.1.1) + +#### CI-04: Bazel JVM CI job passes on PR +- **ID**: CI-04 +- **Description**: The `bazel-jvm` GitHub Actions job (running `bazel test //kmp:jvm_tests --config=ci`) passes on a PR against `main`. +- **Requirements covered**: G5 +- **Pass criteria**: GitHub Actions job shows green checkmark; `bazel-ci.yml` `bazel-jvm` job status = success. +- **Automated/Manual**: Automated +- **Epic**: 5 (Story 5.1, Task 5.1.1) + +#### CI-05: Bazel Android build CI job passes on PR +- **ID**: CI-05 +- **Description**: The `bazel-android` job (running `bazel build //kmp:android_app --config=ci`) passes on a PR. +- **Requirements covered**: G5 +- **Pass criteria**: GitHub Actions `bazel-android` job status = success; APK artifact produced. +- **Automated/Manual**: Automated +- **Epic**: 5 (Task 5.1.1) + +#### CI-06: Bazel Android unit test CI job passes on PR +- **ID**: CI-06 +- **Description**: The `bazel-android-tests` job passes on a PR. +- **Requirements covered**: G5 +- **Pass criteria**: GitHub Actions `bazel-android-tests` job status = success; all Android unit tests pass. +- **Automated/Manual**: Automated +- **Epic**: 5 (Task 5.1.1) + +#### CI-07: Detekt still blocks merge on lint failures +- **ID**: CI-07 +- **Description**: Introduce a deliberate Detekt violation in a PR. Verify the Detekt CI job fails and blocks merge. +- **Requirements covered**: G5 +- **Pass criteria**: Detekt job exits non-zero; GitHub branch protection prevents merge. +- **Automated/Manual**: Manual (one-time verification during Epic 6) +- **Epic**: 6 (Story 6.1, Task 6.1.1) + +#### CI-08: Gradle screenshot/Roborazzi jobs still pass +- **ID**: CI-08 +- **Description**: During the transition period (Epics 1–6), the existing Gradle-based CI jobs for screenshot tests and Roborazzi still pass on every PR. +- **Requirements covered**: G5 +- **Pass criteria**: All pre-existing Gradle CI jobs that were passing before the Bazel migration continue to pass. Zero new failures attributable to the Bazel migration. +- **Automated/Manual**: Automated (existing CI jobs) +- **Epic**: 5 (Task 5.1.1) — maintained alongside Bazel jobs + +--- + +## Test Stack + +- **Unit / Build**: Bazel (`bazel build`, `bazel test`) with `rules_kotlin` `kt_jvm_test` and `android_local_test` +- **JVM test framework**: `kotlin-test-junit` (JUnit 4 runner via `kt_jvm_test`) +- **Android test framework**: Robolectric 4.14.1 via `android_local_test`; `androidx.test.ext:junit` +- **Coroutine testing**: `kotlinx-coroutines-test` 1.10.2 +- **Remote cache validation**: BuildBuddy free tier dashboard + `--build_event_log_file` +- **CI**: GitHub Actions via `bazel-contrib/setup-bazel` + `bazel-ci.yml` +- **Benchmark / timing**: `time` command + manual wall-clock measurement for G3 (BV-05) +- **Screenshot tests (Gradle-only, out of scope for Bazel)**: Roborazzi + `roborazzi-compose` + +--- + +## Coverage Targets + +- All 6 requirements (G1–G6) covered by at least 2 test cases each +- Unit / build test coverage: all public Bazel targets (`kt_jvm_library`, `kt_android_library`, `kt_jvm_test`, `android_local_test`) have at least one automated build or test validation +- All external integrations mocked or locked: Maven resolution via lockfile (CV-04), remote cache validated via BuildBuddy (CI-01) +- Test count goal: ≥20 automated test cases (mix of build targets and test suite runs); 8 manual verification steps + +--- + +## Requirement Traceability Matrix + +| Requirement | Description | Test IDs | Coverage | +|---|---|---|---| +| G1 | All KMP targets build (JVM + Android in scope) | BV-01, BV-02, BV-03, BV-04, TM-04, CV-01, CV-04, CV-05 | 8/8 test cases — full | +| G2 | Full Gradle replacement | CV-01, CV-02, CV-03 | 3/3 test cases — full (Epic 7 gate) | +| G3 | Incremental builds < 5s | BV-05, BV-06, BV-07 | 3/3 test cases — full | +| G4 | Remote caching via GHA | CI-01, CI-02, CI-03, BV-03 (hermetic), CV-04 | 5/5 test cases — full | +| G5 | CI passes using Bazel | CI-04, CI-05, CI-06, CI-07, CI-08, TM-01, TM-02, TM-03, TM-06 | 9/9 test cases — full | +| G6 | Developer experience preserved | BV-08, TM-01, TM-02, TM-03, TM-04 | 5/5 test cases — full | + +**Overall requirement coverage: 6/6 (100%)** + +--- + +## Test Execution Order (per Epic) + +| Epic | Tests to run before marking Epic done | +|---|---| +| Epic 1: Bazel Scaffolding | CV-04, CV-05, BV-03 (toolchain error path) | +| Epic 2: JVM/Desktop | BV-01, BV-04, BV-05, BV-06, BV-08, CV-01, CV-02 | +| Epic 3: Android | BV-02, BV-07 | +| Epic 4: Test Targets | TM-01, TM-02, TM-03, TM-04, TM-05, TM-06 | +| Epic 5: CI Integration | CI-01, CI-02, CI-03, CI-04, CI-05, CI-06, CI-08 | +| Epic 6: Detekt | CI-07 | +| Epic 7: Gradle Removal | CV-01 (re-run), CV-03 | + +--- + +## Open Risks and Mitigations + +| Risk | Test that catches it | Mitigation | +|---|---|---| +| `commonMain` compiled twice (JVM + Android) doubles action count, slowing incremental builds | BV-05, BV-06 | Monitor action graph depth; ADR-005 documents the trade-off | +| Compose compiler plugin K2 compatibility breaks on Kotlin upgrade | BV-01, TM-01 | Pin `suppressKotlinVersionCompatibilityCheck` to `2.3.21`; ADR-004 documents the risk | +| SQLDelight schema drift (generated sources out of sync with `.sq` files) | CV-01 | Document regeneration in `README_REGEN.md`; add `./gradlew generateCommonMainSteleDatabase` to PR checklist | +| BuildBuddy free tier storage cap hit | CI-01, CI-02 | Monitor BuildBuddy dashboard; configure `--remote_cache_eviction_retries` | +| Robolectric `android-all` JAR not available in `maven_install.json` | TM-03 | Include `@robolectric//bazel:android-all` via the `robolectric` Bzlmod dep; test in Epic 4 | diff --git a/project_plans/stelekit-bazel/requirements.md b/project_plans/stelekit-bazel/requirements.md new file mode 100644 index 00000000..be583a23 --- /dev/null +++ b/project_plans/stelekit-bazel/requirements.md @@ -0,0 +1,65 @@ +# SteleKit Bazel Migration — Requirements + +## Summary + +Migrate SteleKit's build system from Gradle to Bazel to improve incremental local build performance. The migration is a full replacement — Gradle is removed entirely once all targets are working under Bazel. + +## Problem Statement + +Gradle incremental builds are unreliable or too slow on the developer's machine, causing long feedback loops during development. Bazel's hermetic, action-graph-based incrementality should deliver faster local rebuilds by reusing cached actions correctly across builds. + +## Goals + +| # | Requirement | Priority | +|---|-------------|----------| +| G1 | All KMP targets build under Bazel: JVM/Desktop, Android, iOS, WASM/JS | Must Have | +| G2 | Full Gradle replacement — no `gradlew` or `build.gradle.kts` in the final state | Must Have | +| G3 | Local incremental builds are measurably faster than Gradle baseline | Must Have | +| G4 | Remote caching via GitHub Actions cache (actions/cache or bazel-remote) | Should Have | +| G5 | CI passes using Bazel commands (mirrors current `./gradlew ciCheck` workflow) | Must Have | +| G6 | Developer experience preserved: `run`, `test`, `package` equivalents available | Must Have | + +## Non-Goals + +- Multi-language monorepo support (not needed now) +- Replacing Bazel with Buck2/Pants (out of scope) +- Supporting Windows build hosts (Linux + macOS are primary) + +## Constraints + +- Kotlin Multiplatform project — `rules_kotlin` alone does not cover KMP; `rules_kmp` (or equivalent) required +- SQLDelight 2.3.2 code generation must be preserved — Bazel must invoke the code generator or check in generated sources +- Compose Multiplatform UI compiler plugin must be wired into Kotlin compilation +- iOS builds require macOS host (cross-compilation is not in scope for initial migration) + +## Rulesets & Toolchain + +- **Primary KT rules**: `rules_kotlin` (bazelbuild/rules_kotlin) — JVM + Android Kotlin +- **KMP overlay**: `rules_kmp` or experimental KMP support — to be validated in research +- **Remote cache**: GitHub Actions `actions/cache` keyed on Bazel content hash, or `bazel-remote` sidecar in CI + +## Current Build Commands (Gradle → Bazel equivalents needed) + +| Gradle command | Required Bazel equivalent | +|----------------|--------------------------| +| `./gradlew run` | `bazel run //kmp:desktop_app` (or similar) | +| `./gradlew jvmTest` | `bazel test //kmp:jvm_tests` | +| `./gradlew allTests` | `bazel test //...` | +| `./gradlew ciCheck` | `bazel test //... --config=ci` | +| `./gradlew installAndroid` | `bazel mobile-install //kmp:android_app` | +| `./gradlew packageDistributionForCurrentOS` | `bazel build //kmp:desktop_dist` | + +## Success Criteria + +1. `bazel build //...` succeeds from a clean checkout on Linux (JVM + Android targets at minimum) +2. Incremental rebuild after a single `.kt` file change takes < 5 s locally (vs. current Gradle baseline) +3. GitHub Actions CI passes using Bazel commands +4. All existing jvmTest tests pass under Bazel +5. SQLDelight-generated Kotlin is available to all targets (either via codegen rule or checked-in sources) + +## Open Questions (for research) + +- Is `rules_kmp` production-ready for Compose Multiplatform, or is a different approach needed? +- How does SQLDelight 2.3.2 integrate with Bazel (custom rule, Gazelle extension, or checked-in sources)? +- What is the migration path for the Compose compiler plugin (K2 + Bazel)? +- Is `bazel-remote` or native GHA cache the better fit for this project's CI budget? diff --git a/project_plans/stelekit-bazel/research/architecture.md b/project_plans/stelekit-bazel/research/architecture.md new file mode 100644 index 00000000..b0f1ef28 --- /dev/null +++ b/project_plans/stelekit-bazel/research/architecture.md @@ -0,0 +1,449 @@ +# SteleKit Bazel Migration — Architecture Research + +## Executive Summary + +Three critical findings: +1. **No production-ready KMP Bazel ruleset exists.** `rules_kotlin` covers JVM + Android only; full KMP (iOS, WASM/JS, commonMain) has no official Bazel support. The practical migration path is JVM-first: migrate the JVM and Android targets to Bazel, treat iOS/WASM as a later phase or keep them in Gradle during transition. +2. **Use `MODULE.bazel` (Bzlmod), not `WORKSPACE`.** `WORKSPACE` is disabled by default in Bazel 8 (released Dec 2024) and will be removed in Bazel 9. All new projects must use `MODULE.bazel`. The Bazel Central Registry now hosts 650+ modules including `rules_kotlin`, `rules_jvm_external`, and `rules_android`. +3. **`commonMain` must be compiled twice — once as `kt_jvm_library`, once as `kt_android_library`.** There is no KMP-aware rule that handles expect/actual dispatch. The shared source set is expressed as a single Bazel target per platform-flavor, with each platform target adding it to `deps`. This is the standard pattern for sharing Kotlin code across JVM and Android in Bazel. + +--- + +## 1. BUILD File Structure for a KMP Project + +### The Core Problem: No KMP Rule + +`rules_kotlin` (bazelbuild/rules_kotlin) supports three flavors: +- `kt_jvm_*` — JVM compilation +- `kt_android_*` — Android compilation via AGP integration +- `kt_js_*` — Kotlin/JS (limited, experimental) + +There is **no `kt_kmp_*` or `kt_multiplatform_*` rule**. The GitHub issue tracking KMP support ([#567 Kotlin Bazel Cross-Platform Roadmap](https://github.com/bazelbuild/rules_kotlin/issues/567)) has been open since 2021 and remains "investigating." The August 2025 KMP roadmap from JetBrains mentions a "Kotlin Build Tools API" to ease integration with Bazel eventually — but this is future work, not available today. + +**Practical implication**: KMP's expect/actual mechanism is a compiler feature tied to the Kotlin multiplatform compiler plugin. Bazel cannot invoke it without a rule that understands source sets and target architectures. For iOS (Kotlin/Native) and WASM/JS, no stable Bazel rules exist. + +### Recommended BUILD Layout + +Given the constraint above, the migration should proceed in layers: + +``` +// +├── MODULE.bazel +├── .bazelrc +├── kmp/ +│ ├── BUILD.bazel # Top-level aliases and visibility +│ ├── src/ +│ │ ├── commonMain/ +│ │ │ └── BUILD.bazel # kt_jvm_library (jvm variant) + kt_android_library (android variant) +│ │ ├── jvmCommonMain/ +│ │ │ └── BUILD.bazel # kt_jvm_library + kt_android_library (shared JVM/Android extras) +│ │ ├── jvmMain/ +│ │ │ └── BUILD.bazel # kt_jvm_library :jvm_main, kt_jvm_binary :desktop_app +│ │ ├── androidMain/ +│ │ │ └── BUILD.bazel # kt_android_library :android_main +│ │ └── sqldelight/ +│ │ └── BUILD.bazel # sqldelight_codegen rule or pregenerated sources +│ └── src/jvmTest/ +│ └── BUILD.bazel # kt_jvm_test targets +└── androidApp/ + └── BUILD.bazel # android_binary :android_app +``` + +**One BUILD file per source set** is the recommended approach because: +- Each source set has a distinct dependency graph +- Bazel's incremental model rewards smaller, well-scoped targets +- Test targets stay co-located with the sources they test + +### commonMain Handling + +`commonMain` sources contain platform-agnostic Kotlin that must be compiled for each target platform. Since rules_kotlin has no multiplatform rule, the pattern is: + +```python +# kmp/src/commonMain/BUILD.bazel + +load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") +load("@rules_kotlin//kotlin:android.bzl", "kt_android_library") + +# JVM flavor — used by jvmMain and jvmTest +kt_jvm_library( + name = "common_jvm", + srcs = glob(["kotlin/**/*.kt"]), + deps = [ + # Arrow, kotlinx-coroutines, SQLDelight runtime, Compose runtime jars + "@maven//:io_arrow_kt_arrow_core_jvm", + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_core_jvm", + # ... + ], + visibility = ["//kmp:__subpackages__"], +) + +# Android flavor — used by androidMain and android tests +kt_android_library( + name = "common_android", + srcs = glob(["kotlin/**/*.kt"]), + custom_package = "dev.stapler.stelekit", + manifest = "//kmp:AndroidManifest.xml", + deps = [ + "@maven//:io_arrow_kt_arrow_core_jvm", + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_core_jvm", + # ... + ], + visibility = ["//kmp:__subpackages__"], +) +``` + +`jvmMain` depends on `:common_jvm`; `androidMain` depends on `:common_android`. The source files are shared (same `glob`), compiled twice with different Bazel rules. This duplicates compile work but is the only supported approach without a KMP rule. + +**Alternative**: Check in SQLDelight-generated sources and treat `commonMain` as a single `kt_jvm_library` for both targets by using `kt_android_library` rules that inherit from it. Some teams flatten commonMain + jvmMain into a single target per platform to reduce complexity. + +--- + +## 2. WORKSPACE vs MODULE.bazel (Bzlmod) + +**Use `MODULE.bazel` for all new projects without exception.** + +| Aspect | WORKSPACE | MODULE.bazel (Bzlmod) | +|--------|-----------|----------------------| +| Status in Bazel 8 | Disabled by default | Default and recommended | +| Status in Bazel 9 | Cannot be enabled | Only supported mode | +| Transitive deps | Manual, conflict-prone | Automatically resolved | +| Bazel Central Registry | Not used | 650+ modules available | +| rules_kotlin | Available | Available (v2.x on BCR) | +| rules_jvm_external | Available | Available (v6.6+ supports `maven.from_toml`) | + +### MODULE.bazel Skeleton for SteleKit + +```python +module( + name = "stelekit", + version = "0.0.0", +) + +bazel_dep(name = "rules_kotlin", version = "2.1.3") +bazel_dep(name = "rules_android", version = "0.6.0") +bazel_dep(name = "rules_jvm_external", version = "6.6") +bazel_dep(name = "bazel_skylib", version = "1.7.1") + +# Maven dependency resolution +maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven") + +# Option A: import from the existing libs.versions.toml (see section 6) +maven.from_toml( + libs_versions_toml = "//gradle:libs.versions.toml", +) + +# Option B: declare artifacts inline +maven.install( + artifacts = [ + "io.arrow-kt:arrow-core:2.2.1.1", + "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2", + # ... + ], + repositories = [ + "https://repo1.maven.org/maven2", + "https://maven.google.com", + "https://jitpack.io", + ], +) + +use_repo(maven, "maven") + +# Android SDK +android_sdk_repository_extension = use_extension( + "@rules_android//rules/android_sdk_repository:rule.bzl", + "android_sdk_repository_extension", +) +use_repo(android_sdk_repository_extension, "androidsdk") + +# Kotlin toolchain (registered in root BUILD.bazel) +register_toolchains("//:kotlin_toolchain") +``` + +--- + +## 3. rules_kotlin Rule Mapping to KMP Source Sets + +| Gradle source set | Bazel rule | Notes | +|-------------------|-----------|-------| +| `commonMain` | `kt_jvm_library` + `kt_android_library` | Compiled twice, one per platform; no KMP rule | +| `jvmCommonMain` | `kt_jvm_library` | Depends on `:common_jvm`; JVM+Android shared extras | +| `jvmMain` | `kt_jvm_library` | Desktop app logic; depends on `:jvm_common` | +| `androidMain` | `kt_android_library` | Depends on `:common_android` + `:jvm_common_android` | +| `iosMain` | **Not supported** | Requires Kotlin/Native toolchain; no stable rules | +| `wasmJsMain` | **Not supported** | Requires WASM target toolchain; no stable rules | +| `jvmTest` | `kt_jvm_test` | Standard JUnit4 runner | +| `androidUnitTest` | `android_local_test` | Requires Robolectric setup | +| `businessTest` | `kt_jvm_test` | Pure JVM tests, depends on `:common_jvm` | + +### Compose Multiplatform Complication + +The Compose compiler plugin is distributed as a Kotlin compiler plugin and requires specific wiring in `kotlinc_opts`. As of 2025, there are no dedicated Bazel rules for Compose Multiplatform. The Compose desktop JAR can be added as a Maven artifact and passed to `kt_jvm_library`, but the compiler plugin must be explicitly threaded through `kt_kotlinc_options`: + +```python +kt_kotlinc_options( + name = "kotlinc_opts_compose", + x_optin = ["androidx.compose.runtime.ExperimentalComposeApi"], + plugin_options = [ + # compose compiler plugin options + ], +) +``` + +This is an open engineering problem — the Compose compiler plugin has historically required Gradle's compose plugin to configure correctly. Teams building Compose apps with Bazel typically wrap the compiler plugin jar manually. + +--- + +## 4. Toolchain Declaration Patterns + +### Root BUILD.bazel — Kotlin Toolchain + +```python +# //:BUILD.bazel +load("@rules_kotlin//kotlin:core.bzl", "define_kt_toolchain") + +define_kt_toolchain( + name = "kotlin_toolchain", + api_version = "2.1", # matches Kotlin 2.1.x in settings.gradle.kts + jvm_target = "21", # matches jvmToolchain(21) + language_version = "2.1", +) +``` + +### JDK Toolchain + +Bazel 7+ uses the `rules_java` JDK toolchain. In `.bazelrc`: + +``` +build --java_runtime_version=21 +build --tool_java_runtime_version=21 +``` + +Or declare explicitly in MODULE.bazel: +```python +bazel_dep(name = "rules_java", version = "8.3.2") +``` + +### Android SDK Toolchain + +```python +# In MODULE.bazel +android_sdk_repository_extension = use_extension( + "@rules_android//rules/android_sdk_repository:rule.bzl", + "android_sdk_repository_extension", +) +android_sdk_repository_extension.configure( + api_level = 36, # compileSdk = 36 + build_tools_version = "35.0.0", +) +use_repo(android_sdk_repository_extension, "androidsdk") +``` + +`.bazelrc`: +``` +build --android_sdk=@androidsdk//:sdk +build --android_platforms=//platforms:android_arm64 +``` + +--- + +## 5. commonMain: Separate Library vs Inline + +**Recommendation: separate `kt_jvm_library` and `kt_android_library` targets, one each.** + +Do not inline commonMain sources directly into each platform target via `glob`. Separate targets give: +- Better incremental caching (change to commonMain invalidates both flavors simultaneously, allowing parallel recompile) +- Cleaner visibility scoping — only `jvmMain` and `jvmTest` see `:common_jvm` +- Easier migration path when/if a KMP rule becomes available (replace two targets with one) + +The penalty is that the ~80-100 commonMain Kotlin files are compiled twice per build. On modern hardware with Bazel's action graph, this is typically <10 seconds incremental and cached on subsequent builds. + +--- + +## 6. Dependency Management: rules_jvm_external and the Version Catalog + +### Key Finding: `maven.from_toml` — Direct TOML Import + +`rules_jvm_external` v6.6+ supports importing Maven artifacts directly from a Gradle `libs.versions.toml` version catalog: + +```python +# MODULE.bazel +maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven") +maven.from_toml( + libs_versions_toml = "//gradle:libs.versions.toml", +) +``` + +This means SteleKit's existing `gradle/libs.versions.toml` can be the single source of truth for Maven versions shared between Gradle (during transition) and Bazel. The TOML file would need to be in a Bazel-visible location under `//gradle/`. + +### Coordinate Mapping + +Gradle artifact coordinates (`group:artifact:version`) map to Bazel label targets with colons replaced by underscores: + +| Gradle | Bazel label | +|--------|-------------| +| `io.arrow-kt:arrow-core:2.2.1.1` | `@maven//:io_arrow_kt_arrow_core` | +| `org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2` | `@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_core` | +| `app.cash.sqldelight:runtime:2.3.2` | `@maven//:app_cash_sqldelight_runtime` | +| `androidx.compose.ui:ui:1.10.6` | `@maven//:androidx_compose_ui_ui` | + +### KMP Artifact Disambiguation + +KMP libraries publish multiple variants (JVM, Android, iOS, JS). `rules_jvm_external` resolves Maven artifacts using POM metadata, which for KMP libraries means it typically picks the JVM variant. For Android-specific variants, the `target_substitutions` attribute or explicit artifact coordinates (e.g., `io.arrow-kt:arrow-core-jvm:2.2.1.1`) may be needed. + +The Gradle metadata resolution issue ([rules_jvm_external#864](https://github.com/bazel-contrib/rules_jvm_external/issues/864)) tracks KMP artifact disambiguation in Bazel. As of 2025, the recommended workaround is to use explicit `-jvm` classifier coordinates for JVM targets and `-android` for Android targets. + +### Lock File + +Pin all resolved Maven artifact checksums using `maven_install.json` for reproducible builds: + +```python +maven.install( + lock_file = "//:maven_install.json", + # ... +) +``` + +Generate/update: `bazel run @maven//:pin` + +--- + +## 7. Test Target Structure + +### JVM Unit Tests (jvmTest / businessTest) + +```python +# kmp/src/jvmTest/BUILD.bazel +load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_test") + +kt_jvm_test( + name = "jvm_tests", + srcs = glob(["kotlin/**/*.kt"]), + test_class = "dev.stapler.stelekit.AllTestsSuite", # or use junit runner + deps = [ + "//kmp/src/jvmMain:jvm_main", + "//kmp/src/businessTest:business_tests", + "@maven//:junit_junit", + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_test", + "@maven//:io_ktor_ktor_client_mock", + ], + jvm_flags = [ + "-Djdk.attach.allowAttachSelf=true", + "--add-opens=java.base/java.lang=ALL-UNNAMED", + "-Djava.awt.headless=false", + ], +) +``` + +### businessTest (Pure Logic, No UI) + +```python +# kmp/src/businessTest/BUILD.bazel +kt_jvm_library( + name = "business_tests", + srcs = glob(["kotlin/**/*.kt"]), + deps = [ + "//kmp/src/commonMain:common_jvm", + "@maven//:org_jetbrains_kotlin_kotlin_test_junit", + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_test", + ], + visibility = ["//kmp:__subpackages__"], + testonly = True, +) +``` + +### Android Unit Tests (androidUnitTest with Robolectric) + +Robolectric has dedicated Bazel support via [robolectric-bazel](https://github.com/robolectric/robolectric-bazel). Use `android_local_test` (from `rules_android`), not `kt_android_local_test` (which does not exist): + +```python +# kmp/src/androidUnitTest/BUILD.bazel +load("@rules_android//rules:rules.bzl", "android_local_test") +load("@rules_kotlin//kotlin:android.bzl", "kt_android_library") + +# Compile test sources as an Android library first +kt_android_library( + name = "android_unit_test_lib", + srcs = glob(["kotlin/**/*.kt"]), + custom_package = "dev.stapler.stelekit", + deps = [ + "//kmp/src/androidMain:android_main", + "@maven//:junit_junit", + "@maven//:org_robolectric_robolectric", + "@maven//:androidx_test_core", + "@maven//:org_jetbrains_kotlinx_kotlinx_coroutines_test", + ], + testonly = True, +) + +android_local_test( + name = "android_unit_tests", + srcs = glob(["kotlin/**/*.kt"]), + manifest = "//kmp:TestAndroidManifest.xml", + deps = [ + ":android_unit_test_lib", + "@robolectric//bazel:android-all", + "@maven//:org_robolectric_robolectric", + ], +) +``` + +MODULE.bazel must include: +```python +bazel_dep(name = "robolectric", version = "4.14.1") +``` + +### Screenshot Tests (Roborazzi) + +Roborazzi does not have official Bazel support. The Roborazzi GitHub repository acknowledges this. Options: +1. **Keep screenshot tests in Gradle**: Run `./gradlew testDebugUnitTest` for screenshot verification; run all other tests via Bazel. +2. **Manual integration**: Add Roborazzi JARs via `maven_install` and configure `android_local_test` with the correct JVM flags and test runner. This requires manually wiring Compose UI test infrastructure and is undocumented. +3. **Exclude from Bazel CI initially**: Mark screenshot test targets as `tags = ["manual"]` so `bazel test //...` skips them. + +**Recommendation**: Keep screenshot tests in Gradle during the initial migration phase (Phase 1 of migration). This is the lowest-risk approach and unblocks the core migration. + +--- + +## 8. SQLDelight Code Generation + +### Option A: Checked-in Generated Sources (Recommended for Initial Migration) + +Run `./gradlew generateCommonMainSteleDatabase` once to produce the generated Kotlin under `kmp/build/generated/`, copy these files to a committed source directory (e.g., `kmp/src/commonMain/generated/sqldelight/`), and include them in the `commonMain` BUILD target's `srcs` glob. + +Pros: Zero Bazel rule complexity; works immediately. +Cons: Generated files in version control; must regenerate manually on schema change. + +### Option B: Custom `sqldelight_codegen` Rule + +[square/sqldelight_bazel_rules](https://github.com/square/sqldelight_bazel_rules) provides a `sqldelight_codegen` rule, but it targets SQLDelight 1.x. For SQLDelight 2.x, there is no maintained Bazel rule. A custom rule invoking the SQLDelight CLI (`sqldelight-gradle-plugin` exposes a CLI entrypoint) would need to be written. + +For a migration project, Option A is strongly recommended. Option B can be adopted once the initial migration is stable. + +--- + +## 9. Key Risk Summary + +| Risk | Severity | Mitigation | +|------|----------|-----------| +| No KMP rule for iOS/WASM | High | Phase 1 targets JVM + Android only; iOS/WASM remain in Gradle | +| Compose compiler plugin wiring | High | Pre-generate `.class` files or use Compose desktop JAR directly; investigate `kt_compiler_plugin` rule | +| SQLDelight 2.x codegen | Medium | Check in generated sources for Phase 1 | +| KMP Maven variant disambiguation | Medium | Use explicit `-jvm`/`-android` artifact classifiers in `maven_install` | +| Roborazzi screenshot tests | Low | Keep in Gradle; exclude from Bazel CI | +| `rules_android` maturity | Medium | `rules_android` 0.x is still pre-1.0; Google uses it internally but API may change | + +--- + +## References + +- [rules_kotlin GitHub](https://github.com/bazelbuild/rules_kotlin) +- [rules_kotlin rule reference](https://bazelbuild.github.io/rules_kotlin/kotlin.html) +- [Bzlmod Migration Guide](https://bazel.build/external/migration) +- [Bazel 8 Release Notes](https://blog.bazel.build/2024/12/09/bazel-8-release.html) +- [rules_jvm_external Bzlmod docs](https://github.com/bazel-contrib/rules_jvm_external/blob/master/docs/bzlmod.md) +- [rules_jvm_external MODULE.bazel example](https://github.com/bazel-contrib/rules_jvm_external/blob/master/examples/bzlmod/MODULE.bazel) +- [robolectric-bazel](https://github.com/robolectric/robolectric-bazel) +- [square/sqldelight_bazel_rules](https://github.com/square/sqldelight_bazel_rules) +- [KMP Bazel Cross-Platform Roadmap Issue #567](https://github.com/bazelbuild/rules_kotlin/issues/567) +- [Compose Multiplatform + Bazel discussion](https://slack-chats.kotlinlang.org/t/3145636/does-compose-multiplatform-support-bazel) +- [KMP + Bazel discussion (kotlinlang Slack)](https://slack-chats.kotlinlang.org/t/16406255/we-need-a-build-system-for-kotlin-we-have-reached-our-limit-) +- [KMP August 2025 Roadmap](https://blog.jetbrains.com/kotlin/2025/08/kmp-roadmap-aug-2025/) diff --git a/project_plans/stelekit-bazel/research/features.md b/project_plans/stelekit-bazel/research/features.md new file mode 100644 index 00000000..441ab120 --- /dev/null +++ b/project_plans/stelekit-bazel/research/features.md @@ -0,0 +1,264 @@ +# Bazel Migration Features Research + +**Project**: SteleKit — KMP project targeting Desktop (JVM), Android, iOS, Web +**Research Date**: 2026-05-17 +**Goal**: Understand what Bazel provides vs Gradle, real migration experiences, and how to set up remote caching on GitHub Actions. + +--- + +## 1. OSS Projects That Migrated Android/Kotlin from Gradle to Bazel + +### Grab (Superapp — 2.5M+ LOC) + +- **Scale**: Android Passenger app with 2.5 million lines of code across hundreds of modules. +- **Motivation**: Gradle performs reasonably up to ~1M LOC; beyond that, build times degrade enough to hurt engineering velocity. At Grab's scale, Bazel was essential. +- **Tool**: Built [Grazel](https://github.com/grab/Grazel) — a Gradle plugin that generates equivalent Bazel BUILD rules from existing Gradle scripts, enabling incremental/automated migration. +- **Result**: Grab stated they would make the same choice again without hesitation. ABI jars provided significant compile avoidance on non-ABI changes. +- **Timeline**: ~5 months for initial proof of concept and impact estimation, before full rollout. +- **Source**: [How Grab is Blazing Through the Superapp Bazel Migration](https://engineering.grab.com/how-grab-is-blazing-through-the-super-app-bazel-migration) + +### Turo + +- **Scale**: Large multi-module Android app. +- **Approach**: Ran Gradle and Bazel side-by-side during transition — Gradle remained the source of truth; Bazel was evaluated on selected CI workflows. +- **Tools**: Built [Airin](https://github.com/Morfly/airin) and Pendant (open source). Airin is a Gradle plugin that scans project structure and generates Starlark scripts via Pendant (a Kotlin DSL for Bazel file generation). +- **Key lesson**: "Bazel adoption is not an overnight process." Running two build systems in parallel reduces risk but requires ongoing sync. +- **Automation benefit**: With automated tooling, migration cost dropped by at least 50% vs manual effort. +- **Source**: [Boosting Bazel Adoption on Android With Automation — Turo Engineering](https://medium.com/turo-engineering/boosting-bazel-adoption-on-android-with-automation-6dc79d298628) + +### General Android/Kotlin Migration Consensus (2022–2024) + +- Migrating from Gradle to Bazel loses some "magic" Gradle gives for free (plugin ecosystem, convention plugins, AGP auto-wiring). +- Custom Gradle build logic and plugins require equivalent Bazel rules — these have no automated migration path. +- Dependency conflict management is harder in Bazel: `rules_android` and `rules_kotlin` version bumps often require a Bazel version bump too. +- Fully automatic migration is not feasible for projects with custom Gradle tasks/plugins — partial automation (Airin, Grazel) is the practical approach. +- Source: [Migrating Android Projects from Gradle to Bazel — Medium](https://medium.com/@imamyusufb123/migrating-android-projects-from-gradle-to-bazel-a-complete-guide-for-developers-4e67aea0883c), [Automated migration with Airin — ProAndroidDev](https://proandroiddev.com/automated-migration-of-your-projects-to-bazel-build-system-with-airin-304fa8b3680c) + +--- + +## 2. Bazel vs Gradle for KMP Specifically + +### KMP Support Status in Bazel (CRITICAL FINDING) + +**Bazel does not natively support Kotlin Multiplatform as of mid-2025.** This is the most important finding for SteleKit. + +- `rules_kotlin` supports: JVM, Android, and JS (JS is under-maintained). +- `rules_kotlin` does NOT support: **iOS/Kotlin Native**, **WebAssembly/Wasm**, or the **expect/actual cross-compilation mechanism** that KMP depends on. +- A Google Summer of Code 2025 project is specifically focused on improving Bazel's KMP support (dependency resolution, rules_kotlin + rules_jvm_external compatibility, expect/actual handling) — this indicates the feature is still actively in development, not yet production-ready. +- The Kotlin community on Slack explicitly states: "Bazel's support for Kotlin is evolving, but proper KMP integration remains a challenge" and "there is no support for KMP" in Bazel as currently packaged. +- JetBrains is developing a Kotlin Build Tools API (unified entry point for build systems) to make Bazel/Buck integration easier, but this is forward-looking, not yet released. +- Sources: [rules_kotlin GitHub](https://github.com/bazelbuild/rules_kotlin), [KMP Cross-Platform Roadmap Issue #567](https://github.com/bazelbuild/rules_kotlin/issues/567), [GSoC 2025 Kotlin](https://kotlinlang.org/docs/gsoc-2025.html), [Kotlinlang Slack — Compose Multiplatform Bazel support](https://slack-chats.kotlinlang.org/t/3145636/does-compose-multiplatform-support-bazel) + +### Incremental Build Accuracy + +- **Bazel**: Correctness by construction. Bazel computes a cryptographic hash of every input (source, deps, compiler flags). If the hash hasn't changed, the output is reused. This is more accurate than Gradle's task-based approach and avoids "stale output" false incremental builds. +- **Gradle**: Relies on users correctly declaring inputs/outputs. Many potential problems caught by the Gradle Plugin Development Plugin, but correctness is an honor system for custom tasks. Real-world Gradle incremental builds frequently produce incorrect results when inputs are not fully declared. +- **Bazel sandboxing**: Ensures all inputs/outputs are correctly declared by isolating actions. Many users disable it (especially macOS) due to performance overhead — when disabled, the correctness guarantee weakens. +- **Key nuance**: Gradle claims 5–16x faster incremental builds than Bazel in their own benchmark (for the monolith case). However, this comparison is disputed and reflects Gradle's situation without remote caching, vs Bazel with a cold local cache. At scale with remote caching active, Bazel wins decisively. +- Sources: [Bazel vs Gradle — Buildkite](https://buildkite.com/resources/comparison/bazel-vs-gradle/), [Gradle vs Bazel for JVM Projects — Gradle Blog](https://blog.gradle.org/gradle-vs-bazel-jvm), [Empirical Study — Does Bazel Speed Up CI Builds? (2024)](https://dl.acm.org/doi/10.1007/s10664-024-10497-x) + +### Developer Experience vs Gradle + +| Dimension | Bazel | Gradle | +|---|---|---| +| First-build time | Similar or slower | Similar | +| Incremental (cached) | Faster at scale; reproducible | Faster for small monolith; stale-output risk | +| BUILD file maintenance | Manual; no auto-generation for KMP | Automatic via plugins/conventions | +| Plugin ecosystem | Limited; fewer rules than Gradle plugins | Very large ecosystem | +| Custom build logic | Starlark (Python-like) — unfamiliar to most | Kotlin/Groovy DSL — familiar | +| KMP expect/actual | **Not supported** | Fully supported | +| Compose Multiplatform | **Not supported** | Fully supported | +| Learning curve | High (new language: Starlark, new concepts) | Moderate (familiar for Android devs) | + +--- + +## 3. GitHub Actions Remote Caching with Bazel + +### Option A: BuildBuddy Free Tier + +- BuildBuddy is open-source (MIT-licensed for individual features) and offers a free cloud tier for small teams and OSS projects. +- Provides a remote cache + build event viewer at `remote.buildbuddy.io`. +- GitHub Actions integration via `.bazelrc`: + ``` + build:remote --remote_cache=grpcs://remote.buildbuddy.io + build:remote --remote_executor=grpcs://remote.buildbuddy.io + build:remote --remote_header=x-buildbuddy-api-key=${{ secrets.BUILDBUDDY_ORG_API_KEY }} + ``` +- Also supports Remote Build Execution (RBE) for parallelizing compilation across machines (paid tiers). +- Free tier limits not explicitly published; suitable for OSS/small-team use. +- Sources: [BuildBuddy RBE with GitHub Actions](https://www.buildbuddy.io/docs/rbe-github-actions/), [Bazel Remote Caching Explained — BuildBuddy](https://www.buildbuddy.io/blog/bazels-remote-caching-and-remote-execution-explained/) + +### Option B: bazel-remote (Self-Hosted) + +- [buchgr/bazel-remote](https://github.com/buchgr/bazel-remote): A dedicated remote cache server, battle-tested (serving TBs/day since 2018). +- Implements the Bazel Remote Execution API v2 (ActionCache + CAS + Capabilities + Byte Stream). +- Can be run as a Docker container; backends: local disk, AWS S3, GCS, Azure Blob. +- With GitHub Actions: deploy bazel-remote on a persistent server or AWS/GCP, point Bazel at its gRPC/HTTP endpoint. +- Self-hosting cost vs BuildBuddy free tier: bazel-remote requires infrastructure management; BuildBuddy free removes this overhead for small teams. + +### Option C: bazel-github-actions-cache + +- [tsawada/bazel-github-actions-cache](https://github.com/tsawada/bazel-github-actions-cache): Acts as a local Bazel remote cache server that uses GitHub Actions' cache API as its backend. +- Usage: add one workflow step + point Bazel at the local cache server. +- Advantage: zero infrastructure cost (uses GitHub's existing cache storage). +- Disadvantage: GitHub Actions cache is per-repo, has 10 GB limit, and the undocumented API may break. +- Best for: small-to-medium projects where BuildBuddy free tier limits are a concern. + +### "Build without the Bytes" (Bazel 7.0+, Dec 2023) + +- Enabled by default in Bazel 7.0 LTS. +- Prevents intermediate output downloads from remote cache/execution — only final outputs are downloaded. +- Major CI speedup for projects using remote caching, as network transfer was previously the bottleneck. +- Source: [Bazel 7.0 Release Blog](https://blog.bazel.build/2023/12/11/bazel-7-release.html) + +### Reported Cache Hit Rates + +- No specific public benchmarks for cache hit rates with BuildBuddy free tier on Android/Kotlin were found. +- General Bazel literature reports: with a properly seeded remote cache and `--config=ci`, typical CI hit rates for large monorepos are 70–90% on non-main-branch builds (i.e., only changed modules rebuild). +- The 2024 empirical study (3,500 experiments, 383 GitHub projects) found: incremental builds achieve **median 4.22x speedup** (tool-independent cache) and **4.71x speedup** (Bazel-specific cache) vs clean builds. + +--- + +## 4. Developer Experience Features + +### `bazel run` / `bazel test` + +- `bazel run //kmp:run` — analogous to `./gradlew run`. Builds the target and executes it. +- `bazel test //...` — runs all tests. `bazel test //kmp:jvmTest` — runs specific test target. +- Test caching: Bazel caches test results by input hash. If no inputs changed, the test is reported as passed from cache (no rerun). This is a significant CI speedup. +- Bazel test results are cached even across machines via remote cache — a PR that shares an ancestor with main can skip tests already green on main. + +### `ibazel` (Watch Mode) + +- [ibazel](https://github.com/bazelbuild/bazel-watcher): Watches source files and re-runs a Bazel command on change. Analogous to `gradle -t` (continuous build). +- Supports `ibazel run //app:desktop` for live-reload style development. +- Note: no specific 2024–2025 ibazel improvements were found in this research; it is a stable tool. + +### IntelliJ / Android Studio Bazel Plugin + +- **Legacy plugin** (Google): [Bazel for IntelliJ](https://plugins.jetbrains.com/plugin/8609-bazel-for-intellij) — still available but being deprecated in 2026. +- **New JetBrains plugin** (GA as of 2025.2): Full IDE experience — code assistance during editing, run/debug targets, code coverage, Search Everywhere for Bazel targets. Android support available for early testing as of Q2 2025. +- Transition: JetBrains took over from Google's original plugin. Google's plugin will be kept with compatibility updates through 2025, fully deprecated 2026. +- Sources: [Bazel Plugin GA Release — JetBrains Blog](https://blog.jetbrains.com/idea/2025/07/bazel-ga-release/), [Getting Started with JetBrains Bazel Plugin](https://blog.jetbrains.com/idea/2024/12/getting-started-with-the-jetbrains-bazel-plugin/) +- **Critical gap for SteleKit**: Android Studio Bazel plugin is built from a separate Google branch; Android Studio support lags IntelliJ support significantly. + +--- + +## 5. Migration Tooling + +### Airin + Pendant (Turo / Morfly) + +- [Airin](https://github.com/Morfly/airin): Gradle plugin that analyzes project structure and generates Bazel BUILD files. +- Pendant: Kotlin DSL for generating Starlark code programmatically. +- Best for: Android/JVM Kotlin projects. Does not handle KMP targets (iOS, Wasm). +- Last known active: May 2024. + +### Grazel (Grab) + +- [Grazel](https://github.com/grab/Grazel): Gradle plugin for incremental, automated Gradle-to-Bazel migration. +- Generates `WORKSPACE`, `BUILD.bazel` files from existing Gradle scripts. +- Designed for large Android monorepos; Grab uses it for their 2.5M LOC app. +- Does not handle KMP multi-target builds. + +### Gazelle Kotlin Extension + +- [gazelle-kotlin](https://pkg.go.dev/github.com/srmocher/gazelle-kotlin): Early-stage Gazelle extension for Kotlin that generates `kt_jvm_library` targets from `.kt` files. +- Still experimental / work-in-progress. Not suitable as a primary migration tool. + +### bazel-diff (Tinder) + +- [bazel-diff](https://github.com/Tinder/bazel-diff): Computes the affected Bazel target set between two Git revisions. +- Enables "run only affected tests" in CI — a major CI time saver for large projects. +- Supports projects with tens of thousands of targets (uses streaming protobuf for scalability). +- BazelCon 2024 talk: "Not Going the Distance: Filtering Tests by Build Graph Distance." + +### Bazel Project Generator (Cirrus Labs) + +- [bazel-project-generator](https://github.com/cirruslabs/bazel-project-generator): Generates Bazel BUILD files for Kotlin/Java projects. +- Automates ~90% of the work for dependency declarations. + +--- + +## 6. Realistic Timeline / Effort for ~50k LOC KMP Project + +### Baseline: Pure Android/Kotlin JVM Projects + +- **Small Android app** (no custom Gradle logic, <10 modules): 1–4 weeks with automated tooling (Airin/Grazel). +- **Medium Android app** (20–50 modules, some custom Gradle tasks): 2–3 months with automation + manual fixes. +- **Large Android monorepo** (100+ modules): 5+ months for PoC (Grab's reported timeline); 12–18 months for full migration with CI integration. + +### SteleKit-Specific Assessment (KMP with Desktop, Android, iOS, Web) + +SteleKit is NOT a typical Android/Kotlin project — it is a full KMP project. This fundamentally changes the migration calculus: + +| Target | Bazel Support Status | Effort Implication | +|---|---|---| +| JVM (Desktop) | Supported via `rules_kotlin` | Feasible | +| Android | Supported via `rules_android` + `rules_kotlin` | Feasible but complex (AGP replacement) | +| iOS (Kotlin Native) | **NOT supported** in rules_kotlin | **Blocker** — requires custom rules or waiting for GSoC 2025 output | +| WebAssembly | **NOT supported** | **Blocker** — no Wasm compilation in Bazel Kotlin rules | +| Compose Multiplatform | **NOT supported** | **Blocker** — no Compose compiler integration in Bazel for KMP | + +**Honest timeline estimate for full SteleKit migration (all targets)**: +- **JVM-only (Desktop + shared JVM code)**: 2–4 months. Feasible with current tooling. +- **JVM + Android (dropping iOS/Wasm for now)**: 4–8 months. Requires replacing AGP entirely with `rules_android`. Dependency management with `rules_jvm_external` is the main challenge. +- **Full KMP (all 4 targets)**: **Not feasible with current Bazel tooling.** iOS/Kotlin Native and Wasm support must wait for `rules_kotlin` KMP work (GSoC 2025 deliverables, likely available late 2025–2026). Estimated: **12–24+ months**, mostly blocked on upstream tooling maturity. + +**Key risks and pain points for any KMP Bazel migration**: +1. `expect/actual` mechanism requires compiler coordination across platform compilations — Bazel has no model for this today. +2. Compose Multiplatform's compiler plugin integration is tightly coupled to the Kotlin Gradle Plugin (KGP); extracting it for Bazel is non-trivial. +3. `rules_jvm_external` (Maven dependency resolution for Bazel) is the only viable dependency manager, but it does not understand Gradle Metadata (`.module` files) which KMP libraries use for platform-specific artifact selection. +4. Every KMP library update (e.g., Kotlinx Coroutines, SQLDelight) requires verifying it works in the Bazel build — no automated mechanism. +5. The developer inner loop (edit → compile → test) requires IntelliJ's Bazel plugin, which has rough edges for Android and no KMP-specific support. + +--- + +## Summary Table + +| Topic | Finding | +|---|---| +| Best OSS migration examples | Grab (Grazel, 2.5M LOC), Turo (Airin, large multi-module) | +| KMP support in Bazel | iOS, Wasm, Compose: NOT supported. JVM + Android: feasible. | +| Remote caching options | BuildBuddy free tier (easiest), bazel-remote (self-hosted), bazel-github-actions-cache | +| Incremental build benefit | 4.22–4.71x median speedup over clean builds with caching | +| IntelliJ IDE support | JetBrains new plugin GA 2025.2; Android Studio lags | +| Migration tooling | Airin, Grazel, bazel-diff — all Android/JVM only, not KMP-aware | +| Timeline (JVM-only) | 2–4 months | +| Timeline (JVM + Android) | 4–8 months | +| Timeline (full KMP) | 12–24+ months, blocked on upstream rules_kotlin KMP work | + +--- + +## Sources + +- [How Grab is Blazing Through the Superapp Bazel Migration](https://engineering.grab.com/how-grab-is-blazing-through-the-super-app-bazel-migration) +- [Grazel — Gradle to Bazel Migration Tool (Grab)](https://github.com/grab/Grazel) +- [Boosting Bazel Adoption on Android With Automation — Turo Engineering](https://medium.com/turo-engineering/boosting-bazel-adoption-on-android-with-automation-6dc79d298628) +- [Airin — Automated Gradle-to-Bazel Migration](https://github.com/Morfly/airin) +- [Automated migration with Airin — ProAndroidDev](https://proandroiddev.com/automated-migration-of-your-projects-to-bazel-build-system-with-airin-304fa8b3680c) +- [Migrating Android Projects from Gradle to Bazel — Medium](https://medium.com/@imamyusufb123/migrating-android-projects-from-gradle-to-bazel-a-complete-guide-for-developers-4e67aea0883c) +- [Taming Bazel Dependency Conflicts: An Android Case Study](https://medium.com/@taufik.amary/taming-bazel-dependency-conflicts-an-android-case-study-44b7926839be) +- [rules_kotlin — GitHub](https://github.com/bazelbuild/rules_kotlin) +- [Kotlin Bazel Cross-Platform Roadmap Issue #567](https://github.com/bazelbuild/rules_kotlin/issues/567) +- [Kotlin Bazel Roadmap (rules_kotlin)](https://bazel.googlesource.com/rules_kotlin/+/59dc7473c777b5054e91c1af6b95ed0ecbdc0ace/ROADMAP.md) +- [GSoC 2025 Kotlin — KMP Bazel project](https://kotlinlang.org/docs/gsoc-2025.html) +- [Compose Multiplatform Bazel support — Kotlinlang Slack](https://slack-chats.kotlinlang.org/t/3145636/does-compose-multiplatform-support-bazel) +- [We need a build system for Kotlin — Kotlinlang Slack](https://slack-chats.kotlinlang.org/t/16406255/we-need-a-build-system-for-kotlin-we-have-reached-our-limit-) +- [Bazel vs Gradle — Buildkite](https://buildkite.com/resources/comparison/bazel-vs-gradle/) +- [Gradle vs Bazel for JVM Projects — Gradle Blog](https://blog.gradle.org/gradle-vs-bazel-jvm) +- [Does Using Bazel Help Speed Up CI Builds? (2024 Empirical Study)](https://dl.acm.org/doi/10.1007/s10664-024-10497-x) +- [Android Build Performance — Bazel Docs](https://bazel.build/docs/android-build-performance) +- [Bazel 7.0 LTS Release](https://blog.bazel.build/2023/12/11/bazel-7-release.html) +- [BuildBuddy RBE with GitHub Actions](https://www.buildbuddy.io/docs/rbe-github-actions/) +- [Bazel Remote Caching Explained — BuildBuddy](https://www.buildbuddy.io/blog/bazels-remote-caching-and-remote-execution-explained/) +- [buchgr/bazel-remote](https://github.com/buchgr/bazel-remote) +- [bazel-github-actions-cache](https://github.com/tsawada/bazel-github-actions-cache) +- [Remote Caching — Bazel Docs](https://bazel.build/remote/caching) +- [bazel-diff — Tinder](https://github.com/Tinder/bazel-diff) +- [JetBrains Bazel Plugin GA Release](https://blog.jetbrains.com/idea/2025/07/bazel-ga-release/) +- [Introducing the New Bazel Plugin EAP for IntelliJ IDEA](https://blog.jetbrains.com/idea/2024/12/introducing-the-new-bazel-plugin-eap-for-intellij-idea/) +- [Getting Started with JetBrains Bazel Plugin](https://blog.jetbrains.com/idea/2024/12/getting-started-with-the-jetbrains-bazel-plugin/) +- [Bazel with Android + Kotlin — Scalio](https://scal.io/blog/bazel-with-android-kotlin) +- [KMP Scalability Challenges — ProAndroidDev](https://proandroiddev.com/kotlin-multiplatform-scalability-challenges-on-a-large-project-b3140e12da9d) +- [gazelle-kotlin](https://pkg.go.dev/github.com/srmocher/gazelle-kotlin) +- [bazel-project-generator — Cirrus Labs](https://github.com/cirruslabs/bazel-project-generator) diff --git a/project_plans/stelekit-bazel/research/pitfalls.md b/project_plans/stelekit-bazel/research/pitfalls.md new file mode 100644 index 00000000..5ec7548a --- /dev/null +++ b/project_plans/stelekit-bazel/research/pitfalls.md @@ -0,0 +1,241 @@ +# Bazel + Kotlin Multiplatform Migration: Pitfalls Research + +**Researched**: 2026-05-17 +**Scope**: Known failure modes, gotchas, and risks for migrating SteleKit (KMP project) from Gradle to Bazel + +--- + +## 1. Compose Compiler Plugin in Bazel + +### How wiring works + +The Compose compiler plugin must be declared via `kt_compiler_plugin` in `rules_kotlin`. The correct pattern: + +```starlark +load("@rules_kotlin//kotlin:core.bzl", "kt_compiler_plugin") + +kt_compiler_plugin( + name = "jetpack_compose_compiler_plugin", + id = "androidx.compose.compiler.plugins.kotlin", + target_embedded_compiler = True, + visibility = ["//visibility:public"], + options = { + "suppressKotlinVersionCompatibilityCheck": "2.x.x", + "sourceInformation": "true", + }, + deps = [ + artifact("org.jetbrains.kotlin:kotlin-compose-compiler-plugin-embeddable"), + ], +) +``` + +Each `kt_jvm_library` or `kt_android_library` that uses Compose must reference the plugin via its `plugins` attribute. + +### K2 mode breaking change (CRITICAL) + +Starting with Compose Multiplatform 1.8.0, the framework **requires** K2. Since Kotlin 2.0, the Compose compiler has been bundled into the Kotlin repository itself (the `kotlin-compose-compiler-plugin-embeddable` artifact), rather than being a separate JetBrains artifact. + +**Active open issue (rules_kotlin #1388, filed Oct 2025)**: Using Compose BOM 2025.10.00 with Kotlin 2.x in Bazel causes: +``` +Argument type mismatch: actual type is 'Function0', but +'@Composable() ComposableFunction0' was expected. +``` +This error means **the Compose plugin is not active during compilation**, even when `kt_compiler_plugin` is declared. The plugin registration mechanism changed between K1 and K2, and `rules_kotlin` has not yet fully adapted. `suppressKotlinVersionCompatibilityCheck` is a workaround, but its correct value for K2 is non-obvious. + +### Plugin ordering risk + +When both KSP (for Arrow Optics) and the Compose compiler plugin are active on the same target, ordering matters. The Compose plugin must run before the KSP processor sees the transformed composable types; Bazel's `plugins` list order is not guaranteed to be honored in the same way Gradle subplugins are. This requires careful testing. + +### Version pinning requirement + +The Compose compiler version must exactly match the Kotlin version (`kotlin-compose-compiler-plugin-embeddable:2.x.x` must equal the Kotlin toolchain version). In Gradle this is enforced by the `org.jetbrains.kotlin.plugin.compose` Gradle plugin; in Bazel you must pin it manually in `rules_jvm_external` and ensure it never drifts. + +--- + +## 2. SQLDelight + Bazel + +### Official support exists but is scoped + +Square maintains `github.com/square/sqldelight_bazel_rules` — a dedicated `sqldelight_codegen` Starlark rule. This is a real, maintained artifact, not a DIY exercise. + +```starlark +sqldelight_codegen( + name = "stele_database_gen", + package_name = "dev.stapler.stelekit", + srcs = glob(["src/commonMain/sqldelight/**/*.sq"]), + database_dialect = "sqlite:3.24", + src_dir = "src/commonMain/sqldelight", +) +``` + +### Key limitations + +- **KMP not fully covered**: `sqldelight_bazel_rules` is primarily tested for JVM and Android targets. Generating code for multiple KMP targets (iOS native, WASM) from a single Bazel rule is undocumented and likely requires custom per-platform `sqldelight_codegen` calls or a wrapper. +- **No Gradle CLI**: SQLDelight has no standalone CLI or non-Gradle entry point, so the Bazel rule invokes the Gradle plugin logic via a bootstrapped runner. This is a maintenance liability — SQLDelight Gradle plugin version changes may break the Bazel rule without notice. +- **Checked-in generated sources alternative**: The pragmatic fallback is to check in the generated Kotlin sources and treat them as regular source files in Bazel. This trades build hermeticity for simplicity but creates a dual-maintenance risk (schema and generated code can diverge). +- **Sub-package naming**: The rule generates `DatabaseImpl` in a sub-package derived from the Bazel package/target name, not from the SQLDelight `packageName` in the `.sq` file. This diverges from the Gradle behavior and may require source-level changes. + +--- + +## 3. KSP (Kotlin Symbol Processing) in Bazel + +### Arrow's actual KSP usage + +Arrow core (`arrow-core`, `arrow-coroutines`, `arrow-fx`) does **not** require KSP or KAPT — it is a pure Kotlin library with no annotation processing. **The exception is `arrow-optics`**, which requires: + +```kotlin +ksp("io.arrow-kt:arrow-optics-ksp-plugin:2.x.x") +``` + +SteleKit's CLAUDE.md shows Arrow is used for `Either`-based error handling only. Unless `@optics` annotations are used anywhere, **Arrow does not trigger a KSP requirement**. Confirm by grepping for `@optics` before treating KSP as mandatory. + +### KSP in rules_kotlin + +KSP is officially supported since `rules_kotlin` 1.8 via `kt_ksp_plugin`. The migration from KSP1 (compiler plugin) to KSP2 (standalone tool) is underway; KSP2 has been the default since early 2025. The `rules_kotlin` team is tracking this migration. + +**Open limitation (rules_kotlin issue #1035)**: Passing options to KSP processors was not supported until recently. This is now fixed, but combined KSP + Compose plugin targets remain under-tested in Bazel. + +### KAPT status + +KAPT is in maintenance mode and deprecated. If any dependency still requires KAPT (not KSP), Bazel support is weaker. Verify all annotation-processing dependencies have KSP variants before committing to the migration. + +--- + +## 4. IDE Integration Risks + +### Two plugin ecosystems, both in flux + +There are now **two separate Bazel plugins for IntelliJ/Android Studio**: + +| Plugin | Status (May 2026) | Origin | +|--------|------------------|--------| +| Google's IJwB (`bazelbuild/intellij`) | Maintenance-only, will be deprecated in 2026 | Google (transferred ownership) | +| JetBrains new Bazel plugin | GA since 2025.2, requires IntelliJ 2025.2+ | JetBrains | + +The JetBrains plugin reached GA only in mid-2025 and is focused on JVM, Kotlin, Scala, Python, Go. **KMP-specific features in the Bazel plugin are not documented** — the KMP plugin (beta, macOS-only until IntelliJ 2025.2.2) is separate and its interaction with Bazel projects is untested. + +### Kotlin Multiplatform plugin vs Bazel + +The KMP IDE plugin (which gives expect/actual navigation, KMP facet support, etc.) is designed for Gradle-based KMP projects. There is no documented path for KMP + Bazel projects to get full KMP IDE tooling. Developers would likely lose: +- expect/actual cross-navigation +- Platform-specific source set highlighting +- KMP run configurations + +### Known issue: wrong Kotlin version in IDE + +`bazelbuild/intellij` issue #1274: The Bazel IntelliJ plugin sets the wrong Kotlin version in IDE project model, causing spurious red errors in the editor that do not reflect actual build failures. + +--- + +## 5. iOS + Bazel + +### macOS build host is non-negotiable + +Kotlin/Native **cannot produce final iOS binaries on Linux or Windows**. The Kotlin/Native documentation is explicit: "Building final binaries for Apple targets on Linux and Windows is not possible." Intermediate `.klib` artifacts can be cross-compiled, but the final `.framework` or `.xcframework` must be built on macOS. + +**Implication**: If CI currently runs on Linux (e.g., GitHub Actions `ubuntu-latest`), a macOS runner must be added (or substituted) for iOS builds. This is a cost and infrastructure change. + +### rules_apple complexity + +Bazel's official `rules_apple` covers bundling `.ipa`/`.app` but: +- Still relies on `xcrun` to invoke Apple tools (not hermetic — xcrun searches the system PATH) +- Cross-compilation scenarios require careful platform constraint configuration +- Swift interop (needed for Kotlin/Native XCFramework consumption by Swift/Obj-C host apps) adds a `rules_swift` dependency on top of `rules_apple` + +### Kotlin/Native toolchain download + +Kotlin/Native downloads its own compiler distribution (`~/.konan/`) during builds. In a hermetic Bazel environment this download is **forbidden** during the build phase. The toolchain must be pre-fetched and declared as a Bazel repository dependency via a `http_archive` or similar. There is no out-of-the-box `rules_kotlin` support for this; it requires custom Starlark toolchain rules. + +### Community alternative: rules_ios + +`github.com/bazel-ios/rules_ios` is a community-maintained alternative to `rules_apple` with broader iOS feature coverage, but adds a third-party dependency with its own update cadence risk. + +--- + +## 6. Hermetic Build Risks + +### Gradle plugins that do network access + +The following patterns in the current SteleKit Gradle build would break Bazel's sandboxing: + +| Pattern | Gradle behavior | Bazel impact | +|---------|----------------|--------------| +| Kotlin/Native toolchain | Downloads from `download.jetbrains.com/kotlin/native/` automatically | Must be pre-declared as `http_archive` | +| SQLDelight code generation | Gradle plugin may resolve additional artifacts at configure time | Code gen rule must have all deps in `WORKSPACE` | +| Compose resources (fonts, images) | May fetch from Maven or CDN | All assets must be local or pre-fetched | +| Version catalogs (`libs.versions.toml`) | Gradle resolves BOMs at sync time | BOM contents must be pinned in `rules_jvm_external` lockfile | + +### rules_jvm_external and BOM support + +Gradle's BOM (Bill of Materials) support is native. In Bazel, `rules_jvm_external` supports BOMs but requires explicit `bom_imports` configuration. Version alignment that Gradle does automatically (e.g., Compose BOM aligning all `androidx.compose.*` versions) must be replicated manually in the `maven_install` rule. + +### Minimal Version Selection vs Newest Version Selection + +Gradle uses Newest Version Selection; Bazel's `rules_jvm_external` uses a Maven-compatible resolver. This means transitive version conflicts that Gradle silently resolved via "pick the newest" will **surface as hard errors** in Bazel until the lockfile is explicitly fixed. KMP projects with many transitive dependencies (Compose, Coroutines, SQLDelight, Arrow) are particularly exposed. + +--- + +## 7. Migration Effort Realism + +### Google's AOSP Bazel migration was cancelled (2024) + +Google's project to migrate Android Open Source Project (AOSP) to Bazel was cancelled in April 2024, citing that "the project took longer than anticipated" and Android business priority reviews. This is the largest Android/Kotlin Bazel migration attempt ever made — its cancellation is a strong signal about the difficulty ceiling. + +### Academic research: 11% abandonment rate + +A study by the REBELs group (U. of Waterloo) of 35,000 GitHub projects found ~11% of projects that adopted Bazel abandoned it around the 2-year mark. Reasons cited: technical challenges, team onboarding difficulty, and observing other high-profile projects (e.g., Kubernetes) leaving Bazel. + +### KMP-specific difficulty + +A Google Summer of Code 2025 project was proposed specifically to improve Bazel's KMP support — treating it as a research/engineering problem rather than a solved one. The proposal targets dependency resolution issues and cross-platform build support that remain open as of 2025. + +### Compose BOM version lock-in + +Teams using Bazel with Kotlin/Compose have reported being **stuck on older Compose BOM versions** because updating to 2025.x requires Kotlin 2.x, which requires adapting `rules_kotlin` in ways that are non-trivial. This creates a maintenance lag: the Gradle ecosystem moves fast; Bazel wrappers follow slowly. + +### Plugin ecosystem gap + +Gradle has hundreds of ecosystem plugins (Detekt, Dokka, Spotless, versions plugin, etc.) that SteleKit likely uses (CLAUDE.md shows Detekt in CI). Each Gradle plugin must be replicated as a Bazel rule or dropped. There is no Detekt Bazel rule; it would need to run as a `genrule` or separate CI step, losing Bazel caching benefits. + +--- + +## 8. Version Compatibility Matrix + +### rules_kotlin version vs Kotlin version + +`rules_kotlin` releases track Kotlin versions closely. The latest is `v2.3.20`, supporting Kotlin language levels 1.9, 2.0, 2.1, 2.2, 2.3. There is no published formal compatibility matrix, but the pattern is: + +| rules_kotlin release | Kotlin version | K2 support | KSP version | +|---------------------|---------------|-----------|-------------| +| 1.8.x | Kotlin 1.9.x | KSP1 only | KSP1 | +| 2.0.x–2.1.x | Kotlin 2.0–2.1 | `x_use_k2` flag | KSP1 → KSP2 transition | +| 2.3.x (current) | Kotlin 2.3 | K2 default | KSP2 | + +**Critical constraint**: `rules_kotlin` does **not** support Kotlin/Native or Kotlin/WASM targets. Only JVM, Android, and JS (partially maintained) are supported. For a full KMP build (JVM + Android + iOS/Native + WASM), multiple rule sets are required — and several of those rule sets do not exist yet in a production-ready state. + +### Bazel version requirements + +`rules_kotlin` 2.x requires Bazel 6.0+ (Bzlmod-compatible). Bazel 8.0 LTS was released December 2024 and is the current recommended version. The Bzlmod module system (replacing WORKSPACE) is now the default; older WORKSPACE-based setups are deprecated. + +### Compose Multiplatform version requirements + +| Compose Multiplatform | Required Kotlin | Compose compiler source | +|----------------------|----------------|------------------------| +| < 1.6.0 | Kotlin 1.9.x | Separate JetBrains artifact | +| 1.6.x–1.7.x | Kotlin 2.0–2.1 | Bundled in Kotlin repo | +| 1.8.0+ | Kotlin 2.0+ (K2 required) | `kotlin-compose-compiler-plugin-embeddable` | + +SteleKit should be using Compose Multiplatform 1.8.x by now. This means: +- K2 is mandatory +- The Gradle plugin `org.jetbrains.kotlin.plugin.compose` approach doesn't translate to Bazel +- Manual `kt_compiler_plugin` wiring is required, with the active bug (issue #1388) unresolved + +--- + +## Summary of Highest-Risk Items + +1. **Kotlin/Native + iOS is unsupported by rules_kotlin** — there are no `kt_native_*` rules. Building the iOS target requires writing custom Starlark toolchain rules for the Kotlin/Native compiler distribution (which also cannot be network-fetched during builds). This is the single largest gap and could block full KMP migration. + +2. **Compose compiler plugin K2 wiring is actively broken** — rules_kotlin issue #1388 (October 2025) shows that Compose BOM 2025 + Kotlin 2.x does not work out-of-the-box in Bazel. The `@Composable` type transformation fails silently, producing type mismatch errors at call sites. This must be resolved before any Compose UI code can build under Bazel. + +3. **SQLDelight multiplatform code generation is undocumented** — `sqldelight_bazel_rules` exists for JVM/Android but has no documented KMP multi-target support. Generating `commonMain` Kotlin + native drivers for all platforms will require either custom Starlark work or a checked-in generated sources strategy, both of which have ongoing maintenance costs. diff --git a/project_plans/stelekit-bazel/research/stack.md b/project_plans/stelekit-bazel/research/stack.md new file mode 100644 index 00000000..4d65db9b --- /dev/null +++ b/project_plans/stelekit-bazel/research/stack.md @@ -0,0 +1,231 @@ +# Stack Research: Bazel Ruleset Ecosystem for Kotlin Multiplatform + +_Researched: 2026-05-17_ + +--- + +## 1. `bazelbuild/rules_kotlin` — Current State and KMP Support + +### Status + +- **Latest release**: `2.3.20` (available in the Bazel Central Registry as of May 2026). +- `bazel_dep(name = "rules_kotlin", version = "2.3.20")` in MODULE.bazel is the current entry point. +- Actively maintained under `bazel-contrib/rules_kotlin` (moved from `bazelbuild/`). + +### What Is Supported + +- `kt_jvm_library`, `kt_jvm_binary`, `kt_jvm_test` — stable and production-quality. +- `kt_android_library` — works; used by companies like Turo and Grab in production monorepositories. +- `kt_js_library` — exists but is less mature. +- Compiler plugins via `kt_compiler_plugin` and `kt_ksp_plugin` (KSP support since 1.8). +- KAPT annotation processing via `java_plugin` / `exported_plugins`. + +### What Is NOT Supported + +- **Kotlin Multiplatform (KMP) in the full sense is not supported.** There are no `kt_multiplatform_library` rules, no `expect`/`actual` mechanism, and no way to express source set hierarchies (`commonMain`, `jvmMain`, `androidMain`, `iosMain`, `jsMain`) in Bazel BUILD files. +- **Issue #567** ("Kotlin Bazel Cross-Platform Roadmap") has been open for years. The roadmap document acknowledges the gap but there is no concrete implementation of `expect`/`actual` handling in rules_kotlin. +- **Kotlin/Native (iOS) is completely absent.** rules_kotlin has no `kt_native_*` rules. Compiling to a Kotlin/Native framework for iOS or a `.klib` for WASM is outside its scope. +- A 2022 Kotlin Slack answer confirmed: "Bazel migration is possible for Kotlin JVM or JS projects, but not for KMP." + +### Kotlin 2.x / K2 Compatibility + +- Kotlin 2.3.20 (the latest as of May 2026) is the language release; `rules_kotlin 2.3.20` tracks a similar version number but the two are not guaranteed to be in sync. +- **Compose with Kotlin 2.x is a known friction point.** Issue #1388 in rules_kotlin (filed October 2025) reports that using Compose BOM `2025.10.00` with Kotlin 2.x fails because the Compose compiler moved from a standalone artifact to `org.jetbrains.kotlin:kotlin-compose-compiler-plugin-embeddable` (bundled with Kotlin since 2.0). The Compose compiler plugin integration in rules_kotlin requires a `suppressKotlinVersionCompatibilityCheck` workaround and is not yet seamlessly supported. +- The working pattern for Compose on JVM with rules_kotlin is: + +```starlark +kt_compiler_plugin( + name = "compose_compiler_plugin", + id = "androidx.compose.compiler.plugins.kotlin", + target_embedded_compiler = True, + options = { + "suppressKotlinVersionCompatibilityCheck": "2.0.21", + "sourceInformation": "true", + }, + deps = [ + artifact("org.jetbrains.kotlin:kotlin-compose-compiler-plugin-embeddable"), + ], +) +``` + +This works for **Compose on JVM/Android** only. Compose Multiplatform (Desktop, iOS, WASM) has no Bazel support path. + +### Kotlin Build Tools API (KEEP-421) + +JetBrains introduced the Build Tools API in Kotlin 1.9.20 as the official integration point for non-Gradle build tools, including incremental compilation support. Meta used this to enable Kotlin incremental compilation in Buck2 (announced August 2025). rules_kotlin has not yet adopted this API — it still drives `kotlinc` directly. Adoption of KEEP-421 would unlock true incremental builds in Bazel, but there is no public timeline. + +--- + +## 2. `rules_kmp` — Community KMP + Bazel Projects + +There is **no mature, production-ready `rules_kmp` project** as of May 2026. Searches across GitHub, the Bazel Central Registry, and the Kotlin Slack archive found: + +- No GitHub repository named `rules_kmp` with meaningful adoption. +- A GSoC 2025 Kotlin project description referencing Bazel KMP support improvements (dependency resolution, Gradle metadata, `expect`/`actual` linkage), but no shipped artifact from that work is publicly available. +- Individual developer experiments exist (not indexed in BCR, no versioned releases). + +**Conclusion**: `rules_kmp` does not exist as a usable library. KMP in Bazel requires custom bespoke rules or a different strategy. + +--- + +## 3. Alternative Approaches + +### 3a. Bazel for JVM-only, Gradle for Native Targets (Hybrid) + +The pragmatic approach used by the few teams building KMP + Bazel: +- Use Bazel to compile `commonMain` + `jvmMain` + `androidMain` source sets (these are all JVM-compatible). +- Leave iOS (`iosMain`, Kotlin/Native) and WASM (`jsMain`) compiled by Gradle, or produce `.klib` artifacts via Gradle and treat them as pre-built inputs to Bazel. +- This gives incremental Bazel benefits for the 80% of the code (JVM + Android) while keeping Gradle as a peripheral tool. + +### 3b. Gradle as a Bazel Pre-processor / Code Generator + +Run Gradle once to generate: +- SQLDelight Kotlin output (checked in or as a Gradle task artifact). +- Any KSP-generated code. +- `expect`/`actual` resolved source sets for each platform. + +Then feed the generated Kotlin files into Bazel's `kt_jvm_library` / `kt_android_library`. This approach makes Gradle a one-time generator, not the build system. The downside is that changes to `.sq` files or annotated code require re-running Gradle. + +### 3c. Gazelle for BUILD File Generation + +`srmocher/gazelle-kotlin` is a Gazelle extension that generates `kt_jvm_library` targets from Kotlin source files. It is described as "early work-in-progress" and relies on `rules_jvm_external` for dependency inference. It generates `kt_jvm_library` only — no KMP awareness. + +Gazelle reduces the BUILD file maintenance burden for JVM Kotlin, but it has no understanding of KMP source set structure (`commonMain` vs `jvmMain` etc.). + +### 3d. Airin (Morfly/airin) — Gradle-to-Bazel Migration Tool + +- A Gradle plugin that reads your Gradle project model and emits `.bzl` / `BUILD.bazel` files. +- Last updated February 2026, actively maintained by a Turo engineer. +- Targets Android + JVM Kotlin projects. No KMP multiplatform awareness. +- Useful for bootstrapping the initial BUILD file set for JVM/Android modules. + +### 3e. Grazel (Grab) — Incremental Gradle-to-Bazel Migration + +- Another Gradle plugin approach (`./gradlew migrateToBazel`), used in production at Grab. +- Handles Android, `kt_jvm_library`, Dagger, Hilt. No KMP multiplatform support. +- As of June 2025, still receiving issues and updates. + +### 3f. Buck2 as an Alternative to Bazel + +Meta's Buck2 is the strongest alternative for Kotlin + Android: +- KotlinConf 2025 (May, Copenhagen) featured "Build your Kotlin and Android apps with Buck2" by Meta's Sergei Rybalkin. +- Meta enabled Kotlin incremental compilation in Buck2 via the Build Tools API (KEEP-421), announced August 2025. +- Buck2 has mature Android rules (in Meta's monorepository) and remote execution. +- **But**: Buck2 also has no KMP (Kotlin/Native, WASM) rules. The same gap exists. Buck2 is written in Rust with all rules in Starlark, giving it better long-term extensibility but a steeper learning curve. + +--- + +## 4. SQLDelight + Bazel Integration + +### square/sqldelight_bazel_rules + +- **Official repository**: `github.com/square/sqldelight_bazel_rules` +- Provides a `sqldelight_codegen` Starlark rule that runs the SQLDelight compiler as a Bazel action, emitting generated Kotlin sources. +- Key attributes: `name`, `package_name`, `srcs` (`.sq` files), `database_dialect`, `src_dir`, `module_name`. +- The README states: "SQLDelight doesn't presently have a CLI or non-Gradle entry point, so the Bazel tooling provides this front-end until it can be upgraded." + +### SQLDelight 2.x Compatibility + +- **Critical issue**: The `square/sqldelight_bazel_rules` repository was built against SQLDelight 1.x (`com.squareup.sqldelight`). SQLDelight 2.0 changed the Maven group ID to `app.cash.sqldelight` — a breaking change. +- The last substantive commit in `sqldelight_bazel_rules` predates the 2.0 release, and there is no evidence of a 2.x-compatible release. +- **For SteleKit (SQLDelight 2.3.2)**: The existing Bazel rules are incompatible. Options: + 1. Fork `sqldelight_bazel_rules` and update it to invoke the `app.cash.sqldelight` 2.x CLI/compiler. + 2. Check in generated Kotlin sources from SQLDelight (`./gradlew generateCommonMainSteleDatabaseInterface`) and treat them as static source files in Bazel. + 3. Write a custom Bazel `genrule` / Starlark rule that shells out to the SQLDelight Gradle task and captures outputs. + +Option 2 (checked-in generated sources) is the lowest-risk path for initial migration: run Gradle once per schema change, commit the generated files, build everything else in Bazel. + +--- + +## 5. Compose Multiplatform + Bazel + +### Summary + +Compose Multiplatform (JetBrains) has **no official Bazel support**. The Kotlin Slack archive (2022, still accurate as of 2026) confirms: "Does compose multiplatform support Bazel? No." + +### JVM / Android Compose in Bazel (Partial Support) + +For **Compose on JVM** (Desktop) and **Jetpack Compose on Android**, the `kt_compiler_plugin` mechanism works with the workaround described in Section 1. This covers the `jvmMain` / `androidMain` Compose UI code in SteleKit. + +### Compose for iOS and WASM + +- These targets require Kotlin/Native and Kotlin/WASM toolchains respectively. +- Neither is available in rules_kotlin or any Bazel ruleset. +- Compose for iOS is stable as of 2025; Compose for Web (WASM) is in Beta. Both are Gradle-only from a build tooling perspective. + +### Compose Compiler Plugin Versioning + +- Since Kotlin 2.0, the Compose compiler is bundled: `org.jetbrains.kotlin:kotlin-compose-compiler-plugin-embeddable` (matches the Kotlin version). +- In rules_kotlin, you must explicitly declare this as a `kt_compiler_plugin`. The version must exactly match the Kotlin version used in the `kotlin_repositories()` call. Mismatches cause cryptic type errors ("actual type is `Function0`, expected `@Composable ComposableFunction0`"). + +--- + +## 6. Toolchain Requirements + +### JDK Version Pinning + +- Bazel 7.4+ / 8.x supports `local_java_repository` / `remote_java_repository` for pinning. +- `rules_kotlin 2.3.20` requires a minimum of Bazel 7.4; Bazel 8.x is recommended. +- JDK 17 or 21 should be pinned via MODULE.bazel `java_toolchains` extension for reproducible builds. + +### Kotlin Version Compatibility + +- rules_kotlin 2.3.20 supports recent Kotlin releases. It declares the Kotlin toolchain in `kotlin_repositories(kotlin_release_version = "2.x.y")`. +- The Kotlin version in rules_kotlin must match the version of `kotlin-compose-compiler-plugin-embeddable` used in the Compose plugin declaration. +- Kotlin 2.3.x (December 2025 release) brought stricter KMP metadata dependency matching that can cause metadata compilation failures. This is a KMP-specific concern less relevant if we compile only JVM/Android targets in Bazel. + +### Android SDK (rules_android) + +- `rules_android 0.6.6` supports Bazel 7.4+ / 8.x. Available in the Bazel Central Registry. +- Android SDK is configured via `MODULE.bazel` with `android_sdk_repository` or `android_sdk_repository_name`. +- Toolchain registration covers `@rules_android//toolchains/android:android_default_toolchain`. +- The Android NDK (for any JNI) requires Android NDK 25b+ with `rules_android_ndk`. +- `rules_jvm_external` handles Maven dependency resolution. **Critical gap**: `rules_jvm_external` uses POM files by default, but KMP libraries publish Gradle Module Metadata (`.module` files) which encode platform-variant selection. AndroidX is reportedly considering dropping `.pom` support entirely (Issue #1376). PR #1357 in `rules_jvm_external` adds a Gradle metadata resolver, but it was still failing tests and was very slow as of late 2025. This means KMP Maven artifacts (e.g., `app.cash.sqldelight:runtime`) may resolve to the wrong variant (or fail to resolve) in Bazel without manual `artifact()` overrides specifying the correct classifier. + +### iOS Toolchain + +There are no Bazel rules for Kotlin/Native iOS compilation. iOS targets must remain in Gradle (or Xcode directly via the Kotlin/Native Xcode integration). rules_apple exists for Swift/ObjC iOS apps, but Kotlin/Native is not supported in any Bazel ruleset. + +### WASM/JS Toolchain + +`rules_kotlin` has basic `kt_js_library` but Kotlin/WASM (`wasm-js` target) has no Bazel support. WASM builds remain Gradle-only. + +--- + +## 7. Dependency Resolution: KMP Artifacts in rules_jvm_external + +KMP libraries publish platform-specific variants selected via Gradle Module Metadata. `rules_jvm_external` is POM-centric. This creates two concrete problems for SteleKit: + +1. **SQLDelight runtime** (`app.cash.sqldelight:runtime`) has a `jvm` artifact and an `android` artifact; without Gradle metadata resolution, Bazel may pick the wrong one or fail. +2. **Coroutines, Arrow, etc.** are KMP libraries. Their JVM artifacts are usually available with explicit classifiers (`:jvm` suffix or no classifier for the JVM variant), so manual `artifact()` declarations often work. + +Workaround: specify JVM-specific artifact coordinates explicitly in `maven_install`: +```starlark +artifact("app.cash.sqldelight:runtime-jvm:2.3.2") +artifact("app.cash.sqldelight:android-driver:2.3.2") +``` + +--- + +## 8. Key Open-Source Projects Reference Table + +| Project | URL | Maturity | KMP Support | Notes | +|---|---|---|---|---| +| rules_kotlin | github.com/bazel-contrib/rules_kotlin | Stable (2.3.20) | JVM + Android + JS only | No `expect`/`actual`, no Native/WASM | +| rules_android | github.com/bazelbuild/rules_android | Active (0.6.6) | Android only | SDK + NDK toolchains | +| rules_jvm_external | github.com/bazel-contrib/rules_jvm_external | Active | Partial (POM-only, KMP variant gap) | PR #1357 adds Gradle resolver (incomplete) | +| sqldelight_bazel_rules | github.com/square/sqldelight_bazel_rules | Stale (1.x only) | N/A | Does not support SQLDelight 2.x | +| gazelle-kotlin | github.com/srmocher/gazelle-kotlin | Early WIP | None | JVM BUILD file gen only | +| Airin | github.com/Morfly/airin | Active (Feb 2026) | None | Gradle→Bazel migration, Android/JVM | +| Grazel | github.com/grab/grazel | Active | None | Gradle→Bazel migration, Android | +| Buck2 | buck2.build | Active (Meta) | None | Best alternative to Bazel for Kotlin + Android | + +--- + +## Summary + +1. **rules_kotlin supports JVM and Android Kotlin well, but KMP is a hard wall.** The `expect`/`actual` mechanism, Kotlin/Native (iOS), and Kotlin/WASM are completely absent from rules_kotlin and from any other publicly available Bazel ruleset. There is no `rules_kmp` project worth adopting. A Bazel migration for SteleKit must either scope down to JVM + Android only, or adopt a hybrid where iOS and WASM targets remain Gradle-compiled. + +2. **SQLDelight 2.x has no working Bazel rules.** `square/sqldelight_bazel_rules` is stale and incompatible with `app.cash.sqldelight` 2.x. The lowest-risk path is to check in generated Kotlin sources from SQLDelight as a build artifact and exclude them from Bazel's incremental graph. A custom genrule invoking the SQLDelight CLI is the next step up. + +3. **Compose on JVM/Android in Bazel works with friction.** Using `kt_compiler_plugin` with `kotlin-compose-compiler-plugin-embeddable` is the documented path, but active issues (e.g., #1388) show that Kotlin 2.x + Compose BOM 2025.x requires careful version pinning and `suppressKotlinVersionCompatibilityCheck` workarounds. Compose Multiplatform (iOS, Web) has zero Bazel support. diff --git a/rules_jvm_external++maven+maven_install.json b/rules_jvm_external++maven+maven_install.json new file mode 100755 index 00000000..200125e3 --- /dev/null +++ b/rules_jvm_external++maven+maven_install.json @@ -0,0 +1,9405 @@ +{ + "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL", + "__INPUT_ARTIFACTS_HASH": 429783620, + "__RESOLVED_ARTIFACTS_HASH": 1257889864, + "artifacts": { + "androidx.activity:activity-compose:aar": { + "shasums": { + "jar": "adf2d7965116ea0d57b48e07c1e6e379739d0131084ec06c42bf9eabb963fbe6" + }, + "version": "1.9.2" + }, + "androidx.activity:activity-ktx:aar": { + "shasums": { + "jar": "046c0d51a1d0a0dfd56f9af1f418f9cc3d08839a8c404302b60547aaf224dcb6" + }, + "version": "1.9.2" + }, + "androidx.activity:activity:aar": { + "shasums": { + "jar": "72751e5895b6fd600faf3ebdfd3c9b2faf70e8d17b413c0b66dad98ca64b2a77" + }, + "version": "1.9.2" + }, + "androidx.annotation:annotation": { + "shasums": { + "jar": "38322afa7345c37e29c65ec8852178ae1c26e23096a0634d07a4a3893931f58c" + }, + "version": "1.9.1" + }, + "androidx.annotation:annotation-experimental:aar": { + "shasums": { + "jar": "6bd4c7c7476f8260cd3bdbb81183583e93fc9f790c27dea7dc314181cbf87aa0" + }, + "version": "1.4.1" + }, + "androidx.annotation:annotation-jvm": { + "shasums": { + "jar": "1e343917ebf27ba96fe4dc52b1cad7fd32b738fbc6355bb6cd5b3b305d7212d0" + }, + "version": "1.9.1" + }, + "androidx.appcompat:appcompat-resources:aar": { + "shasums": { + "jar": "55b6778602680f3c288ce350a2c2d3dd158d97dbffc63476275826655582c388" + }, + "version": "1.7.0" + }, + "androidx.appcompat:appcompat:aar": { + "shasums": { + "jar": "67189713b30a3fab6971713cc5fab1cb7f022bcf648a257563715c91d719d584" + }, + "version": "1.7.0" + }, + "androidx.arch.core:core-common": { + "shasums": { + "jar": "65308a06b1c00ee186cb9e19321383f043b993813f1522c47f4a3e3303bdba41" + }, + "version": "2.2.0" + }, + "androidx.arch.core:core-runtime:aar": { + "shasums": { + "jar": "a1be5e0caa2b07623862af6ae21b3ab0718123245184d0e30dea81b53f990a47" + }, + "version": "2.2.0" + }, + "androidx.arch.core:core-testing:aar": { + "shasums": { + "jar": "85e1fe770ed673ecb8552eaadc23b96d8db0a14a10eaa7789518496e5d99362c" + }, + "version": "2.2.0" + }, + "androidx.autofill:autofill:aar": { + "shasums": { + "jar": "c9468f56e05006ea151a426c54957cd0799b8b83a579d2846dd22061f33e5ecd" + }, + "version": "1.0.0" + }, + "androidx.camera:camera-camera2:aar": { + "shasums": { + "jar": "173253ed32c2f60e77081aab72e61dbcc4e767c9fe56cbb9b88f762b7725e99b" + }, + "version": "1.4.1" + }, + "androidx.camera:camera-core:aar": { + "shasums": { + "jar": "6c77068806cf259bbaa7ed955935bf2cd16dc103feb32f7ae3d55823fc9fcfc7" + }, + "version": "1.4.1" + }, + "androidx.camera:camera-lifecycle:aar": { + "shasums": { + "jar": "8324adb2c047905fffbd10a5bd978818157943619b91fcf410de94bd97b619a9" + }, + "version": "1.4.1" + }, + "androidx.collection:collection": { + "shasums": { + "jar": "f5ffb8f461c4b5d6f2883a2c7047977773b31d5b23ef030c057514c0c9eceb47" + }, + "version": "1.5.0" + }, + "androidx.collection:collection-jvm": { + "shasums": { + "jar": "70b35924e4babcdffa37d0e575ee039c56a2d97123342624c48b603233704341" + }, + "version": "1.5.0" + }, + "androidx.collection:collection-ktx": { + "shasums": { + "jar": "c6deada2fac53b8ea6523dbda77597b128006674616f140f04df23264c6d1aa3" + }, + "version": "1.4.2" + }, + "androidx.compose.animation:animation-android:aar": { + "shasums": { + "jar": "07acf0914030402924fcf1f698983e2e3220485ec636da7773421c150f765a7b" + }, + "version": "1.10.5" + }, + "androidx.compose.animation:animation-core-android:aar": { + "shasums": { + "jar": "a2ad085d080b05dd80c85646a015edfc278c03b9d096cc8c80fa3cc8fd9f8902" + }, + "version": "1.10.5" + }, + "androidx.compose.animation:animation-core:aar": { + "shasums": { + "jar": "854d6771e4d832319bbc103a52290dace4f3af9c4d48f93e452b13489a2babcd" + }, + "version": "1.10.5" + }, + "androidx.compose.animation:animation:aar": { + "shasums": { + "jar": "69221abe3cb686d82346464b08f0e80f450684b7ea6f9059a69ad4f90f1ba2ff" + }, + "version": "1.10.5" + }, + "androidx.compose.foundation:foundation-android:aar": { + "shasums": { + "jar": "7fd9f592d9b2e37fd7bbd3b07b35fe3869ce0391603f651e6bfc1caf6d13a693" + }, + "version": "1.10.5" + }, + "androidx.compose.foundation:foundation-layout-android:aar": { + "shasums": { + "jar": "b11250c899e65f73bb1f68643ebc37d9c6d9ddd014b4b86ce1e17e502a2fca59" + }, + "version": "1.10.5" + }, + "androidx.compose.foundation:foundation-layout:aar": { + "shasums": { + "jar": "f8a28cab65b33f66f8e221a28d4242122020fed3b9ea3b0221cff9b38b0cde09" + }, + "version": "1.10.5" + }, + "androidx.compose.foundation:foundation:aar": { + "shasums": { + "jar": "f0b2328af92337e63a9e0fe68d0da048d71218de001299689a3268361ac4724b" + }, + "version": "1.10.5" + }, + "androidx.compose.material3:material3-android:aar": { + "shasums": { + "jar": "3a37e8b36df3822fe1e6059f0f9fafda8800388860477624ac1b9422c418a36e" + }, + "version": "1.4.0" + }, + "androidx.compose.material3:material3:aar": { + "shasums": { + "jar": "178e7c4ba39f5c84a7a8fe78915d6cabf433ac7775cac73b14d395fabd3074cd" + }, + "version": "1.4.0" + }, + "androidx.compose.material:material-android:aar": { + "shasums": { + "jar": "636bb053b873ebb0c5be55c8ffb38c725e3aff4cfa58508a32505f3c24082c29" + }, + "version": "1.10.5" + }, + "androidx.compose.material:material-icons-core-android:aar": { + "shasums": { + "jar": "332c06b25e662cc417fb087e76b8faa5cb249f4992ffa3360084a3d4ab882284" + }, + "version": "1.7.8" + }, + "androidx.compose.material:material-icons-core:aar": { + "shasums": { + "jar": "cd9e25206c8d7f45e204c9be284671c2c3b6c7c30f14c623fe758e4364122b03" + }, + "version": "1.7.8" + }, + "androidx.compose.material:material-icons-extended-android:aar": { + "shasums": { + "jar": "64e86269f1106848981dd76f0046f81b46f3bd92efb22645de8fd044c0402b61" + }, + "version": "1.7.8" + }, + "androidx.compose.material:material-icons-extended:aar": { + "shasums": { + "jar": "83b3bd069950401ba04386e5df927d594b03fd5fdd45f82ea9f135d31c821636" + }, + "version": "1.7.8" + }, + "androidx.compose.material:material-ripple-android:aar": { + "shasums": { + "jar": "ceb7e8a584f80092f16fef2975e281949d8a58184236a87a8b214ec94c74e066" + }, + "version": "1.10.5" + }, + "androidx.compose.material:material-ripple:aar": { + "shasums": { + "jar": "ed6ac4b4d03054b30c8a84a6c06dbaece25c72d7c318447fe81d4bc7d69c35de" + }, + "version": "1.10.5" + }, + "androidx.compose.material:material:aar": { + "shasums": { + "jar": "392b95c284bd3288aef3ade8d14a94444b23d53c0634578e63d1de2ae792d9a7" + }, + "version": "1.10.5" + }, + "androidx.compose.runtime:runtime-android:aar": { + "shasums": { + "jar": "fd57586cf86d8b89f070d05cf5f0a2afcd15dd57411e767decc9e6b929764d43" + }, + "version": "1.10.5" + }, + "androidx.compose.runtime:runtime-annotation": { + "shasums": { + "jar": "5d4ce82699f501a0c8e1e672658f1f8089534e06989bf253bdfab11e2c730595" + }, + "version": "1.10.5" + }, + "androidx.compose.runtime:runtime-annotation-android:aar": { + "shasums": { + "jar": "6cb10d3d205c68969f6ad4f589a52650707aca3d23ab880197f1e30d50ec9527" + }, + "version": "1.10.5" + }, + "androidx.compose.runtime:runtime-annotation-jvm": { + "shasums": { + "jar": "f89dda8bcd73876d0fc16568844b2bd79443ee7ca62810874d25c7dcaa394bd6" + }, + "version": "1.10.5" + }, + "androidx.compose.runtime:runtime-desktop": { + "shasums": { + "jar": "b195860542f612de0512b54a75353e0f6d58815f0c9530a03bc5b0e734474829" + }, + "version": "1.10.5" + }, + "androidx.compose.runtime:runtime-retain-android:aar": { + "shasums": { + "jar": "7be3cf36cef2b57cbb5db122f70435ad00ae331dcde0c3a048580c800f44cf4a" + }, + "version": "1.10.5" + }, + "androidx.compose.runtime:runtime-retain-desktop": { + "shasums": { + "jar": "463ee9c1e93d1b913458bfecc96d128a3574a802f41c8c9781d7320c3b55ed8b" + }, + "version": "1.10.5" + }, + "androidx.compose.runtime:runtime-retain:aar": { + "shasums": { + "jar": "acc35bf3860d8c5dc395e995ccaa801740bfd8cff26f5008f07aca628cb4efdd" + }, + "version": "1.10.5" + }, + "androidx.compose.runtime:runtime-saveable-android:aar": { + "shasums": { + "jar": "0b51cc6a3fdfa26c4cc0669dfd959d02772612cca12fd61e9a0030e9c2ecd213" + }, + "version": "1.10.5" + }, + "androidx.compose.runtime:runtime-saveable-desktop": { + "shasums": { + "jar": "ef24e24cc8c9c3b9871007fbdf589ed9aaaecf95979a66b7484806f9f0e24d91" + }, + "version": "1.10.5" + }, + "androidx.compose.runtime:runtime-saveable:aar": { + "shasums": { + "jar": "035e94e12f13ffdb778093b4e47314b08fe2b0ec993a2d3a87ef5d958aeac952" + }, + "version": "1.10.5" + }, + "androidx.compose.runtime:runtime:aar": { + "shasums": { + "jar": "db320db683750ffdebcf71c62b5deabe46402349aa584c78b1a5001dca0e5764" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui-android:aar": { + "shasums": { + "jar": "6bc88fc41214aa2eb4a7b980dea2e55e002abdc4cd448ade52b3fd150a9299ea" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui-geometry-android:aar": { + "shasums": { + "jar": "fdf23c8cfd8157f5ecc8920234b164bc9a0a5d35bc7a88cf9e0fbe7f183a0fcd" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui-geometry:aar": { + "shasums": { + "jar": "747ce53d7869e02f69eea729722e783ab2728202e99bb348b7c1b87f87a6b431" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui-graphics-android:aar": { + "shasums": { + "jar": "e42cfe175036fbdbdfa851feb24cb1ffce39ea6e3bf2acebfa160453e71c3afb" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui-graphics:aar": { + "shasums": { + "jar": "a5dadc1764a22073d29ae69f0889adfe7524df061a1be60a70eff30b764c9aeb" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui-test-android:aar": { + "shasums": { + "jar": "e26d8331bccc81e87e947840041f4e15aa975d6f62cb340bbccf73df0cab95b2" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui-test-junit4-android:aar": { + "shasums": { + "jar": "a9ecb747104fc5da2db6286989167d8ebda9a558f693684b37154857b856e12f" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui-test-junit4:aar": { + "shasums": { + "jar": "b7f31d73482386277ba858b880b146921445bd9d2d5dfd2f2a6370b57ee4ddb2" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui-test-manifest:aar": { + "shasums": { + "jar": "e0325fb6db31d3e496e81e94552b1b114683f988dcbc5069ecfdc5051de8480f" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui-test:aar": { + "shasums": { + "jar": "248f0df19fe033faf3153a5ed1ebb1a88c71bc829e3e7fd1dcfa327e5195b167" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui-text-android:aar": { + "shasums": { + "jar": "f833f923b7bfbf196284fe6e709969e940c58c29d81b7193063da2d34367063e" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui-text:aar": { + "shasums": { + "jar": "d7d225c560c4099c58b138ba182b9a38fd3914dc11d391fa78a9726d7085dc3f" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui-tooling-preview-android:aar": { + "shasums": { + "jar": "bd2d83f99d180f09422a57ce2f0efefaf9bdd098ec7c555495dfd57f03f9d4af" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui-tooling-preview:aar": { + "shasums": { + "jar": "1e2dd2e93bde36484263a9e731f74ac5853ca048a511cf79d575c5f91152c3bb" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui-unit-android:aar": { + "shasums": { + "jar": "b4a2d86d8d9199faed4b116bde350c4c106ce59d11231b56e48b05219a25d115" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui-unit:aar": { + "shasums": { + "jar": "2a7a96ef1c98b2ee34f11714d175aa0fa274bf548a65c2559419fb2d79251023" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui-util-android:aar": { + "shasums": { + "jar": "f586c45c91fe10fffa2073b3913d8f2a676b0896a36b32b4896abbdcbbfdc4dc" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui-util:aar": { + "shasums": { + "jar": "a1b996f9e57ace10efed3f3048a28e7f91411855df1f637dcd11e50cb309eb02" + }, + "version": "1.10.5" + }, + "androidx.compose.ui:ui:aar": { + "shasums": { + "jar": "4e5a57dae2d7262e8822805457a1de7da4ce6986e9b49d7f65de4f7b123c70a8" + }, + "version": "1.10.5" + }, + "androidx.concurrent:concurrent-futures": { + "shasums": { + "jar": "0ce067c514a0d1049d1bebdf709e344ed3266fe9744275682937cdcb13334e9e" + }, + "version": "1.1.0" + }, + "androidx.concurrent:concurrent-futures-ktx": { + "shasums": { + "jar": "1968bf52039e38636aa6f114cd17d7256919d1e8997417716fef9d1da1f24d85" + }, + "version": "1.1.0" + }, + "androidx.core:core-ktx:aar": { + "shasums": { + "jar": "c72c97ff4a32308bcaf3061eea5ddf33455ce413cee4aa1d5c82440c5759d4bc" + }, + "version": "1.15.0" + }, + "androidx.core:core-remoteviews:aar": { + "shasums": { + "jar": "571fa872d3c86b21b4cd0078a980cea76834151fc4958a4af3178f4ba8eb3aba" + }, + "version": "1.1.0" + }, + "androidx.core:core-viewtree:aar": { + "shasums": { + "jar": "dc1b678d58ebcf2bfa1587be68ff826694ce3d221251b9ef30d4d4b36297e6de" + }, + "version": "1.0.0" + }, + "androidx.core:core:aar": { + "shasums": { + "jar": "6bf03d39dbe3744acce227d3b697374c3625aae1025fbec8ad9fd7bd58bce431" + }, + "version": "1.16.0" + }, + "androidx.cursoradapter:cursoradapter:aar": { + "shasums": { + "jar": "a81c8fe78815fa47df5b749deb52727ad11f9397da58b16017f4eb2c11e28564" + }, + "version": "1.0.0" + }, + "androidx.customview:customview-poolingcontainer:aar": { + "shasums": { + "jar": "3584102fc49bf399c56e3b7be4bfe12000c46112320cd8cf85cc0a8f93f3e752" + }, + "version": "1.0.0" + }, + "androidx.customview:customview:aar": { + "shasums": { + "jar": "01f76ab043770a97b054046f9815717b82ce0355c02967d16c61981359dc189a" + }, + "version": "1.1.0" + }, + "androidx.datastore:datastore-core": { + "shasums": { + "jar": "c810505542001593075199355b19d98b855edc36d9575bd764180321e20a92bc" + }, + "version": "1.0.0" + }, + "androidx.datastore:datastore-preferences-core": { + "shasums": { + "jar": "ad54de334ad0f4a53a5ba41876f91684319a8cf3396315b767b51102a4138bd1" + }, + "version": "1.0.0" + }, + "androidx.datastore:datastore-preferences:aar": { + "shasums": { + "jar": "6f9ac72082badb776447cdd579c16c25c18127185c6ba9f2cfab9246473e2db1" + }, + "version": "1.0.0" + }, + "androidx.datastore:datastore:aar": { + "shasums": { + "jar": "28fea28d365b4aef4d5e8732fe51f233e580d2042cd4a70a6b293a518daec703" + }, + "version": "1.0.0" + }, + "androidx.documentfile:documentfile:aar": { + "shasums": { + "jar": "9c53d24ce55e7836b44e5a85b3f6fa006fdf8742d4a1a80d8d432deea66108d1" + }, + "version": "1.0.1" + }, + "androidx.drawerlayout:drawerlayout:aar": { + "shasums": { + "jar": "9402442cdc5a43cf62fb14f8cf98c63342d4d9d9b805c8033c6cf7e802749ac1" + }, + "version": "1.0.0" + }, + "androidx.dynamicanimation:dynamicanimation:aar": { + "shasums": { + "jar": "ce005162c229bf308d2d5b12fb6cad0874069cbbeaccee63a8193bd08d40de04" + }, + "version": "1.0.0" + }, + "androidx.emoji2:emoji2-views-helper:aar": { + "shasums": { + "jar": "ed5d3ed772a5fbf0d570f7526f585cd61a180e60f9372584c328a68e2cff3375" + }, + "version": "1.4.0" + }, + "androidx.emoji2:emoji2:aar": { + "shasums": { + "jar": "433febd3434a45667176c76a64f3f205ca6335a6b544c5b5d57f25a38a375242" + }, + "version": "1.4.0" + }, + "androidx.exifinterface:exifinterface:aar": { + "shasums": { + "jar": "0e8f1832266c5b0667ad3d3b1098e624e49a09075493a014a7e88af01fd30ad3" + }, + "version": "1.3.7" + }, + "androidx.fragment:fragment-ktx:aar": { + "shasums": { + "jar": "8023b7963ec91db7d005d3e915faa78b5c1a2b3cadbfd90a1fd29eb299af494c" + }, + "version": "1.8.5" + }, + "androidx.fragment:fragment:aar": { + "shasums": { + "jar": "1dcb3a05d1b4815951eb492d80e883add888d5f24429d6423a8ad7fae14f48cd" + }, + "version": "1.8.5" + }, + "androidx.glance:glance-appwidget-external-protobuf": { + "shasums": { + "jar": "10176c95e30d3f1069bfef661aae683c6eaa184dfbe4696f103fcad3c458aa96" + }, + "version": "1.1.1" + }, + "androidx.glance:glance-appwidget-proto": { + "shasums": { + "jar": "00f31fabdbb9cf773478d374504b8937303e25699ba622a70d37b1027e5a1f78" + }, + "version": "1.1.1" + }, + "androidx.glance:glance-appwidget-testing:aar": { + "shasums": { + "jar": "57445aa80b02ffc2401c0f4e008e38046391126df0412fb06a91dbca27658c8a" + }, + "version": "1.1.1" + }, + "androidx.glance:glance-appwidget:aar": { + "shasums": { + "jar": "81fc7dc88e444dc3aebb24b773e2846cc2bd62c71f4741f70d6e5ed7f548c59f" + }, + "version": "1.1.1" + }, + "androidx.glance:glance-material3:aar": { + "shasums": { + "jar": "df735abc23da934217663e0176dc989865420538c9d62d299975705dc0e02ee5" + }, + "version": "1.1.1" + }, + "androidx.glance:glance-testing:aar": { + "shasums": { + "jar": "b2e3543df9b39c1c2cf95d03a71af321a2ff14ab64a16ee67889ce87f3cc8386" + }, + "version": "1.1.1" + }, + "androidx.glance:glance:aar": { + "shasums": { + "jar": "fbd512725b341e36ec56bc01e99f7210d4ad3aab7a6419df2e8841862bd3a8dc" + }, + "version": "1.1.1" + }, + "androidx.graphics:graphics-path:aar": { + "shasums": { + "jar": "8ca4032b6d79b351f0b59ad4b580eddbb9423e1652f7c958830687f1eee2ec03" + }, + "version": "1.0.1" + }, + "androidx.interpolator:interpolator:aar": { + "shasums": { + "jar": "33193135a64fe21fa2c35eec6688f1a76e512606c0fc83dc1b689e37add7732a" + }, + "version": "1.0.0" + }, + "androidx.legacy:legacy-support-core-utils:aar": { + "shasums": { + "jar": "a7edcf01d5b52b3034073027bc4775b78a4764bb6202bb91d61c829add8dd1c7" + }, + "version": "1.0.0" + }, + "androidx.lifecycle:lifecycle-common": { + "shasums": { + "jar": "c7a6e835da0712d15efeae0d72df91e6631042df4fcf0f9c20ceca740638c685" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-common-java8": { + "shasums": { + "jar": "497dd84de9f2fd46324f25f9a3af032d3a23d087e87af515c4b19435f6d6a651" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-common-jvm": { + "shasums": { + "jar": "37d89b2101f074ac6c260917dabb185607645ee200aa3018c7c5bde70edcf184" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-livedata-core-ktx:aar": { + "shasums": { + "jar": "f55b7a8d433e9b8163154ccaa42fa2be55c70cd1ede5eeea521a4b4b884dd4fe" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-livedata-core:aar": { + "shasums": { + "jar": "ea866f0c379d1f92837994010ab5ac0a5d5499dbab521efc71b3bc2b497d6ba4" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-livedata:aar": { + "shasums": { + "jar": "f240c2c94a96d4a5eae5d379c2a8589d426a33b989d83ae9f0e01f69502c0181" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-process:aar": { + "shasums": { + "jar": "4784b8d083c211e076d9115bfa1737f7e0f62b553e801cf50caa4400e34a95d6" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-runtime-android:aar": { + "shasums": { + "jar": "86f16a1330eb23600ba90d0334b3e1db38d3a30c8b1efcd92ca21aa85afa8173" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-runtime-compose-android:aar": { + "shasums": { + "jar": "b6803f906a89fd85c77df343dd4aeeb349125ca79e12d55d68d4cf42f42231f6" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-runtime-compose-desktop": { + "shasums": { + "jar": "d25c083df93da718a1876a3293bd15f7dc7a811e998735943bce590683a57835" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-runtime-compose:aar": { + "shasums": { + "jar": "f0725c1f0c6a0aa334cf109197f902fbebaa734ccc03c03f0ed0ad88e2a107e1" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-runtime-desktop": { + "shasums": { + "jar": "2fb49f76d1021792fb359e0a9246c1509f2f5b555f0a46591d24d58deb68bd5c" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-runtime-ktx-android:aar": { + "shasums": { + "jar": "970199c9ed1ac13d620aa8de7f8abbc28ce80653c3ce328d0ac2f15272b56e1b" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-runtime-ktx:aar": { + "shasums": { + "jar": "f1c6b56258cfb8a994721997ef2c5da59ae3933a809ccf778a3bf78bba76479f" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-runtime:aar": { + "shasums": { + "jar": "142b8d22e93e4a6f3871901493c26e2bdfe1d5da1f88f2d8031d46ec6b6cc12b" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-service:aar": { + "shasums": { + "jar": "674155d592d5de18175ef0727442f7827a86cf8fe68d9927ba6a4140b69a5bc9" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-viewmodel-android:aar": { + "shasums": { + "jar": "4b236b2e504db5ca5d09334fef05aa8cdc31ee35a433c3aa4d0420efa9613332" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-viewmodel-compose-android:aar": { + "shasums": { + "jar": "f7825a08ca661de84044b6891293084bea8fbcc84aa08d8c13a3c558fc5956c9" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-viewmodel-compose:aar": { + "shasums": { + "jar": "2c658e844f5e8a8278fc7cdf40b6112824e506a9071751bb937fc581b3242671" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-viewmodel-desktop": { + "shasums": { + "jar": "98f816be6869407c87d46058756f97780fa6c6cf61acdba97216f413731af15d" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-viewmodel-ktx:aar": { + "shasums": { + "jar": "b7d58bb86bb8e2ccc607d1f8570e714810f7cfb3feba37d375ff1646383435a1" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-viewmodel-savedstate-android:aar": { + "shasums": { + "jar": "079441c43fa3ff8ea7a02df3b12eec483c3e57583f832cfaff663750527c1421" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-viewmodel-savedstate-desktop": { + "shasums": { + "jar": "3e0b44e2514eafdd6938d5457d9f46e4785077c45d3b4364b5c23c4dcb93efd3" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-viewmodel-savedstate:aar": { + "shasums": { + "jar": "ae70b02386c0733b193644c58a42608ad3e4f8e7731eda859f7888405b5f36b9" + }, + "version": "2.9.4" + }, + "androidx.lifecycle:lifecycle-viewmodel:aar": { + "shasums": { + "jar": "cab404b05d5faed209104a2aef14c0cbb316ab9fabe4a8f037b043e5d2f43435" + }, + "version": "2.9.4" + }, + "androidx.loader:loader:aar": { + "shasums": { + "jar": "11f735cb3b55c458d470bed9e25254375b518b4b1bad6926783a7026db0f5025" + }, + "version": "1.0.0" + }, + "androidx.localbroadcastmanager:localbroadcastmanager:aar": { + "shasums": { + "jar": "e71c328ceef5c4a7d76f2d86df1b65d65fe2acf868b1a4efd84a3f34336186d8" + }, + "version": "1.0.0" + }, + "androidx.metrics:metrics-performance:aar": { + "shasums": { + "jar": "ef05fbf5e00c0894b9137548de1fd88f526750746065e46a8e880aec39d68e79" + }, + "version": "1.0.0-beta02" + }, + "androidx.navigationevent:navigationevent-android:aar": { + "shasums": { + "jar": "3fa191e3da2f6b601e944fb03a09a12278e49418dd1a9b22cd6b99f66e4283fd" + }, + "version": "1.0.2" + }, + "androidx.navigationevent:navigationevent-desktop": { + "shasums": { + "jar": "43deeb5774fd737fa945e09a47f93b6f1a508d17fac8f3b65f1c863e7f7d0660" + }, + "version": "1.0.2" + }, + "androidx.navigationevent:navigationevent:aar": { + "shasums": { + "jar": "3069f1643e26a990bb71023524c852bb02036b8f9c5dbca8a1ca782064243c3b" + }, + "version": "1.0.2" + }, + "androidx.print:print:aar": { + "shasums": { + "jar": "1d5c7f3135a1bba661fc373fd72e11eb0a4adbb3396787826dd8e4190d5d9edd" + }, + "version": "1.0.0" + }, + "androidx.profileinstaller:profileinstaller:aar": { + "shasums": { + "jar": "d502141fcce902430f62b674c32aecd0f75262e7ee2cd15c74adb617cd13130a" + }, + "version": "1.4.0" + }, + "androidx.resourceinspection:resourceinspection-annotation": { + "shasums": { + "jar": "8cff870ec6fb31db48a52f4a792335b4bf8de07e03bd37823181526433ccd5cb" + }, + "version": "1.0.1" + }, + "androidx.room:room-common": { + "shasums": { + "jar": "0262e2a0e2a2e9c7267b9f7a405847ce636a06c4c16c52976cb68df77866b87d" + }, + "version": "2.5.0" + }, + "androidx.room:room-ktx:aar": { + "shasums": { + "jar": "10f76df56222534c7bf87c98643d6a0fdb7e9d342396a679c315e11036b045f1" + }, + "version": "2.5.0" + }, + "androidx.room:room-runtime:aar": { + "shasums": { + "jar": "9882841877a4437f2002ed9d353f757a5452e13b4ab0ebf195c63ccf0e2e0847" + }, + "version": "2.5.0" + }, + "androidx.savedstate:savedstate-android:aar": { + "shasums": { + "jar": "3d40baf742e6bdc90ada4650502e1d08c55cb5d8c045870d2c7c6d89f237d064" + }, + "version": "1.3.3" + }, + "androidx.savedstate:savedstate-compose-android:aar": { + "shasums": { + "jar": "ec3c09338a005136697824e8ca52ebb4a51b055258e670d4bd2e1f992e32945e" + }, + "version": "1.3.3" + }, + "androidx.savedstate:savedstate-compose-desktop": { + "shasums": { + "jar": "4a94787a6e5bcfe143390a4f2737d4425d2ea867f2b34a847de6cda3c6ccc58a" + }, + "version": "1.3.3" + }, + "androidx.savedstate:savedstate-compose:aar": { + "shasums": { + "jar": "ddaf6bbd26865e0c22832990d7331a5df1917bc8ce916e79f56ca4dc945f17c4" + }, + "version": "1.3.3" + }, + "androidx.savedstate:savedstate-desktop": { + "shasums": { + "jar": "c5c89062ba8402b8f8657efd54db1ff192f91ca95fae59c3b418fbc477c3e3ea" + }, + "version": "1.3.3" + }, + "androidx.savedstate:savedstate-ktx:aar": { + "shasums": { + "jar": "c4df27ba3fef3674da4c5cae64f43ff251f8f9b7507c6597e95a5b7f64860c6c" + }, + "version": "1.3.3" + }, + "androidx.savedstate:savedstate:aar": { + "shasums": { + "jar": "85ea36f18a33c4acf6ed62747a1b4cbef191f218121ab37a51175d82c5be89ad" + }, + "version": "1.3.3" + }, + "androidx.security:security-crypto:aar": { + "shasums": { + "jar": "976111170b3f13d2f0f9457d9f9f579347143cb65c054265906d33c7618a4c2a" + }, + "version": "1.1.0-alpha06" + }, + "androidx.sqlite:sqlite-android:aar": { + "shasums": { + "jar": "514f8de4f7bdba2fa8d748d2b22fdcdfb623bd3770a667bf0adc0ad259f03ed2" + }, + "version": "2.6.2" + }, + "androidx.sqlite:sqlite-framework-android:aar": { + "shasums": { + "jar": "b19125c7fff34222e0f380361fc179ab214e4d82e1a50b0c068ca26c851a6231" + }, + "version": "2.6.2" + }, + "androidx.sqlite:sqlite-framework:aar": { + "shasums": { + "jar": "2ee94f32a637effbe3532419298ec681e4fe0774d5d96fa3d2402a7f59071291" + }, + "version": "2.6.2" + }, + "androidx.sqlite:sqlite:aar": { + "shasums": { + "jar": "2dadc048dd87a0d3d15809c85f5bee32f597a4ccbb0ec88e287bea46336f3bb8" + }, + "version": "2.6.2" + }, + "androidx.startup:startup-runtime:aar": { + "shasums": { + "jar": "f51d361d17b30b09cfb9e2aebf301d113f99437cbf462a066092795fb60eddd2" + }, + "version": "1.2.0" + }, + "androidx.test.espresso:espresso-core:aar": { + "shasums": { + "jar": "343027645b30d7b3e30e5d0649646a72cbec88335777e121f5b003dd95bde483" + }, + "version": "3.6.0" + }, + "androidx.test.espresso:espresso-idling-resource:aar": { + "shasums": { + "jar": "2c18dcebda8fefe049f5df5f5c5573e53ae322e426055e66523048537d82a5ea" + }, + "version": "3.6.0" + }, + "androidx.test.ext:junit:aar": { + "shasums": { + "jar": "7b146a73c545b983430d2fae0081df67c76722c19a9abd2904e131696a8c5b20" + }, + "version": "1.2.1" + }, + "androidx.test.services:storage:aar": { + "shasums": { + "jar": "f97e3cf6aaf4e3fb97ef219d37a9c0a0720183c1f6db87b37642521e26fb6d30" + }, + "version": "1.6.0" + }, + "androidx.test:core:aar": { + "shasums": { + "jar": "7a7af31c21785ddb7c4319c838847e6d4d9b5bb531f3a951481ec3b98780bf51" + }, + "version": "1.6.1" + }, + "androidx.test:monitor:aar": { + "shasums": { + "jar": "56cb7496a06d9f2dca7d3ff76c50a8a30bd18e00a24a3b267d5a31437b278e67" + }, + "version": "1.8.0" + }, + "androidx.test:rules:aar": { + "shasums": { + "jar": "8f334bd208161c4eb221bea54a833ac70400ff5eb022a03631affadea4a606c7" + }, + "version": "1.6.0" + }, + "androidx.test:runner:aar": { + "shasums": { + "jar": "d8eac6d9864f432b15962b2c2739a7b31685c87777364ac97323c9e4b2c94744" + }, + "version": "1.6.2" + }, + "androidx.tracing:tracing-android:aar": { + "shasums": { + "jar": "f59782bbe3470a6b0c531cef262dd1fc9d9a0233490bb5e6d553e1fe6a1816b2" + }, + "version": "1.3.0" + }, + "androidx.tracing:tracing-ktx:aar": { + "shasums": { + "jar": "c33f9cbd931e6190ca38aa09bf8a7a8a19391d4b0fb7a7605a6b59f2d42580d1" + }, + "version": "1.2.0" + }, + "androidx.tracing:tracing:aar": { + "shasums": { + "jar": "87064cb2cf8c115f2938512dcb136967302c6c925012b67f929bcbf9e627c397" + }, + "version": "1.3.0" + }, + "androidx.transition:transition:aar": { + "shasums": { + "jar": "248c45e1254d31181d2047b0b01394f09a2e539a5d9e89b773d53c62c96860f6" + }, + "version": "1.6.0" + }, + "androidx.vectordrawable:vectordrawable-animated:aar": { + "shasums": { + "jar": "76da2c502371d9c38054df5e2b248d00da87809ed058f3363eae87ce5e2403f8" + }, + "version": "1.1.0" + }, + "androidx.vectordrawable:vectordrawable:aar": { + "shasums": { + "jar": "46fd633ac01b49b7fcabc263bf098c5a8b9e9a69774d234edcca04fb02df8e26" + }, + "version": "1.1.0" + }, + "androidx.versionedparcelable:versionedparcelable:aar": { + "shasums": { + "jar": "57e8d93260d18d5b9007c9eed3c64ad159de90c8609ebfc74a347cbd514535a4" + }, + "version": "1.1.1" + }, + "androidx.viewpager:viewpager:aar": { + "shasums": { + "jar": "147af4e14a1984010d8f155e5e19d781f03c1d70dfed02a8e0d18428b8fc8682" + }, + "version": "1.0.0" + }, + "androidx.window:window-core": { + "shasums": { + "jar": "46021e4e764e11b7674089942d9a5dbaad0a88deb84c245dabdb850f24d4823b" + }, + "version": "1.5.0" + }, + "androidx.window:window-core-jvm": { + "shasums": { + "jar": "c3bef837bbeb9caeb9ac2570ee015f6fa02cd80cdfa30a2e360f9671e60737e0" + }, + "version": "1.5.0" + }, + "androidx.window:window:aar": { + "shasums": { + "jar": "5de2d48aa578402f46deb5294a955cee62f0c7d8c1840ef626fc7afb8abe22f9" + }, + "version": "1.5.0" + }, + "androidx.work:work-runtime-ktx:aar": { + "shasums": { + "jar": "8f4cc53ac1879665b14d2f17ad4fbcb3045a4b74774250b99829b1c13f7b7728" + }, + "version": "2.9.1" + }, + "androidx.work:work-runtime:aar": { + "shasums": { + "jar": "1be76486b894af179462941a39cab242b00d7235c3aeb4d756f45262b0c2e4a3" + }, + "version": "2.9.1" + }, + "app.cash.sqldelight:android-driver:aar": { + "shasums": { + "jar": "50c92e248d48f85a67390469254261a3bcd2295bf4f031f442396610b012ffeb" + }, + "version": "2.3.2" + }, + "app.cash.sqldelight:async-extensions-jvm": { + "shasums": { + "jar": "11e54f95912455dff97ff0fbb5d8b200a4f3f6d02fd155a9d5722f43ef56cc11" + }, + "version": "2.3.2" + }, + "app.cash.sqldelight:coroutines-extensions-jvm": { + "shasums": { + "jar": "ad0f3966c7a6ec88f2ca580dc8c5b85b0ed3988699658cbf99f0fb449e0e107d" + }, + "version": "2.3.2" + }, + "app.cash.sqldelight:jdbc-driver": { + "shasums": { + "jar": "66f28e6b98867b822ad652126766e62a200c72bbca9b6f22fbafaccdcbf292a2" + }, + "version": "2.3.2" + }, + "app.cash.sqldelight:runtime": { + "shasums": { + "jar": "a986b0c6d09d85f1cc5a1daa0e4f10c442e1753c2283fc37eb98885ff3566091" + }, + "version": "2.3.2" + }, + "app.cash.sqldelight:runtime-jvm": { + "shasums": { + "jar": "9b01bc44676db299fd22440f3261569f6d8659bfbd3bd4da374ee38cbd4ab4b6" + }, + "version": "2.3.2" + }, + "app.cash.sqldelight:sqlite-driver": { + "shasums": { + "jar": "4809b633a0d7ae896d250bc7e977b9ce91aab0e5fce8861b40bfd13fda172199" + }, + "version": "2.3.2" + }, + "co.touchlab:stately-concurrency-jvm": { + "shasums": { + "jar": "86739675892fb1c17d6bd36d05347e89ff313957421bb01a45a743ce774e8e29" + }, + "version": "2.1.0" + }, + "co.touchlab:stately-strict-jvm": { + "shasums": { + "jar": "581070db2802cbad81f6e6e2d9d2494835443153b314458d53aa43c68260c9fa" + }, + "version": "2.1.0" + }, + "com.almworks.sqlite4java:sqlite4java": { + "shasums": { + "jar": "243a64470fda0e86a6fddeb0af4c7aa9426ce84e68cbfe18d75ee5da4b7e0b92" + }, + "version": "1.0.392" + }, + "com.android.tools:desugar_jdk_libs": { + "shasums": { + "jar": "d7604feeef3a771d5d616b68fcc2c42f516243311ea286cfd41e1962829a6d28" + }, + "version": "2.1.4" + }, + "com.android.tools:desugar_jdk_libs_configuration": { + "shasums": { + "jar": "5d770c1ba225c2cdf09086bf662954ae765ee481f901b02cd7b1dc3c8077c3f4" + }, + "version": "2.1.4" + }, + "com.benasher44:uuid-jvm": { + "shasums": { + "jar": "4520ffe0fcccdf8e72c8ce67d9ea6546e38946bbe11cc2963f1864be2eb2c5e3" + }, + "version": "0.8.4" + }, + "com.fleeksoft.charset:charset-jvm": { + "shasums": { + "jar": "0e316c317627280c253372e1c2bc5f0370992f3cfaa26b766eed7572439d9e3b" + }, + "version": "0.0.8" + }, + "com.fleeksoft.io:io-core-jvm": { + "shasums": { + "jar": "c3091155ee3acd8ff3a8274e52baf0f8e200cbad2fd440a121943bfceb7dc1f0" + }, + "version": "0.0.8" + }, + "com.fleeksoft.ksoup:ksoup-jvm": { + "shasums": { + "jar": "ec9c20bc08d0cb28293a38580c6fb107521b4fdb781c1251a3fdd0a7e8ff1f92" + }, + "version": "0.2.6" + }, + "com.github.mwiede:jsch": { + "shasums": { + "jar": "2330df0841be84eefa7c6ba4b5a2c98faa153855c80a5af418fdedacc2a4bc5b" + }, + "version": "0.2.21" + }, + "com.github.requery:sqlite-android:aar": { + "shasums": { + "jar": "2a746d7d9d68f4393d80bbca4e2af07643bc963e22ef737a7fa035d70e07aa70" + }, + "version": "3.49.0" + }, + "com.google.android.datatransport:transport-api:aar": { + "shasums": { + "jar": "e62f73ba1c7f5d15f5d86d8e9a298c42ccd0648e7ce60b9e312f2ecd123b5ed0" + }, + "version": "2.2.1" + }, + "com.google.android.datatransport:transport-backend-cct:aar": { + "shasums": { + "jar": "b22a14d560a590dc875e902424b29a13a02d1faf297b7c39a9007967ffadccbd" + }, + "version": "2.3.3" + }, + "com.google.android.datatransport:transport-runtime:aar": { + "shasums": { + "jar": "d83ad23c134429691161c92476a3c83df236cd1f8badbfd4f00723b4eccd741c" + }, + "version": "2.2.6" + }, + "com.google.android.gms:play-services-base:aar": { + "shasums": { + "jar": "59a5c0c2da12311d75d965ce1f419498536b1a167fb28ff7dfc2dfd9cefa4157" + }, + "version": "18.5.0" + }, + "com.google.android.gms:play-services-basement:aar": { + "shasums": { + "jar": "c6ed7236b1b3ce0296b508a5c0a09108fd52d83559d35cad2639505cd04ab255" + }, + "version": "18.9.0" + }, + "com.google.android.gms:play-services-mlkit-text-recognition-common:aar": { + "shasums": { + "jar": "3be02b3c3c829476100f01d0ab79f0b4a923da23909d3ac63e486d1a63381c58" + }, + "version": "19.1.0" + }, + "com.google.android.gms:play-services-mlkit-text-recognition:aar": { + "shasums": { + "jar": "6b504dc053758407a507883fa9495bcb4c1c2bae8069012ff3a8f70f93bc89d4" + }, + "version": "19.0.1" + }, + "com.google.android.gms:play-services-tasks:aar": { + "shasums": { + "jar": "7f2aaa8f502068eaf54356ca92aec04271d6e7c416c52c45c0d23440fcbd1654" + }, + "version": "18.2.0" + }, + "com.google.android.odml:image:aar": { + "shasums": { + "jar": "2e71aa31f83a9415277f119de67195726f07d1760e9542c111778c320e3aa1f2" + }, + "version": "1.0.0-beta1" + }, + "com.google.ar:core:aar": { + "shasums": { + "jar": "c4eac78a54a3b23aa03e87a8c0ac5c69027df735b155316cbfd72fe2f5c899ea" + }, + "version": "1.46.0" + }, + "com.google.auto.value:auto-value-annotations": { + "shasums": { + "jar": "5a055ce4255333b3346e1a8703da5bf8ff049532286fdcd31712d624abe111dd" + }, + "version": "1.11.0" + }, + "com.google.code.findbugs:jsr305": { + "shasums": { + "jar": "766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7" + }, + "version": "3.0.2" + }, + "com.google.code.gson:gson": { + "shasums": { + "jar": "d3999291855de495c94c743761b8ab5176cfeabe281a5ab0d8e8d45326fd703e" + }, + "version": "2.8.9" + }, + "com.google.crypto.tink:tink-android": { + "shasums": { + "jar": "5efe8f1cb6e75814ae06793d5ff8d9b01e6f88ef97ecc062d14ebc27027dbf78" + }, + "version": "1.8.0" + }, + "com.google.errorprone:error_prone_annotation": { + "shasums": { + "jar": "192e99ad3be8a0a44fe210cdc9b0265601dcb446e521ba922c793e50add413c3" + }, + "version": "2.41.0" + }, + "com.google.errorprone:error_prone_annotations": { + "shasums": { + "jar": "ff80626baaf12a09342befd4e84cba9d50662f5fcd7f7a9b3490a6b7cf87e66c" + }, + "version": "2.5.1" + }, + "com.google.firebase:firebase-annotations": { + "shasums": { + "jar": "8830f2e8a5e434cbc5e4bd18133073b6e8518a8ce8ec2ce6f3b273c91d9664c2" + }, + "version": "16.0.0" + }, + "com.google.firebase:firebase-components:aar": { + "shasums": { + "jar": "82e91aa5ed186eedaf1f2210f5d241ba6e4456cf0c32949d5cdbe152b0e2e88b" + }, + "version": "16.1.0" + }, + "com.google.firebase:firebase-encoders": { + "shasums": { + "jar": "8f89a74298bbccc2c543385208a2f0c67f603ce67e6ec21cc772e98e688f7cf5" + }, + "version": "16.1.0" + }, + "com.google.firebase:firebase-encoders-json:aar": { + "shasums": { + "jar": "8295c755bcadc87a2aaee5b9e568f27fd138fd45ff1159a8ee747cf4c3a38d85" + }, + "version": "17.1.0" + }, + "com.google.guava:failureaccess": { + "shasums": { + "jar": "a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26" + }, + "version": "1.0.1" + }, + "com.google.guava:guava": { + "shasums": { + "jar": "bd7fa227591fb8509677d0d1122cf95158f3b8a9f45653f58281d879f6dc48c5" + }, + "version": "32.0.1-jre" + }, + "com.google.guava:listenablefuture": { + "shasums": { + "jar": "b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99" + }, + "version": "9999.0-empty-to-avoid-conflict-with-guava" + }, + "com.google.j2objc:j2objc-annotations": { + "shasums": { + "jar": "f02a95fa1a5e95edb3ed859fd0fb7df709d121a35290eff8b74dce2ab7f4d6ed" + }, + "version": "2.8" + }, + "com.google.mlkit:common:aar": { + "shasums": { + "jar": "66408a08dbb2465687ff5dd0c8f6410b56549ce3ecf449d9096f3712282131d0" + }, + "version": "18.11.0" + }, + "com.google.mlkit:genai-common:aar": { + "shasums": { + "jar": "b88266e12b1704c560be8ecbc9204b6983b87c49cfcf4cb7cbc98a81e4d5a447" + }, + "version": "1.0.0-beta3" + }, + "com.google.mlkit:genai-prompt:aar": { + "shasums": { + "jar": "554da3168a59e5de40b7c9ccee3f074a93fe0c7c3caba66b26830c8efe547f9e" + }, + "version": "1.0.0-beta2" + }, + "com.google.mlkit:image-labeling-common:aar": { + "shasums": { + "jar": "4448f6fe28b7034ec15c1ada8f53e237ea1c915fa5181661deb8c492e783f0f8" + }, + "version": "18.1.0" + }, + "com.google.mlkit:image-labeling-default-common:aar": { + "shasums": { + "jar": "0606e484d71936450dbd3ca03f4212e7b2086c5f0731b58ca3f68647cb5ab31d" + }, + "version": "17.0.0" + }, + "com.google.mlkit:image-labeling:aar": { + "shasums": { + "jar": "566e38fe4ed07b8f83f1e3a7e39e3a9c1a29268272b57b3ea580105c856597ed" + }, + "version": "17.0.9" + }, + "com.google.mlkit:text-recognition-bundled-common:aar": { + "shasums": { + "jar": "fb1d4e26d69125659b6f5a94f03cce145544b0116807d04333335a9775636e05" + }, + "version": "17.0.0" + }, + "com.google.mlkit:text-recognition:aar": { + "shasums": { + "jar": "da753265d02479a8cfe4dbf891ba7d189248e7c8430b6f72bd4d532c757a69b3" + }, + "version": "16.0.1" + }, + "com.google.mlkit:vision-common:aar": { + "shasums": { + "jar": "c0085ca5fba00f11529c0a83b12851ea6c599bbcc8affd927e914b29a743459f" + }, + "version": "17.3.0" + }, + "com.google.mlkit:vision-interfaces:aar": { + "shasums": { + "jar": "8f0192a26d01b728a01a15a620d829fff7095822822694438a93127c04cb16fb" + }, + "version": "16.3.0" + }, + "com.google.mlkit:vision-internal-vkp:aar": { + "shasums": { + "jar": "297d1de9167251494036a7559f057bb140f724be0d60feb61ba09474ed81707f" + }, + "version": "18.2.3" + }, + "com.google.testparameterinjector:test-parameter-injector": { + "shasums": { + "jar": "e5a7c649c54c412049908247ca5e25fe6921d746849c6017a84dc6044237a4b4" + }, + "version": "1.18" + }, + "com.google.truth:truth": { + "shasums": { + "jar": "1ccf4334e7a94cf00a20a619b5462b53acf3274e00b70498bf5b28a3bc1be9b1" + }, + "version": "1.0.1" + }, + "com.googlecode.java-diff-utils:diffutils": { + "shasums": { + "jar": "61ba4dc49adca95243beaa0569adc2a23aedb5292ae78aa01186fa782ebdc5c2" + }, + "version": "1.3.0" + }, + "com.googlecode.javaewah:JavaEWAH": { + "shasums": { + "jar": "d65226949713c4c61a784f41c51167e7b0316f93764398ebba9e4336b3d954c2" + }, + "version": "1.2.3" + }, + "com.ibm.icu:icu4j": { + "shasums": { + "jar": "b3640b9f416a4411fd33c59abbeea8fd57d024c23e1819bf9673220a97499fe3" + }, + "version": "77.1" + }, + "com.jcraft:jsch": { + "shasums": { + "jar": "d492b15a6d2ea3f1cc39c422c953c40c12289073dbe8360d98c0f6f9ec74fc44" + }, + "version": "0.1.55" + }, + "com.jcraft:jzlib": { + "shasums": { + "jar": "5cb1e9f9cf0be011487545694ff0a178237c6bfcbb21c97865cdc52c60b9347a" + }, + "version": "1.1.1" + }, + "com.juul.kable:core-android:aar": { + "shasums": { + "jar": "0524a1763d25e88d612d784cab94209fe918107d3130e8f30f2d60a79e5006a3" + }, + "version": "0.32.0" + }, + "com.juul.kable:exceptions-jvm": { + "shasums": { + "jar": "c34814c518b31b465f6d4ed93c9d54d356b71bd0cc8680dda8f960fd8fab41b6" + }, + "version": "0.32.0" + }, + "com.juul.tuulbox:collections-jvm": { + "shasums": { + "jar": "2441f70de3f5dbd7dff4b9d17b405f6e188f71f7409b96e98ec7b3ab2fec7a6e" + }, + "version": "7.2.0" + }, + "com.juul.tuulbox:coroutines-android:aar": { + "shasums": { + "jar": "46438ea6591e77fe2e4efd6e26816dd66a6b80e838c50b5659cabfd6d66039f5" + }, + "version": "7.2.0" + }, + "com.microsoft.onnxruntime:onnxruntime-android:aar": { + "shasums": { + "jar": "07a8f71ef890afed8c6087a56220e6d558a492804276ee2dd7cb7f6262242027" + }, + "version": "1.20.0" + }, + "com.squareup.okhttp3:okhttp": { + "shasums": { + "jar": "b1050081b14bb7a3a7e55a4d3ef01b5dcfabc453b4573a4fc019767191d5f4e0" + }, + "version": "4.12.0" + }, + "com.squareup.okhttp3:okhttp-sse": { + "shasums": { + "jar": "bff4fbcaef7aac2d910d4ff46dafaa4e6d15da127df6bac97216da46943a7d4c" + }, + "version": "4.12.0" + }, + "com.squareup.okio:okio": { + "shasums": { + "jar": "8e63292e5c53bb93c4a6b0c213e79f15990fed250c1340f1c343880e1c9c39b5" + }, + "version": "3.6.0" + }, + "com.squareup.okio:okio-jvm": { + "shasums": { + "jar": "3b13dcc3e1573047c2d507fc4f7fcb0bb0cbcd9d395da21d20e09406e2cd6a73" + }, + "version": "3.17.0" + }, + "com.tom-roush:pdfbox-android:aar": { + "shasums": { + "jar": "30277f879cfd571db2a137582c95516a0d4ea6778e945519bc58ca93d57d88c7" + }, + "version": "2.0.27.0" + }, + "commons-codec:commons-codec": { + "shasums": { + "jar": "ba005f304cef92a3dede24a38ad5ac9b8afccf0d8f75839d6c1338634cf7f6e4" + }, + "version": "1.18.0" + }, + "commons-logging:commons-logging": { + "shasums": { + "jar": "bc2dfe32f1ef06509e6a065144c1adf7b420eabf11a87f30bd127f8faa332016" + }, + "version": "1.3.4" + }, + "io.arrow-kt:arrow-annotations-jvm": { + "shasums": { + "jar": "579e6b6918fab3a2ce4fe7b72d70afdef71c4097ef075ca4fc5db032973b9040" + }, + "version": "2.2.1.1" + }, + "io.arrow-kt:arrow-atomic-jvm": { + "shasums": { + "jar": "4bda03d528a74ff76b215487afab361ef9038de5fef669de9f75e337f63d978e" + }, + "version": "2.2.1.1" + }, + "io.arrow-kt:arrow-autoclose-jvm": { + "shasums": { + "jar": "d81a921e45f75ca9e3e4920cfa7b0bafc5c99413ea253f3d4be42213dadcd825" + }, + "version": "2.2.1.1" + }, + "io.arrow-kt:arrow-core-jvm": { + "shasums": { + "jar": "80e205019e58969aa0ee2ad27137be985683a3facdb4b3eb9ca3916295fcbd7c" + }, + "version": "2.2.1.1" + }, + "io.arrow-kt:arrow-exception-utils-jvm": { + "shasums": { + "jar": "bd59b9e8b93e3006bb2c8849bd39238e0e9559fd2c0532678983644e56ffad16" + }, + "version": "2.2.1.1" + }, + "io.arrow-kt:arrow-fx-coroutines-jvm": { + "shasums": { + "jar": "7ea6bf0935f70f5ff8ebd3ca7c4930d621a55f0834654c4bfb594499907927bb" + }, + "version": "2.2.1.1" + }, + "io.arrow-kt:arrow-optics-jvm": { + "shasums": { + "jar": "7c3f25845c71a31e893023836788f1c6f8a92310d01f8b861c06bb514e019551" + }, + "version": "2.2.1.1" + }, + "io.arrow-kt:arrow-resilience-jvm": { + "shasums": { + "jar": "49407f4f91bcd1ad50102081cda0277ae620ee1e9a62fe9797a1287977877be2" + }, + "version": "2.2.1.1" + }, + "io.coil-kt.coil3:coil-compose-core-jvm": { + "shasums": { + "jar": "a74b96cb179fe8f872d4e9f03468e0477d32787e9b6430a9d137aafb76012a60" + }, + "version": "3.2.0" + }, + "io.coil-kt.coil3:coil-compose-jvm": { + "shasums": { + "jar": "b135eafcff7545cba7e39c0c8d4e724c0f42e91050b10df5d635a6c7dfd3fb42" + }, + "version": "3.2.0" + }, + "io.coil-kt.coil3:coil-core-jvm": { + "shasums": { + "jar": "2c64e5a3be4c59a2bf1ead26891cd9c455c37a2802d258ea50a960e7dd1e121a" + }, + "version": "3.2.0" + }, + "io.coil-kt.coil3:coil-jvm": { + "shasums": { + "jar": "7d0182c987052d6502135a6a6cc7cc68288ef48f990d75ad4c4ae03e25be786e" + }, + "version": "3.2.0" + }, + "io.coil-kt.coil3:coil-network-core-jvm": { + "shasums": { + "jar": "54cff2971fbcb1743b6d4cb6fb5bb863b4f6fae37002ec57a2fdf837b0c3242e" + }, + "version": "3.2.0" + }, + "io.coil-kt.coil3:coil-network-ktor3-jvm": { + "shasums": { + "jar": "377ea37e058df261bcc274ea0c947eccc67fec5a0499bdf646b99c2f34f74a6a" + }, + "version": "3.2.0" + }, + "io.github.petertrr:kotlin-multiplatform-diff-jvm": { + "shasums": { + "jar": "db3d8270f30c0e92a03bd7f7ce99c17ed6dddf197df5b3c4154ad45facf698a8" + }, + "version": "1.3.0" + }, + "io.ktor:ktor-client-content-negotiation-jvm": { + "shasums": { + "jar": "9cbf59168645f54a9a9c21c1a0f15cd628234b20bbff3ec1bd64680f10aa779d" + }, + "version": "3.1.3" + }, + "io.ktor:ktor-client-core-jvm": { + "shasums": { + "jar": "746e2a3dece87379d64c40999401969001d373de1458fe851c0d2e0f880b42ef" + }, + "version": "3.1.3" + }, + "io.ktor:ktor-client-mock-jvm": { + "shasums": { + "jar": "2ae0d57bb9fceb8ee2aeda6536acc6f3e1de355984b4c9da720566b85f1525e8" + }, + "version": "3.1.3" + }, + "io.ktor:ktor-client-okhttp-jvm": { + "shasums": { + "jar": "a3c111c85eabb8149c485c275768d57cd96a05b595ca1946781c0d4c5fb1654a" + }, + "version": "3.1.3" + }, + "io.ktor:ktor-events-jvm": { + "shasums": { + "jar": "da7069c6e78809d7c37d104e415613cbd4cd5cec1ed54a332cb64ef6a864a060" + }, + "version": "3.1.3" + }, + "io.ktor:ktor-http-cio-jvm": { + "shasums": { + "jar": "b04aede18e9c008168096dc53a3fc016177b61a5ec3024afbf8caca0cd5dbf42" + }, + "version": "3.1.3" + }, + "io.ktor:ktor-http-jvm": { + "shasums": { + "jar": "8a50d94b46f91bd56580b9169272d6cd636f442032ba078a141da70413465946" + }, + "version": "3.1.3" + }, + "io.ktor:ktor-io-jvm": { + "shasums": { + "jar": "bb2fb6c00afaa34b539cb30e7584d37bfcba171c266bbdb9990e003579dc24c1" + }, + "version": "3.1.3" + }, + "io.ktor:ktor-network-jvm": { + "shasums": { + "jar": "fa4e6165b5ad4bf5db337ebd5f16f9b596dc5e401fbea343b9deacb6138240af" + }, + "version": "3.1.3" + }, + "io.ktor:ktor-serialization-jvm": { + "shasums": { + "jar": "0d704bc1148a8fd9a1f2005e0b5189cdaed3030efe24b8236459c41c356f5620" + }, + "version": "3.1.3" + }, + "io.ktor:ktor-serialization-kotlinx-json-jvm": { + "shasums": { + "jar": "9b810f01caa6e3f27e02d71caba8595e2b4b04071dba16e0e426e20115bed354" + }, + "version": "3.1.3" + }, + "io.ktor:ktor-serialization-kotlinx-jvm": { + "shasums": { + "jar": "b4dc2f9d4d1dda8d481a054d7f833ba195f064f5115fde3ab0dfdb8b42f61fda" + }, + "version": "3.1.3" + }, + "io.ktor:ktor-sse-jvm": { + "shasums": { + "jar": "a2ae8a338bb1d446d16dcfea2189ef5a5be31a88123b3879562b7955667a5639" + }, + "version": "3.1.3" + }, + "io.ktor:ktor-utils-jvm": { + "shasums": { + "jar": "33333937b98fc0c8e943ee4b10b3ea66b49782dfb569c44c142da4f32d85dffc" + }, + "version": "3.1.3" + }, + "io.ktor:ktor-websocket-serialization-jvm": { + "shasums": { + "jar": "67f0f566e2ed51717f6ed55f6d2b4dee1c84be4ea2cd96fc636d0bdf0fd43067" + }, + "version": "3.1.3" + }, + "io.ktor:ktor-websockets-jvm": { + "shasums": { + "jar": "ef28b4f12054ee125765b72fe3230e215a60b73b2ff2072a5c280fcf09329077" + }, + "version": "3.1.3" + }, + "io.opentelemetry:opentelemetry-api": { + "shasums": { + "jar": "4d08915aa1590bd64b3fced39bae06489e3f597c4bf7fa12f413e13c5a98be39" + }, + "version": "1.43.0" + }, + "io.opentelemetry:opentelemetry-api-incubator": { + "shasums": { + "jar": "a64d48638cdd4324e5ffab80c85784173f8c5068f059c07d8380f428d7c39ec8" + }, + "version": "1.43.0-alpha" + }, + "io.opentelemetry:opentelemetry-context": { + "shasums": { + "jar": "83d54bed8a7aa74a8648d43974c743f470c9ceab3dea57f26a938667a2dc0160" + }, + "version": "1.43.0" + }, + "io.opentelemetry:opentelemetry-exporter-logging": { + "shasums": { + "jar": "68dff3d10b0875db8fa4c137f3e1f42f3fde8470f87463feae9c10acdcef7e32" + }, + "version": "1.43.0" + }, + "io.opentelemetry:opentelemetry-sdk": { + "shasums": { + "jar": "99fd821997190e9fa1a6f6820b8cedd8e38297ab727b3b98db4d86ab518c0155" + }, + "version": "1.43.0" + }, + "io.opentelemetry:opentelemetry-sdk-common": { + "shasums": { + "jar": "8d0cc91322e85ea6f71dbf5d35f829808958fd0427e0c43aa3fdd2e94e56a48b" + }, + "version": "1.43.0" + }, + "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi": { + "shasums": { + "jar": "ae0b08fbe8b3146ff2a8e14cc48af418d6f8f808527d00406b0778748cd07f24" + }, + "version": "1.43.0" + }, + "io.opentelemetry:opentelemetry-sdk-logs": { + "shasums": { + "jar": "5465297bac529a32be7c3e37bc854f1f683df967551cc092397deaa2596f4462" + }, + "version": "1.43.0" + }, + "io.opentelemetry:opentelemetry-sdk-metrics": { + "shasums": { + "jar": "b3cd4906157c559005d6890441d367730c337ad4d860adeee7ceda1106cfc245" + }, + "version": "1.43.0" + }, + "io.opentelemetry:opentelemetry-sdk-trace": { + "shasums": { + "jar": "7e28072cf33eaa7d5e5f3ab2f8b2e51e54d24e0fe3dae3482769b0f6ff0dfcfc" + }, + "version": "1.43.0" + }, + "io.projectreactor.tools:blockhound": { + "shasums": { + "jar": "1f356d81efa24033db359b67dc4aca1d69984d66ef226e0e35cdd37c3f316a89" + }, + "version": "1.0.9.RELEASE" + }, + "javax.annotation:javax.annotation-api": { + "shasums": { + "jar": "e04ba5195bcd555dc95650f7cc614d151e4bcd52d29a10b8aa2197f3ab89ab9b" + }, + "version": "1.3.2" + }, + "javax.inject:javax.inject": { + "shasums": { + "jar": "91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff" + }, + "version": "1" + }, + "junit:junit": { + "shasums": { + "jar": "8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3" + }, + "version": "4.13.2" + }, + "org.apache.pdfbox:fontbox": { + "shasums": { + "jar": "2deec6232f5d6d3b31276592d31680ae9722af57d24cb0f76da70e2ba0e99e12" + }, + "version": "3.0.4" + }, + "org.apache.pdfbox:pdfbox": { + "shasums": { + "jar": "09a0ff27d6f84a1dc40060cb0a01decf2ad4ef91c36bc91b9836c254be8aae45" + }, + "version": "3.0.4" + }, + "org.apache.pdfbox:pdfbox-io": { + "shasums": { + "jar": "7a9d4746f2e13a1e22f4efe47fbaf999763caea41748535af93a01eedc50f554" + }, + "version": "3.0.4" + }, + "org.apache.sshd:sshd-osgi": { + "shasums": { + "jar": "3c8a183f81e176d9c452c9bb94007574bc8188446b4fc98b527aa79074cd0dda" + }, + "version": "2.15.0" + }, + "org.apache.sshd:sshd-sftp": { + "shasums": { + "jar": "4dcf4f8cc123dca9802fa993b754308be388f13daa6d59148e38cf8d0673962b" + }, + "version": "2.15.0" + }, + "org.bouncycastle:bcpkix-jdk15to18": { + "shasums": { + "jar": "d9b97477b72499bcee02f5a906510810257ff36a94bf69fbca0b1e65e7ffdb6e" + }, + "version": "1.72" + }, + "org.bouncycastle:bcprov-jdk15to18": { + "shasums": { + "jar": "ea66ea8a450810b2193e8bf9a7ad3e46307c9896224c0f407d1b7d96ba1221cc" + }, + "version": "1.72" + }, + "org.bouncycastle:bcprov-jdk18on": { + "shasums": { + "jar": "e8ad209f8c58d291a37ca9750e9e9fac60596956c983e49dd8282381dd8b3249" + }, + "version": "1.80" + }, + "org.bouncycastle:bcutil-jdk15to18": { + "shasums": { + "jar": "d92184bdeb3105a11ad9e36acbd66b5f8eed091b08b9c8f3e2549e42b7f131f1" + }, + "version": "1.72" + }, + "org.checkerframework:checker-compat-qual": { + "shasums": { + "jar": "11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a" + }, + "version": "2.5.5" + }, + "org.checkerframework:checker-qual": { + "shasums": { + "jar": "e316255bbfcd9fe50d165314b85abb2b33cb2a66a93c491db648e498a82c2de1" + }, + "version": "3.33.0" + }, + "org.conscrypt:conscrypt-openjdk-uber": { + "shasums": { + "jar": "eaf537d98e033d0f0451cd1b8cc74e02d7b55ec882da63c88060d806ba89c348" + }, + "version": "2.5.2" + }, + "org.eclipse.jgit:org.eclipse.jgit": { + "shasums": { + "jar": "c4c4e1a3eb1afe9dc6a9c93b1c8906eaaab9a5a9cdb5c95de4cc80eff4ca0dc1" + }, + "version": "7.3.0.202506031305-r" + }, + "org.eclipse.jgit:org.eclipse.jgit.ssh.apache": { + "shasums": { + "jar": "beac5323f71f7a44e9c7441cef6f8489886d35e27ec9ba865a33c0f86dfff729" + }, + "version": "7.3.0.202506031305-r" + }, + "org.eclipse.jgit:org.eclipse.jgit.ssh.jsch": { + "shasums": { + "jar": "d4a3ccbcc52e1550523d7e733b26ce633695b327b4f8d9b9e5d68f2fe264303d" + }, + "version": "5.13.3.202401111512-r" + }, + "org.hamcrest:hamcrest-core": { + "shasums": { + "jar": "66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9" + }, + "version": "1.3" + }, + "org.hamcrest:hamcrest-library": { + "shasums": { + "jar": "711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c" + }, + "version": "1.3" + }, + "org.jetbrains.androidx.lifecycle:lifecycle-common": { + "shasums": { + "jar": "b21a149fe28cccc7ece37b55098d10027aba3d2e0db31d12d3cdc907ded2368a" + }, + "version": "2.9.6" + }, + "org.jetbrains.androidx.lifecycle:lifecycle-runtime": { + "shasums": { + "jar": "9dd583b709136e0aafe60e1b90249bf63bc80cd7ba6e0641ce74a1ab3613c64f" + }, + "version": "2.9.6" + }, + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose": { + "shasums": { + "jar": "adb75b2b89d68f338d9420b8b24dd9ba5368872a4fc70e32282c2fa0f193a0fc" + }, + "version": "2.9.6" + }, + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose-desktop": { + "shasums": { + "jar": "31c3c4b6dea38f078c46829dee2c43abba2bf8757b7ee8a0f660f31217364898" + }, + "version": "2.9.6" + }, + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel": { + "shasums": { + "jar": "9ecd2bc61365fb4fa3f6f284aba92148dbfd3d1aca38662ad54bcecac2ab5546" + }, + "version": "2.9.6" + }, + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose": { + "shasums": { + "jar": "8173b469236f3d28dda0c9aa0a03085490268a8b5c602233b5374527ec2bca24" + }, + "version": "2.9.6" + }, + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-savedstate": { + "shasums": { + "jar": "74239398cb1f20a8113b37b93d309f1f57494a14f70d6578648e8bb083f80f5d" + }, + "version": "2.9.6" + }, + "org.jetbrains.androidx.savedstate:savedstate": { + "shasums": { + "jar": "0741a750940978c7e8b1605f117be62e399fd57a7625ab1ae80a28a2ca0f3415" + }, + "version": "1.3.6" + }, + "org.jetbrains.androidx.savedstate:savedstate-compose": { + "shasums": { + "jar": "61b8b51d04b4d992e8e1b618ad4cf117324301e492ad06a058fc96cdf861b780" + }, + "version": "1.3.6" + }, + "org.jetbrains.androidx.savedstate:savedstate-compose-desktop": { + "shasums": { + "jar": "0f3d045c5fd7e1301ab6c38cd0778067b0484cf39acac1233be71a723a6a8075" + }, + "version": "1.3.6" + }, + "org.jetbrains.compose.animation:animation": { + "shasums": { + "jar": "c24d85a90247b7ae31ee6e5dbbec62715ed046812a48886142afd88d5683f464" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.animation:animation-core": { + "shasums": { + "jar": "bfc4f43d664575ac10db61649212f45392f968247f96ae91e1a73e4bd0a204f3" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.animation:animation-core-desktop": { + "shasums": { + "jar": "41c0220ddbc55cb897feb0d5816b748f9c11162171f12743c04b50d0d84db628" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.animation:animation-desktop": { + "shasums": { + "jar": "1881c5575440055d54a679418f7ad7e86c0349743389360bed0f6a36af16ba34" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.annotation-internal:annotation": { + "shasums": { + "jar": "59a0e9b77b3e1f61d3e3f0df8f99ed2a12b168ded809ea39e6fd75eeff94be12" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.collection-internal:collection": { + "shasums": { + "jar": "367b8ea28496dc024531a0fe97576dd76864bb066ffa09ba2141f73c79bf3c3d" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.components:components-resources-desktop": { + "shasums": { + "jar": "7dbbe06683befa8110b4ac926a7432b7e2ee446ed156adf55ad17e9c868ae0e2" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.desktop:desktop": { + "shasums": { + "jar": "089e24417bf9f6c34eec5720eebb2cbcc82ea2855ecef90133eb17e1079d5868" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.desktop:desktop-jvm-linux-x64:pom": { + "shasums": { + "jar": "5a6361c112715bea2334898e208ec82640863d592287c2828b9edf56d5d733a9" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.foundation:foundation": { + "shasums": { + "jar": "e1922ed2a810b419e53f3b621a09d22783a1bb853d6f427da9f3201209712b1f" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.foundation:foundation-desktop": { + "shasums": { + "jar": "3a9b7bfae72f1a92a8123d3290bb7d7f61d92e5cde877af5373c3e5c2caceb2b" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.foundation:foundation-layout": { + "shasums": { + "jar": "5c29ad93f0557c478abd3fcdff9c195c5e84bda8c97f022ef7c58f4923321475" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.foundation:foundation-layout-desktop": { + "shasums": { + "jar": "8d8e00062a83a147409f42f91798394c3c221d22877953eff7d0a81767b5d0fc" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.material3:material3-desktop": { + "shasums": { + "jar": "78f0787a1c6d20f9b2460a387f51ecf554e211d3c874b22d66530a540390b811" + }, + "version": "1.9.0" + }, + "org.jetbrains.compose.material:material": { + "shasums": { + "jar": "2d2118f77ba789b8fa179803856a7ae1ec753f9ff9928ef48f2077540ab83205" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.material:material-icons-core-desktop": { + "shasums": { + "jar": "bcf6c853b6db2ff148d2d3aad3b7a7ea54d93fc7b42e0afd840eb6daf1a1c681" + }, + "version": "1.7.3" + }, + "org.jetbrains.compose.material:material-icons-extended-desktop": { + "shasums": { + "jar": "dc55d383dca8279e353917e5c5a93d192a95e7ca4f926ee55ee0b4627f99d860" + }, + "version": "1.7.3" + }, + "org.jetbrains.compose.material:material-ripple": { + "shasums": { + "jar": "71eeb6cea9e5fcf3e93e8463e188ceb1e44887183a02021dd0c2f424a5ab1c4a" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.material:material-ripple-desktop": { + "shasums": { + "jar": "2407d9e83c6fd84b90b123cc7ae6291fa7a18bb40938ad210f675e4c86425c8b" + }, + "version": "1.9.1" + }, + "org.jetbrains.compose.runtime:runtime": { + "shasums": { + "jar": "ba3e7e915b19bce05a1e74335a54628ebcee46cb238a1bb6847ad3fb045a56bd" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.runtime:runtime-desktop": { + "shasums": { + "jar": "05f5570c0a7ea8addd6fe9507a70f293efa7f1450d8b9b16dc3c8fee21cc6127" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.runtime:runtime-saveable": { + "shasums": { + "jar": "dd1f459519c3d3440eb578ec412ad06919c9d36b9c17e5cdb398d6bfb08c22fb" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.runtime:runtime-saveable-desktop": { + "shasums": { + "jar": "eb7132b55de2b0913736fdff4705022803e455810f018efecc9eb3230936520a" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.ui:ui": { + "shasums": { + "jar": "aca32b05689bb4116ac10eeeb283a57d0cb7ea1efcd97621d4643f5cb44fec6c" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.ui:ui-backhandler": { + "shasums": { + "jar": "a32331b48694e76791cf41b1e161947ecd73b1cc36f6292c1bbbc73cc411776b" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.ui:ui-backhandler-desktop": { + "shasums": { + "jar": "1babf68f5a05cbe1ba8cf934f0e575bb0d0b184444514e6aa7ec1f8004c9ce33" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.ui:ui-desktop": { + "shasums": { + "jar": "ec8887c03a333fa374d0b4c46bb9fb700937857f4088eaea4c4cc0ec835f7498" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.ui:ui-geometry": { + "shasums": { + "jar": "16ee911b8b3e51d69cc08981d95723a1682d578fefaf7f8e8a54d5555bf85925" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.ui:ui-geometry-desktop": { + "shasums": { + "jar": "cdbfdabccac8abef2d9bc0420ec0c4be7a880f6d26b2d1cc4e2317c0d252ee27" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.ui:ui-graphics": { + "shasums": { + "jar": "17d42a50b1cedd3bcedf7b5de796583edf73fd29cdc20795c5e580db1f7f6e0c" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.ui:ui-graphics-desktop": { + "shasums": { + "jar": "9fa604364dc4de23d3f8101f2f5968afa742d847105a5e2c41b6a0aa9123f11b" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.ui:ui-test-desktop": { + "shasums": { + "jar": "b7d61af17254d98ffb858ceb80bd38597c2486eead80c2cfe0a37ba3ee9724b2" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.ui:ui-test-junit4-desktop": { + "shasums": { + "jar": "de2f63543b8f646b85c789e3bf53121e4e6d89d3c7c0afc0358954cc27316a71" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.ui:ui-text": { + "shasums": { + "jar": "b537d0b3bb23ec795a1b35627deaa93703cfd0733bc7b2dc346415df06243a91" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.ui:ui-text-desktop": { + "shasums": { + "jar": "fbca4db945be286b84f75c0c9c784218470bebefa831f73f08edfb3294b6c8e8" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.ui:ui-tooling-preview": { + "shasums": { + "jar": "625c9e0ff93b928e5860f11c5108a2cd511797b9b43a6dccbb39d7c9da305233" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.ui:ui-uikit": { + "shasums": { + "jar": "1a13b39adf3ad2767f967f764ba0a0d2ed2a2d09eef310f22d2c0304d7bda6cb" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.ui:ui-unit": { + "shasums": { + "jar": "92107f897d6d868fc33e7e4eddc3e874ca9aeb22d87127646ac8ed2b676bc47a" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.ui:ui-unit-desktop": { + "shasums": { + "jar": "f0f3439928b3d9132f07cb2d7a86091696372ebc8354d16b48830b6ce15e8161" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.ui:ui-util": { + "shasums": { + "jar": "f0adcb93a17f27b5548314207db8aaf98faed62e3db2d22ca98c499ea2bc23ed" + }, + "version": "1.10.3" + }, + "org.jetbrains.compose.ui:ui-util-desktop": { + "shasums": { + "jar": "7bfc93a8cad2974cdfd5a2c817e3083e0e3c48ef99e4dbba51eb98a14c92ed2d" + }, + "version": "1.10.3" + }, + "org.jetbrains.kotlin:kotlin-android-extensions-runtime": { + "shasums": { + "jar": "5e45bd85b666422a66eca15c4ba74ba574ce82329ee7ea00c693e49d234ba255" + }, + "version": "1.9.24" + }, + "org.jetbrains.kotlin:kotlin-compose-compiler-plugin-embeddable": { + "shasums": { + "jar": "6658edfd25de3dec89bdedc0308014a2ebd97731c6f749df0827c5be1ef95515" + }, + "version": "2.3.21" + }, + "org.jetbrains.kotlin:kotlin-parcelize-runtime": { + "shasums": { + "jar": "5230951fdcdd5e793a30b7aa64692c7e611e7bd9d2e444745899160dbcb139dd" + }, + "version": "1.9.24" + }, + "org.jetbrains.kotlin:kotlin-reflect": { + "shasums": { + "jar": "33e37d9dfa86c7a29ab34e975b5f4a1287b458878611051f3485652220c1a2cb" + }, + "version": "2.3.21" + }, + "org.jetbrains.kotlin:kotlin-serialization-compiler-plugin-embeddable": { + "shasums": { + "jar": "542a36fe5ae5c35b7bb4cc297100f3634d3b5f97c7b5f78ce443621830bbbef4" + }, + "version": "2.3.21" + }, + "org.jetbrains.kotlin:kotlin-stdlib": { + "shasums": { + "jar": "6f64eac736db9434dd6925b4a518b9d1d17177652320c37916cf9ba3ce7d7d7a" + }, + "version": "2.3.21" + }, + "org.jetbrains.kotlin:kotlin-stdlib-common": { + "shasums": { + "jar": "6d3ba6f93ba29f2399d7fc873be479c6c38e449136cf542f55155f00e4ececd4" + }, + "version": "1.9.24" + }, + "org.jetbrains.kotlin:kotlin-stdlib-jdk7": { + "shasums": { + "jar": "e2243abac2bed6e0b47be18b2b7fe1c1b4cf6a431480353dcd49d1ed35f31199" + }, + "version": "2.3.21" + }, + "org.jetbrains.kotlin:kotlin-stdlib-jdk8": { + "shasums": { + "jar": "63091929246beba86b5fb2b020a6f5d06e01693a960b58a59959c8713667991c" + }, + "version": "2.3.21" + }, + "org.jetbrains.kotlin:kotlin-test": { + "shasums": { + "jar": "038f7d2c7df1039450809c486068f301a29c6e90356c9a4b595e34f4f4a813e7" + }, + "version": "2.3.21" + }, + "org.jetbrains.kotlin:kotlin-test-junit": { + "shasums": { + "jar": "554739f282eaca114882ad7effcd8523de2651eb6d65189624425110992ca4ce" + }, + "version": "2.3.21" + }, + "org.jetbrains.kotlinx:atomicfu": { + "shasums": { + "jar": "a2237ad91a3d36494ffb2556f4c59889c81f7ae3b5efb445d12ecd090b37c6e9" + }, + "version": "0.27.0" + }, + "org.jetbrains.kotlinx:atomicfu-jvm": { + "shasums": { + "jar": "2b68464170070a8b085d8a7224c7c002dbd65ea14e1f8b97a9605115a252f7fb" + }, + "version": "0.27.0" + }, + "org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm": { + "shasums": { + "jar": "0c461865231ff825d6fa18d9d333363c1f3866ffb685451e5fca66c1f22c873e" + }, + "version": "0.3.7" + }, + "org.jetbrains.kotlinx:kotlinx-coroutines-android": { + "shasums": { + "jar": "e713f1f874244115a07571065cffa0f24f5e78300e9720fea16de3af1d75fd41" + }, + "version": "1.10.2" + }, + "org.jetbrains.kotlinx:kotlinx-coroutines-core": { + "shasums": { + "jar": "7089c33c145865020760d3dbca5e4634133cc3dd7feb926e830f6de6ede28ac6" + }, + "version": "1.9.0" + }, + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm": { + "shasums": { + "jar": "5ca175b38df331fd64155b35cd8cae1251fa9ee369709b36d42e0a288ccce3fd" + }, + "version": "1.10.2" + }, + "org.jetbrains.kotlinx:kotlinx-coroutines-guava": { + "shasums": { + "jar": "183fab7212f79166d0a0efba48f3c089702fbfa70a4af8ca8a253105879daef8" + }, + "version": "1.5.0" + }, + "org.jetbrains.kotlinx:kotlinx-coroutines-reactive": { + "shasums": { + "jar": "dc6d2add2e9a2d6574bc6f4e80ed0d397e6ca5c27196dfc6ab82322d712d71be" + }, + "version": "1.7.3" + }, + "org.jetbrains.kotlinx:kotlinx-coroutines-slf4j": { + "shasums": { + "jar": "d65dee3cafa6f7bfaefedb493fc68b5c63abe750734fb8af92fac7a0d3101457" + }, + "version": "1.10.2" + }, + "org.jetbrains.kotlinx:kotlinx-coroutines-swing": { + "shasums": { + "jar": "02bdb85f20ec08004429abf6887e8d0e40f3ab637d7462f817f0f8abbe7d1eb5" + }, + "version": "1.10.2" + }, + "org.jetbrains.kotlinx:kotlinx-coroutines-test": { + "shasums": { + "jar": "b9f0603718765fe9f93b4a139198ada254f11c7bf18e48c99629a3a73ce281d1" + }, + "version": "1.9.0" + }, + "org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm": { + "shasums": { + "jar": "590a549f8c1db590c9d98a8a20424a1f581a34162a369e6a6bd884ce7d36d3d7" + }, + "version": "1.10.2" + }, + "org.jetbrains.kotlinx:kotlinx-datetime-jvm": { + "shasums": { + "jar": "3b8b98657c9aff3be7f6b4b575e9f3fb9a3a1f452a801da0f438901734acdade" + }, + "version": "0.7.1" + }, + "org.jetbrains.kotlinx:kotlinx-io-bytestring-jvm": { + "shasums": { + "jar": "ea38a66b0ff46ed82dded9e81d2dce70e5fbe03bd6cc52b4fc8869381dea7b7d" + }, + "version": "0.7.0" + }, + "org.jetbrains.kotlinx:kotlinx-io-core-jvm": { + "shasums": { + "jar": "6ededc9be4d878aea80c7dd609f91bfc47fcd3d36cc91fd0f3f328fbd6656c8f" + }, + "version": "0.7.0" + }, + "org.jetbrains.kotlinx:kotlinx-serialization-core": { + "shasums": { + "jar": "4850682e0e5976862695330d84eb8699f1dc5d50849f625263995cc88bc6f37b" + }, + "version": "1.7.3" + }, + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm": { + "shasums": { + "jar": "14d6f27ce28f61ebc4a516d562f911b7bc01cfbe5397fb884c45ea0db044c635" + }, + "version": "1.10.0" + }, + "org.jetbrains.kotlinx:kotlinx-serialization-json-io-jvm": { + "shasums": { + "jar": "ab5ec8ea48815197c46a7df9f418a62791fe91cda5023b941ce4de872d810cc1" + }, + "version": "1.8.1" + }, + "org.jetbrains.kotlinx:kotlinx-serialization-json-jvm": { + "shasums": { + "jar": "af1e3e1e8ee3176468e1ec729df853b2066071de94a84c412ad9fa135cb37f3a" + }, + "version": "1.10.0" + }, + "org.jetbrains.runtime:jbr-api": { + "shasums": { + "jar": "657ede7d7f8e175c909b23caa10fcd4d4a511304fd938aa9cc8457b4378950d5" + }, + "version": "1.5.0" + }, + "org.jetbrains.skiko:skiko": { + "shasums": { + "jar": "7273db2b088435a30aa6d3cf465f1c82d091e1c538debd7717a3978ab3f897da" + }, + "version": "0.9.37.4" + }, + "org.jetbrains.skiko:skiko-awt": { + "shasums": { + "jar": "9e859aeb982623fab156ba6671c78255f7f5e1b73334f3de7932440fed6455df" + }, + "version": "0.9.37.4" + }, + "org.jetbrains.skiko:skiko-awt-runtime-linux-x64": { + "shasums": { + "jar": "ec796df135d980bbb1740e789fe8668a8184df243e4d1c39997750303c76f13b" + }, + "version": "0.9.37.4" + }, + "org.jetbrains.skiko:skiko-awt-runtime-macos-arm64": { + "shasums": { + "jar": "5d4d47555313d387d742e5225b3f9daffcffd61cb9c3f1db56fc10963cf4280b" + }, + "version": "0.9.37.4" + }, + "org.jetbrains.skiko:skiko-awt-runtime-macos-x64": { + "shasums": { + "jar": "d01dac2dba6965d9989e1ae939a1e889919f1e076cbf61672e14aa4be28655cd" + }, + "version": "0.9.37.4" + }, + "org.jetbrains.skiko:skiko-awt-runtime-windows-x64": { + "shasums": { + "jar": "12cbbc1890773264d99a15a234a35001e61098f9e54a631554f89dc8d84ccd9b" + }, + "version": "0.9.37.4" + }, + "org.jetbrains:annotations": { + "shasums": { + "jar": "7b0f19724082cbfcbc66e5abea2b9bc92cf08a1ea11e191933ed43801eb3cd05" + }, + "version": "23.0.0" + }, + "org.jetbrains:markdown-jvm": { + "shasums": { + "jar": "893abb31f15b6216f74dc704c0c6bf1e567dcf2b62cca29cf42e4f53153637ac" + }, + "version": "0.7.3" + }, + "org.jspecify:jspecify": { + "shasums": { + "jar": "1fad6e6be7557781e4d33729d49ae1cdc8fdda6fe477bb0cc68ce351eafdfbab" + }, + "version": "1.0.0" + }, + "org.mockito:mockito-core": { + "shasums": { + "jar": "28028d70cc27d61442948fcb3d249d9df5b37c47aa0b82490a3d049094ff411f" + }, + "version": "2.25.0" + }, + "org.objenesis:objenesis": { + "shasums": { + "jar": "5e168368fbc250af3c79aa5fef0c3467a2d64e5a7bd74005f25d8399aeb0708d" + }, + "version": "2.6" + }, + "org.ow2.asm:asm": { + "shasums": { + "jar": "876eab6a83daecad5ca67eb9fcabb063c97b5aeb8cf1fca7a989ecde17522051" + }, + "version": "9.8" + }, + "org.ow2.asm:asm-commons": { + "shasums": { + "jar": "3301a1c1cb4c59fcc5292648dac1d7c5aed4c0f067dfbe88873b8cdfe77404f4" + }, + "version": "9.8" + }, + "org.ow2.asm:asm-tree": { + "shasums": { + "jar": "14b7880cb7c85eed101e2710432fc3ffb83275532a6a894dc4c4095d49ad59f1" + }, + "version": "9.8" + }, + "org.reactivestreams:reactive-streams": { + "shasums": { + "jar": "1dee0481072d19c929b623e155e14d2f6085dc011529a0a0dbefc84cf571d865" + }, + "version": "1.0.3" + }, + "org.robolectric:annotations": { + "shasums": { + "jar": "409f50354fc08b382a8fa8c42416438d3664d2cb4e63bf252022c875288fbf7a" + }, + "version": "4.16" + }, + "org.robolectric:junit": { + "shasums": { + "jar": "2c9aca263f0c41b1f0452c88d28ad618e553325f0213ce75de42fb02dd5c0479" + }, + "version": "4.16" + }, + "org.robolectric:nativeruntime": { + "shasums": { + "jar": "85c9c9763de195a166a2cfc88e8623b572bef92cb96f60342fcca3cbbd69ed25" + }, + "version": "4.16" + }, + "org.robolectric:nativeruntime-dist-compat": { + "shasums": { + "jar": "a6c34d92c990754e5aee076032a36f8e38fcacb5eb878ebe0a324509f3864eef" + }, + "version": "1.0.18" + }, + "org.robolectric:pluginapi": { + "shasums": { + "jar": "ffdb38f7d0a667e10d0609472ec13792018a69ccaf52c776166e03c61eae6428" + }, + "version": "4.16" + }, + "org.robolectric:plugins-maven-dependency-resolver": { + "shasums": { + "jar": "60858ba0f8c21b2ca38aca7bf18b0fb39ebd10ddf80ef74777fac9ba8909880a" + }, + "version": "4.16" + }, + "org.robolectric:resources": { + "shasums": { + "jar": "0d6abfd274d3c853a564ea23ce1c52d31d075281ae0e7d64bbbc1477b2ed7679" + }, + "version": "4.16" + }, + "org.robolectric:robolectric": { + "shasums": { + "jar": "d5b073aa051c88995a621e13c9c0d2afd1be835800d59c80d58c1dbfd8eca19b" + }, + "version": "4.16" + }, + "org.robolectric:sandbox": { + "shasums": { + "jar": "78462f9987db60b24283eebdf31a7f4d11487197f8508a2ea262aa5ca4bb0b18" + }, + "version": "4.16" + }, + "org.robolectric:shadowapi": { + "shasums": { + "jar": "8502d044ab781668fc52eb8784dcacd50c54eaa819cf5cc5fbb1b8457c9931a6" + }, + "version": "4.16" + }, + "org.robolectric:shadows-framework": { + "shasums": { + "jar": "f3ddb731c95cb4663634355bed62932ec8f2c7a3daab876885a16b48e1530eda" + }, + "version": "4.16" + }, + "org.robolectric:utils": { + "shasums": { + "jar": "51940c4668ed065101c8a932c6b8a7efa7b546fd5a8e98180f40ac3840b27428" + }, + "version": "4.16" + }, + "org.robolectric:utils-reflector": { + "shasums": { + "jar": "efa21dcd2d68b8f3e202580a141b5f338a33e194a46bcd33b70ddb9e6d5ad63d" + }, + "version": "4.16" + }, + "org.slf4j:jcl-over-slf4j": { + "shasums": { + "jar": "ab57ca8fd223772c17365d121f59e94ecbf0ae59d08c03a3cb5b81071c019195" + }, + "version": "1.7.36" + }, + "org.slf4j:slf4j-api": { + "shasums": { + "jar": "a12578dde1ba00bd9b816d388a0b879928d00bab3c83c240f7013bf4196c579a" + }, + "version": "2.0.16" + }, + "org.xerial:sqlite-jdbc": { + "shasums": { + "jar": "3684ac5e9bd893cbe68eb0ac1708343f66be829b1d2b5ab317e783d05acd5aef" + }, + "version": "3.51.3.0" + }, + "org.yaml:snakeyaml": { + "shasums": { + "jar": "ef779af5d29a9dde8cc70ce0341f5c6f7735e23edff9685ceaa9d35359b7bb7f" + }, + "version": "2.4" + } + }, + "dependencies": { + "androidx.activity:activity-compose:aar": [ + "androidx.activity:activity-ktx:aar", + "androidx.compose.runtime:runtime-saveable:aar", + "androidx.compose.runtime:runtime:aar", + "androidx.compose.ui:ui:aar", + "androidx.lifecycle:lifecycle-viewmodel:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.activity:activity-ktx:aar": [ + "androidx.activity:activity:aar", + "androidx.core:core-ktx:aar", + "androidx.lifecycle:lifecycle-runtime-ktx:aar", + "androidx.lifecycle:lifecycle-viewmodel-ktx:aar", + "androidx.savedstate:savedstate-ktx:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.activity:activity:aar": [ + "androidx.annotation:annotation", + "androidx.collection:collection", + "androidx.core:core:aar", + "androidx.lifecycle:lifecycle-runtime:aar", + "androidx.lifecycle:lifecycle-viewmodel-savedstate:aar", + "androidx.lifecycle:lifecycle-viewmodel:aar", + "androidx.profileinstaller:profileinstaller:aar", + "androidx.savedstate:savedstate:aar", + "androidx.tracing:tracing:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.annotation:annotation": [ + "androidx.annotation:annotation-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.annotation:annotation-experimental:aar": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.annotation:annotation-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.appcompat:appcompat-resources:aar": [ + "androidx.annotation:annotation", + "androidx.collection:collection", + "androidx.core:core:aar", + "androidx.vectordrawable:vectordrawable-animated:aar", + "androidx.vectordrawable:vectordrawable:aar" + ], + "androidx.appcompat:appcompat:aar": [ + "androidx.activity:activity:aar", + "androidx.annotation:annotation", + "androidx.appcompat:appcompat-resources:aar", + "androidx.collection:collection", + "androidx.core:core-ktx:aar", + "androidx.core:core:aar", + "androidx.cursoradapter:cursoradapter:aar", + "androidx.drawerlayout:drawerlayout:aar", + "androidx.emoji2:emoji2-views-helper:aar", + "androidx.emoji2:emoji2:aar", + "androidx.fragment:fragment:aar", + "androidx.lifecycle:lifecycle-runtime:aar", + "androidx.lifecycle:lifecycle-viewmodel:aar", + "androidx.profileinstaller:profileinstaller:aar", + "androidx.resourceinspection:resourceinspection-annotation", + "androidx.savedstate:savedstate:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.arch.core:core-common": [ + "androidx.annotation:annotation" + ], + "androidx.arch.core:core-runtime:aar": [ + "androidx.annotation:annotation", + "androidx.arch.core:core-common" + ], + "androidx.arch.core:core-testing:aar": [ + "androidx.annotation:annotation", + "androidx.arch.core:core-runtime:aar", + "junit:junit", + "org.mockito:mockito-core" + ], + "androidx.autofill:autofill:aar": [ + "androidx.core:core:aar" + ], + "androidx.camera:camera-camera2:aar": [ + "androidx.annotation:annotation", + "androidx.camera:camera-core:aar", + "androidx.concurrent:concurrent-futures", + "androidx.core:core:aar", + "androidx.tracing:tracing:aar", + "com.google.auto.value:auto-value-annotations", + "com.google.guava:listenablefuture" + ], + "androidx.camera:camera-core:aar": [ + "androidx.annotation:annotation", + "androidx.annotation:annotation-experimental:aar", + "androidx.concurrent:concurrent-futures", + "androidx.concurrent:concurrent-futures-ktx", + "androidx.core:core:aar", + "androidx.exifinterface:exifinterface:aar", + "androidx.lifecycle:lifecycle-common", + "androidx.lifecycle:lifecycle-livedata:aar", + "androidx.tracing:tracing:aar", + "com.google.auto.value:auto-value-annotations", + "com.google.guava:listenablefuture", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-android" + ], + "androidx.camera:camera-lifecycle:aar": [ + "androidx.camera:camera-core:aar", + "androidx.concurrent:concurrent-futures", + "androidx.concurrent:concurrent-futures-ktx", + "androidx.core:core:aar", + "androidx.lifecycle:lifecycle-common", + "androidx.tracing:tracing-ktx:aar", + "com.google.auto.value:auto-value-annotations", + "com.google.guava:listenablefuture", + "org.jetbrains.kotlinx:kotlinx-coroutines-android" + ], + "androidx.collection:collection": [ + "androidx.annotation:annotation", + "androidx.collection:collection-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.collection:collection-jvm": [ + "androidx.annotation:annotation-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.collection:collection-ktx": [ + "androidx.collection:collection-jvm" + ], + "androidx.compose.animation:animation-android:aar": [ + "androidx.annotation:annotation-experimental:aar", + "androidx.annotation:annotation-jvm", + "androidx.collection:collection-jvm", + "androidx.compose.animation:animation-core-android:aar", + "androidx.compose.foundation:foundation-layout-android:aar", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.ui:ui-android:aar", + "androidx.compose.ui:ui-geometry-android:aar", + "androidx.compose.ui:ui-graphics-android:aar", + "androidx.compose.ui:ui-util-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.animation:animation-core-android:aar": [ + "androidx.annotation:annotation-jvm", + "androidx.collection:collection-jvm", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.ui:ui-android:aar", + "androidx.compose.ui:ui-graphics-android:aar", + "androidx.compose.ui:ui-unit-android:aar", + "androidx.compose.ui:ui-util-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "androidx.compose.animation:animation-core:aar": [ + "androidx.compose.animation:animation-core-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "androidx.compose.animation:animation:aar": [ + "androidx.compose.animation:animation-android:aar", + "androidx.compose.animation:animation-core:aar", + "androidx.compose.foundation:foundation-layout:aar", + "androidx.compose.runtime:runtime:aar", + "androidx.compose.ui:ui-geometry:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.foundation:foundation-android:aar": [ + "androidx.annotation:annotation-experimental:aar", + "androidx.annotation:annotation-jvm", + "androidx.collection:collection-jvm", + "androidx.compose.animation:animation-android:aar", + "androidx.compose.foundation:foundation-layout-android:aar", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.ui:ui-android:aar", + "androidx.compose.ui:ui-text-android:aar", + "androidx.compose.ui:ui-util-android:aar", + "androidx.core:core:aar", + "androidx.emoji2:emoji2:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.foundation:foundation-layout-android:aar": [ + "androidx.annotation:annotation-experimental:aar", + "androidx.annotation:annotation-jvm", + "androidx.collection:collection-jvm", + "androidx.compose.animation:animation-core:aar", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.ui:ui-android:aar", + "androidx.compose.ui:ui-unit-android:aar", + "androidx.compose.ui:ui-util-android:aar", + "androidx.core:core:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.foundation:foundation-layout:aar": [ + "androidx.compose.foundation:foundation-layout-android:aar", + "androidx.compose.ui:ui:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.foundation:foundation:aar": [ + "androidx.collection:collection", + "androidx.compose.animation:animation:aar", + "androidx.compose.foundation:foundation-android:aar", + "androidx.compose.runtime:runtime:aar", + "androidx.compose.ui:ui:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.material3:material3-android:aar": [ + "androidx.activity:activity-compose:aar", + "androidx.annotation:annotation-experimental:aar", + "androidx.annotation:annotation-jvm", + "androidx.collection:collection-jvm", + "androidx.compose.animation:animation-core-android:aar", + "androidx.compose.foundation:foundation-android:aar", + "androidx.compose.foundation:foundation-layout-android:aar", + "androidx.compose.material:material-ripple-android:aar", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.ui:ui-android:aar", + "androidx.compose.ui:ui-text-android:aar", + "androidx.compose.ui:ui-util-android:aar", + "androidx.lifecycle:lifecycle-common-java8", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.material3:material3:aar": [ + "androidx.compose.foundation:foundation-layout:aar", + "androidx.compose.foundation:foundation:aar", + "androidx.compose.material3:material3-android:aar", + "androidx.compose.material:material-ripple:aar", + "androidx.compose.runtime:runtime:aar", + "androidx.compose.ui:ui-text:aar", + "androidx.compose.ui:ui:aar" + ], + "androidx.compose.material:material-android:aar": [ + "androidx.annotation:annotation-experimental:aar", + "androidx.annotation:annotation-jvm", + "androidx.compose.animation:animation-android:aar", + "androidx.compose.animation:animation-core-android:aar", + "androidx.compose.foundation:foundation-android:aar", + "androidx.compose.foundation:foundation-layout-android:aar", + "androidx.compose.material:material-ripple-android:aar", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.ui:ui-android:aar", + "androidx.compose.ui:ui-text-android:aar", + "androidx.compose.ui:ui-util-android:aar", + "androidx.lifecycle:lifecycle-runtime-android:aar", + "androidx.lifecycle:lifecycle-viewmodel-android:aar", + "androidx.savedstate:savedstate-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.material:material-icons-core-android:aar": [ + "androidx.compose.ui:ui-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlin:kotlin-stdlib-common" + ], + "androidx.compose.material:material-icons-core:aar": [ + "androidx.compose.material:material-icons-core-android:aar", + "androidx.compose.ui:ui:aar" + ], + "androidx.compose.material:material-icons-extended-android:aar": [ + "androidx.compose.material:material-icons-core-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib-common" + ], + "androidx.compose.material:material-icons-extended:aar": [ + "androidx.compose.material:material-icons-core:aar", + "androidx.compose.material:material-icons-extended-android:aar" + ], + "androidx.compose.material:material-ripple-android:aar": [ + "androidx.collection:collection-jvm", + "androidx.compose.animation:animation-android:aar", + "androidx.compose.foundation:foundation-android:aar", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.ui:ui-util-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.material:material-ripple:aar": [ + "androidx.compose.foundation:foundation:aar", + "androidx.compose.material:material-ripple-android:aar", + "androidx.compose.runtime:runtime:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.material:material:aar": [ + "androidx.compose.animation:animation-core:aar", + "androidx.compose.foundation:foundation:aar", + "androidx.compose.material:material-android:aar", + "androidx.compose.material:material-ripple:aar", + "androidx.compose.runtime:runtime:aar", + "androidx.compose.ui:ui-text:aar", + "androidx.compose.ui:ui:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.runtime:runtime-android:aar": [ + "androidx.annotation:annotation-experimental:aar", + "androidx.collection:collection-jvm", + "androidx.compose.runtime:runtime-annotation-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-android", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "androidx.compose.runtime:runtime-annotation": [ + "androidx.compose.runtime:runtime-annotation-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.runtime:runtime-annotation-android:aar": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.runtime:runtime-annotation-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.runtime:runtime-desktop": [ + "androidx.collection:collection-jvm", + "androidx.compose.runtime:runtime-annotation-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "androidx.compose.runtime:runtime-retain-android:aar": [ + "androidx.collection:collection-jvm", + "androidx.compose.runtime:runtime-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "androidx.compose.runtime:runtime-retain-desktop": [ + "androidx.collection:collection-jvm", + "androidx.compose.runtime:runtime-desktop", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "androidx.compose.runtime:runtime-retain:aar": [ + "androidx.collection:collection", + "androidx.compose.runtime:runtime-retain-android:aar", + "androidx.compose.runtime:runtime:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:atomicfu", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "androidx.compose.runtime:runtime-saveable-android:aar": [ + "androidx.annotation:annotation-jvm", + "androidx.collection:collection-jvm", + "androidx.compose.runtime:runtime-android:aar", + "androidx.lifecycle:lifecycle-runtime-compose-android:aar", + "androidx.savedstate:savedstate-compose-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.runtime:runtime-saveable-desktop": [ + "androidx.collection:collection-jvm", + "androidx.compose.runtime:runtime-desktop", + "androidx.lifecycle:lifecycle-runtime-compose-desktop", + "androidx.savedstate:savedstate-compose-desktop", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.runtime:runtime-saveable:aar": [ + "androidx.compose.runtime:runtime-saveable-android:aar", + "androidx.compose.runtime:runtime:aar", + "androidx.savedstate:savedstate-compose:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.runtime:runtime:aar": [ + "androidx.collection:collection", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.runtime:runtime-annotation", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:atomicfu", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "androidx.compose.ui:ui-android:aar": [ + "androidx.activity:activity-ktx:aar", + "androidx.annotation:annotation-experimental:aar", + "androidx.annotation:annotation-jvm", + "androidx.autofill:autofill:aar", + "androidx.collection:collection-jvm", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.runtime:runtime-retain-android:aar", + "androidx.compose.runtime:runtime-saveable-android:aar", + "androidx.compose.ui:ui-geometry-android:aar", + "androidx.compose.ui:ui-graphics-android:aar", + "androidx.compose.ui:ui-text-android:aar", + "androidx.compose.ui:ui-unit-android:aar", + "androidx.compose.ui:ui-util-android:aar", + "androidx.core:core:aar", + "androidx.customview:customview-poolingcontainer:aar", + "androidx.emoji2:emoji2:aar", + "androidx.lifecycle:lifecycle-runtime-compose-android:aar", + "androidx.lifecycle:lifecycle-viewmodel-android:aar", + "androidx.lifecycle:lifecycle-viewmodel-ktx:aar", + "androidx.profileinstaller:profileinstaller:aar", + "androidx.savedstate:savedstate-compose-android:aar", + "androidx.savedstate:savedstate-ktx:aar", + "androidx.transition:transition:aar", + "androidx.window:window:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-android", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jspecify:jspecify" + ], + "androidx.compose.ui:ui-geometry-android:aar": [ + "androidx.annotation:annotation-jvm", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.ui:ui-util-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.ui:ui-geometry:aar": [ + "androidx.compose.ui:ui-geometry-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.ui:ui-graphics-android:aar": [ + "androidx.annotation:annotation-experimental:aar", + "androidx.annotation:annotation-jvm", + "androidx.collection:collection-jvm", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.ui:ui-unit-android:aar", + "androidx.compose.ui:ui-util-android:aar", + "androidx.core:core:aar", + "androidx.graphics:graphics-path:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.ui:ui-graphics:aar": [ + "androidx.annotation:annotation", + "androidx.compose.ui:ui-graphics-android:aar", + "androidx.compose.ui:ui-unit:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.ui:ui-test-android:aar": [ + "androidx.activity:activity-compose:aar", + "androidx.annotation:annotation-jvm", + "androidx.collection:collection-jvm", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.ui:ui-android:aar", + "androidx.compose.ui:ui-graphics-android:aar", + "androidx.compose.ui:ui-text-android:aar", + "androidx.compose.ui:ui-unit-android:aar", + "androidx.compose.ui:ui-util-android:aar", + "androidx.core:core-ktx:aar", + "androidx.test.espresso:espresso-core:aar", + "androidx.test.espresso:espresso-idling-resource:aar", + "androidx.test:monitor:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm" + ], + "androidx.compose.ui:ui-test-junit4-android:aar": [ + "androidx.activity:activity-compose:aar", + "androidx.activity:activity:aar", + "androidx.annotation:annotation-jvm", + "androidx.compose.runtime:runtime-saveable-android:aar", + "androidx.compose.ui:ui-test-android:aar", + "androidx.lifecycle:lifecycle-common-jvm", + "androidx.lifecycle:lifecycle-runtime-android:aar", + "androidx.test.ext:junit:aar", + "androidx.test:core:aar", + "androidx.test:monitor:aar", + "junit:junit", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm" + ], + "androidx.compose.ui:ui-test-junit4:aar": [ + "androidx.compose.ui:ui-test-junit4-android:aar", + "androidx.compose.ui:ui-test:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.ui:ui-test-manifest:aar": [ + "androidx.activity:activity:aar" + ], + "androidx.compose.ui:ui-test:aar": [ + "androidx.compose.runtime:runtime:aar", + "androidx.compose.ui:ui-test-android:aar", + "androidx.compose.ui:ui-text:aar", + "androidx.compose.ui:ui-unit:aar", + "androidx.compose.ui:ui:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.kotlinx:kotlinx-coroutines-test" + ], + "androidx.compose.ui:ui-text-android:aar": [ + "androidx.annotation:annotation-experimental:aar", + "androidx.annotation:annotation-jvm", + "androidx.collection:collection-jvm", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.runtime:runtime-saveable-android:aar", + "androidx.compose.ui:ui-graphics-android:aar", + "androidx.compose.ui:ui-unit-android:aar", + "androidx.compose.ui:ui-util-android:aar", + "androidx.core:core:aar", + "androidx.emoji2:emoji2:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "androidx.compose.ui:ui-text:aar": [ + "androidx.compose.ui:ui-graphics:aar", + "androidx.compose.ui:ui-text-android:aar", + "androidx.compose.ui:ui-unit:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.ui:ui-tooling-preview-android:aar": [ + "androidx.annotation:annotation-jvm", + "androidx.compose.runtime:runtime-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.ui:ui-tooling-preview:aar": [ + "androidx.annotation:annotation", + "androidx.compose.runtime:runtime:aar", + "androidx.compose.ui:ui-tooling-preview-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.ui:ui-unit-android:aar": [ + "androidx.annotation:annotation-experimental:aar", + "androidx.annotation:annotation-jvm", + "androidx.collection:collection-jvm", + "androidx.collection:collection-ktx", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.ui:ui-geometry-android:aar", + "androidx.compose.ui:ui-util-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.ui:ui-unit:aar": [ + "androidx.annotation:annotation", + "androidx.compose.ui:ui-geometry:aar", + "androidx.compose.ui:ui-unit-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.ui:ui-util-android:aar": [ + "androidx.annotation:annotation-experimental:aar", + "androidx.collection:collection-jvm", + "androidx.compose.runtime:runtime-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.ui:ui-util:aar": [ + "androidx.compose.ui:ui-util-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.compose.ui:ui:aar": [ + "androidx.annotation:annotation", + "androidx.compose.runtime:runtime-retain:aar", + "androidx.compose.runtime:runtime-saveable:aar", + "androidx.compose.ui:ui-android:aar", + "androidx.compose.ui:ui-geometry:aar", + "androidx.compose.ui:ui-graphics:aar", + "androidx.compose.ui:ui-text:aar", + "androidx.compose.ui:ui-unit:aar", + "androidx.compose.ui:ui-util:aar", + "androidx.lifecycle:lifecycle-runtime-compose:aar", + "androidx.savedstate:savedstate-compose:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.concurrent:concurrent-futures": [ + "androidx.annotation:annotation", + "com.google.guava:listenablefuture" + ], + "androidx.concurrent:concurrent-futures-ktx": [ + "androidx.concurrent:concurrent-futures", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "androidx.core:core-ktx:aar": [ + "androidx.annotation:annotation", + "androidx.core:core:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.core:core-remoteviews:aar": [ + "androidx.annotation:annotation", + "androidx.core:core:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.core:core-viewtree:aar": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.core:core:aar": [ + "androidx.annotation:annotation", + "androidx.annotation:annotation-experimental:aar", + "androidx.collection:collection", + "androidx.concurrent:concurrent-futures", + "androidx.core:core-viewtree:aar", + "androidx.interpolator:interpolator:aar", + "androidx.lifecycle:lifecycle-runtime:aar", + "androidx.tracing:tracing:aar", + "androidx.versionedparcelable:versionedparcelable:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jspecify:jspecify" + ], + "androidx.cursoradapter:cursoradapter:aar": [ + "androidx.annotation:annotation" + ], + "androidx.customview:customview-poolingcontainer:aar": [ + "androidx.core:core-ktx:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.customview:customview:aar": [ + "androidx.annotation:annotation", + "androidx.collection:collection", + "androidx.core:core:aar" + ], + "androidx.datastore:datastore-core": [ + "androidx.annotation:annotation", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm" + ], + "androidx.datastore:datastore-preferences-core": [ + "androidx.datastore:datastore-core", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.datastore:datastore-preferences:aar": [ + "androidx.datastore:datastore-preferences-core", + "androidx.datastore:datastore:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.datastore:datastore:aar": [ + "androidx.annotation:annotation", + "androidx.datastore:datastore-core", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "androidx.documentfile:documentfile:aar": [ + "androidx.annotation:annotation" + ], + "androidx.drawerlayout:drawerlayout:aar": [ + "androidx.annotation:annotation", + "androidx.core:core:aar", + "androidx.customview:customview:aar" + ], + "androidx.dynamicanimation:dynamicanimation:aar": [ + "androidx.collection:collection", + "androidx.core:core:aar", + "androidx.legacy:legacy-support-core-utils:aar" + ], + "androidx.emoji2:emoji2-views-helper:aar": [ + "androidx.collection:collection", + "androidx.core:core:aar", + "androidx.emoji2:emoji2:aar" + ], + "androidx.emoji2:emoji2:aar": [ + "androidx.annotation:annotation", + "androidx.collection:collection", + "androidx.core:core:aar", + "androidx.lifecycle:lifecycle-process:aar", + "androidx.startup:startup-runtime:aar" + ], + "androidx.exifinterface:exifinterface:aar": [ + "androidx.annotation:annotation" + ], + "androidx.fragment:fragment-ktx:aar": [ + "androidx.activity:activity-ktx:aar", + "androidx.collection:collection-ktx", + "androidx.core:core-ktx:aar", + "androidx.fragment:fragment:aar", + "androidx.lifecycle:lifecycle-livedata-core-ktx:aar", + "androidx.lifecycle:lifecycle-viewmodel-ktx:aar", + "androidx.savedstate:savedstate-ktx:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.fragment:fragment:aar": [ + "androidx.activity:activity:aar", + "androidx.annotation:annotation", + "androidx.annotation:annotation-experimental:aar", + "androidx.collection:collection", + "androidx.core:core-ktx:aar", + "androidx.lifecycle:lifecycle-livedata-core:aar", + "androidx.lifecycle:lifecycle-runtime:aar", + "androidx.lifecycle:lifecycle-viewmodel-savedstate:aar", + "androidx.lifecycle:lifecycle-viewmodel:aar", + "androidx.loader:loader:aar", + "androidx.profileinstaller:profileinstaller:aar", + "androidx.savedstate:savedstate:aar", + "androidx.viewpager:viewpager:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.glance:glance-appwidget-proto": [ + "androidx.glance:glance-appwidget-external-protobuf" + ], + "androidx.glance:glance-appwidget-testing:aar": [ + "androidx.glance:glance-appwidget:aar", + "androidx.glance:glance-testing:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-test" + ], + "androidx.glance:glance-appwidget:aar": [ + "androidx.annotation:annotation", + "androidx.compose.runtime:runtime:aar", + "androidx.compose.ui:ui-graphics:aar", + "androidx.compose.ui:ui-unit:aar", + "androidx.core:core-ktx:aar", + "androidx.core:core-remoteviews:aar", + "androidx.datastore:datastore-core", + "androidx.datastore:datastore-preferences-core", + "androidx.datastore:datastore-preferences:aar", + "androidx.datastore:datastore:aar", + "androidx.glance:glance-appwidget-proto", + "androidx.glance:glance:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.glance:glance-material3:aar": [ + "androidx.annotation:annotation", + "androidx.compose.material3:material3:aar", + "androidx.compose.runtime:runtime:aar", + "androidx.core:core:aar", + "androidx.glance:glance:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.glance:glance-testing:aar": [ + "androidx.glance:glance:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.glance:glance:aar": [ + "androidx.annotation:annotation", + "androidx.annotation:annotation-experimental:aar", + "androidx.compose.runtime:runtime:aar", + "androidx.compose.ui:ui-graphics:aar", + "androidx.compose.ui:ui-unit:aar", + "androidx.concurrent:concurrent-futures-ktx", + "androidx.datastore:datastore-core", + "androidx.datastore:datastore-preferences-core", + "androidx.datastore:datastore-preferences:aar", + "androidx.work:work-runtime-ktx:aar", + "androidx.work:work-runtime:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.graphics:graphics-path:aar": [ + "androidx.core:core:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.interpolator:interpolator:aar": [ + "androidx.annotation:annotation" + ], + "androidx.legacy:legacy-support-core-utils:aar": [ + "androidx.annotation:annotation", + "androidx.core:core:aar", + "androidx.documentfile:documentfile:aar", + "androidx.loader:loader:aar", + "androidx.localbroadcastmanager:localbroadcastmanager:aar", + "androidx.print:print:aar" + ], + "androidx.lifecycle:lifecycle-common": [ + "androidx.annotation:annotation", + "androidx.lifecycle:lifecycle-common-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "androidx.lifecycle:lifecycle-common-java8": [ + "androidx.annotation:annotation", + "androidx.lifecycle:lifecycle-common" + ], + "androidx.lifecycle:lifecycle-common-jvm": [ + "androidx.annotation:annotation-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jspecify:jspecify" + ], + "androidx.lifecycle:lifecycle-livedata-core-ktx:aar": [ + "androidx.lifecycle:lifecycle-livedata-core:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.lifecycle:lifecycle-livedata-core:aar": [ + "androidx.arch.core:core-common", + "androidx.arch.core:core-runtime:aar", + "androidx.lifecycle:lifecycle-common", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jspecify:jspecify" + ], + "androidx.lifecycle:lifecycle-livedata:aar": [ + "androidx.arch.core:core-common", + "androidx.arch.core:core-runtime:aar", + "androidx.lifecycle:lifecycle-livedata-core-ktx:aar", + "androidx.lifecycle:lifecycle-livedata-core:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jspecify:jspecify" + ], + "androidx.lifecycle:lifecycle-process:aar": [ + "androidx.annotation:annotation", + "androidx.lifecycle:lifecycle-runtime:aar", + "androidx.startup:startup-runtime:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.lifecycle:lifecycle-runtime-android:aar": [ + "androidx.annotation:annotation-jvm", + "androidx.arch.core:core-common", + "androidx.arch.core:core-runtime:aar", + "androidx.core:core-viewtree:aar", + "androidx.lifecycle:lifecycle-common", + "androidx.profileinstaller:profileinstaller:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-android", + "org.jspecify:jspecify" + ], + "androidx.lifecycle:lifecycle-runtime-compose-android:aar": [ + "androidx.annotation:annotation-jvm", + "androidx.compose.runtime:runtime-android:aar", + "androidx.lifecycle:lifecycle-runtime-ktx:aar", + "androidx.lifecycle:lifecycle-runtime:aar" + ], + "androidx.lifecycle:lifecycle-runtime-compose-desktop": [ + "androidx.annotation:annotation-jvm", + "androidx.compose.runtime:runtime-desktop", + "androidx.lifecycle:lifecycle-runtime-desktop" + ], + "androidx.lifecycle:lifecycle-runtime-compose:aar": [ + "androidx.annotation:annotation", + "androidx.compose.runtime:runtime:aar", + "androidx.lifecycle:lifecycle-runtime-compose-android:aar", + "androidx.lifecycle:lifecycle-runtime:aar" + ], + "androidx.lifecycle:lifecycle-runtime-desktop": [ + "androidx.annotation:annotation-jvm", + "androidx.arch.core:core-common", + "androidx.lifecycle:lifecycle-common-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.lifecycle:lifecycle-runtime-ktx-android:aar": [ + "androidx.annotation:annotation-jvm", + "androidx.lifecycle:lifecycle-runtime-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-android" + ], + "androidx.lifecycle:lifecycle-runtime-ktx:aar": [ + "androidx.annotation:annotation", + "androidx.lifecycle:lifecycle-runtime-ktx-android:aar", + "androidx.lifecycle:lifecycle-runtime:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.lifecycle:lifecycle-runtime:aar": [ + "androidx.annotation:annotation", + "androidx.arch.core:core-common", + "androidx.lifecycle:lifecycle-common", + "androidx.lifecycle:lifecycle-runtime-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.lifecycle:lifecycle-service:aar": [ + "androidx.lifecycle:lifecycle-runtime:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.lifecycle:lifecycle-viewmodel-android:aar": [ + "androidx.annotation:annotation-jvm", + "androidx.core:core-viewtree:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-android", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm" + ], + "androidx.lifecycle:lifecycle-viewmodel-compose-android:aar": [ + "androidx.annotation:annotation-jvm", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.ui:ui-android:aar", + "androidx.lifecycle:lifecycle-common", + "androidx.lifecycle:lifecycle-viewmodel-savedstate:aar", + "androidx.lifecycle:lifecycle-viewmodel:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm" + ], + "androidx.lifecycle:lifecycle-viewmodel-compose:aar": [ + "androidx.annotation:annotation", + "androidx.compose.runtime:runtime:aar", + "androidx.lifecycle:lifecycle-common", + "androidx.lifecycle:lifecycle-viewmodel-compose-android:aar", + "androidx.lifecycle:lifecycle-viewmodel:aar", + "org.jetbrains.kotlinx:kotlinx-serialization-core" + ], + "androidx.lifecycle:lifecycle-viewmodel-desktop": [ + "androidx.annotation:annotation-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "androidx.lifecycle:lifecycle-viewmodel-ktx:aar": [ + "androidx.lifecycle:lifecycle-viewmodel:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-android" + ], + "androidx.lifecycle:lifecycle-viewmodel-savedstate-android:aar": [ + "androidx.annotation:annotation-jvm", + "androidx.core:core-ktx:aar", + "androidx.lifecycle:lifecycle-common", + "androidx.lifecycle:lifecycle-livedata-core:aar", + "androidx.lifecycle:lifecycle-viewmodel:aar", + "androidx.savedstate:savedstate-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-android", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm" + ], + "androidx.lifecycle:lifecycle-viewmodel-savedstate-desktop": [ + "androidx.annotation:annotation-jvm", + "androidx.lifecycle:lifecycle-common-jvm", + "androidx.lifecycle:lifecycle-viewmodel-desktop", + "androidx.savedstate:savedstate-desktop", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm" + ], + "androidx.lifecycle:lifecycle-viewmodel-savedstate:aar": [ + "androidx.annotation:annotation", + "androidx.lifecycle:lifecycle-common", + "androidx.lifecycle:lifecycle-viewmodel-savedstate-android:aar", + "androidx.lifecycle:lifecycle-viewmodel:aar", + "androidx.savedstate:savedstate:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.kotlinx:kotlinx-serialization-core" + ], + "androidx.lifecycle:lifecycle-viewmodel:aar": [ + "androidx.annotation:annotation", + "androidx.lifecycle:lifecycle-viewmodel-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "androidx.loader:loader:aar": [ + "androidx.annotation:annotation", + "androidx.core:core:aar", + "androidx.lifecycle:lifecycle-livedata:aar", + "androidx.lifecycle:lifecycle-viewmodel:aar" + ], + "androidx.localbroadcastmanager:localbroadcastmanager:aar": [ + "androidx.annotation:annotation" + ], + "androidx.metrics:metrics-performance:aar": [ + "androidx.collection:collection", + "androidx.core:core:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.navigationevent:navigationevent-android:aar": [ + "androidx.annotation:annotation-jvm", + "androidx.compose.runtime:runtime-annotation-android:aar", + "androidx.core:core-viewtree:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-android", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "androidx.navigationevent:navigationevent-desktop": [ + "androidx.annotation:annotation-jvm", + "androidx.compose.runtime:runtime-annotation-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "androidx.navigationevent:navigationevent:aar": [ + "androidx.annotation:annotation", + "androidx.compose.runtime:runtime-annotation", + "androidx.navigationevent:navigationevent-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "androidx.print:print:aar": [ + "androidx.annotation:annotation" + ], + "androidx.profileinstaller:profileinstaller:aar": [ + "androidx.annotation:annotation", + "androidx.concurrent:concurrent-futures", + "androidx.startup:startup-runtime:aar", + "com.google.guava:listenablefuture" + ], + "androidx.resourceinspection:resourceinspection-annotation": [ + "androidx.annotation:annotation" + ], + "androidx.room:room-common": [ + "androidx.annotation:annotation", + "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + ], + "androidx.room:room-ktx:aar": [ + "androidx.room:room-common", + "androidx.room:room-runtime:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-android" + ], + "androidx.room:room-runtime:aar": [ + "androidx.annotation:annotation-experimental:aar", + "androidx.arch.core:core-runtime:aar", + "androidx.room:room-common", + "androidx.sqlite:sqlite-framework:aar", + "androidx.sqlite:sqlite:aar" + ], + "androidx.savedstate:savedstate-android:aar": [ + "androidx.annotation:annotation-jvm", + "androidx.core:core-ktx:aar", + "androidx.core:core-viewtree:aar", + "androidx.lifecycle:lifecycle-common-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm" + ], + "androidx.savedstate:savedstate-compose-android:aar": [ + "androidx.annotation:annotation-jvm", + "androidx.compose.runtime:runtime-android:aar", + "androidx.core:core-ktx:aar", + "androidx.savedstate:savedstate-android:aar" + ], + "androidx.savedstate:savedstate-compose-desktop": [ + "androidx.compose.runtime:runtime-desktop", + "androidx.savedstate:savedstate-desktop" + ], + "androidx.savedstate:savedstate-compose:aar": [ + "androidx.compose.runtime:runtime:aar", + "androidx.savedstate:savedstate-compose-android:aar", + "androidx.savedstate:savedstate:aar" + ], + "androidx.savedstate:savedstate-desktop": [ + "androidx.annotation:annotation-jvm", + "androidx.lifecycle:lifecycle-common-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm" + ], + "androidx.savedstate:savedstate-ktx:aar": [ + "androidx.savedstate:savedstate:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.savedstate:savedstate:aar": [ + "androidx.annotation:annotation", + "androidx.lifecycle:lifecycle-common", + "androidx.savedstate:savedstate-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.kotlinx:kotlinx-serialization-core" + ], + "androidx.security:security-crypto:aar": [ + "androidx.annotation:annotation", + "androidx.collection:collection", + "com.google.crypto.tink:tink-android" + ], + "androidx.sqlite:sqlite-android:aar": [ + "androidx.annotation:annotation-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.sqlite:sqlite-framework-android:aar": [ + "androidx.annotation:annotation-jvm", + "androidx.sqlite:sqlite-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.sqlite:sqlite-framework:aar": [ + "androidx.annotation:annotation", + "androidx.sqlite:sqlite-framework-android:aar", + "androidx.sqlite:sqlite:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.sqlite:sqlite:aar": [ + "androidx.annotation:annotation", + "androidx.sqlite:sqlite-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.startup:startup-runtime:aar": [ + "androidx.annotation:annotation", + "androidx.tracing:tracing:aar" + ], + "androidx.test.espresso:espresso-core:aar": [ + "androidx.annotation:annotation", + "androidx.concurrent:concurrent-futures", + "androidx.test.espresso:espresso-idling-resource:aar", + "androidx.test.services:storage:aar", + "androidx.test:core:aar", + "androidx.test:monitor:aar", + "androidx.test:runner:aar", + "com.google.code.findbugs:jsr305", + "com.google.errorprone:error_prone_annotations", + "com.google.guava:listenablefuture", + "javax.inject:javax.inject", + "junit:junit", + "org.hamcrest:hamcrest-core", + "org.hamcrest:hamcrest-library", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.test.ext:junit:aar": [ + "androidx.annotation:annotation", + "androidx.test.services:storage:aar", + "androidx.test:core:aar", + "androidx.test:monitor:aar", + "junit:junit", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.test.services:storage:aar": [ + "androidx.annotation:annotation", + "androidx.test:monitor:aar" + ], + "androidx.test:core:aar": [ + "androidx.annotation:annotation", + "androidx.concurrent:concurrent-futures-ktx", + "androidx.lifecycle:lifecycle-common", + "androidx.test:monitor:aar", + "androidx.tracing:tracing:aar", + "com.google.guava:listenablefuture", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm" + ], + "androidx.test:monitor:aar": [ + "androidx.annotation:annotation", + "androidx.tracing:tracing:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.test:rules:aar": [ + "androidx.annotation:annotation", + "androidx.test:runner:aar", + "junit:junit" + ], + "androidx.test:runner:aar": [ + "androidx.annotation:annotation", + "androidx.test.services:storage:aar", + "androidx.test:monitor:aar", + "androidx.tracing:tracing:aar", + "junit:junit" + ], + "androidx.tracing:tracing-android:aar": [ + "androidx.annotation:annotation-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.tracing:tracing-ktx:aar": [ + "androidx.tracing:tracing:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.tracing:tracing:aar": [ + "androidx.tracing:tracing-android:aar", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.transition:transition:aar": [ + "androidx.annotation:annotation", + "androidx.collection:collection", + "androidx.core:core:aar", + "androidx.dynamicanimation:dynamicanimation:aar", + "org.jspecify:jspecify" + ], + "androidx.vectordrawable:vectordrawable-animated:aar": [ + "androidx.collection:collection", + "androidx.interpolator:interpolator:aar", + "androidx.vectordrawable:vectordrawable:aar" + ], + "androidx.vectordrawable:vectordrawable:aar": [ + "androidx.annotation:annotation", + "androidx.collection:collection", + "androidx.core:core:aar" + ], + "androidx.versionedparcelable:versionedparcelable:aar": [ + "androidx.annotation:annotation", + "androidx.collection:collection" + ], + "androidx.viewpager:viewpager:aar": [ + "androidx.annotation:annotation", + "androidx.core:core:aar", + "androidx.customview:customview:aar" + ], + "androidx.window:window-core": [ + "androidx.annotation:annotation", + "androidx.window:window-core-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.window:window-core-jvm": [ + "androidx.annotation:annotation-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "androidx.window:window:aar": [ + "androidx.annotation:annotation", + "androidx.collection:collection", + "androidx.core:core:aar", + "androidx.window:window-core", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-android", + "org.jspecify:jspecify" + ], + "androidx.work:work-runtime-ktx:aar": [ + "androidx.work:work-runtime:aar" + ], + "androidx.work:work-runtime:aar": [ + "androidx.annotation:annotation-experimental:aar", + "androidx.core:core:aar", + "androidx.lifecycle:lifecycle-livedata:aar", + "androidx.lifecycle:lifecycle-service:aar", + "androidx.room:room-ktx:aar", + "androidx.sqlite:sqlite-framework:aar", + "androidx.startup:startup-runtime:aar", + "com.google.guava:listenablefuture", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-android" + ], + "app.cash.sqldelight:android-driver:aar": [ + "androidx.sqlite:sqlite-framework:aar", + "androidx.sqlite:sqlite:aar", + "app.cash.sqldelight:runtime", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "app.cash.sqldelight:async-extensions-jvm": [ + "app.cash.sqldelight:runtime-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm" + ], + "app.cash.sqldelight:coroutines-extensions-jvm": [ + "app.cash.sqldelight:async-extensions-jvm", + "app.cash.sqldelight:runtime-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm" + ], + "app.cash.sqldelight:jdbc-driver": [ + "app.cash.sqldelight:runtime-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "app.cash.sqldelight:runtime": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "app.cash.sqldelight:runtime-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "app.cash.sqldelight:sqlite-driver": [ + "app.cash.sqldelight:jdbc-driver", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.xerial:sqlite-jdbc" + ], + "co.touchlab:stately-concurrency-jvm": [ + "co.touchlab:stately-strict-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "co.touchlab:stately-strict-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "com.android.tools:desugar_jdk_libs": [ + "com.android.tools:desugar_jdk_libs_configuration" + ], + "com.benasher44:uuid-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "com.fleeksoft.charset:charset-jvm": [ + "co.touchlab:stately-concurrency-jvm", + "com.fleeksoft.io:io-core-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "com.fleeksoft.io:io-core-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "com.fleeksoft.ksoup:ksoup-jvm": [ + "co.touchlab:stately-concurrency-jvm", + "com.fleeksoft.charset:charset-jvm", + "com.fleeksoft.io:io-core-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "com.github.requery:sqlite-android:aar": [ + "androidx.core:core:aar", + "androidx.sqlite:sqlite:aar" + ], + "com.google.android.datatransport:transport-api:aar": [ + "androidx.annotation:annotation" + ], + "com.google.android.datatransport:transport-backend-cct:aar": [ + "androidx.annotation:annotation", + "com.google.android.datatransport:transport-api:aar", + "com.google.android.datatransport:transport-runtime:aar", + "com.google.firebase:firebase-encoders", + "com.google.firebase:firebase-encoders-json:aar" + ], + "com.google.android.datatransport:transport-runtime:aar": [ + "androidx.annotation:annotation", + "com.google.android.datatransport:transport-api:aar", + "javax.inject:javax.inject" + ], + "com.google.android.gms:play-services-base:aar": [ + "androidx.collection:collection", + "androidx.core:core:aar", + "androidx.fragment:fragment:aar", + "com.google.android.gms:play-services-basement:aar", + "com.google.android.gms:play-services-tasks:aar" + ], + "com.google.android.gms:play-services-basement:aar": [ + "androidx.collection:collection", + "androidx.core:core:aar", + "androidx.fragment:fragment:aar" + ], + "com.google.android.gms:play-services-mlkit-text-recognition-common:aar": [ + "com.google.android.datatransport:transport-api:aar", + "com.google.android.datatransport:transport-backend-cct:aar", + "com.google.android.datatransport:transport-runtime:aar", + "com.google.android.gms:play-services-base:aar", + "com.google.android.gms:play-services-basement:aar", + "com.google.android.gms:play-services-tasks:aar", + "com.google.android.odml:image:aar", + "com.google.firebase:firebase-components:aar", + "com.google.firebase:firebase-encoders", + "com.google.firebase:firebase-encoders-json:aar", + "com.google.mlkit:common:aar", + "com.google.mlkit:vision-common:aar", + "com.google.mlkit:vision-interfaces:aar" + ], + "com.google.android.gms:play-services-mlkit-text-recognition:aar": [ + "com.google.android.gms:play-services-base:aar", + "com.google.android.gms:play-services-basement:aar", + "com.google.android.gms:play-services-mlkit-text-recognition-common:aar", + "com.google.mlkit:common:aar" + ], + "com.google.android.gms:play-services-tasks:aar": [ + "com.google.android.gms:play-services-basement:aar" + ], + "com.google.ar:core:aar": [ + "androidx.annotation:annotation" + ], + "com.google.crypto.tink:tink-android": [ + "com.google.code.gson:gson" + ], + "com.google.errorprone:error_prone_annotation": [ + "com.google.guava:guava" + ], + "com.google.firebase:firebase-components:aar": [ + "androidx.annotation:annotation", + "com.google.firebase:firebase-annotations" + ], + "com.google.firebase:firebase-encoders": [ + "androidx.annotation:annotation" + ], + "com.google.firebase:firebase-encoders-json:aar": [ + "androidx.annotation:annotation", + "com.google.firebase:firebase-encoders" + ], + "com.google.guava:guava": [ + "com.google.code.findbugs:jsr305", + "com.google.errorprone:error_prone_annotations", + "com.google.guava:failureaccess", + "com.google.guava:listenablefuture", + "com.google.j2objc:j2objc-annotations", + "org.checkerframework:checker-qual" + ], + "com.google.mlkit:common:aar": [ + "androidx.appcompat:appcompat:aar", + "androidx.core:core:aar", + "com.google.android.datatransport:transport-api:aar", + "com.google.android.datatransport:transport-backend-cct:aar", + "com.google.android.datatransport:transport-runtime:aar", + "com.google.android.gms:play-services-base:aar", + "com.google.android.gms:play-services-basement:aar", + "com.google.android.gms:play-services-tasks:aar", + "com.google.firebase:firebase-components:aar", + "com.google.firebase:firebase-encoders", + "com.google.firebase:firebase-encoders-json:aar" + ], + "com.google.mlkit:genai-common:aar": [ + "com.google.android.gms:play-services-basement:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.kotlinx:kotlinx-coroutines-guava" + ], + "com.google.mlkit:genai-prompt:aar": [ + "com.google.android.datatransport:transport-api:aar", + "com.google.android.datatransport:transport-backend-cct:aar", + "com.google.android.datatransport:transport-runtime:aar", + "com.google.android.gms:play-services-basement:aar", + "com.google.android.gms:play-services-tasks:aar", + "com.google.firebase:firebase-encoders", + "com.google.firebase:firebase-encoders-json:aar", + "com.google.guava:listenablefuture", + "com.google.mlkit:common:aar", + "com.google.mlkit:genai-common:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.kotlinx:kotlinx-coroutines-guava", + "org.jetbrains.kotlinx:kotlinx-coroutines-reactive" + ], + "com.google.mlkit:image-labeling-common:aar": [ + "com.google.android.gms:play-services-base:aar", + "com.google.android.gms:play-services-basement:aar", + "com.google.android.gms:play-services-tasks:aar", + "com.google.android.odml:image:aar", + "com.google.mlkit:common:aar", + "com.google.mlkit:vision-common:aar", + "com.google.mlkit:vision-interfaces:aar" + ], + "com.google.mlkit:image-labeling-default-common:aar": [ + "com.google.android.gms:play-services-base:aar", + "com.google.android.gms:play-services-basement:aar", + "com.google.android.gms:play-services-tasks:aar", + "com.google.mlkit:common:aar", + "com.google.mlkit:image-labeling-common:aar" + ], + "com.google.mlkit:image-labeling:aar": [ + "com.google.android.datatransport:transport-api:aar", + "com.google.android.datatransport:transport-backend-cct:aar", + "com.google.android.datatransport:transport-runtime:aar", + "com.google.android.gms:play-services-base:aar", + "com.google.android.gms:play-services-basement:aar", + "com.google.android.gms:play-services-tasks:aar", + "com.google.firebase:firebase-components:aar", + "com.google.firebase:firebase-encoders", + "com.google.firebase:firebase-encoders-json:aar", + "com.google.mlkit:common:aar", + "com.google.mlkit:image-labeling-common:aar", + "com.google.mlkit:image-labeling-default-common:aar", + "com.google.mlkit:vision-common:aar", + "com.google.mlkit:vision-internal-vkp:aar" + ], + "com.google.mlkit:text-recognition-bundled-common:aar": [ + "com.google.android.gms:play-services-base:aar", + "com.google.android.gms:play-services-basement:aar", + "com.google.android.gms:play-services-tasks:aar", + "com.google.mlkit:common:aar", + "com.google.mlkit:vision-common:aar" + ], + "com.google.mlkit:text-recognition:aar": [ + "com.google.android.gms:play-services-base:aar", + "com.google.android.gms:play-services-basement:aar", + "com.google.android.gms:play-services-mlkit-text-recognition:aar", + "com.google.mlkit:common:aar", + "com.google.mlkit:text-recognition-bundled-common:aar" + ], + "com.google.mlkit:vision-common:aar": [ + "androidx.exifinterface:exifinterface:aar", + "com.google.android.datatransport:transport-api:aar", + "com.google.android.datatransport:transport-backend-cct:aar", + "com.google.android.datatransport:transport-runtime:aar", + "com.google.android.gms:play-services-base:aar", + "com.google.android.gms:play-services-basement:aar", + "com.google.android.gms:play-services-tasks:aar", + "com.google.android.odml:image:aar", + "com.google.firebase:firebase-components:aar", + "com.google.firebase:firebase-encoders", + "com.google.firebase:firebase-encoders-json:aar", + "com.google.mlkit:common:aar" + ], + "com.google.mlkit:vision-interfaces:aar": [ + "com.google.android.gms:play-services-basement:aar", + "com.google.android.gms:play-services-tasks:aar" + ], + "com.google.mlkit:vision-internal-vkp:aar": [ + "com.google.android.datatransport:transport-api:aar", + "com.google.android.datatransport:transport-backend-cct:aar", + "com.google.android.datatransport:transport-runtime:aar", + "com.google.android.gms:play-services-base:aar", + "com.google.android.gms:play-services-basement:aar", + "com.google.android.gms:play-services-tasks:aar", + "com.google.firebase:firebase-components:aar", + "com.google.firebase:firebase-encoders", + "com.google.firebase:firebase-encoders-json:aar", + "com.google.mlkit:common:aar", + "com.google.mlkit:vision-common:aar", + "com.squareup.okhttp3:okhttp" + ], + "com.google.truth:truth": [ + "com.google.auto.value:auto-value-annotations", + "com.google.errorprone:error_prone_annotations", + "com.google.guava:guava", + "com.googlecode.java-diff-utils:diffutils", + "junit:junit", + "org.checkerframework:checker-compat-qual" + ], + "com.juul.kable:core-android:aar": [ + "androidx.core:core-ktx:aar", + "androidx.startup:startup-runtime:aar", + "com.benasher44:uuid-jvm", + "com.juul.kable:exceptions-jvm", + "com.juul.tuulbox:collections-jvm", + "com.juul.tuulbox:coroutines-android:aar", + "org.jetbrains.kotlin:kotlin-parcelize-runtime", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:atomicfu-jvm", + "org.jetbrains.kotlinx:kotlinx-coroutines-android", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm" + ], + "com.juul.kable:exceptions-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "com.juul.tuulbox:collections-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm" + ], + "com.juul.tuulbox:coroutines-android:aar": [ + "androidx.core:core:aar", + "androidx.startup:startup-runtime:aar", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-android", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.jetbrains.kotlinx:kotlinx-datetime-jvm" + ], + "com.squareup.okhttp3:okhttp": [ + "com.squareup.okio:okio", + "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + ], + "com.squareup.okhttp3:okhttp-sse": [ + "com.squareup.okhttp3:okhttp", + "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + ], + "com.squareup.okio:okio": [ + "com.squareup.okio:okio-jvm" + ], + "com.squareup.okio:okio-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "com.tom-roush:pdfbox-android:aar": [ + "org.bouncycastle:bcpkix-jdk15to18", + "org.bouncycastle:bcprov-jdk15to18", + "org.bouncycastle:bcutil-jdk15to18" + ], + "io.arrow-kt:arrow-annotations-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "io.arrow-kt:arrow-atomic-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "io.arrow-kt:arrow-autoclose-jvm": [ + "io.arrow-kt:arrow-atomic-jvm", + "io.arrow-kt:arrow-exception-utils-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "io.arrow-kt:arrow-core-jvm": [ + "io.arrow-kt:arrow-annotations-jvm", + "io.arrow-kt:arrow-atomic-jvm", + "io.arrow-kt:arrow-exception-utils-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "io.arrow-kt:arrow-exception-utils-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "io.arrow-kt:arrow-fx-coroutines-jvm": [ + "io.arrow-kt:arrow-autoclose-jvm", + "io.arrow-kt:arrow-core-jvm", + "io.arrow-kt:arrow-exception-utils-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm" + ], + "io.arrow-kt:arrow-optics-jvm": [ + "io.arrow-kt:arrow-core-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "io.arrow-kt:arrow-resilience-jvm": [ + "io.arrow-kt:arrow-fx-coroutines-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "io.coil-kt.coil3:coil-compose-core-jvm": [ + "io.coil-kt.coil3:coil-core-jvm", + "org.jetbrains.compose.foundation:foundation-desktop", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "io.coil-kt.coil3:coil-compose-jvm": [ + "io.coil-kt.coil3:coil-compose-core-jvm", + "io.coil-kt.coil3:coil-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "io.coil-kt.coil3:coil-core-jvm": [ + "com.squareup.okio:okio-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.jetbrains.skiko:skiko-awt" + ], + "io.coil-kt.coil3:coil-jvm": [ + "io.coil-kt.coil3:coil-core-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "io.coil-kt.coil3:coil-network-core-jvm": [ + "io.coil-kt.coil3:coil-core-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "io.coil-kt.coil3:coil-network-ktor3-jvm": [ + "io.coil-kt.coil3:coil-core-jvm", + "io.coil-kt.coil3:coil-network-core-jvm", + "io.ktor:ktor-client-core-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "io.github.petertrr:kotlin-multiplatform-diff-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "io.ktor:ktor-client-content-negotiation-jvm": [ + "io.ktor:ktor-client-core-jvm", + "io.ktor:ktor-serialization-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.slf4j:slf4j-api" + ], + "io.ktor:ktor-client-core-jvm": [ + "io.ktor:ktor-events-jvm", + "io.ktor:ktor-http-cio-jvm", + "io.ktor:ktor-http-jvm", + "io.ktor:ktor-sse-jvm", + "io.ktor:ktor-websocket-serialization-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.jetbrains.kotlinx:kotlinx-coroutines-slf4j", + "org.slf4j:slf4j-api" + ], + "io.ktor:ktor-client-mock-jvm": [ + "io.ktor:ktor-client-core-jvm", + "io.ktor:ktor-http-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.slf4j:slf4j-api" + ], + "io.ktor:ktor-client-okhttp-jvm": [ + "com.squareup.okhttp3:okhttp", + "com.squareup.okhttp3:okhttp-sse", + "com.squareup.okio:okio-jvm", + "io.ktor:ktor-client-core-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.slf4j:slf4j-api" + ], + "io.ktor:ktor-events-jvm": [ + "io.ktor:ktor-utils-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.slf4j:slf4j-api" + ], + "io.ktor:ktor-http-cio-jvm": [ + "io.ktor:ktor-http-jvm", + "io.ktor:ktor-io-jvm", + "io.ktor:ktor-network-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.slf4j:slf4j-api" + ], + "io.ktor:ktor-http-jvm": [ + "io.ktor:ktor-utils-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm", + "org.slf4j:slf4j-api" + ], + "io.ktor:ktor-io-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.jetbrains.kotlinx:kotlinx-io-core-jvm", + "org.slf4j:slf4j-api" + ], + "io.ktor:ktor-network-jvm": [ + "io.ktor:ktor-utils-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.slf4j:slf4j-api" + ], + "io.ktor:ktor-serialization-jvm": [ + "io.ktor:ktor-websockets-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.slf4j:slf4j-api" + ], + "io.ktor:ktor-serialization-kotlinx-json-jvm": [ + "io.ktor:ktor-serialization-kotlinx-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-json-io-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-json-jvm", + "org.slf4j:slf4j-api" + ], + "io.ktor:ktor-serialization-kotlinx-jvm": [ + "io.ktor:ktor-serialization-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm", + "org.slf4j:slf4j-api" + ], + "io.ktor:ktor-sse-jvm": [ + "io.ktor:ktor-utils-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.slf4j:slf4j-api" + ], + "io.ktor:ktor-utils-jvm": [ + "io.ktor:ktor-io-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm", + "org.slf4j:slf4j-api" + ], + "io.ktor:ktor-websocket-serialization-jvm": [ + "io.ktor:ktor-serialization-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.slf4j:slf4j-api" + ], + "io.ktor:ktor-websockets-jvm": [ + "io.ktor:ktor-http-jvm", + "io.ktor:ktor-utils-jvm", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.slf4j:slf4j-api" + ], + "io.opentelemetry:opentelemetry-api": [ + "io.opentelemetry:opentelemetry-context" + ], + "io.opentelemetry:opentelemetry-api-incubator": [ + "io.opentelemetry:opentelemetry-api" + ], + "io.opentelemetry:opentelemetry-exporter-logging": [ + "io.opentelemetry:opentelemetry-sdk", + "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi" + ], + "io.opentelemetry:opentelemetry-sdk": [ + "io.opentelemetry:opentelemetry-api", + "io.opentelemetry:opentelemetry-sdk-common", + "io.opentelemetry:opentelemetry-sdk-logs", + "io.opentelemetry:opentelemetry-sdk-metrics", + "io.opentelemetry:opentelemetry-sdk-trace" + ], + "io.opentelemetry:opentelemetry-sdk-common": [ + "io.opentelemetry:opentelemetry-api" + ], + "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi": [ + "io.opentelemetry:opentelemetry-sdk" + ], + "io.opentelemetry:opentelemetry-sdk-logs": [ + "io.opentelemetry:opentelemetry-api", + "io.opentelemetry:opentelemetry-api-incubator", + "io.opentelemetry:opentelemetry-sdk-common" + ], + "io.opentelemetry:opentelemetry-sdk-metrics": [ + "io.opentelemetry:opentelemetry-api", + "io.opentelemetry:opentelemetry-api-incubator", + "io.opentelemetry:opentelemetry-sdk-common" + ], + "io.opentelemetry:opentelemetry-sdk-trace": [ + "io.opentelemetry:opentelemetry-api", + "io.opentelemetry:opentelemetry-api-incubator", + "io.opentelemetry:opentelemetry-sdk-common" + ], + "junit:junit": [ + "org.hamcrest:hamcrest-core" + ], + "org.apache.pdfbox:fontbox": [ + "commons-logging:commons-logging", + "org.apache.pdfbox:pdfbox-io" + ], + "org.apache.pdfbox:pdfbox": [ + "commons-logging:commons-logging", + "org.apache.pdfbox:fontbox", + "org.apache.pdfbox:pdfbox-io" + ], + "org.apache.pdfbox:pdfbox-io": [ + "commons-logging:commons-logging" + ], + "org.apache.sshd:sshd-osgi": [ + "org.slf4j:jcl-over-slf4j", + "org.slf4j:slf4j-api" + ], + "org.apache.sshd:sshd-sftp": [ + "org.slf4j:jcl-over-slf4j", + "org.slf4j:slf4j-api" + ], + "org.bouncycastle:bcpkix-jdk15to18": [ + "org.bouncycastle:bcprov-jdk15to18", + "org.bouncycastle:bcutil-jdk15to18" + ], + "org.bouncycastle:bcutil-jdk15to18": [ + "org.bouncycastle:bcprov-jdk15to18" + ], + "org.eclipse.jgit:org.eclipse.jgit": [ + "com.googlecode.javaewah:JavaEWAH", + "commons-codec:commons-codec", + "org.slf4j:slf4j-api" + ], + "org.eclipse.jgit:org.eclipse.jgit.ssh.apache": [ + "org.apache.sshd:sshd-osgi", + "org.apache.sshd:sshd-sftp", + "org.eclipse.jgit:org.eclipse.jgit", + "org.slf4j:slf4j-api" + ], + "org.eclipse.jgit:org.eclipse.jgit.ssh.jsch": [ + "com.jcraft:jsch", + "com.jcraft:jzlib", + "org.eclipse.jgit:org.eclipse.jgit", + "org.slf4j:slf4j-api" + ], + "org.hamcrest:hamcrest-library": [ + "org.hamcrest:hamcrest-core" + ], + "org.jetbrains.androidx.lifecycle:lifecycle-common": [ + "androidx.lifecycle:lifecycle-common" + ], + "org.jetbrains.androidx.lifecycle:lifecycle-runtime": [ + "androidx.lifecycle:lifecycle-runtime:aar", + "org.jetbrains.androidx.lifecycle:lifecycle-common" + ], + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose": [ + "androidx.lifecycle:lifecycle-runtime-compose:aar", + "org.jetbrains.androidx.lifecycle:lifecycle-common", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime", + "org.jetbrains.compose.runtime:runtime" + ], + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose-desktop": [ + "androidx.lifecycle:lifecycle-common-jvm", + "androidx.lifecycle:lifecycle-runtime-compose-desktop", + "androidx.lifecycle:lifecycle-runtime-desktop", + "org.jetbrains.compose.runtime:runtime-desktop" + ], + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel": [ + "androidx.lifecycle:lifecycle-viewmodel:aar" + ], + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose": [ + "androidx.annotation:annotation", + "androidx.lifecycle:lifecycle-viewmodel-compose:aar", + "org.jetbrains.androidx.lifecycle:lifecycle-common", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-savedstate", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.ui:ui", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-serialization-core" + ], + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-savedstate": [ + "androidx.lifecycle:lifecycle-viewmodel-savedstate:aar", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel", + "org.jetbrains.androidx.savedstate:savedstate" + ], + "org.jetbrains.androidx.savedstate:savedstate": [ + "androidx.savedstate:savedstate:aar" + ], + "org.jetbrains.androidx.savedstate:savedstate-compose": [ + "androidx.savedstate:savedstate-compose:aar", + "org.jetbrains.androidx.savedstate:savedstate", + "org.jetbrains.compose.runtime:runtime" + ], + "org.jetbrains.androidx.savedstate:savedstate-compose-desktop": [ + "androidx.savedstate:savedstate-compose-desktop", + "androidx.savedstate:savedstate-desktop", + "org.jetbrains.compose.runtime:runtime-desktop" + ], + "org.jetbrains.compose.animation:animation": [ + "androidx.compose.animation:animation:aar", + "org.jetbrains.compose.animation:animation-core", + "org.jetbrains.compose.collection-internal:collection", + "org.jetbrains.compose.foundation:foundation-layout", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.ui:ui", + "org.jetbrains.compose.ui:ui-geometry", + "org.jetbrains.compose.ui:ui-util", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.compose.animation:animation-core": [ + "androidx.compose.animation:animation-core:aar", + "org.jetbrains.compose.annotation-internal:annotation", + "org.jetbrains.compose.collection-internal:collection", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.ui:ui", + "org.jetbrains.compose.ui:ui-unit", + "org.jetbrains.compose.ui:ui-util", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:atomicfu", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "org.jetbrains.compose.animation:animation-core-desktop": [ + "androidx.annotation:annotation-jvm", + "androidx.collection:collection-jvm", + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.compose.ui:ui-desktop", + "org.jetbrains.compose.ui:ui-unit-desktop", + "org.jetbrains.compose.ui:ui-util-desktop", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:atomicfu-jvm", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "org.jetbrains.compose.animation:animation-desktop": [ + "androidx.collection:collection-jvm", + "org.jetbrains.compose.animation:animation-core-desktop", + "org.jetbrains.compose.foundation:foundation-layout-desktop", + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.compose.ui:ui-desktop", + "org.jetbrains.compose.ui:ui-geometry-desktop", + "org.jetbrains.compose.ui:ui-util-desktop", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.compose.annotation-internal:annotation": [ + "androidx.annotation:annotation" + ], + "org.jetbrains.compose.collection-internal:collection": [ + "androidx.collection:collection" + ], + "org.jetbrains.compose.components:components-resources-desktop": [ + "org.jetbrains.compose.foundation:foundation-desktop", + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm" + ], + "org.jetbrains.compose.desktop:desktop": [ + "org.jetbrains.compose.foundation:foundation", + "org.jetbrains.compose.material:material", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.ui:ui", + "org.jetbrains.compose.ui:ui-tooling-preview" + ], + "org.jetbrains.compose.desktop:desktop-jvm-linux-x64:pom": [ + "org.jetbrains.compose.desktop:desktop", + "org.jetbrains.skiko:skiko-awt-runtime-linux-x64" + ], + "org.jetbrains.compose.foundation:foundation": [ + "androidx.compose.foundation:foundation:aar", + "org.jetbrains.compose.animation:animation", + "org.jetbrains.compose.annotation-internal:annotation", + "org.jetbrains.compose.collection-internal:collection", + "org.jetbrains.compose.foundation:foundation-layout", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.ui:ui", + "org.jetbrains.compose.ui:ui-text", + "org.jetbrains.compose.ui:ui-uikit", + "org.jetbrains.compose.ui:ui-util", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:atomicfu", + "org.jetbrains.skiko:skiko" + ], + "org.jetbrains.compose.foundation:foundation-desktop": [ + "androidx.annotation:annotation-jvm", + "androidx.collection:collection-jvm", + "org.jetbrains.compose.animation:animation-desktop", + "org.jetbrains.compose.foundation:foundation-layout-desktop", + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.compose.ui:ui-desktop", + "org.jetbrains.compose.ui:ui-text-desktop", + "org.jetbrains.compose.ui:ui-util-desktop", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:atomicfu-jvm", + "org.jetbrains.skiko:skiko-awt" + ], + "org.jetbrains.compose.foundation:foundation-layout": [ + "androidx.compose.foundation:foundation-layout:aar", + "org.jetbrains.compose.annotation-internal:annotation", + "org.jetbrains.compose.collection-internal:collection", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.ui:ui", + "org.jetbrains.compose.ui:ui-util", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.compose.foundation:foundation-layout-desktop": [ + "androidx.annotation:annotation-jvm", + "androidx.collection:collection-jvm", + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.compose.ui:ui-desktop", + "org.jetbrains.compose.ui:ui-util-desktop", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.compose.material3:material3-desktop": [ + "androidx.annotation:annotation-jvm", + "androidx.collection:collection-jvm", + "org.jetbrains.compose.animation:animation-core-desktop", + "org.jetbrains.compose.foundation:foundation-desktop", + "org.jetbrains.compose.foundation:foundation-layout-desktop", + "org.jetbrains.compose.material:material-ripple-desktop", + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.compose.ui:ui-backhandler-desktop", + "org.jetbrains.compose.ui:ui-graphics-desktop", + "org.jetbrains.compose.ui:ui-text-desktop", + "org.jetbrains.compose.ui:ui-util-desktop", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:atomicfu-jvm", + "org.jetbrains.kotlinx:kotlinx-datetime-jvm" + ], + "org.jetbrains.compose.material:material": [ + "androidx.compose.material:material:aar", + "org.jetbrains.compose.animation:animation", + "org.jetbrains.compose.animation:animation-core", + "org.jetbrains.compose.annotation-internal:annotation", + "org.jetbrains.compose.foundation:foundation", + "org.jetbrains.compose.foundation:foundation-layout", + "org.jetbrains.compose.material:material-ripple", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.ui:ui", + "org.jetbrains.compose.ui:ui-text", + "org.jetbrains.compose.ui:ui-util", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:atomicfu" + ], + "org.jetbrains.compose.material:material-icons-core-desktop": [ + "org.jetbrains.compose.ui:ui-desktop", + "org.jetbrains.compose.ui:ui-graphics-desktop", + "org.jetbrains.compose.ui:ui-unit-desktop", + "org.jetbrains.kotlin:kotlin-stdlib-common" + ], + "org.jetbrains.compose.material:material-icons-extended-desktop": [ + "org.jetbrains.compose.material:material-icons-core-desktop", + "org.jetbrains.compose.ui:ui-desktop", + "org.jetbrains.compose.ui:ui-graphics-desktop" + ], + "org.jetbrains.compose.material:material-ripple": [ + "androidx.compose.material:material-ripple:aar", + "org.jetbrains.compose.animation:animation", + "org.jetbrains.compose.collection-internal:collection", + "org.jetbrains.compose.foundation:foundation", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.ui:ui-util", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.compose.material:material-ripple-desktop": [ + "androidx.collection:collection-jvm", + "org.jetbrains.compose.animation:animation-desktop", + "org.jetbrains.compose.foundation:foundation-desktop", + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.compose.ui:ui-util-desktop", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.compose.runtime:runtime": [ + "androidx.compose.runtime:runtime:aar" + ], + "org.jetbrains.compose.runtime:runtime-desktop": [ + "androidx.compose.runtime:runtime-desktop" + ], + "org.jetbrains.compose.runtime:runtime-saveable": [ + "androidx.compose.runtime:runtime-saveable:aar", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose", + "org.jetbrains.androidx.savedstate:savedstate-compose", + "org.jetbrains.compose.runtime:runtime" + ], + "org.jetbrains.compose.runtime:runtime-saveable-desktop": [ + "androidx.compose.runtime:runtime-saveable-desktop", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose-desktop", + "org.jetbrains.androidx.savedstate:savedstate-compose-desktop", + "org.jetbrains.compose.runtime:runtime-desktop" + ], + "org.jetbrains.compose.ui:ui": [ + "androidx.compose.runtime:runtime-retain:aar", + "androidx.compose.ui:ui:aar", + "androidx.navigationevent:navigationevent:aar", + "org.jetbrains.androidx.lifecycle:lifecycle-common", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-savedstate", + "org.jetbrains.compose.annotation-internal:annotation", + "org.jetbrains.compose.collection-internal:collection", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.runtime:runtime-saveable", + "org.jetbrains.compose.ui:ui-backhandler", + "org.jetbrains.compose.ui:ui-geometry", + "org.jetbrains.compose.ui:ui-graphics", + "org.jetbrains.compose.ui:ui-text", + "org.jetbrains.compose.ui:ui-uikit", + "org.jetbrains.compose.ui:ui-unit", + "org.jetbrains.compose.ui:ui-util", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:atomicfu", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.skiko:skiko" + ], + "org.jetbrains.compose.ui:ui-backhandler": [ + "androidx.navigationevent:navigationevent:aar", + "org.jetbrains.compose.annotation-internal:annotation", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.ui:ui-util", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "org.jetbrains.compose.ui:ui-backhandler-desktop": [ + "androidx.annotation:annotation-jvm", + "androidx.navigationevent:navigationevent-desktop", + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.compose.ui:ui-util-desktop", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "org.jetbrains.compose.ui:ui-desktop": [ + "androidx.annotation:annotation-jvm", + "androidx.collection:collection-jvm", + "androidx.compose.runtime:runtime-retain-desktop", + "androidx.lifecycle:lifecycle-common-jvm", + "androidx.lifecycle:lifecycle-runtime-desktop", + "androidx.lifecycle:lifecycle-viewmodel-desktop", + "androidx.lifecycle:lifecycle-viewmodel-savedstate-desktop", + "androidx.navigationevent:navigationevent-desktop", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose-desktop", + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.compose.runtime:runtime-saveable-desktop", + "org.jetbrains.compose.ui:ui-backhandler-desktop", + "org.jetbrains.compose.ui:ui-geometry-desktop", + "org.jetbrains.compose.ui:ui-graphics-desktop", + "org.jetbrains.compose.ui:ui-text-desktop", + "org.jetbrains.compose.ui:ui-unit-desktop", + "org.jetbrains.compose.ui:ui-util-desktop", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlin:kotlin-stdlib-jdk8", + "org.jetbrains.kotlinx:atomicfu-jvm", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.skiko:skiko-awt" + ], + "org.jetbrains.compose.ui:ui-geometry": [ + "androidx.compose.ui:ui-geometry:aar", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.ui:ui-util", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.compose.ui:ui-geometry-desktop": [ + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.compose.ui:ui-util-desktop", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.compose.ui:ui-graphics": [ + "androidx.compose.ui:ui-graphics:aar", + "org.jetbrains.compose.annotation-internal:annotation", + "org.jetbrains.compose.collection-internal:collection", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.ui:ui-geometry", + "org.jetbrains.compose.ui:ui-unit", + "org.jetbrains.compose.ui:ui-util", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.skiko:skiko" + ], + "org.jetbrains.compose.ui:ui-graphics-desktop": [ + "androidx.annotation:annotation-jvm", + "androidx.collection:collection-jvm", + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.compose.ui:ui-geometry-desktop", + "org.jetbrains.compose.ui:ui-unit-desktop", + "org.jetbrains.compose.ui:ui-util-desktop", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlin:kotlin-stdlib-jdk8", + "org.jetbrains.skiko:skiko-awt" + ], + "org.jetbrains.compose.ui:ui-test-desktop": [ + "androidx.annotation:annotation-jvm", + "androidx.collection:collection-jvm", + "androidx.lifecycle:lifecycle-viewmodel-desktop", + "androidx.lifecycle:lifecycle-viewmodel-savedstate-desktop", + "androidx.navigationevent:navigationevent-desktop", + "com.google.truth:truth", + "junit:junit", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose-desktop", + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.compose.ui:ui-desktop", + "org.jetbrains.compose.ui:ui-text-desktop", + "org.jetbrains.compose.ui:ui-unit-desktop", + "org.jetbrains.compose.ui:ui-util-desktop", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:atomicfu-jvm", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm", + "org.jetbrains.skiko:skiko-awt" + ], + "org.jetbrains.compose.ui:ui-test-junit4-desktop": [ + "androidx.annotation:annotation-jvm", + "com.google.truth:truth", + "junit:junit", + "org.jetbrains.compose.ui:ui-test-desktop", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm", + "org.jetbrains.skiko:skiko-awt" + ], + "org.jetbrains.compose.ui:ui-text": [ + "androidx.compose.ui:ui-text:aar", + "org.jetbrains.compose.annotation-internal:annotation", + "org.jetbrains.compose.collection-internal:collection", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.runtime:runtime-saveable", + "org.jetbrains.compose.ui:ui-geometry", + "org.jetbrains.compose.ui:ui-graphics", + "org.jetbrains.compose.ui:ui-unit", + "org.jetbrains.compose.ui:ui-util", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:atomicfu", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.skiko:skiko" + ], + "org.jetbrains.compose.ui:ui-text-desktop": [ + "androidx.annotation:annotation-jvm", + "androidx.collection:collection-jvm", + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.compose.runtime:runtime-saveable-desktop", + "org.jetbrains.compose.ui:ui-geometry-desktop", + "org.jetbrains.compose.ui:ui-graphics-desktop", + "org.jetbrains.compose.ui:ui-unit-desktop", + "org.jetbrains.compose.ui:ui-util-desktop", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:atomicfu-jvm", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.skiko:skiko-awt" + ], + "org.jetbrains.compose.ui:ui-tooling-preview": [ + "androidx.annotation:annotation", + "androidx.compose.ui:ui-tooling-preview:aar", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.compose.ui:ui-unit": [ + "androidx.compose.ui:ui-unit:aar", + "org.jetbrains.compose.annotation-internal:annotation", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.ui:ui-geometry", + "org.jetbrains.compose.ui:ui-util", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.compose.ui:ui-unit-desktop": [ + "androidx.annotation:annotation-jvm", + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.compose.ui:ui-geometry-desktop", + "org.jetbrains.compose.ui:ui-util-desktop", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.compose.ui:ui-util": [ + "androidx.compose.ui:ui-util:aar", + "org.jetbrains.compose.collection-internal:collection", + "org.jetbrains.compose.ui:ui-uikit", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.compose.ui:ui-util-desktop": [ + "androidx.collection:collection-jvm", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.kotlin:kotlin-android-extensions-runtime": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.kotlin:kotlin-parcelize-runtime": [ + "org.jetbrains.kotlin:kotlin-android-extensions-runtime", + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.kotlin:kotlin-reflect": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.kotlin:kotlin-stdlib": [ + "org.jetbrains:annotations" + ], + "org.jetbrains.kotlin:kotlin-stdlib-jdk7": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.kotlin:kotlin-stdlib-jdk8": [ + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlin:kotlin-stdlib-jdk7" + ], + "org.jetbrains.kotlin:kotlin-test": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.kotlin:kotlin-test-junit": [ + "junit:junit", + "org.jetbrains.kotlin:kotlin-test" + ], + "org.jetbrains.kotlinx:atomicfu": [ + "org.jetbrains.kotlinx:atomicfu-jvm" + ], + "org.jetbrains.kotlinx:atomicfu-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.kotlinx:kotlinx-coroutines-android": [ + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm" + ], + "org.jetbrains.kotlinx:kotlinx-coroutines-core": [ + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm" + ], + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains:annotations" + ], + "org.jetbrains.kotlinx:kotlinx-coroutines-guava": [ + "com.google.guava:guava", + "org.jetbrains.kotlin:kotlin-stdlib-jdk8", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm" + ], + "org.jetbrains.kotlinx:kotlinx-coroutines-reactive": [ + "org.jetbrains.kotlin:kotlin-stdlib-jdk8", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.reactivestreams:reactive-streams" + ], + "org.jetbrains.kotlinx:kotlinx-coroutines-slf4j": [ + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.slf4j:slf4j-api" + ], + "org.jetbrains.kotlinx:kotlinx-coroutines-swing": [ + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm" + ], + "org.jetbrains.kotlinx:kotlinx-coroutines-test": [ + "org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm" + ], + "org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.jetbrains:annotations" + ], + "org.jetbrains.kotlinx:kotlinx-datetime-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.kotlinx:kotlinx-io-bytestring-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.kotlinx:kotlinx-io-core-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-io-bytestring-jvm" + ], + "org.jetbrains.kotlinx:kotlinx-serialization-core": [ + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm" + ], + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.jetbrains.kotlinx:kotlinx-serialization-json-io-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-io-core-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-json-jvm" + ], + "org.jetbrains.kotlinx:kotlinx-serialization-json-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm" + ], + "org.jetbrains.skiko:skiko": [ + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core" + ], + "org.jetbrains.skiko:skiko-awt": [ + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.jetbrains.runtime:jbr-api" + ], + "org.jetbrains.skiko:skiko-awt-runtime-linux-x64": [ + "org.jetbrains.skiko:skiko-awt" + ], + "org.jetbrains.skiko:skiko-awt-runtime-macos-arm64": [ + "org.jetbrains.skiko:skiko-awt" + ], + "org.jetbrains.skiko:skiko-awt-runtime-macos-x64": [ + "org.jetbrains.skiko:skiko-awt" + ], + "org.jetbrains.skiko:skiko-awt-runtime-windows-x64": [ + "org.jetbrains.skiko:skiko-awt" + ], + "org.jetbrains:markdown-jvm": [ + "org.jetbrains.kotlin:kotlin-stdlib" + ], + "org.mockito:mockito-core": [ + "org.objenesis:objenesis" + ], + "org.ow2.asm:asm-commons": [ + "org.ow2.asm:asm", + "org.ow2.asm:asm-tree" + ], + "org.ow2.asm:asm-tree": [ + "org.ow2.asm:asm" + ], + "org.robolectric:junit": [ + "org.robolectric:pluginapi", + "org.robolectric:sandbox" + ], + "org.robolectric:nativeruntime": [ + "com.google.guava:guava", + "org.robolectric:nativeruntime-dist-compat", + "org.robolectric:shadowapi", + "org.robolectric:utils" + ], + "org.robolectric:pluginapi": [ + "com.google.guava:guava", + "org.robolectric:annotations" + ], + "org.robolectric:plugins-maven-dependency-resolver": [ + "com.google.auto.value:auto-value-annotations", + "com.google.guava:guava", + "org.robolectric:pluginapi", + "org.robolectric:utils" + ], + "org.robolectric:resources": [ + "com.google.auto.value:auto-value-annotations", + "com.google.guava:guava", + "org.robolectric:pluginapi", + "org.robolectric:utils" + ], + "org.robolectric:robolectric": [ + "androidx.test.espresso:espresso-idling-resource:aar", + "androidx.test:monitor:aar", + "com.google.testparameterinjector:test-parameter-injector", + "javax.annotation:javax.annotation-api", + "javax.inject:javax.inject", + "org.bouncycastle:bcprov-jdk18on", + "org.conscrypt:conscrypt-openjdk-uber", + "org.robolectric:annotations", + "org.robolectric:junit", + "org.robolectric:pluginapi", + "org.robolectric:plugins-maven-dependency-resolver", + "org.robolectric:resources", + "org.robolectric:sandbox", + "org.robolectric:shadows-framework", + "org.robolectric:utils", + "org.robolectric:utils-reflector", + "org.yaml:snakeyaml" + ], + "org.robolectric:sandbox": [ + "com.google.guava:guava", + "javax.annotation:javax.annotation-api", + "javax.inject:javax.inject", + "org.ow2.asm:asm", + "org.ow2.asm:asm-commons", + "org.robolectric:annotations", + "org.robolectric:shadowapi", + "org.robolectric:utils", + "org.robolectric:utils-reflector" + ], + "org.robolectric:shadowapi": [ + "org.robolectric:annotations", + "org.robolectric:utils" + ], + "org.robolectric:shadows-framework": [ + "androidx.test:monitor:aar", + "com.almworks.sqlite4java:sqlite4java", + "com.google.auto.value:auto-value-annotations", + "com.google.errorprone:error_prone_annotation", + "com.ibm.icu:icu4j", + "org.robolectric:annotations", + "org.robolectric:nativeruntime", + "org.robolectric:pluginapi", + "org.robolectric:resources", + "org.robolectric:sandbox", + "org.robolectric:shadowapi", + "org.robolectric:utils", + "org.robolectric:utils-reflector" + ], + "org.robolectric:utils": [ + "javax.annotation:javax.annotation-api", + "javax.inject:javax.inject", + "org.robolectric:pluginapi" + ], + "org.robolectric:utils-reflector": [ + "org.ow2.asm:asm", + "org.ow2.asm:asm-commons", + "org.robolectric:utils" + ], + "org.slf4j:jcl-over-slf4j": [ + "org.slf4j:slf4j-api" + ] + }, + "packages": { + "androidx.annotation:annotation-jvm": [ + "androidx.annotation" + ], + "androidx.arch.core:core-common": [ + "androidx.arch.core.internal", + "androidx.arch.core.util" + ], + "androidx.collection:collection-jvm": [ + "androidx.collection", + "androidx.collection.internal" + ], + "androidx.compose.runtime:runtime-annotation-jvm": [ + "androidx.compose.runtime", + "androidx.compose.runtime.annotation" + ], + "androidx.compose.runtime:runtime-desktop": [ + "androidx.compose.runtime", + "androidx.compose.runtime.changelist", + "androidx.compose.runtime.collection", + "androidx.compose.runtime.external.kotlinx.collections.immutable", + "androidx.compose.runtime.external.kotlinx.collections.immutable.adapters", + "androidx.compose.runtime.external.kotlinx.collections.immutable.implementations.immutableList", + "androidx.compose.runtime.external.kotlinx.collections.immutable.implementations.immutableMap", + "androidx.compose.runtime.external.kotlinx.collections.immutable.implementations.immutableSet", + "androidx.compose.runtime.external.kotlinx.collections.immutable.implementations.persistentOrderedMap", + "androidx.compose.runtime.external.kotlinx.collections.immutable.implementations.persistentOrderedSet", + "androidx.compose.runtime.external.kotlinx.collections.immutable.internal", + "androidx.compose.runtime.internal", + "androidx.compose.runtime.platform", + "androidx.compose.runtime.reflect", + "androidx.compose.runtime.snapshots", + "androidx.compose.runtime.snapshots.tooling", + "androidx.compose.runtime.tooling" + ], + "androidx.compose.runtime:runtime-retain-desktop": [ + "androidx.compose.runtime.retain", + "androidx.compose.runtime.retain.impl" + ], + "androidx.compose.runtime:runtime-saveable-desktop": [ + "androidx.compose.runtime.saveable", + "androidx.compose.runtime.saveable.serialization" + ], + "androidx.concurrent:concurrent-futures": [ + "androidx.concurrent.futures" + ], + "androidx.concurrent:concurrent-futures-ktx": [ + "androidx.concurrent.futures" + ], + "androidx.datastore:datastore-core": [ + "androidx.datastore.core", + "androidx.datastore.core.handlers" + ], + "androidx.datastore:datastore-preferences-core": [ + "androidx.datastore.preferences", + "androidx.datastore.preferences.core", + "androidx.datastore.preferences.protobuf" + ], + "androidx.glance:glance-appwidget-external-protobuf": [ + "androidx.glance.appwidget.protobuf" + ], + "androidx.glance:glance-appwidget-proto": [ + "androidx.glance.appwidget.proto" + ], + "androidx.lifecycle:lifecycle-common-jvm": [ + "androidx.lifecycle" + ], + "androidx.lifecycle:lifecycle-runtime-compose-desktop": [ + "androidx.lifecycle.compose" + ], + "androidx.lifecycle:lifecycle-runtime-desktop": [ + "androidx.lifecycle" + ], + "androidx.lifecycle:lifecycle-viewmodel-desktop": [ + "androidx.lifecycle", + "androidx.lifecycle.viewmodel", + "androidx.lifecycle.viewmodel.internal" + ], + "androidx.lifecycle:lifecycle-viewmodel-savedstate-desktop": [ + "androidx.lifecycle", + "androidx.lifecycle.internal", + "androidx.lifecycle.serialization" + ], + "androidx.navigationevent:navigationevent-desktop": [ + "androidx.navigationevent", + "androidx.navigationevent.internal" + ], + "androidx.resourceinspection:resourceinspection-annotation": [ + "androidx.resourceinspection.annotation" + ], + "androidx.room:room-common": [ + "androidx.room" + ], + "androidx.savedstate:savedstate-compose-desktop": [ + "androidx.savedstate.compose", + "androidx.savedstate.compose.serialization.serializers" + ], + "androidx.savedstate:savedstate-desktop": [ + "androidx.savedstate", + "androidx.savedstate.internal", + "androidx.savedstate.serialization", + "androidx.savedstate.serialization.serializers" + ], + "androidx.window:window-core-jvm": [ + "androidx.window.core", + "androidx.window.core.layout" + ], + "app.cash.sqldelight:async-extensions-jvm": [ + "app.cash.sqldelight.async.coroutines" + ], + "app.cash.sqldelight:coroutines-extensions-jvm": [ + "app.cash.sqldelight.coroutines" + ], + "app.cash.sqldelight:jdbc-driver": [ + "app.cash.sqldelight.driver.jdbc" + ], + "app.cash.sqldelight:runtime-jvm": [ + "app.cash.sqldelight", + "app.cash.sqldelight.db", + "app.cash.sqldelight.internal", + "app.cash.sqldelight.logs" + ], + "app.cash.sqldelight:sqlite-driver": [ + "app.cash.sqldelight.driver.jdbc.sqlite" + ], + "co.touchlab:stately-concurrency-jvm": [ + "co.touchlab.stately.concurrency" + ], + "co.touchlab:stately-strict-jvm": [ + "co.touchlab.stately.strict" + ], + "com.almworks.sqlite4java:sqlite4java": [ + "com.almworks.sqlite4java", + "javolution.util.stripped" + ], + "com.android.tools:desugar_jdk_libs": [ + "desugar.sun.nio.fs", + "java.io", + "java.lang", + "java.lang.annotation", + "java.net", + "java.nio.channels", + "java.nio.charset", + "java.nio.charset.spi", + "java.nio.file", + "java.nio.file.attribute", + "java.nio.file.spi", + "java.time", + "java.time.chrono", + "java.time.format", + "java.time.temporal", + "java.time.zone", + "java.util", + "java.util.concurrent", + "java.util.concurrent.atomic", + "java.util.function", + "java.util.stream", + "jdk.internal.util", + "libcore.api", + "libcore.content.type", + "libcore.util", + "sun.misc", + "sun.nio", + "sun.nio.ch", + "sun.nio.cs", + "sun.nio.fs", + "sun.security.action", + "sun.util" + ], + "com.android.tools:desugar_jdk_libs_configuration": [ + "java.adapter", + "java.nio.channels", + "java.nio.file", + "java.nio.file.attribute", + "java.time", + "java.util", + "java.util.stream" + ], + "com.benasher44:uuid-jvm": [ + "com.benasher44.uuid" + ], + "com.fleeksoft.charset:charset-jvm": [ + "com.fleeksoft.charset", + "com.fleeksoft.charset.annotation", + "com.fleeksoft.charset.internal", + "com.fleeksoft.charset.spi" + ], + "com.fleeksoft.io:io-core-jvm": [ + "com.fleeksoft.io", + "com.fleeksoft.io.exception", + "com.fleeksoft.io.internal", + "com.fleeksoft.lang" + ], + "com.fleeksoft.ksoup:ksoup-jvm": [ + "com.fleeksoft.ksoup", + "com.fleeksoft.ksoup.exception", + "com.fleeksoft.ksoup.helper", + "com.fleeksoft.ksoup.internal", + "com.fleeksoft.ksoup.io", + "com.fleeksoft.ksoup.model", + "com.fleeksoft.ksoup.nodes", + "com.fleeksoft.ksoup.parser", + "com.fleeksoft.ksoup.ported", + "com.fleeksoft.ksoup.safety", + "com.fleeksoft.ksoup.select" + ], + "com.github.mwiede:jsch": [ + "com.jcraft.jsch", + "com.jcraft.jsch.annotations", + "com.jcraft.jsch.bc", + "com.jcraft.jsch.jbcrypt", + "com.jcraft.jsch.jce", + "com.jcraft.jsch.jgss", + "com.jcraft.jsch.juz", + "com.jcraft.jsch.jzlib" + ], + "com.google.auto.value:auto-value-annotations": [ + "com.google.auto.value", + "com.google.auto.value.extension.memoized", + "com.google.auto.value.extension.serializable", + "com.google.auto.value.extension.toprettystring" + ], + "com.google.code.findbugs:jsr305": [ + "javax.annotation", + "javax.annotation.concurrent", + "javax.annotation.meta" + ], + "com.google.code.gson:gson": [ + "com.google.gson", + "com.google.gson.annotations", + "com.google.gson.internal", + "com.google.gson.internal.bind", + "com.google.gson.internal.bind.util", + "com.google.gson.internal.reflect", + "com.google.gson.internal.sql", + "com.google.gson.reflect", + "com.google.gson.stream" + ], + "com.google.crypto.tink:tink-android": [ + "com.google.crypto.tink", + "com.google.crypto.tink.aead", + "com.google.crypto.tink.aead.internal", + "com.google.crypto.tink.aead.subtle", + "com.google.crypto.tink.annotations", + "com.google.crypto.tink.config", + "com.google.crypto.tink.config.internal", + "com.google.crypto.tink.daead", + "com.google.crypto.tink.hybrid", + "com.google.crypto.tink.hybrid.internal", + "com.google.crypto.tink.hybrid.subtle", + "com.google.crypto.tink.integration.android", + "com.google.crypto.tink.internal", + "com.google.crypto.tink.jwt", + "com.google.crypto.tink.mac", + "com.google.crypto.tink.mac.internal", + "com.google.crypto.tink.monitoring", + "com.google.crypto.tink.prf", + "com.google.crypto.tink.proto", + "com.google.crypto.tink.shaded.protobuf", + "com.google.crypto.tink.signature", + "com.google.crypto.tink.signature.internal", + "com.google.crypto.tink.streamingaead", + "com.google.crypto.tink.subtle", + "com.google.crypto.tink.subtle.prf", + "com.google.crypto.tink.tinkkey", + "com.google.crypto.tink.tinkkey.internal", + "com.google.crypto.tink.util" + ], + "com.google.errorprone:error_prone_annotation": [ + "com.google.errorprone" + ], + "com.google.errorprone:error_prone_annotations": [ + "com.google.errorprone.annotations", + "com.google.errorprone.annotations.concurrent" + ], + "com.google.firebase:firebase-annotations": [ + "com.google.firebase.annotations" + ], + "com.google.firebase:firebase-encoders": [ + "com.google.firebase.encoders", + "com.google.firebase.encoders.annotations", + "com.google.firebase.encoders.config" + ], + "com.google.guava:failureaccess": [ + "com.google.common.util.concurrent.internal" + ], + "com.google.guava:guava": [ + "com.google.common.annotations", + "com.google.common.base", + "com.google.common.base.internal", + "com.google.common.cache", + "com.google.common.collect", + "com.google.common.escape", + "com.google.common.eventbus", + "com.google.common.graph", + "com.google.common.hash", + "com.google.common.html", + "com.google.common.io", + "com.google.common.math", + "com.google.common.net", + "com.google.common.primitives", + "com.google.common.reflect", + "com.google.common.util.concurrent", + "com.google.common.xml", + "com.google.thirdparty.publicsuffix" + ], + "com.google.j2objc:j2objc-annotations": [ + "com.google.j2objc.annotations" + ], + "com.google.testparameterinjector:test-parameter-injector": [ + "com.google.testing.junit.testparameterinjector" + ], + "com.google.truth:truth": [ + "com.google.common.truth" + ], + "com.googlecode.java-diff-utils:diffutils": [ + "difflib", + "difflib.myers" + ], + "com.googlecode.javaewah:JavaEWAH": [ + "com.googlecode.javaewah", + "com.googlecode.javaewah.datastructure", + "com.googlecode.javaewah.symmetric", + "com.googlecode.javaewah32", + "com.googlecode.javaewah32.symmetric" + ], + "com.ibm.icu:icu4j": [ + "com.ibm.icu.impl", + "com.ibm.icu.impl.breakiter", + "com.ibm.icu.impl.coll", + "com.ibm.icu.impl.data", + "com.ibm.icu.impl.duration", + "com.ibm.icu.impl.duration.impl", + "com.ibm.icu.impl.locale", + "com.ibm.icu.impl.number", + "com.ibm.icu.impl.number.parse", + "com.ibm.icu.impl.number.range", + "com.ibm.icu.impl.personname", + "com.ibm.icu.impl.text", + "com.ibm.icu.impl.units", + "com.ibm.icu.lang", + "com.ibm.icu.math", + "com.ibm.icu.message2", + "com.ibm.icu.number", + "com.ibm.icu.text", + "com.ibm.icu.util" + ], + "com.jcraft:jsch": [ + "com.jcraft.jsch", + "com.jcraft.jsch.jce", + "com.jcraft.jsch.jcraft", + "com.jcraft.jsch.jgss" + ], + "com.jcraft:jzlib": [ + "com.jcraft.jzlib" + ], + "com.juul.kable:exceptions-jvm": [ + "com.juul.kable" + ], + "com.juul.tuulbox:collections-jvm": [ + "com.juul.tuulbox.collections" + ], + "com.squareup.okhttp3:okhttp": [ + "okhttp3", + "okhttp3.internal", + "okhttp3.internal.authenticator", + "okhttp3.internal.cache", + "okhttp3.internal.cache2", + "okhttp3.internal.concurrent", + "okhttp3.internal.connection", + "okhttp3.internal.http", + "okhttp3.internal.http1", + "okhttp3.internal.http2", + "okhttp3.internal.io", + "okhttp3.internal.platform", + "okhttp3.internal.platform.android", + "okhttp3.internal.proxy", + "okhttp3.internal.publicsuffix", + "okhttp3.internal.tls", + "okhttp3.internal.ws" + ], + "com.squareup.okhttp3:okhttp-sse": [ + "okhttp3.internal.sse", + "okhttp3.sse" + ], + "com.squareup.okio:okio-jvm": [ + "okio", + "okio.internal" + ], + "commons-codec:commons-codec": [ + "org.apache.commons.codec", + "org.apache.commons.codec.binary", + "org.apache.commons.codec.cli", + "org.apache.commons.codec.digest", + "org.apache.commons.codec.language", + "org.apache.commons.codec.language.bm", + "org.apache.commons.codec.net" + ], + "commons-logging:commons-logging": [ + "org.apache.commons.logging", + "org.apache.commons.logging.impl" + ], + "io.arrow-kt:arrow-annotations-jvm": [ + "arrow", + "arrow.optics" + ], + "io.arrow-kt:arrow-atomic-jvm": [ + "arrow.atomic" + ], + "io.arrow-kt:arrow-autoclose-jvm": [ + "arrow" + ], + "io.arrow-kt:arrow-core-jvm": [ + "arrow.core", + "arrow.core.raise", + "arrow.core.raise.context" + ], + "io.arrow-kt:arrow-exception-utils-jvm": [ + "arrow.core" + ], + "io.arrow-kt:arrow-fx-coroutines-jvm": [ + "arrow.fx.coroutines", + "arrow.fx.coroutines.await" + ], + "io.arrow-kt:arrow-optics-jvm": [ + "arrow.optics", + "arrow.optics.dsl", + "arrow.optics.regex", + "arrow.optics.regex.dsl", + "arrow.optics.typeclasses" + ], + "io.arrow-kt:arrow-resilience-jvm": [ + "arrow.resilience" + ], + "io.coil-kt.coil3:coil-compose-core-jvm": [ + "coil3.compose", + "coil3.compose.internal" + ], + "io.coil-kt.coil3:coil-compose-jvm": [ + "coil3.compose" + ], + "io.coil-kt.coil3:coil-core-jvm": [ + "coil3", + "coil3.annotation", + "coil3.decode", + "coil3.disk", + "coil3.fetch", + "coil3.intercept", + "coil3.key", + "coil3.map", + "coil3.memory", + "coil3.request", + "coil3.size", + "coil3.target", + "coil3.transform", + "coil3.util" + ], + "io.coil-kt.coil3:coil-jvm": [ + "coil3" + ], + "io.coil-kt.coil3:coil-network-core-jvm": [ + "coil3.network", + "coil3.network.internal" + ], + "io.coil-kt.coil3:coil-network-ktor3-jvm": [ + "coil3.network.ktor3", + "coil3.network.ktor3.internal" + ], + "io.github.petertrr:kotlin-multiplatform-diff-jvm": [ + "io.github.petertrr.diffutils", + "io.github.petertrr.diffutils.algorithm", + "io.github.petertrr.diffutils.algorithm.myers", + "io.github.petertrr.diffutils.patch", + "io.github.petertrr.diffutils.text" + ], + "io.ktor:ktor-client-content-negotiation-jvm": [ + "io.ktor.client.plugins.contentnegotiation" + ], + "io.ktor:ktor-client-core-jvm": [ + "io.ktor.client", + "io.ktor.client.call", + "io.ktor.client.content", + "io.ktor.client.engine", + "io.ktor.client.network.sockets", + "io.ktor.client.plugins", + "io.ktor.client.plugins.api", + "io.ktor.client.plugins.cache", + "io.ktor.client.plugins.cache.storage", + "io.ktor.client.plugins.cookies", + "io.ktor.client.plugins.internal", + "io.ktor.client.plugins.observer", + "io.ktor.client.plugins.sse", + "io.ktor.client.plugins.websocket", + "io.ktor.client.request", + "io.ktor.client.request.forms", + "io.ktor.client.statement", + "io.ktor.client.utils" + ], + "io.ktor:ktor-client-mock-jvm": [ + "io.ktor.client.engine.mock" + ], + "io.ktor:ktor-client-okhttp-jvm": [ + "io.ktor.client.engine.okhttp" + ], + "io.ktor:ktor-events-jvm": [ + "io.ktor.events" + ], + "io.ktor:ktor-http-cio-jvm": [ + "io.ktor.http.cio", + "io.ktor.http.cio.internals" + ], + "io.ktor:ktor-http-jvm": [ + "io.ktor.content", + "io.ktor.http", + "io.ktor.http.auth", + "io.ktor.http.content", + "io.ktor.http.header", + "io.ktor.http.parsing", + "io.ktor.http.parsing.regex", + "io.ktor.http.websocket" + ], + "io.ktor:ktor-io-jvm": [ + "io.ktor.utils.io", + "io.ktor.utils.io.bits", + "io.ktor.utils.io.charsets", + "io.ktor.utils.io.core", + "io.ktor.utils.io.core.internal", + "io.ktor.utils.io.errors", + "io.ktor.utils.io.jvm.javaio", + "io.ktor.utils.io.jvm.nio", + "io.ktor.utils.io.locks", + "io.ktor.utils.io.pool", + "io.ktor.utils.io.streams" + ], + "io.ktor:ktor-network-jvm": [ + "io.ktor.network.selector", + "io.ktor.network.sockets", + "io.ktor.network.util" + ], + "io.ktor:ktor-serialization-jvm": [ + "io.ktor.serialization" + ], + "io.ktor:ktor-serialization-kotlinx-json-jvm": [ + "io.ktor.serialization.kotlinx.json" + ], + "io.ktor:ktor-serialization-kotlinx-jvm": [ + "io.ktor.serialization.kotlinx" + ], + "io.ktor:ktor-sse-jvm": [ + "io.ktor.sse" + ], + "io.ktor:ktor-utils-jvm": [ + "io.ktor.util", + "io.ktor.util.cio", + "io.ktor.util.collections", + "io.ktor.util.converters", + "io.ktor.util.date", + "io.ktor.util.debug", + "io.ktor.util.debug.plugins", + "io.ktor.util.internal", + "io.ktor.util.logging", + "io.ktor.util.network", + "io.ktor.util.pipeline", + "io.ktor.util.reflect" + ], + "io.ktor:ktor-websocket-serialization-jvm": [ + "io.ktor.websocket.serialization" + ], + "io.ktor:ktor-websockets-jvm": [ + "io.ktor.websocket", + "io.ktor.websocket.internals" + ], + "io.opentelemetry:opentelemetry-api": [ + "io.opentelemetry.api", + "io.opentelemetry.api.baggage", + "io.opentelemetry.api.baggage.propagation", + "io.opentelemetry.api.common", + "io.opentelemetry.api.internal", + "io.opentelemetry.api.logs", + "io.opentelemetry.api.metrics", + "io.opentelemetry.api.trace", + "io.opentelemetry.api.trace.propagation", + "io.opentelemetry.api.trace.propagation.internal" + ], + "io.opentelemetry:opentelemetry-api-incubator": [ + "io.opentelemetry.api.incubator.events", + "io.opentelemetry.api.incubator.logs", + "io.opentelemetry.api.incubator.metrics", + "io.opentelemetry.api.incubator.propagation", + "io.opentelemetry.api.incubator.trace" + ], + "io.opentelemetry:opentelemetry-context": [ + "io.opentelemetry.context", + "io.opentelemetry.context.internal.shaded", + "io.opentelemetry.context.propagation" + ], + "io.opentelemetry:opentelemetry-exporter-logging": [ + "io.opentelemetry.exporter.logging", + "io.opentelemetry.exporter.logging.internal" + ], + "io.opentelemetry:opentelemetry-sdk": [ + "io.opentelemetry.sdk" + ], + "io.opentelemetry:opentelemetry-sdk-common": [ + "io.opentelemetry.sdk.common", + "io.opentelemetry.sdk.common.export", + "io.opentelemetry.sdk.common.internal", + "io.opentelemetry.sdk.internal", + "io.opentelemetry.sdk.resources" + ], + "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi": [ + "io.opentelemetry.sdk.autoconfigure.spi", + "io.opentelemetry.sdk.autoconfigure.spi.internal", + "io.opentelemetry.sdk.autoconfigure.spi.logs", + "io.opentelemetry.sdk.autoconfigure.spi.metrics", + "io.opentelemetry.sdk.autoconfigure.spi.traces" + ], + "io.opentelemetry:opentelemetry-sdk-logs": [ + "io.opentelemetry.sdk.logs", + "io.opentelemetry.sdk.logs.data", + "io.opentelemetry.sdk.logs.export", + "io.opentelemetry.sdk.logs.internal" + ], + "io.opentelemetry:opentelemetry-sdk-metrics": [ + "io.opentelemetry.sdk.metrics", + "io.opentelemetry.sdk.metrics.data", + "io.opentelemetry.sdk.metrics.export", + "io.opentelemetry.sdk.metrics.internal", + "io.opentelemetry.sdk.metrics.internal.aggregator", + "io.opentelemetry.sdk.metrics.internal.concurrent", + "io.opentelemetry.sdk.metrics.internal.data", + "io.opentelemetry.sdk.metrics.internal.debug", + "io.opentelemetry.sdk.metrics.internal.descriptor", + "io.opentelemetry.sdk.metrics.internal.exemplar", + "io.opentelemetry.sdk.metrics.internal.export", + "io.opentelemetry.sdk.metrics.internal.state", + "io.opentelemetry.sdk.metrics.internal.view" + ], + "io.opentelemetry:opentelemetry-sdk-trace": [ + "io.opentelemetry.internal.shaded.jctools.counters", + "io.opentelemetry.internal.shaded.jctools.maps", + "io.opentelemetry.internal.shaded.jctools.queues", + "io.opentelemetry.internal.shaded.jctools.queues.atomic", + "io.opentelemetry.internal.shaded.jctools.queues.atomic.unpadded", + "io.opentelemetry.internal.shaded.jctools.queues.unpadded", + "io.opentelemetry.internal.shaded.jctools.util", + "io.opentelemetry.sdk.trace", + "io.opentelemetry.sdk.trace.data", + "io.opentelemetry.sdk.trace.export", + "io.opentelemetry.sdk.trace.internal", + "io.opentelemetry.sdk.trace.internal.data", + "io.opentelemetry.sdk.trace.samplers" + ], + "io.projectreactor.tools:blockhound": [ + "reactor.blockhound", + "reactor.blockhound.integration", + "reactor.blockhound.shaded.net.bytebuddy", + "reactor.blockhound.shaded.net.bytebuddy.agent", + "reactor.blockhound.shaded.net.bytebuddy.agent.builder", + "reactor.blockhound.shaded.net.bytebuddy.agent.utility.nullability", + "reactor.blockhound.shaded.net.bytebuddy.asm", + "reactor.blockhound.shaded.net.bytebuddy.build", + "reactor.blockhound.shaded.net.bytebuddy.description", + "reactor.blockhound.shaded.net.bytebuddy.description.annotation", + "reactor.blockhound.shaded.net.bytebuddy.description.enumeration", + "reactor.blockhound.shaded.net.bytebuddy.description.field", + "reactor.blockhound.shaded.net.bytebuddy.description.method", + "reactor.blockhound.shaded.net.bytebuddy.description.modifier", + "reactor.blockhound.shaded.net.bytebuddy.description.type", + "reactor.blockhound.shaded.net.bytebuddy.dynamic", + "reactor.blockhound.shaded.net.bytebuddy.dynamic.loading", + "reactor.blockhound.shaded.net.bytebuddy.dynamic.scaffold", + "reactor.blockhound.shaded.net.bytebuddy.dynamic.scaffold.inline", + "reactor.blockhound.shaded.net.bytebuddy.dynamic.scaffold.subclass", + "reactor.blockhound.shaded.net.bytebuddy.implementation", + "reactor.blockhound.shaded.net.bytebuddy.implementation.attribute", + "reactor.blockhound.shaded.net.bytebuddy.implementation.auxiliary", + "reactor.blockhound.shaded.net.bytebuddy.implementation.bind", + "reactor.blockhound.shaded.net.bytebuddy.implementation.bind.annotation", + "reactor.blockhound.shaded.net.bytebuddy.implementation.bytecode", + "reactor.blockhound.shaded.net.bytebuddy.implementation.bytecode.assign", + "reactor.blockhound.shaded.net.bytebuddy.implementation.bytecode.assign.primitive", + "reactor.blockhound.shaded.net.bytebuddy.implementation.bytecode.assign.reference", + "reactor.blockhound.shaded.net.bytebuddy.implementation.bytecode.collection", + "reactor.blockhound.shaded.net.bytebuddy.implementation.bytecode.constant", + "reactor.blockhound.shaded.net.bytebuddy.implementation.bytecode.member", + "reactor.blockhound.shaded.net.bytebuddy.jar.asm", + "reactor.blockhound.shaded.net.bytebuddy.jar.asm.commons", + "reactor.blockhound.shaded.net.bytebuddy.jar.asm.signature", + "reactor.blockhound.shaded.net.bytebuddy.matcher", + "reactor.blockhound.shaded.net.bytebuddy.pool", + "reactor.blockhound.shaded.net.bytebuddy.utility", + "reactor.blockhound.shaded.net.bytebuddy.utility.dispatcher", + "reactor.blockhound.shaded.net.bytebuddy.utility.nullability", + "reactor.blockhound.shaded.net.bytebuddy.utility.privilege", + "reactor.blockhound.shaded.net.bytebuddy.utility.visitor" + ], + "javax.annotation:javax.annotation-api": [ + "javax.annotation", + "javax.annotation.security", + "javax.annotation.sql" + ], + "javax.inject:javax.inject": [ + "javax.inject" + ], + "junit:junit": [ + "junit.extensions", + "junit.framework", + "junit.runner", + "junit.textui", + "org.junit", + "org.junit.experimental", + "org.junit.experimental.categories", + "org.junit.experimental.max", + "org.junit.experimental.results", + "org.junit.experimental.runners", + "org.junit.experimental.theories", + "org.junit.experimental.theories.internal", + "org.junit.experimental.theories.suppliers", + "org.junit.function", + "org.junit.internal", + "org.junit.internal.builders", + "org.junit.internal.management", + "org.junit.internal.matchers", + "org.junit.internal.requests", + "org.junit.internal.runners", + "org.junit.internal.runners.model", + "org.junit.internal.runners.rules", + "org.junit.internal.runners.statements", + "org.junit.matchers", + "org.junit.rules", + "org.junit.runner", + "org.junit.runner.manipulation", + "org.junit.runner.notification", + "org.junit.runners", + "org.junit.runners.model", + "org.junit.runners.parameterized", + "org.junit.validator" + ], + "org.apache.pdfbox:fontbox": [ + "org.apache.fontbox", + "org.apache.fontbox.afm", + "org.apache.fontbox.cff", + "org.apache.fontbox.cmap", + "org.apache.fontbox.encoding", + "org.apache.fontbox.pfb", + "org.apache.fontbox.ttf", + "org.apache.fontbox.ttf.gsub", + "org.apache.fontbox.ttf.model", + "org.apache.fontbox.ttf.table.common", + "org.apache.fontbox.ttf.table.gsub", + "org.apache.fontbox.type1", + "org.apache.fontbox.util", + "org.apache.fontbox.util.autodetect" + ], + "org.apache.pdfbox:pdfbox": [ + "org.apache.pdfbox", + "org.apache.pdfbox.contentstream", + "org.apache.pdfbox.contentstream.operator", + "org.apache.pdfbox.contentstream.operator.color", + "org.apache.pdfbox.contentstream.operator.graphics", + "org.apache.pdfbox.contentstream.operator.markedcontent", + "org.apache.pdfbox.contentstream.operator.state", + "org.apache.pdfbox.contentstream.operator.text", + "org.apache.pdfbox.cos", + "org.apache.pdfbox.filter", + "org.apache.pdfbox.multipdf", + "org.apache.pdfbox.pdfparser", + "org.apache.pdfbox.pdfparser.xref", + "org.apache.pdfbox.pdfwriter", + "org.apache.pdfbox.pdfwriter.compress", + "org.apache.pdfbox.pdmodel", + "org.apache.pdfbox.pdmodel.common", + "org.apache.pdfbox.pdmodel.common.filespecification", + "org.apache.pdfbox.pdmodel.common.function", + "org.apache.pdfbox.pdmodel.common.function.type4", + "org.apache.pdfbox.pdmodel.documentinterchange.logicalstructure", + "org.apache.pdfbox.pdmodel.documentinterchange.markedcontent", + "org.apache.pdfbox.pdmodel.documentinterchange.prepress", + "org.apache.pdfbox.pdmodel.documentinterchange.taggedpdf", + "org.apache.pdfbox.pdmodel.encryption", + "org.apache.pdfbox.pdmodel.fdf", + "org.apache.pdfbox.pdmodel.fixup", + "org.apache.pdfbox.pdmodel.fixup.processor", + "org.apache.pdfbox.pdmodel.font", + "org.apache.pdfbox.pdmodel.font.encoding", + "org.apache.pdfbox.pdmodel.graphics", + "org.apache.pdfbox.pdmodel.graphics.blend", + "org.apache.pdfbox.pdmodel.graphics.color", + "org.apache.pdfbox.pdmodel.graphics.form", + "org.apache.pdfbox.pdmodel.graphics.image", + "org.apache.pdfbox.pdmodel.graphics.optionalcontent", + "org.apache.pdfbox.pdmodel.graphics.pattern", + "org.apache.pdfbox.pdmodel.graphics.shading", + "org.apache.pdfbox.pdmodel.graphics.state", + "org.apache.pdfbox.pdmodel.interactive.action", + "org.apache.pdfbox.pdmodel.interactive.annotation", + "org.apache.pdfbox.pdmodel.interactive.annotation.handlers", + "org.apache.pdfbox.pdmodel.interactive.annotation.layout", + "org.apache.pdfbox.pdmodel.interactive.digitalsignature", + "org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible", + "org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination", + "org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline", + "org.apache.pdfbox.pdmodel.interactive.form", + "org.apache.pdfbox.pdmodel.interactive.measurement", + "org.apache.pdfbox.pdmodel.interactive.pagenavigation", + "org.apache.pdfbox.pdmodel.interactive.viewerpreferences", + "org.apache.pdfbox.printing", + "org.apache.pdfbox.rendering", + "org.apache.pdfbox.text", + "org.apache.pdfbox.util", + "org.apache.pdfbox.util.filetypedetector" + ], + "org.apache.pdfbox:pdfbox-io": [ + "org.apache.pdfbox.io" + ], + "org.apache.sshd:sshd-osgi": [ + "org.apache.sshd.agent", + "org.apache.sshd.agent.common", + "org.apache.sshd.agent.local", + "org.apache.sshd.agent.unix", + "org.apache.sshd.certificate", + "org.apache.sshd.client", + "org.apache.sshd.client.auth", + "org.apache.sshd.client.auth.hostbased", + "org.apache.sshd.client.auth.keyboard", + "org.apache.sshd.client.auth.password", + "org.apache.sshd.client.auth.pubkey", + "org.apache.sshd.client.channel", + "org.apache.sshd.client.channel.exit", + "org.apache.sshd.client.config", + "org.apache.sshd.client.config.hosts", + "org.apache.sshd.client.config.keys", + "org.apache.sshd.client.future", + "org.apache.sshd.client.global", + "org.apache.sshd.client.kex", + "org.apache.sshd.client.keyverifier", + "org.apache.sshd.client.session", + "org.apache.sshd.client.session.forward", + "org.apache.sshd.client.simple", + "org.apache.sshd.client.subsystem", + "org.apache.sshd.common", + "org.apache.sshd.common.auth", + "org.apache.sshd.common.channel", + "org.apache.sshd.common.channel.exception", + "org.apache.sshd.common.channel.throttle", + "org.apache.sshd.common.cipher", + "org.apache.sshd.common.compression", + "org.apache.sshd.common.config", + "org.apache.sshd.common.config.keys", + "org.apache.sshd.common.config.keys.impl", + "org.apache.sshd.common.config.keys.loader", + "org.apache.sshd.common.config.keys.loader.openssh", + "org.apache.sshd.common.config.keys.loader.openssh.kdf", + "org.apache.sshd.common.config.keys.loader.pem", + "org.apache.sshd.common.config.keys.loader.ssh2", + "org.apache.sshd.common.config.keys.u2f", + "org.apache.sshd.common.config.keys.writer", + "org.apache.sshd.common.config.keys.writer.openssh", + "org.apache.sshd.common.digest", + "org.apache.sshd.common.file", + "org.apache.sshd.common.file.nativefs", + "org.apache.sshd.common.file.nonefs", + "org.apache.sshd.common.file.root", + "org.apache.sshd.common.file.util", + "org.apache.sshd.common.file.virtualfs", + "org.apache.sshd.common.forward", + "org.apache.sshd.common.future", + "org.apache.sshd.common.global", + "org.apache.sshd.common.helpers", + "org.apache.sshd.common.io", + "org.apache.sshd.common.io.nio2", + "org.apache.sshd.common.kex", + "org.apache.sshd.common.kex.dh", + "org.apache.sshd.common.kex.extension", + "org.apache.sshd.common.kex.extension.parser", + "org.apache.sshd.common.keyprovider", + "org.apache.sshd.common.mac", + "org.apache.sshd.common.random", + "org.apache.sshd.common.session", + "org.apache.sshd.common.session.helpers", + "org.apache.sshd.common.signature", + "org.apache.sshd.common.util", + "org.apache.sshd.common.util.buffer", + "org.apache.sshd.common.util.buffer.keys", + "org.apache.sshd.common.util.closeable", + "org.apache.sshd.common.util.functors", + "org.apache.sshd.common.util.helper", + "org.apache.sshd.common.util.io", + "org.apache.sshd.common.util.io.der", + "org.apache.sshd.common.util.io.functors", + "org.apache.sshd.common.util.io.input", + "org.apache.sshd.common.util.io.output", + "org.apache.sshd.common.util.io.resource", + "org.apache.sshd.common.util.logging", + "org.apache.sshd.common.util.net", + "org.apache.sshd.common.util.security", + "org.apache.sshd.common.util.security.bouncycastle", + "org.apache.sshd.common.util.security.eddsa", + "org.apache.sshd.common.util.security.eddsa.bouncycastle", + "org.apache.sshd.common.util.security.eddsa.generic", + "org.apache.sshd.common.util.threads", + "org.apache.sshd.core", + "org.apache.sshd.server", + "org.apache.sshd.server.auth", + "org.apache.sshd.server.auth.gss", + "org.apache.sshd.server.auth.hostbased", + "org.apache.sshd.server.auth.keyboard", + "org.apache.sshd.server.auth.password", + "org.apache.sshd.server.auth.pubkey", + "org.apache.sshd.server.channel", + "org.apache.sshd.server.command", + "org.apache.sshd.server.config", + "org.apache.sshd.server.config.keys", + "org.apache.sshd.server.forward", + "org.apache.sshd.server.global", + "org.apache.sshd.server.jaas", + "org.apache.sshd.server.kex", + "org.apache.sshd.server.keyprovider", + "org.apache.sshd.server.session", + "org.apache.sshd.server.shell", + "org.apache.sshd.server.subsystem", + "org.apache.sshd.server.x11" + ], + "org.apache.sshd:sshd-sftp": [ + "org.apache.sshd.sftp", + "org.apache.sshd.sftp.client", + "org.apache.sshd.sftp.client.extensions", + "org.apache.sshd.sftp.client.extensions.helpers", + "org.apache.sshd.sftp.client.extensions.openssh", + "org.apache.sshd.sftp.client.extensions.openssh.helpers", + "org.apache.sshd.sftp.client.fs", + "org.apache.sshd.sftp.client.impl", + "org.apache.sshd.sftp.common", + "org.apache.sshd.sftp.common.extensions", + "org.apache.sshd.sftp.common.extensions.openssh", + "org.apache.sshd.sftp.server" + ], + "org.bouncycastle:bcpkix-jdk15to18": [ + "org.bouncycastle.cert", + "org.bouncycastle.cert.bc", + "org.bouncycastle.cert.cmp", + "org.bouncycastle.cert.crmf", + "org.bouncycastle.cert.crmf.bc", + "org.bouncycastle.cert.crmf.jcajce", + "org.bouncycastle.cert.dane", + "org.bouncycastle.cert.dane.fetcher", + "org.bouncycastle.cert.jcajce", + "org.bouncycastle.cert.ocsp", + "org.bouncycastle.cert.ocsp.jcajce", + "org.bouncycastle.cert.path", + "org.bouncycastle.cert.path.validations", + "org.bouncycastle.cert.selector", + "org.bouncycastle.cert.selector.jcajce", + "org.bouncycastle.cmc", + "org.bouncycastle.cms", + "org.bouncycastle.cms.bc", + "org.bouncycastle.cms.jcajce", + "org.bouncycastle.dvcs", + "org.bouncycastle.eac", + "org.bouncycastle.eac.jcajce", + "org.bouncycastle.eac.operator", + "org.bouncycastle.eac.operator.jcajce", + "org.bouncycastle.est", + "org.bouncycastle.est.jcajce", + "org.bouncycastle.its", + "org.bouncycastle.its.bc", + "org.bouncycastle.its.jcajce", + "org.bouncycastle.its.operator", + "org.bouncycastle.mime", + "org.bouncycastle.mime.encoding", + "org.bouncycastle.mime.smime", + "org.bouncycastle.mozilla", + "org.bouncycastle.mozilla.jcajce", + "org.bouncycastle.openssl", + "org.bouncycastle.openssl.bc", + "org.bouncycastle.openssl.jcajce", + "org.bouncycastle.operator", + "org.bouncycastle.operator.bc", + "org.bouncycastle.operator.jcajce", + "org.bouncycastle.pkcs", + "org.bouncycastle.pkcs.bc", + "org.bouncycastle.pkcs.jcajce", + "org.bouncycastle.pkix", + "org.bouncycastle.pkix.jcajce", + "org.bouncycastle.tsp", + "org.bouncycastle.tsp.cms", + "org.bouncycastle.tsp.ers", + "org.bouncycastle.voms" + ], + "org.bouncycastle:bcprov-jdk15to18": [ + "org.bouncycastle", + "org.bouncycastle.asn1", + "org.bouncycastle.asn1.anssi", + "org.bouncycastle.asn1.bc", + "org.bouncycastle.asn1.cryptlib", + "org.bouncycastle.asn1.cryptopro", + "org.bouncycastle.asn1.edec", + "org.bouncycastle.asn1.gm", + "org.bouncycastle.asn1.gnu", + "org.bouncycastle.asn1.iana", + "org.bouncycastle.asn1.isara", + "org.bouncycastle.asn1.iso", + "org.bouncycastle.asn1.kisa", + "org.bouncycastle.asn1.microsoft", + "org.bouncycastle.asn1.misc", + "org.bouncycastle.asn1.mozilla", + "org.bouncycastle.asn1.nist", + "org.bouncycastle.asn1.nsri", + "org.bouncycastle.asn1.ntt", + "org.bouncycastle.asn1.ocsp", + "org.bouncycastle.asn1.oiw", + "org.bouncycastle.asn1.pkcs", + "org.bouncycastle.asn1.rosstandart", + "org.bouncycastle.asn1.sec", + "org.bouncycastle.asn1.teletrust", + "org.bouncycastle.asn1.ua", + "org.bouncycastle.asn1.util", + "org.bouncycastle.asn1.x500", + "org.bouncycastle.asn1.x500.style", + "org.bouncycastle.asn1.x509", + "org.bouncycastle.asn1.x509.qualified", + "org.bouncycastle.asn1.x509.sigi", + "org.bouncycastle.asn1.x9", + "org.bouncycastle.crypto", + "org.bouncycastle.crypto.agreement", + "org.bouncycastle.crypto.agreement.jpake", + "org.bouncycastle.crypto.agreement.kdf", + "org.bouncycastle.crypto.agreement.srp", + "org.bouncycastle.crypto.commitments", + "org.bouncycastle.crypto.constraints", + "org.bouncycastle.crypto.digests", + "org.bouncycastle.crypto.ec", + "org.bouncycastle.crypto.encodings", + "org.bouncycastle.crypto.engines", + "org.bouncycastle.crypto.examples", + "org.bouncycastle.crypto.fpe", + "org.bouncycastle.crypto.generators", + "org.bouncycastle.crypto.io", + "org.bouncycastle.crypto.kems", + "org.bouncycastle.crypto.macs", + "org.bouncycastle.crypto.modes", + "org.bouncycastle.crypto.modes.gcm", + "org.bouncycastle.crypto.modes.kgcm", + "org.bouncycastle.crypto.paddings", + "org.bouncycastle.crypto.params", + "org.bouncycastle.crypto.parsers", + "org.bouncycastle.crypto.prng", + "org.bouncycastle.crypto.prng.drbg", + "org.bouncycastle.crypto.signers", + "org.bouncycastle.crypto.util", + "org.bouncycastle.i18n", + "org.bouncycastle.i18n.filter", + "org.bouncycastle.iana", + "org.bouncycastle.internal.asn1.bsi", + "org.bouncycastle.internal.asn1.cms", + "org.bouncycastle.internal.asn1.eac", + "org.bouncycastle.internal.asn1.isismtt", + "org.bouncycastle.jcajce", + "org.bouncycastle.jcajce.interfaces", + "org.bouncycastle.jcajce.io", + "org.bouncycastle.jcajce.provider.asymmetric", + "org.bouncycastle.jcajce.provider.asymmetric.dh", + "org.bouncycastle.jcajce.provider.asymmetric.dsa", + "org.bouncycastle.jcajce.provider.asymmetric.dstu", + "org.bouncycastle.jcajce.provider.asymmetric.ec", + "org.bouncycastle.jcajce.provider.asymmetric.ecgost", + "org.bouncycastle.jcajce.provider.asymmetric.ecgost12", + "org.bouncycastle.jcajce.provider.asymmetric.edec", + "org.bouncycastle.jcajce.provider.asymmetric.elgamal", + "org.bouncycastle.jcajce.provider.asymmetric.gost", + "org.bouncycastle.jcajce.provider.asymmetric.ies", + "org.bouncycastle.jcajce.provider.asymmetric.rsa", + "org.bouncycastle.jcajce.provider.asymmetric.util", + "org.bouncycastle.jcajce.provider.asymmetric.x509", + "org.bouncycastle.jcajce.provider.config", + "org.bouncycastle.jcajce.provider.digest", + "org.bouncycastle.jcajce.provider.drbg", + "org.bouncycastle.jcajce.provider.keystore", + "org.bouncycastle.jcajce.provider.keystore.bc", + "org.bouncycastle.jcajce.provider.keystore.bcfks", + "org.bouncycastle.jcajce.provider.keystore.pkcs12", + "org.bouncycastle.jcajce.provider.keystore.util", + "org.bouncycastle.jcajce.provider.symmetric", + "org.bouncycastle.jcajce.provider.symmetric.util", + "org.bouncycastle.jcajce.provider.util", + "org.bouncycastle.jcajce.spec", + "org.bouncycastle.jcajce.util", + "org.bouncycastle.jce", + "org.bouncycastle.jce.exception", + "org.bouncycastle.jce.interfaces", + "org.bouncycastle.jce.netscape", + "org.bouncycastle.jce.provider", + "org.bouncycastle.jce.spec", + "org.bouncycastle.math", + "org.bouncycastle.math.ec", + "org.bouncycastle.math.ec.custom.djb", + "org.bouncycastle.math.ec.custom.gm", + "org.bouncycastle.math.ec.custom.sec", + "org.bouncycastle.math.ec.endo", + "org.bouncycastle.math.ec.rfc7748", + "org.bouncycastle.math.ec.rfc8032", + "org.bouncycastle.math.ec.tools", + "org.bouncycastle.math.field", + "org.bouncycastle.math.raw", + "org.bouncycastle.pqc.asn1", + "org.bouncycastle.pqc.crypto", + "org.bouncycastle.pqc.crypto.bike", + "org.bouncycastle.pqc.crypto.cmce", + "org.bouncycastle.pqc.crypto.crystals.dilithium", + "org.bouncycastle.pqc.crypto.crystals.kyber", + "org.bouncycastle.pqc.crypto.falcon", + "org.bouncycastle.pqc.crypto.frodo", + "org.bouncycastle.pqc.crypto.hqc", + "org.bouncycastle.pqc.crypto.lms", + "org.bouncycastle.pqc.crypto.newhope", + "org.bouncycastle.pqc.crypto.ntru", + "org.bouncycastle.pqc.crypto.ntruprime", + "org.bouncycastle.pqc.crypto.picnic", + "org.bouncycastle.pqc.crypto.saber", + "org.bouncycastle.pqc.crypto.sike", + "org.bouncycastle.pqc.crypto.sphincs", + "org.bouncycastle.pqc.crypto.sphincsplus", + "org.bouncycastle.pqc.crypto.util", + "org.bouncycastle.pqc.crypto.xmss", + "org.bouncycastle.pqc.jcajce.interfaces", + "org.bouncycastle.pqc.jcajce.provider", + "org.bouncycastle.pqc.jcajce.provider.bike", + "org.bouncycastle.pqc.jcajce.provider.cmce", + "org.bouncycastle.pqc.jcajce.provider.dilithium", + "org.bouncycastle.pqc.jcajce.provider.falcon", + "org.bouncycastle.pqc.jcajce.provider.frodo", + "org.bouncycastle.pqc.jcajce.provider.gmss", + "org.bouncycastle.pqc.jcajce.provider.hqc", + "org.bouncycastle.pqc.jcajce.provider.kyber", + "org.bouncycastle.pqc.jcajce.provider.lms", + "org.bouncycastle.pqc.jcajce.provider.mceliece", + "org.bouncycastle.pqc.jcajce.provider.newhope", + "org.bouncycastle.pqc.jcajce.provider.ntru", + "org.bouncycastle.pqc.jcajce.provider.ntruprime", + "org.bouncycastle.pqc.jcajce.provider.picnic", + "org.bouncycastle.pqc.jcajce.provider.qtesla", + "org.bouncycastle.pqc.jcajce.provider.rainbow", + "org.bouncycastle.pqc.jcajce.provider.saber", + "org.bouncycastle.pqc.jcajce.provider.sike", + "org.bouncycastle.pqc.jcajce.provider.sphincs", + "org.bouncycastle.pqc.jcajce.provider.sphincsplus", + "org.bouncycastle.pqc.jcajce.provider.util", + "org.bouncycastle.pqc.jcajce.provider.xmss", + "org.bouncycastle.pqc.jcajce.spec", + "org.bouncycastle.pqc.legacy.crypto.gmss", + "org.bouncycastle.pqc.legacy.crypto.gmss.util", + "org.bouncycastle.pqc.legacy.crypto.mceliece", + "org.bouncycastle.pqc.legacy.crypto.qtesla", + "org.bouncycastle.pqc.legacy.crypto.rainbow", + "org.bouncycastle.pqc.legacy.crypto.rainbow.util", + "org.bouncycastle.pqc.legacy.math.linearalgebra", + "org.bouncycastle.pqc.math.linearalgebra", + "org.bouncycastle.pqc.math.ntru", + "org.bouncycastle.pqc.math.ntru.parameters", + "org.bouncycastle.util", + "org.bouncycastle.util.encoders", + "org.bouncycastle.util.io", + "org.bouncycastle.util.io.pem", + "org.bouncycastle.util.test", + "org.bouncycastle.x509", + "org.bouncycastle.x509.extension", + "org.bouncycastle.x509.util" + ], + "org.bouncycastle:bcprov-jdk18on": [ + "org.bouncycastle", + "org.bouncycastle.asn1", + "org.bouncycastle.asn1.anssi", + "org.bouncycastle.asn1.bc", + "org.bouncycastle.asn1.cryptopro", + "org.bouncycastle.asn1.gm", + "org.bouncycastle.asn1.nist", + "org.bouncycastle.asn1.ocsp", + "org.bouncycastle.asn1.pkcs", + "org.bouncycastle.asn1.sec", + "org.bouncycastle.asn1.teletrust", + "org.bouncycastle.asn1.ua", + "org.bouncycastle.asn1.util", + "org.bouncycastle.asn1.x500", + "org.bouncycastle.asn1.x500.style", + "org.bouncycastle.asn1.x509", + "org.bouncycastle.asn1.x509.qualified", + "org.bouncycastle.asn1.x509.sigi", + "org.bouncycastle.asn1.x9", + "org.bouncycastle.crypto", + "org.bouncycastle.crypto.agreement", + "org.bouncycastle.crypto.agreement.ecjpake", + "org.bouncycastle.crypto.agreement.jpake", + "org.bouncycastle.crypto.agreement.kdf", + "org.bouncycastle.crypto.agreement.srp", + "org.bouncycastle.crypto.commitments", + "org.bouncycastle.crypto.constraints", + "org.bouncycastle.crypto.digests", + "org.bouncycastle.crypto.ec", + "org.bouncycastle.crypto.encodings", + "org.bouncycastle.crypto.engines", + "org.bouncycastle.crypto.examples", + "org.bouncycastle.crypto.fpe", + "org.bouncycastle.crypto.generators", + "org.bouncycastle.crypto.hpke", + "org.bouncycastle.crypto.io", + "org.bouncycastle.crypto.kems", + "org.bouncycastle.crypto.macs", + "org.bouncycastle.crypto.modes", + "org.bouncycastle.crypto.modes.gcm", + "org.bouncycastle.crypto.modes.kgcm", + "org.bouncycastle.crypto.paddings", + "org.bouncycastle.crypto.params", + "org.bouncycastle.crypto.parsers", + "org.bouncycastle.crypto.prng", + "org.bouncycastle.crypto.prng.drbg", + "org.bouncycastle.crypto.signers", + "org.bouncycastle.crypto.threshold", + "org.bouncycastle.crypto.tls", + "org.bouncycastle.crypto.util", + "org.bouncycastle.i18n", + "org.bouncycastle.i18n.filter", + "org.bouncycastle.iana", + "org.bouncycastle.internal.asn1.bsi", + "org.bouncycastle.internal.asn1.cms", + "org.bouncycastle.internal.asn1.cryptlib", + "org.bouncycastle.internal.asn1.eac", + "org.bouncycastle.internal.asn1.edec", + "org.bouncycastle.internal.asn1.gnu", + "org.bouncycastle.internal.asn1.iana", + "org.bouncycastle.internal.asn1.isara", + "org.bouncycastle.internal.asn1.isismtt", + "org.bouncycastle.internal.asn1.iso", + "org.bouncycastle.internal.asn1.kisa", + "org.bouncycastle.internal.asn1.microsoft", + "org.bouncycastle.internal.asn1.misc", + "org.bouncycastle.internal.asn1.nsri", + "org.bouncycastle.internal.asn1.ntt", + "org.bouncycastle.internal.asn1.oiw", + "org.bouncycastle.internal.asn1.rosstandart", + "org.bouncycastle.jcajce", + "org.bouncycastle.jcajce.interfaces", + "org.bouncycastle.jcajce.io", + "org.bouncycastle.jcajce.provider.asymmetric", + "org.bouncycastle.jcajce.provider.asymmetric.compositesignatures", + "org.bouncycastle.jcajce.provider.asymmetric.dh", + "org.bouncycastle.jcajce.provider.asymmetric.dsa", + "org.bouncycastle.jcajce.provider.asymmetric.dstu", + "org.bouncycastle.jcajce.provider.asymmetric.ec", + "org.bouncycastle.jcajce.provider.asymmetric.ecgost", + "org.bouncycastle.jcajce.provider.asymmetric.ecgost12", + "org.bouncycastle.jcajce.provider.asymmetric.edec", + "org.bouncycastle.jcajce.provider.asymmetric.elgamal", + "org.bouncycastle.jcajce.provider.asymmetric.gost", + "org.bouncycastle.jcajce.provider.asymmetric.ies", + "org.bouncycastle.jcajce.provider.asymmetric.mldsa", + "org.bouncycastle.jcajce.provider.asymmetric.mlkem", + "org.bouncycastle.jcajce.provider.asymmetric.rsa", + "org.bouncycastle.jcajce.provider.asymmetric.slhdsa", + "org.bouncycastle.jcajce.provider.asymmetric.util", + "org.bouncycastle.jcajce.provider.asymmetric.x509", + "org.bouncycastle.jcajce.provider.config", + "org.bouncycastle.jcajce.provider.digest", + "org.bouncycastle.jcajce.provider.drbg", + "org.bouncycastle.jcajce.provider.keystore", + "org.bouncycastle.jcajce.provider.keystore.bc", + "org.bouncycastle.jcajce.provider.keystore.bcfks", + "org.bouncycastle.jcajce.provider.keystore.pkcs12", + "org.bouncycastle.jcajce.provider.keystore.util", + "org.bouncycastle.jcajce.provider.symmetric", + "org.bouncycastle.jcajce.provider.symmetric.util", + "org.bouncycastle.jcajce.provider.util", + "org.bouncycastle.jcajce.spec", + "org.bouncycastle.jcajce.util", + "org.bouncycastle.jce", + "org.bouncycastle.jce.exception", + "org.bouncycastle.jce.interfaces", + "org.bouncycastle.jce.netscape", + "org.bouncycastle.jce.provider", + "org.bouncycastle.jce.spec", + "org.bouncycastle.math", + "org.bouncycastle.math.ec", + "org.bouncycastle.math.ec.custom.djb", + "org.bouncycastle.math.ec.custom.gm", + "org.bouncycastle.math.ec.custom.sec", + "org.bouncycastle.math.ec.endo", + "org.bouncycastle.math.ec.rfc7748", + "org.bouncycastle.math.ec.rfc8032", + "org.bouncycastle.math.ec.tools", + "org.bouncycastle.math.field", + "org.bouncycastle.math.raw", + "org.bouncycastle.pqc.asn1", + "org.bouncycastle.pqc.crypto", + "org.bouncycastle.pqc.crypto.bike", + "org.bouncycastle.pqc.crypto.cmce", + "org.bouncycastle.pqc.crypto.crystals.dilithium", + "org.bouncycastle.pqc.crypto.falcon", + "org.bouncycastle.pqc.crypto.frodo", + "org.bouncycastle.pqc.crypto.gemss", + "org.bouncycastle.pqc.crypto.hqc", + "org.bouncycastle.pqc.crypto.lms", + "org.bouncycastle.pqc.crypto.mldsa", + "org.bouncycastle.pqc.crypto.mlkem", + "org.bouncycastle.pqc.crypto.newhope", + "org.bouncycastle.pqc.crypto.ntru", + "org.bouncycastle.pqc.crypto.ntruprime", + "org.bouncycastle.pqc.crypto.picnic", + "org.bouncycastle.pqc.crypto.rainbow", + "org.bouncycastle.pqc.crypto.saber", + "org.bouncycastle.pqc.crypto.slhdsa", + "org.bouncycastle.pqc.crypto.sphincs", + "org.bouncycastle.pqc.crypto.sphincsplus", + "org.bouncycastle.pqc.crypto.util", + "org.bouncycastle.pqc.crypto.xmss", + "org.bouncycastle.pqc.crypto.xwing", + "org.bouncycastle.pqc.jcajce.interfaces", + "org.bouncycastle.pqc.jcajce.provider", + "org.bouncycastle.pqc.jcajce.provider.bike", + "org.bouncycastle.pqc.jcajce.provider.cmce", + "org.bouncycastle.pqc.jcajce.provider.dilithium", + "org.bouncycastle.pqc.jcajce.provider.falcon", + "org.bouncycastle.pqc.jcajce.provider.frodo", + "org.bouncycastle.pqc.jcajce.provider.gmss", + "org.bouncycastle.pqc.jcajce.provider.hqc", + "org.bouncycastle.pqc.jcajce.provider.kyber", + "org.bouncycastle.pqc.jcajce.provider.lms", + "org.bouncycastle.pqc.jcajce.provider.mceliece", + "org.bouncycastle.pqc.jcajce.provider.newhope", + "org.bouncycastle.pqc.jcajce.provider.ntru", + "org.bouncycastle.pqc.jcajce.provider.ntruprime", + "org.bouncycastle.pqc.jcajce.provider.picnic", + "org.bouncycastle.pqc.jcajce.provider.rainbow", + "org.bouncycastle.pqc.jcajce.provider.saber", + "org.bouncycastle.pqc.jcajce.provider.sphincs", + "org.bouncycastle.pqc.jcajce.provider.sphincsplus", + "org.bouncycastle.pqc.jcajce.provider.util", + "org.bouncycastle.pqc.jcajce.provider.xmss", + "org.bouncycastle.pqc.jcajce.spec", + "org.bouncycastle.pqc.legacy.crypto.gmss", + "org.bouncycastle.pqc.legacy.crypto.gmss.util", + "org.bouncycastle.pqc.legacy.crypto.mceliece", + "org.bouncycastle.pqc.legacy.crypto.ntru", + "org.bouncycastle.pqc.legacy.crypto.qtesla", + "org.bouncycastle.pqc.legacy.crypto.rainbow", + "org.bouncycastle.pqc.legacy.crypto.rainbow.util", + "org.bouncycastle.pqc.legacy.math.linearalgebra", + "org.bouncycastle.pqc.legacy.math.ntru.euclid", + "org.bouncycastle.pqc.legacy.math.ntru.polynomial", + "org.bouncycastle.pqc.legacy.math.ntru.util", + "org.bouncycastle.pqc.math.ntru", + "org.bouncycastle.pqc.math.ntru.parameters", + "org.bouncycastle.util", + "org.bouncycastle.util.encoders", + "org.bouncycastle.util.io", + "org.bouncycastle.util.io.pem", + "org.bouncycastle.util.test", + "org.bouncycastle.x509", + "org.bouncycastle.x509.extension", + "org.bouncycastle.x509.util" + ], + "org.bouncycastle:bcutil-jdk15to18": [ + "org.bouncycastle.asn1.bsi", + "org.bouncycastle.asn1.cmc", + "org.bouncycastle.asn1.cmp", + "org.bouncycastle.asn1.cms", + "org.bouncycastle.asn1.cms.ecc", + "org.bouncycastle.asn1.crmf", + "org.bouncycastle.asn1.dvcs", + "org.bouncycastle.asn1.eac", + "org.bouncycastle.asn1.esf", + "org.bouncycastle.asn1.ess", + "org.bouncycastle.asn1.est", + "org.bouncycastle.asn1.icao", + "org.bouncycastle.asn1.isismtt", + "org.bouncycastle.asn1.isismtt.ocsp", + "org.bouncycastle.asn1.isismtt.x509", + "org.bouncycastle.asn1.smime", + "org.bouncycastle.asn1.tsp", + "org.bouncycastle.oer", + "org.bouncycastle.oer.its", + "org.bouncycastle.oer.its.etsi102941", + "org.bouncycastle.oer.its.etsi102941.basetypes", + "org.bouncycastle.oer.its.etsi103097", + "org.bouncycastle.oer.its.etsi103097.extension", + "org.bouncycastle.oer.its.ieee1609dot2", + "org.bouncycastle.oer.its.ieee1609dot2.basetypes", + "org.bouncycastle.oer.its.ieee1609dot2dot1", + "org.bouncycastle.oer.its.template.etsi102941", + "org.bouncycastle.oer.its.template.etsi102941.basetypes", + "org.bouncycastle.oer.its.template.etsi103097", + "org.bouncycastle.oer.its.template.etsi103097.extension", + "org.bouncycastle.oer.its.template.ieee1609dot2", + "org.bouncycastle.oer.its.template.ieee1609dot2.basetypes", + "org.bouncycastle.oer.its.template.ieee1609dot2dot1" + ], + "org.checkerframework:checker-compat-qual": [ + "org.checkerframework.checker.nullness.compatqual" + ], + "org.checkerframework:checker-qual": [ + "org.checkerframework.checker.builder.qual", + "org.checkerframework.checker.calledmethods.qual", + "org.checkerframework.checker.compilermsgs.qual", + "org.checkerframework.checker.fenum.qual", + "org.checkerframework.checker.formatter.qual", + "org.checkerframework.checker.guieffect.qual", + "org.checkerframework.checker.i18n.qual", + "org.checkerframework.checker.i18nformatter.qual", + "org.checkerframework.checker.index.qual", + "org.checkerframework.checker.initialization.qual", + "org.checkerframework.checker.interning.qual", + "org.checkerframework.checker.lock.qual", + "org.checkerframework.checker.mustcall.qual", + "org.checkerframework.checker.nullness.qual", + "org.checkerframework.checker.optional.qual", + "org.checkerframework.checker.propkey.qual", + "org.checkerframework.checker.regex.qual", + "org.checkerframework.checker.signature.qual", + "org.checkerframework.checker.signedness.qual", + "org.checkerframework.checker.tainting.qual", + "org.checkerframework.checker.units.qual", + "org.checkerframework.common.aliasing.qual", + "org.checkerframework.common.initializedfields.qual", + "org.checkerframework.common.reflection.qual", + "org.checkerframework.common.returnsreceiver.qual", + "org.checkerframework.common.subtyping.qual", + "org.checkerframework.common.util.report.qual", + "org.checkerframework.common.value.qual", + "org.checkerframework.dataflow.qual", + "org.checkerframework.framework.qual" + ], + "org.conscrypt:conscrypt-openjdk-uber": [ + "org.conscrypt", + "org.conscrypt.ct", + "org.conscrypt.io" + ], + "org.eclipse.jgit:org.eclipse.jgit": [ + "org.eclipse.jgit.annotations", + "org.eclipse.jgit.api", + "org.eclipse.jgit.api.errors", + "org.eclipse.jgit.attributes", + "org.eclipse.jgit.blame", + "org.eclipse.jgit.blame.cache", + "org.eclipse.jgit.diff", + "org.eclipse.jgit.dircache", + "org.eclipse.jgit.errors", + "org.eclipse.jgit.events", + "org.eclipse.jgit.fnmatch", + "org.eclipse.jgit.gitrepo", + "org.eclipse.jgit.gitrepo.internal", + "org.eclipse.jgit.hooks", + "org.eclipse.jgit.ignore", + "org.eclipse.jgit.ignore.internal", + "org.eclipse.jgit.internal", + "org.eclipse.jgit.internal.diff", + "org.eclipse.jgit.internal.diffmergetool", + "org.eclipse.jgit.internal.fsck", + "org.eclipse.jgit.internal.revwalk", + "org.eclipse.jgit.internal.storage.commitgraph", + "org.eclipse.jgit.internal.storage.dfs", + "org.eclipse.jgit.internal.storage.file", + "org.eclipse.jgit.internal.storage.io", + "org.eclipse.jgit.internal.storage.memory", + "org.eclipse.jgit.internal.storage.midx", + "org.eclipse.jgit.internal.storage.pack", + "org.eclipse.jgit.internal.storage.reftable", + "org.eclipse.jgit.internal.submodule", + "org.eclipse.jgit.internal.transport.connectivity", + "org.eclipse.jgit.internal.transport.http", + "org.eclipse.jgit.internal.transport.parser", + "org.eclipse.jgit.internal.transport.ssh", + "org.eclipse.jgit.internal.util", + "org.eclipse.jgit.lib", + "org.eclipse.jgit.lib.internal", + "org.eclipse.jgit.logging", + "org.eclipse.jgit.merge", + "org.eclipse.jgit.nls", + "org.eclipse.jgit.notes", + "org.eclipse.jgit.patch", + "org.eclipse.jgit.revplot", + "org.eclipse.jgit.revwalk", + "org.eclipse.jgit.revwalk.filter", + "org.eclipse.jgit.storage.file", + "org.eclipse.jgit.storage.pack", + "org.eclipse.jgit.submodule", + "org.eclipse.jgit.transport", + "org.eclipse.jgit.transport.http", + "org.eclipse.jgit.transport.resolver", + "org.eclipse.jgit.treewalk", + "org.eclipse.jgit.treewalk.filter", + "org.eclipse.jgit.util", + "org.eclipse.jgit.util.io", + "org.eclipse.jgit.util.sha1", + "org.eclipse.jgit.util.time" + ], + "org.eclipse.jgit:org.eclipse.jgit.ssh.apache": [ + "org.eclipse.jgit.internal.signing.ssh", + "org.eclipse.jgit.internal.transport.sshd", + "org.eclipse.jgit.internal.transport.sshd.agent", + "org.eclipse.jgit.internal.transport.sshd.auth", + "org.eclipse.jgit.internal.transport.sshd.pkcs11", + "org.eclipse.jgit.internal.transport.sshd.proxy", + "org.eclipse.jgit.signing.ssh", + "org.eclipse.jgit.transport.sshd", + "org.eclipse.jgit.transport.sshd.agent" + ], + "org.eclipse.jgit:org.eclipse.jgit.ssh.jsch": [ + "org.eclipse.jgit.internal.transport.jsch", + "org.eclipse.jgit.transport" + ], + "org.hamcrest:hamcrest-core": [ + "org.hamcrest", + "org.hamcrest.core", + "org.hamcrest.internal" + ], + "org.hamcrest:hamcrest-library": [ + "org.hamcrest", + "org.hamcrest.beans", + "org.hamcrest.collection", + "org.hamcrest.number", + "org.hamcrest.object", + "org.hamcrest.text", + "org.hamcrest.xml" + ], + "org.jetbrains.compose.animation:animation-core-desktop": [ + "androidx.compose.animation.core", + "androidx.compose.animation.core.internal" + ], + "org.jetbrains.compose.animation:animation-desktop": [ + "androidx.compose.animation", + "androidx.compose.animation.internal" + ], + "org.jetbrains.compose.components:components-resources-desktop": [ + "org.jetbrains.compose.resources", + "org.jetbrains.compose.resources.plural", + "org.jetbrains.compose.resources.vector", + "org.jetbrains.compose.resources.vector.xmldom" + ], + "org.jetbrains.compose.foundation:foundation-desktop": [ + "androidx.compose.foundation", + "androidx.compose.foundation.content", + "androidx.compose.foundation.content.internal", + "androidx.compose.foundation.contextmenu", + "androidx.compose.foundation.draganddrop", + "androidx.compose.foundation.gestures", + "androidx.compose.foundation.gestures.cupertino", + "androidx.compose.foundation.gestures.snapping", + "androidx.compose.foundation.interaction", + "androidx.compose.foundation.internal", + "androidx.compose.foundation.lazy", + "androidx.compose.foundation.lazy.grid", + "androidx.compose.foundation.lazy.layout", + "androidx.compose.foundation.lazy.staggeredgrid", + "androidx.compose.foundation.pager", + "androidx.compose.foundation.platform", + "androidx.compose.foundation.relocation", + "androidx.compose.foundation.selection", + "androidx.compose.foundation.shape", + "androidx.compose.foundation.text", + "androidx.compose.foundation.text.contextmenu.builder", + "androidx.compose.foundation.text.contextmenu.data", + "androidx.compose.foundation.text.contextmenu.gestures", + "androidx.compose.foundation.text.contextmenu.internal", + "androidx.compose.foundation.text.contextmenu.modifier", + "androidx.compose.foundation.text.contextmenu.provider", + "androidx.compose.foundation.text.handwriting", + "androidx.compose.foundation.text.input", + "androidx.compose.foundation.text.input.internal", + "androidx.compose.foundation.text.input.internal.selection", + "androidx.compose.foundation.text.input.internal.undo", + "androidx.compose.foundation.text.l10n", + "androidx.compose.foundation.text.modifiers", + "androidx.compose.foundation.text.selection", + "androidx.compose.foundation.v2", + "androidx.compose.foundation.window" + ], + "org.jetbrains.compose.foundation:foundation-layout-desktop": [ + "androidx.compose.foundation.layout", + "androidx.compose.foundation.layout.internal" + ], + "org.jetbrains.compose.material3:material3-desktop": [ + "androidx.compose.material3", + "androidx.compose.material3.carousel", + "androidx.compose.material3.internal", + "androidx.compose.material3.l10n", + "androidx.compose.material3.pulltorefresh", + "androidx.compose.material3.tokens" + ], + "org.jetbrains.compose.material:material-icons-core-desktop": [ + "androidx.compose.material.icons", + "androidx.compose.material.icons.automirrored.filled", + "androidx.compose.material.icons.automirrored.outlined", + "androidx.compose.material.icons.automirrored.rounded", + "androidx.compose.material.icons.automirrored.sharp", + "androidx.compose.material.icons.automirrored.twotone", + "androidx.compose.material.icons.filled", + "androidx.compose.material.icons.outlined", + "androidx.compose.material.icons.rounded", + "androidx.compose.material.icons.sharp", + "androidx.compose.material.icons.twotone" + ], + "org.jetbrains.compose.material:material-icons-extended-desktop": [ + "androidx.compose.material.icons.automirrored.filled", + "androidx.compose.material.icons.automirrored.outlined", + "androidx.compose.material.icons.automirrored.rounded", + "androidx.compose.material.icons.automirrored.sharp", + "androidx.compose.material.icons.automirrored.twotone", + "androidx.compose.material.icons.filled", + "androidx.compose.material.icons.outlined", + "androidx.compose.material.icons.rounded", + "androidx.compose.material.icons.sharp", + "androidx.compose.material.icons.twotone" + ], + "org.jetbrains.compose.material:material-ripple-desktop": [ + "androidx.compose.material.ripple" + ], + "org.jetbrains.compose.ui:ui-backhandler-desktop": [ + "androidx.compose.ui.backhandler" + ], + "org.jetbrains.compose.ui:ui-desktop": [ + "androidx.compose.ui", + "androidx.compose.ui.animation", + "androidx.compose.ui.autofill", + "androidx.compose.ui.awt", + "androidx.compose.ui.draganddrop", + "androidx.compose.ui.draw", + "androidx.compose.ui.focus", + "androidx.compose.ui.graphics", + "androidx.compose.ui.graphics.vector", + "androidx.compose.ui.hapticfeedback", + "androidx.compose.ui.input", + "androidx.compose.ui.input.indirect", + "androidx.compose.ui.input.key", + "androidx.compose.ui.input.mouse", + "androidx.compose.ui.input.nestedscroll", + "androidx.compose.ui.input.pointer", + "androidx.compose.ui.input.pointer.util", + "androidx.compose.ui.input.rotary", + "androidx.compose.ui.internal", + "androidx.compose.ui.layout", + "androidx.compose.ui.modifier", + "androidx.compose.ui.navigationevent", + "androidx.compose.ui.node", + "androidx.compose.ui.platform", + "androidx.compose.ui.platform.a11y", + "androidx.compose.ui.platform.l10n", + "androidx.compose.ui.relocation", + "androidx.compose.ui.res", + "androidx.compose.ui.res.vector", + "androidx.compose.ui.scene", + "androidx.compose.ui.scene.skia", + "androidx.compose.ui.semantics", + "androidx.compose.ui.skiko", + "androidx.compose.ui.spatial", + "androidx.compose.ui.state", + "androidx.compose.ui.text", + "androidx.compose.ui.unit", + "androidx.compose.ui.util", + "androidx.compose.ui.viewinterop", + "androidx.compose.ui.window" + ], + "org.jetbrains.compose.ui:ui-geometry-desktop": [ + "androidx.compose.ui.geometry" + ], + "org.jetbrains.compose.ui:ui-graphics-desktop": [ + "androidx.compose.ui.graphics", + "androidx.compose.ui.graphics.colorspace", + "androidx.compose.ui.graphics.drawscope", + "androidx.compose.ui.graphics.internal", + "androidx.compose.ui.graphics.layer", + "androidx.compose.ui.graphics.painter", + "androidx.compose.ui.graphics.shadow", + "androidx.compose.ui.graphics.vector" + ], + "org.jetbrains.compose.ui:ui-test-desktop": [ + "androidx.compose.ui.test", + "androidx.compose.ui.test.internal", + "androidx.compose.ui.test.platform" + ], + "org.jetbrains.compose.ui:ui-test-junit4-desktop": [ + "androidx.compose.ui.test.junit4", + "androidx.compose.ui.test.junit4.matchers" + ], + "org.jetbrains.compose.ui:ui-text-desktop": [ + "androidx.compose.ui.text", + "androidx.compose.ui.text.font", + "androidx.compose.ui.text.input", + "androidx.compose.ui.text.internal", + "androidx.compose.ui.text.intl", + "androidx.compose.ui.text.platform", + "androidx.compose.ui.text.style" + ], + "org.jetbrains.compose.ui:ui-unit-desktop": [ + "androidx.compose.ui.unit", + "androidx.compose.ui.unit.internal" + ], + "org.jetbrains.compose.ui:ui-util-desktop": [ + "androidx.compose.ui", + "androidx.compose.ui.util" + ], + "org.jetbrains.kotlin:kotlin-android-extensions-runtime": [ + "kotlinx.android.extensions", + "kotlinx.android.parcel" + ], + "org.jetbrains.kotlin:kotlin-compose-compiler-plugin-embeddable": [ + "androidx.compose.compiler.plugins.kotlin", + "androidx.compose.compiler.plugins.kotlin.analysis", + "androidx.compose.compiler.plugins.kotlin.inference", + "androidx.compose.compiler.plugins.kotlin.k1", + "androidx.compose.compiler.plugins.kotlin.k2", + "androidx.compose.compiler.plugins.kotlin.lower", + "androidx.compose.compiler.plugins.kotlin.lower.hiddenfromobjc" + ], + "org.jetbrains.kotlin:kotlin-parcelize-runtime": [ + "kotlinx.parcelize" + ], + "org.jetbrains.kotlin:kotlin-reflect": [ + "kotlin.reflect.full", + "kotlin.reflect.jvm", + "kotlin.reflect.jvm.internal", + "kotlin.reflect.jvm.internal.calls", + "kotlin.reflect.jvm.internal.impl", + "kotlin.reflect.jvm.internal.impl.builtins", + "kotlin.reflect.jvm.internal.impl.builtins.functions", + "kotlin.reflect.jvm.internal.impl.builtins.jvm", + "kotlin.reflect.jvm.internal.impl.descriptors", + "kotlin.reflect.jvm.internal.impl.descriptors.annotations", + "kotlin.reflect.jvm.internal.impl.descriptors.deserialization", + "kotlin.reflect.jvm.internal.impl.descriptors.impl", + "kotlin.reflect.jvm.internal.impl.descriptors.java", + "kotlin.reflect.jvm.internal.impl.descriptors.runtime.components", + "kotlin.reflect.jvm.internal.impl.descriptors.runtime.structure", + "kotlin.reflect.jvm.internal.impl.incremental", + "kotlin.reflect.jvm.internal.impl.incremental.components", + "kotlin.reflect.jvm.internal.impl.km", + "kotlin.reflect.jvm.internal.impl.km.internal", + "kotlin.reflect.jvm.internal.impl.km.internal.common", + "kotlin.reflect.jvm.internal.impl.km.internal.extensions", + "kotlin.reflect.jvm.internal.impl.km.jvm", + "kotlin.reflect.jvm.internal.impl.km.jvm.internal", + "kotlin.reflect.jvm.internal.impl.load.java", + "kotlin.reflect.jvm.internal.impl.load.java.components", + "kotlin.reflect.jvm.internal.impl.load.java.descriptors", + "kotlin.reflect.jvm.internal.impl.load.java.lazy", + "kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors", + "kotlin.reflect.jvm.internal.impl.load.java.lazy.types", + "kotlin.reflect.jvm.internal.impl.load.java.sources", + "kotlin.reflect.jvm.internal.impl.load.java.structure", + "kotlin.reflect.jvm.internal.impl.load.java.typeEnhancement", + "kotlin.reflect.jvm.internal.impl.load.kotlin", + "kotlin.reflect.jvm.internal.impl.load.kotlin.header", + "kotlin.reflect.jvm.internal.impl.metadata", + "kotlin.reflect.jvm.internal.impl.metadata.builtins", + "kotlin.reflect.jvm.internal.impl.metadata.deserialization", + "kotlin.reflect.jvm.internal.impl.metadata.jvm", + "kotlin.reflect.jvm.internal.impl.metadata.jvm.deserialization", + "kotlin.reflect.jvm.internal.impl.metadata.serialization", + "kotlin.reflect.jvm.internal.impl.name", + "kotlin.reflect.jvm.internal.impl.platform", + "kotlin.reflect.jvm.internal.impl.protobuf", + "kotlin.reflect.jvm.internal.impl.renderer", + "kotlin.reflect.jvm.internal.impl.resolve", + "kotlin.reflect.jvm.internal.impl.resolve.calls.inference", + "kotlin.reflect.jvm.internal.impl.resolve.constants", + "kotlin.reflect.jvm.internal.impl.resolve.deprecation", + "kotlin.reflect.jvm.internal.impl.resolve.descriptorUtil", + "kotlin.reflect.jvm.internal.impl.resolve.jvm", + "kotlin.reflect.jvm.internal.impl.resolve.sam", + "kotlin.reflect.jvm.internal.impl.resolve.scopes", + "kotlin.reflect.jvm.internal.impl.resolve.scopes.receivers", + "kotlin.reflect.jvm.internal.impl.serialization", + "kotlin.reflect.jvm.internal.impl.serialization.deserialization", + "kotlin.reflect.jvm.internal.impl.serialization.deserialization.builtins", + "kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors", + "kotlin.reflect.jvm.internal.impl.storage", + "kotlin.reflect.jvm.internal.impl.types", + "kotlin.reflect.jvm.internal.impl.types.checker", + "kotlin.reflect.jvm.internal.impl.types.error", + "kotlin.reflect.jvm.internal.impl.types.extensions", + "kotlin.reflect.jvm.internal.impl.types.model", + "kotlin.reflect.jvm.internal.impl.types.typeUtil", + "kotlin.reflect.jvm.internal.impl.types.typesApproximation", + "kotlin.reflect.jvm.internal.impl.util", + "kotlin.reflect.jvm.internal.impl.util.capitalizeDecapitalize", + "kotlin.reflect.jvm.internal.impl.util.collectionUtils", + "kotlin.reflect.jvm.internal.impl.utils", + "kotlin.reflect.jvm.internal.impl.utils.addToStdlib", + "kotlin.reflect.jvm.internal.types" + ], + "org.jetbrains.kotlin:kotlin-serialization-compiler-plugin-embeddable": [ + "org.jetbrains.kotlinx.serialization.compiler.backend.ir", + "org.jetbrains.kotlinx.serialization.compiler.diagnostic", + "org.jetbrains.kotlinx.serialization.compiler.extensions", + "org.jetbrains.kotlinx.serialization.compiler.fir", + "org.jetbrains.kotlinx.serialization.compiler.fir.checkers", + "org.jetbrains.kotlinx.serialization.compiler.fir.services", + "org.jetbrains.kotlinx.serialization.compiler.resolve" + ], + "org.jetbrains.kotlin:kotlin-stdlib": [ + "kotlin", + "kotlin.annotation", + "kotlin.collections", + "kotlin.collections.builders", + "kotlin.collections.jdk8", + "kotlin.collections.unsigned", + "kotlin.comparisons", + "kotlin.concurrent", + "kotlin.concurrent.atomics", + "kotlin.concurrent.internal", + "kotlin.contracts", + "kotlin.coroutines", + "kotlin.coroutines.cancellation", + "kotlin.coroutines.intrinsics", + "kotlin.coroutines.jvm.internal", + "kotlin.enums", + "kotlin.experimental", + "kotlin.internal", + "kotlin.internal.jdk7", + "kotlin.internal.jdk8", + "kotlin.io", + "kotlin.io.encoding", + "kotlin.io.path", + "kotlin.jdk7", + "kotlin.js", + "kotlin.jvm", + "kotlin.jvm.functions", + "kotlin.jvm.internal", + "kotlin.jvm.internal.markers", + "kotlin.jvm.internal.unsafe", + "kotlin.jvm.jdk8", + "kotlin.jvm.optionals", + "kotlin.math", + "kotlin.properties", + "kotlin.random", + "kotlin.random.jdk8", + "kotlin.ranges", + "kotlin.reflect", + "kotlin.sequences", + "kotlin.streams.jdk8", + "kotlin.system", + "kotlin.text", + "kotlin.text.jdk8", + "kotlin.time", + "kotlin.time.jdk8", + "kotlin.uuid" + ], + "org.jetbrains.kotlin:kotlin-test": [ + "kotlin.test" + ], + "org.jetbrains.kotlin:kotlin-test-junit": [ + "kotlin.test.junit", + "kotlin.test.junit.annotations" + ], + "org.jetbrains.kotlinx:atomicfu-jvm": [ + "kotlinx.atomicfu", + "kotlinx.atomicfu.locks" + ], + "org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm": [ + "kotlinx.collections.immutable", + "kotlinx.collections.immutable.adapters", + "kotlinx.collections.immutable.implementations.immutableList", + "kotlinx.collections.immutable.implementations.immutableMap", + "kotlinx.collections.immutable.implementations.immutableSet", + "kotlinx.collections.immutable.implementations.persistentOrderedMap", + "kotlinx.collections.immutable.implementations.persistentOrderedSet", + "kotlinx.collections.immutable.internal" + ], + "org.jetbrains.kotlinx:kotlinx-coroutines-android": [ + "kotlinx.coroutines.android" + ], + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm": [ + "_COROUTINE", + "kotlinx.coroutines", + "kotlinx.coroutines.channels", + "kotlinx.coroutines.debug.internal", + "kotlinx.coroutines.flow", + "kotlinx.coroutines.flow.internal", + "kotlinx.coroutines.future", + "kotlinx.coroutines.internal", + "kotlinx.coroutines.intrinsics", + "kotlinx.coroutines.scheduling", + "kotlinx.coroutines.selects", + "kotlinx.coroutines.stream", + "kotlinx.coroutines.sync", + "kotlinx.coroutines.time" + ], + "org.jetbrains.kotlinx:kotlinx-coroutines-guava": [ + "kotlinx.coroutines.guava" + ], + "org.jetbrains.kotlinx:kotlinx-coroutines-reactive": [ + "kotlinx.coroutines.reactive" + ], + "org.jetbrains.kotlinx:kotlinx-coroutines-slf4j": [ + "kotlinx.coroutines.slf4j" + ], + "org.jetbrains.kotlinx:kotlinx-coroutines-swing": [ + "kotlinx.coroutines.swing" + ], + "org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm": [ + "kotlinx.coroutines.test", + "kotlinx.coroutines.test.internal" + ], + "org.jetbrains.kotlinx:kotlinx-datetime-jvm": [ + "kotlinx.datetime", + "kotlinx.datetime.format", + "kotlinx.datetime.internal", + "kotlinx.datetime.internal.format", + "kotlinx.datetime.internal.format.formatter", + "kotlinx.datetime.internal.format.parser", + "kotlinx.datetime.serializers" + ], + "org.jetbrains.kotlinx:kotlinx-io-bytestring-jvm": [ + "kotlinx.io.bytestring", + "kotlinx.io.bytestring.unsafe" + ], + "org.jetbrains.kotlinx:kotlinx-io-core-jvm": [ + "kotlinx.io", + "kotlinx.io.files", + "kotlinx.io.internal", + "kotlinx.io.unsafe" + ], + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm": [ + "kotlinx.serialization", + "kotlinx.serialization.builtins", + "kotlinx.serialization.descriptors", + "kotlinx.serialization.encoding", + "kotlinx.serialization.internal", + "kotlinx.serialization.modules" + ], + "org.jetbrains.kotlinx:kotlinx-serialization-json-io-jvm": [ + "kotlinx.serialization.json.io", + "kotlinx.serialization.json.io.internal" + ], + "org.jetbrains.kotlinx:kotlinx-serialization-json-jvm": [ + "kotlinx.serialization.json", + "kotlinx.serialization.json.internal" + ], + "org.jetbrains.runtime:jbr-api": [ + "com.jetbrains" + ], + "org.jetbrains.skiko:skiko-awt": [ + "org.jetbrains.skia", + "org.jetbrains.skia.icu", + "org.jetbrains.skia.impl", + "org.jetbrains.skia.paragraph", + "org.jetbrains.skia.shaper", + "org.jetbrains.skia.skottie", + "org.jetbrains.skia.sksg", + "org.jetbrains.skia.svg", + "org.jetbrains.skiko", + "org.jetbrains.skiko.context", + "org.jetbrains.skiko.graphicapi", + "org.jetbrains.skiko.node", + "org.jetbrains.skiko.redrawer", + "org.jetbrains.skiko.swing", + "org.jetbrains.skiko.windows" + ], + "org.jetbrains:annotations": [ + "org.intellij.lang.annotations", + "org.jetbrains.annotations" + ], + "org.jetbrains:markdown-jvm": [ + "org.intellij.markdown", + "org.intellij.markdown.ast", + "org.intellij.markdown.ast.impl", + "org.intellij.markdown.ast.visitors", + "org.intellij.markdown.flavours", + "org.intellij.markdown.flavours.commonmark", + "org.intellij.markdown.flavours.gfm", + "org.intellij.markdown.flavours.gfm.lexer", + "org.intellij.markdown.flavours.gfm.table", + "org.intellij.markdown.flavours.space", + "org.intellij.markdown.flavours.space.lexer", + "org.intellij.markdown.html", + "org.intellij.markdown.html.entities", + "org.intellij.markdown.lexer", + "org.intellij.markdown.parser", + "org.intellij.markdown.parser.constraints", + "org.intellij.markdown.parser.markerblocks", + "org.intellij.markdown.parser.markerblocks.impl", + "org.intellij.markdown.parser.markerblocks.providers", + "org.intellij.markdown.parser.sequentialparsers", + "org.intellij.markdown.parser.sequentialparsers.impl" + ], + "org.jspecify:jspecify": [ + "org.jspecify.annotations" + ], + "org.mockito:mockito-core": [ + "org.mockito", + "org.mockito.codegen", + "org.mockito.configuration", + "org.mockito.creation.instance", + "org.mockito.exceptions.base", + "org.mockito.exceptions.misusing", + "org.mockito.exceptions.stacktrace", + "org.mockito.exceptions.verification", + "org.mockito.exceptions.verification.junit", + "org.mockito.hamcrest", + "org.mockito.internal", + "org.mockito.internal.configuration", + "org.mockito.internal.configuration.injection", + "org.mockito.internal.configuration.injection.filter", + "org.mockito.internal.configuration.injection.scanner", + "org.mockito.internal.configuration.plugins", + "org.mockito.internal.creation", + "org.mockito.internal.creation.bytebuddy", + "org.mockito.internal.creation.instance", + "org.mockito.internal.creation.settings", + "org.mockito.internal.creation.util", + "org.mockito.internal.debugging", + "org.mockito.internal.exceptions", + "org.mockito.internal.exceptions.stacktrace", + "org.mockito.internal.exceptions.util", + "org.mockito.internal.framework", + "org.mockito.internal.hamcrest", + "org.mockito.internal.handler", + "org.mockito.internal.invocation", + "org.mockito.internal.invocation.finder", + "org.mockito.internal.invocation.mockref", + "org.mockito.internal.junit", + "org.mockito.internal.junit.util", + "org.mockito.internal.listeners", + "org.mockito.internal.matchers", + "org.mockito.internal.matchers.apachecommons", + "org.mockito.internal.matchers.text", + "org.mockito.internal.progress", + "org.mockito.internal.reporting", + "org.mockito.internal.runners", + "org.mockito.internal.runners.util", + "org.mockito.internal.session", + "org.mockito.internal.stubbing", + "org.mockito.internal.stubbing.answers", + "org.mockito.internal.stubbing.defaultanswers", + "org.mockito.internal.util", + "org.mockito.internal.util.collections", + "org.mockito.internal.util.concurrent", + "org.mockito.internal.util.io", + "org.mockito.internal.util.reflection", + "org.mockito.internal.verification", + "org.mockito.internal.verification.api", + "org.mockito.internal.verification.argumentmatching", + "org.mockito.internal.verification.checkers", + "org.mockito.invocation", + "org.mockito.junit", + "org.mockito.listeners", + "org.mockito.mock", + "org.mockito.plugins", + "org.mockito.quality", + "org.mockito.runners", + "org.mockito.session", + "org.mockito.stubbing", + "org.mockito.verification" + ], + "org.objenesis:objenesis": [ + "org.objenesis", + "org.objenesis.instantiator", + "org.objenesis.instantiator.android", + "org.objenesis.instantiator.annotations", + "org.objenesis.instantiator.basic", + "org.objenesis.instantiator.gcj", + "org.objenesis.instantiator.perc", + "org.objenesis.instantiator.sun", + "org.objenesis.instantiator.util", + "org.objenesis.strategy" + ], + "org.ow2.asm:asm": [ + "org.objectweb.asm", + "org.objectweb.asm.signature" + ], + "org.ow2.asm:asm-commons": [ + "org.objectweb.asm.commons" + ], + "org.ow2.asm:asm-tree": [ + "org.objectweb.asm.tree" + ], + "org.reactivestreams:reactive-streams": [ + "org.reactivestreams" + ], + "org.robolectric:annotations": [ + "org.robolectric.annotation", + "org.robolectric.annotation.experimental", + "org.robolectric.annotation.internal", + "org.robolectric.shadow.api", + "org.robolectric.versioning" + ], + "org.robolectric:junit": [ + "org.robolectric.internal" + ], + "org.robolectric:nativeruntime": [ + "org.robolectric.nativeruntime" + ], + "org.robolectric:pluginapi": [ + "org.robolectric.internal.dependency", + "org.robolectric.pluginapi", + "org.robolectric.pluginapi.config", + "org.robolectric.pluginapi.perf" + ], + "org.robolectric:plugins-maven-dependency-resolver": [ + "org.robolectric", + "org.robolectric.internal.dependency" + ], + "org.robolectric:resources": [ + "org.robolectric.manifest", + "org.robolectric.res", + "org.robolectric.res.android", + "org.robolectric.res.builder" + ], + "org.robolectric:robolectric": [ + "org.robolectric", + "org.robolectric.android", + "org.robolectric.android.internal", + "org.robolectric.internal", + "org.robolectric.internal.dependency", + "org.robolectric.junit.rules", + "org.robolectric.plugins", + "org.robolectric.plugins.config" + ], + "org.robolectric:sandbox": [ + "org.robolectric.config", + "org.robolectric.fakes", + "org.robolectric.interceptors", + "org.robolectric.internal.bytecode", + "org.robolectric.sandbox", + "org.robolectric.util" + ], + "org.robolectric:shadowapi": [ + "org.robolectric.annotation.internal", + "org.robolectric.config", + "org.robolectric.internal", + "org.robolectric.shadow.api", + "org.robolectric.util" + ], + "org.robolectric:shadows-framework": [ + "android.webkit", + "org.robolectric", + "org.robolectric.android", + "org.robolectric.android.controller", + "org.robolectric.android.internal", + "org.robolectric.android.util.concurrent", + "org.robolectric.fakes", + "org.robolectric.shadows", + "org.robolectric.shadows.util" + ], + "org.robolectric:utils": [ + "org.robolectric", + "org.robolectric.util", + "org.robolectric.util.inject" + ], + "org.robolectric:utils-reflector": [ + "org.robolectric.util.reflector" + ], + "org.slf4j:jcl-over-slf4j": [ + "org.apache.commons.logging", + "org.apache.commons.logging.impl" + ], + "org.slf4j:slf4j-api": [ + "org.slf4j", + "org.slf4j.event", + "org.slf4j.helpers", + "org.slf4j.spi" + ], + "org.xerial:sqlite-jdbc": [ + "org.sqlite", + "org.sqlite.core", + "org.sqlite.date", + "org.sqlite.javax", + "org.sqlite.jdbc3", + "org.sqlite.jdbc4", + "org.sqlite.nativeimage", + "org.sqlite.util" + ], + "org.yaml:snakeyaml": [ + "org.yaml.snakeyaml", + "org.yaml.snakeyaml.comments", + "org.yaml.snakeyaml.composer", + "org.yaml.snakeyaml.constructor", + "org.yaml.snakeyaml.emitter", + "org.yaml.snakeyaml.env", + "org.yaml.snakeyaml.error", + "org.yaml.snakeyaml.events", + "org.yaml.snakeyaml.extensions.compactnotation", + "org.yaml.snakeyaml.external.com.google.gdata.util.common.base", + "org.yaml.snakeyaml.inspector", + "org.yaml.snakeyaml.internal", + "org.yaml.snakeyaml.introspector", + "org.yaml.snakeyaml.nodes", + "org.yaml.snakeyaml.parser", + "org.yaml.snakeyaml.reader", + "org.yaml.snakeyaml.representer", + "org.yaml.snakeyaml.resolver", + "org.yaml.snakeyaml.scanner", + "org.yaml.snakeyaml.serializer", + "org.yaml.snakeyaml.tokens", + "org.yaml.snakeyaml.util" + ] + }, + "repositories": { + "https://jitpack.io/": [ + "androidx.activity:activity-compose:aar", + "androidx.activity:activity-ktx:aar", + "androidx.activity:activity:aar", + "androidx.annotation:annotation", + "androidx.annotation:annotation-experimental:aar", + "androidx.annotation:annotation-jvm", + "androidx.appcompat:appcompat-resources:aar", + "androidx.appcompat:appcompat:aar", + "androidx.arch.core:core-common", + "androidx.arch.core:core-runtime:aar", + "androidx.arch.core:core-testing:aar", + "androidx.autofill:autofill:aar", + "androidx.camera:camera-camera2:aar", + "androidx.camera:camera-core:aar", + "androidx.camera:camera-lifecycle:aar", + "androidx.collection:collection", + "androidx.collection:collection-jvm", + "androidx.collection:collection-ktx", + "androidx.compose.animation:animation-android:aar", + "androidx.compose.animation:animation-core-android:aar", + "androidx.compose.animation:animation-core:aar", + "androidx.compose.animation:animation:aar", + "androidx.compose.foundation:foundation-android:aar", + "androidx.compose.foundation:foundation-layout-android:aar", + "androidx.compose.foundation:foundation-layout:aar", + "androidx.compose.foundation:foundation:aar", + "androidx.compose.material3:material3-android:aar", + "androidx.compose.material3:material3:aar", + "androidx.compose.material:material-android:aar", + "androidx.compose.material:material-icons-core-android:aar", + "androidx.compose.material:material-icons-core:aar", + "androidx.compose.material:material-icons-extended-android:aar", + "androidx.compose.material:material-icons-extended:aar", + "androidx.compose.material:material-ripple-android:aar", + "androidx.compose.material:material-ripple:aar", + "androidx.compose.material:material:aar", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.runtime:runtime-annotation", + "androidx.compose.runtime:runtime-annotation-android:aar", + "androidx.compose.runtime:runtime-annotation-jvm", + "androidx.compose.runtime:runtime-desktop", + "androidx.compose.runtime:runtime-retain-android:aar", + "androidx.compose.runtime:runtime-retain-desktop", + "androidx.compose.runtime:runtime-retain:aar", + "androidx.compose.runtime:runtime-saveable-android:aar", + "androidx.compose.runtime:runtime-saveable-desktop", + "androidx.compose.runtime:runtime-saveable:aar", + "androidx.compose.runtime:runtime:aar", + "androidx.compose.ui:ui-android:aar", + "androidx.compose.ui:ui-geometry-android:aar", + "androidx.compose.ui:ui-geometry:aar", + "androidx.compose.ui:ui-graphics-android:aar", + "androidx.compose.ui:ui-graphics:aar", + "androidx.compose.ui:ui-test-android:aar", + "androidx.compose.ui:ui-test-junit4-android:aar", + "androidx.compose.ui:ui-test-junit4:aar", + "androidx.compose.ui:ui-test-manifest:aar", + "androidx.compose.ui:ui-test:aar", + "androidx.compose.ui:ui-text-android:aar", + "androidx.compose.ui:ui-text:aar", + "androidx.compose.ui:ui-tooling-preview-android:aar", + "androidx.compose.ui:ui-tooling-preview:aar", + "androidx.compose.ui:ui-unit-android:aar", + "androidx.compose.ui:ui-unit:aar", + "androidx.compose.ui:ui-util-android:aar", + "androidx.compose.ui:ui-util:aar", + "androidx.compose.ui:ui:aar", + "androidx.concurrent:concurrent-futures", + "androidx.concurrent:concurrent-futures-ktx", + "androidx.core:core-ktx:aar", + "androidx.core:core-remoteviews:aar", + "androidx.core:core-viewtree:aar", + "androidx.core:core:aar", + "androidx.cursoradapter:cursoradapter:aar", + "androidx.customview:customview-poolingcontainer:aar", + "androidx.customview:customview:aar", + "androidx.datastore:datastore-core", + "androidx.datastore:datastore-preferences-core", + "androidx.datastore:datastore-preferences:aar", + "androidx.datastore:datastore:aar", + "androidx.documentfile:documentfile:aar", + "androidx.drawerlayout:drawerlayout:aar", + "androidx.dynamicanimation:dynamicanimation:aar", + "androidx.emoji2:emoji2-views-helper:aar", + "androidx.emoji2:emoji2:aar", + "androidx.exifinterface:exifinterface:aar", + "androidx.fragment:fragment-ktx:aar", + "androidx.fragment:fragment:aar", + "androidx.glance:glance-appwidget-external-protobuf", + "androidx.glance:glance-appwidget-proto", + "androidx.glance:glance-appwidget-testing:aar", + "androidx.glance:glance-appwidget:aar", + "androidx.glance:glance-material3:aar", + "androidx.glance:glance-testing:aar", + "androidx.glance:glance:aar", + "androidx.graphics:graphics-path:aar", + "androidx.interpolator:interpolator:aar", + "androidx.legacy:legacy-support-core-utils:aar", + "androidx.lifecycle:lifecycle-common", + "androidx.lifecycle:lifecycle-common-java8", + "androidx.lifecycle:lifecycle-common-jvm", + "androidx.lifecycle:lifecycle-livedata-core-ktx:aar", + "androidx.lifecycle:lifecycle-livedata-core:aar", + "androidx.lifecycle:lifecycle-livedata:aar", + "androidx.lifecycle:lifecycle-process:aar", + "androidx.lifecycle:lifecycle-runtime-android:aar", + "androidx.lifecycle:lifecycle-runtime-compose-android:aar", + "androidx.lifecycle:lifecycle-runtime-compose-desktop", + "androidx.lifecycle:lifecycle-runtime-compose:aar", + "androidx.lifecycle:lifecycle-runtime-desktop", + "androidx.lifecycle:lifecycle-runtime-ktx-android:aar", + "androidx.lifecycle:lifecycle-runtime-ktx:aar", + "androidx.lifecycle:lifecycle-runtime:aar", + "androidx.lifecycle:lifecycle-service:aar", + "androidx.lifecycle:lifecycle-viewmodel-android:aar", + "androidx.lifecycle:lifecycle-viewmodel-compose-android:aar", + "androidx.lifecycle:lifecycle-viewmodel-compose:aar", + "androidx.lifecycle:lifecycle-viewmodel-desktop", + "androidx.lifecycle:lifecycle-viewmodel-ktx:aar", + "androidx.lifecycle:lifecycle-viewmodel-savedstate-android:aar", + "androidx.lifecycle:lifecycle-viewmodel-savedstate-desktop", + "androidx.lifecycle:lifecycle-viewmodel-savedstate:aar", + "androidx.lifecycle:lifecycle-viewmodel:aar", + "androidx.loader:loader:aar", + "androidx.localbroadcastmanager:localbroadcastmanager:aar", + "androidx.metrics:metrics-performance:aar", + "androidx.navigationevent:navigationevent-android:aar", + "androidx.navigationevent:navigationevent-desktop", + "androidx.navigationevent:navigationevent:aar", + "androidx.print:print:aar", + "androidx.profileinstaller:profileinstaller:aar", + "androidx.resourceinspection:resourceinspection-annotation", + "androidx.room:room-common", + "androidx.room:room-ktx:aar", + "androidx.room:room-runtime:aar", + "androidx.savedstate:savedstate-android:aar", + "androidx.savedstate:savedstate-compose-android:aar", + "androidx.savedstate:savedstate-compose-desktop", + "androidx.savedstate:savedstate-compose:aar", + "androidx.savedstate:savedstate-desktop", + "androidx.savedstate:savedstate-ktx:aar", + "androidx.savedstate:savedstate:aar", + "androidx.security:security-crypto:aar", + "androidx.sqlite:sqlite-android:aar", + "androidx.sqlite:sqlite-framework-android:aar", + "androidx.sqlite:sqlite-framework:aar", + "androidx.sqlite:sqlite:aar", + "androidx.startup:startup-runtime:aar", + "androidx.test.espresso:espresso-core:aar", + "androidx.test.espresso:espresso-idling-resource:aar", + "androidx.test.ext:junit:aar", + "androidx.test.services:storage:aar", + "androidx.test:core:aar", + "androidx.test:monitor:aar", + "androidx.test:rules:aar", + "androidx.test:runner:aar", + "androidx.tracing:tracing-android:aar", + "androidx.tracing:tracing-ktx:aar", + "androidx.tracing:tracing:aar", + "androidx.transition:transition:aar", + "androidx.vectordrawable:vectordrawable-animated:aar", + "androidx.vectordrawable:vectordrawable:aar", + "androidx.versionedparcelable:versionedparcelable:aar", + "androidx.viewpager:viewpager:aar", + "androidx.window:window-core", + "androidx.window:window-core-jvm", + "androidx.window:window:aar", + "androidx.work:work-runtime-ktx:aar", + "androidx.work:work-runtime:aar", + "app.cash.sqldelight:android-driver:aar", + "app.cash.sqldelight:async-extensions-jvm", + "app.cash.sqldelight:coroutines-extensions-jvm", + "app.cash.sqldelight:jdbc-driver", + "app.cash.sqldelight:runtime", + "app.cash.sqldelight:runtime-jvm", + "app.cash.sqldelight:sqlite-driver", + "co.touchlab:stately-concurrency-jvm", + "co.touchlab:stately-strict-jvm", + "com.almworks.sqlite4java:sqlite4java", + "com.android.tools:desugar_jdk_libs", + "com.android.tools:desugar_jdk_libs_configuration", + "com.benasher44:uuid-jvm", + "com.fleeksoft.charset:charset-jvm", + "com.fleeksoft.io:io-core-jvm", + "com.fleeksoft.ksoup:ksoup-jvm", + "com.github.mwiede:jsch", + "com.github.requery:sqlite-android:aar", + "com.google.android.datatransport:transport-api:aar", + "com.google.android.datatransport:transport-backend-cct:aar", + "com.google.android.datatransport:transport-runtime:aar", + "com.google.android.gms:play-services-base:aar", + "com.google.android.gms:play-services-basement:aar", + "com.google.android.gms:play-services-mlkit-text-recognition-common:aar", + "com.google.android.gms:play-services-mlkit-text-recognition:aar", + "com.google.android.gms:play-services-tasks:aar", + "com.google.android.odml:image:aar", + "com.google.ar:core:aar", + "com.google.auto.value:auto-value-annotations", + "com.google.code.findbugs:jsr305", + "com.google.code.gson:gson", + "com.google.crypto.tink:tink-android", + "com.google.errorprone:error_prone_annotation", + "com.google.errorprone:error_prone_annotations", + "com.google.firebase:firebase-annotations", + "com.google.firebase:firebase-components:aar", + "com.google.firebase:firebase-encoders", + "com.google.firebase:firebase-encoders-json:aar", + "com.google.guava:failureaccess", + "com.google.guava:guava", + "com.google.guava:listenablefuture", + "com.google.j2objc:j2objc-annotations", + "com.google.mlkit:common:aar", + "com.google.mlkit:genai-common:aar", + "com.google.mlkit:genai-prompt:aar", + "com.google.mlkit:image-labeling-common:aar", + "com.google.mlkit:image-labeling-default-common:aar", + "com.google.mlkit:image-labeling:aar", + "com.google.mlkit:text-recognition-bundled-common:aar", + "com.google.mlkit:text-recognition:aar", + "com.google.mlkit:vision-common:aar", + "com.google.mlkit:vision-interfaces:aar", + "com.google.mlkit:vision-internal-vkp:aar", + "com.google.testparameterinjector:test-parameter-injector", + "com.google.truth:truth", + "com.googlecode.java-diff-utils:diffutils", + "com.googlecode.javaewah:JavaEWAH", + "com.ibm.icu:icu4j", + "com.jcraft:jsch", + "com.jcraft:jzlib", + "com.juul.kable:core-android:aar", + "com.juul.kable:exceptions-jvm", + "com.juul.tuulbox:collections-jvm", + "com.juul.tuulbox:coroutines-android:aar", + "com.microsoft.onnxruntime:onnxruntime-android:aar", + "com.squareup.okhttp3:okhttp", + "com.squareup.okhttp3:okhttp-sse", + "com.squareup.okio:okio", + "com.squareup.okio:okio-jvm", + "com.tom-roush:pdfbox-android:aar", + "commons-codec:commons-codec", + "commons-logging:commons-logging", + "io.arrow-kt:arrow-annotations-jvm", + "io.arrow-kt:arrow-atomic-jvm", + "io.arrow-kt:arrow-autoclose-jvm", + "io.arrow-kt:arrow-core-jvm", + "io.arrow-kt:arrow-exception-utils-jvm", + "io.arrow-kt:arrow-fx-coroutines-jvm", + "io.arrow-kt:arrow-optics-jvm", + "io.arrow-kt:arrow-resilience-jvm", + "io.coil-kt.coil3:coil-compose-core-jvm", + "io.coil-kt.coil3:coil-compose-jvm", + "io.coil-kt.coil3:coil-core-jvm", + "io.coil-kt.coil3:coil-jvm", + "io.coil-kt.coil3:coil-network-core-jvm", + "io.coil-kt.coil3:coil-network-ktor3-jvm", + "io.github.petertrr:kotlin-multiplatform-diff-jvm", + "io.ktor:ktor-client-content-negotiation-jvm", + "io.ktor:ktor-client-core-jvm", + "io.ktor:ktor-client-mock-jvm", + "io.ktor:ktor-client-okhttp-jvm", + "io.ktor:ktor-events-jvm", + "io.ktor:ktor-http-cio-jvm", + "io.ktor:ktor-http-jvm", + "io.ktor:ktor-io-jvm", + "io.ktor:ktor-network-jvm", + "io.ktor:ktor-serialization-jvm", + "io.ktor:ktor-serialization-kotlinx-json-jvm", + "io.ktor:ktor-serialization-kotlinx-jvm", + "io.ktor:ktor-sse-jvm", + "io.ktor:ktor-utils-jvm", + "io.ktor:ktor-websocket-serialization-jvm", + "io.ktor:ktor-websockets-jvm", + "io.opentelemetry:opentelemetry-api", + "io.opentelemetry:opentelemetry-api-incubator", + "io.opentelemetry:opentelemetry-context", + "io.opentelemetry:opentelemetry-exporter-logging", + "io.opentelemetry:opentelemetry-sdk", + "io.opentelemetry:opentelemetry-sdk-common", + "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi", + "io.opentelemetry:opentelemetry-sdk-logs", + "io.opentelemetry:opentelemetry-sdk-metrics", + "io.opentelemetry:opentelemetry-sdk-trace", + "io.projectreactor.tools:blockhound", + "javax.annotation:javax.annotation-api", + "javax.inject:javax.inject", + "junit:junit", + "org.apache.pdfbox:fontbox", + "org.apache.pdfbox:pdfbox", + "org.apache.pdfbox:pdfbox-io", + "org.apache.sshd:sshd-osgi", + "org.apache.sshd:sshd-sftp", + "org.bouncycastle:bcpkix-jdk15to18", + "org.bouncycastle:bcprov-jdk15to18", + "org.bouncycastle:bcprov-jdk18on", + "org.bouncycastle:bcutil-jdk15to18", + "org.checkerframework:checker-compat-qual", + "org.checkerframework:checker-qual", + "org.conscrypt:conscrypt-openjdk-uber", + "org.eclipse.jgit:org.eclipse.jgit", + "org.eclipse.jgit:org.eclipse.jgit.ssh.apache", + "org.eclipse.jgit:org.eclipse.jgit.ssh.jsch", + "org.hamcrest:hamcrest-core", + "org.hamcrest:hamcrest-library", + "org.jetbrains.androidx.lifecycle:lifecycle-common", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose-desktop", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-savedstate", + "org.jetbrains.androidx.savedstate:savedstate", + "org.jetbrains.androidx.savedstate:savedstate-compose", + "org.jetbrains.androidx.savedstate:savedstate-compose-desktop", + "org.jetbrains.compose.animation:animation", + "org.jetbrains.compose.animation:animation-core", + "org.jetbrains.compose.animation:animation-core-desktop", + "org.jetbrains.compose.animation:animation-desktop", + "org.jetbrains.compose.annotation-internal:annotation", + "org.jetbrains.compose.collection-internal:collection", + "org.jetbrains.compose.components:components-resources-desktop", + "org.jetbrains.compose.desktop:desktop", + "org.jetbrains.compose.desktop:desktop-jvm-linux-x64:pom", + "org.jetbrains.compose.foundation:foundation", + "org.jetbrains.compose.foundation:foundation-desktop", + "org.jetbrains.compose.foundation:foundation-layout", + "org.jetbrains.compose.foundation:foundation-layout-desktop", + "org.jetbrains.compose.material3:material3-desktop", + "org.jetbrains.compose.material:material", + "org.jetbrains.compose.material:material-icons-core-desktop", + "org.jetbrains.compose.material:material-icons-extended-desktop", + "org.jetbrains.compose.material:material-ripple", + "org.jetbrains.compose.material:material-ripple-desktop", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.compose.runtime:runtime-saveable", + "org.jetbrains.compose.runtime:runtime-saveable-desktop", + "org.jetbrains.compose.ui:ui", + "org.jetbrains.compose.ui:ui-backhandler", + "org.jetbrains.compose.ui:ui-backhandler-desktop", + "org.jetbrains.compose.ui:ui-desktop", + "org.jetbrains.compose.ui:ui-geometry", + "org.jetbrains.compose.ui:ui-geometry-desktop", + "org.jetbrains.compose.ui:ui-graphics", + "org.jetbrains.compose.ui:ui-graphics-desktop", + "org.jetbrains.compose.ui:ui-test-desktop", + "org.jetbrains.compose.ui:ui-test-junit4-desktop", + "org.jetbrains.compose.ui:ui-text", + "org.jetbrains.compose.ui:ui-text-desktop", + "org.jetbrains.compose.ui:ui-tooling-preview", + "org.jetbrains.compose.ui:ui-uikit", + "org.jetbrains.compose.ui:ui-unit", + "org.jetbrains.compose.ui:ui-unit-desktop", + "org.jetbrains.compose.ui:ui-util", + "org.jetbrains.compose.ui:ui-util-desktop", + "org.jetbrains.kotlin:kotlin-android-extensions-runtime", + "org.jetbrains.kotlin:kotlin-compose-compiler-plugin-embeddable", + "org.jetbrains.kotlin:kotlin-parcelize-runtime", + "org.jetbrains.kotlin:kotlin-reflect", + "org.jetbrains.kotlin:kotlin-serialization-compiler-plugin-embeddable", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlin:kotlin-stdlib-common", + "org.jetbrains.kotlin:kotlin-stdlib-jdk7", + "org.jetbrains.kotlin:kotlin-stdlib-jdk8", + "org.jetbrains.kotlin:kotlin-test", + "org.jetbrains.kotlin:kotlin-test-junit", + "org.jetbrains.kotlinx:atomicfu", + "org.jetbrains.kotlinx:atomicfu-jvm", + "org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm", + "org.jetbrains.kotlinx:kotlinx-coroutines-android", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.jetbrains.kotlinx:kotlinx-coroutines-guava", + "org.jetbrains.kotlinx:kotlinx-coroutines-reactive", + "org.jetbrains.kotlinx:kotlinx-coroutines-slf4j", + "org.jetbrains.kotlinx:kotlinx-coroutines-swing", + "org.jetbrains.kotlinx:kotlinx-coroutines-test", + "org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm", + "org.jetbrains.kotlinx:kotlinx-datetime-jvm", + "org.jetbrains.kotlinx:kotlinx-io-bytestring-jvm", + "org.jetbrains.kotlinx:kotlinx-io-core-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-core", + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-json-io-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-json-jvm", + "org.jetbrains.runtime:jbr-api", + "org.jetbrains.skiko:skiko", + "org.jetbrains.skiko:skiko-awt", + "org.jetbrains.skiko:skiko-awt-runtime-linux-x64", + "org.jetbrains.skiko:skiko-awt-runtime-macos-arm64", + "org.jetbrains.skiko:skiko-awt-runtime-macos-x64", + "org.jetbrains.skiko:skiko-awt-runtime-windows-x64", + "org.jetbrains:annotations", + "org.jetbrains:markdown-jvm", + "org.jspecify:jspecify", + "org.mockito:mockito-core", + "org.objenesis:objenesis", + "org.ow2.asm:asm", + "org.ow2.asm:asm-commons", + "org.ow2.asm:asm-tree", + "org.reactivestreams:reactive-streams", + "org.robolectric:annotations", + "org.robolectric:junit", + "org.robolectric:nativeruntime", + "org.robolectric:nativeruntime-dist-compat", + "org.robolectric:pluginapi", + "org.robolectric:plugins-maven-dependency-resolver", + "org.robolectric:resources", + "org.robolectric:robolectric", + "org.robolectric:sandbox", + "org.robolectric:shadowapi", + "org.robolectric:shadows-framework", + "org.robolectric:utils", + "org.robolectric:utils-reflector", + "org.slf4j:jcl-over-slf4j", + "org.slf4j:slf4j-api", + "org.xerial:sqlite-jdbc", + "org.yaml:snakeyaml" + ], + "https://maven.google.com/": [ + "androidx.activity:activity-compose:aar", + "androidx.activity:activity-ktx:aar", + "androidx.activity:activity:aar", + "androidx.annotation:annotation", + "androidx.annotation:annotation-experimental:aar", + "androidx.annotation:annotation-jvm", + "androidx.appcompat:appcompat-resources:aar", + "androidx.appcompat:appcompat:aar", + "androidx.arch.core:core-common", + "androidx.arch.core:core-runtime:aar", + "androidx.arch.core:core-testing:aar", + "androidx.autofill:autofill:aar", + "androidx.camera:camera-camera2:aar", + "androidx.camera:camera-core:aar", + "androidx.camera:camera-lifecycle:aar", + "androidx.collection:collection", + "androidx.collection:collection-jvm", + "androidx.collection:collection-ktx", + "androidx.compose.animation:animation-android:aar", + "androidx.compose.animation:animation-core-android:aar", + "androidx.compose.animation:animation-core:aar", + "androidx.compose.animation:animation:aar", + "androidx.compose.foundation:foundation-android:aar", + "androidx.compose.foundation:foundation-layout-android:aar", + "androidx.compose.foundation:foundation-layout:aar", + "androidx.compose.foundation:foundation:aar", + "androidx.compose.material3:material3-android:aar", + "androidx.compose.material3:material3:aar", + "androidx.compose.material:material-android:aar", + "androidx.compose.material:material-icons-core-android:aar", + "androidx.compose.material:material-icons-core:aar", + "androidx.compose.material:material-icons-extended-android:aar", + "androidx.compose.material:material-icons-extended:aar", + "androidx.compose.material:material-ripple-android:aar", + "androidx.compose.material:material-ripple:aar", + "androidx.compose.material:material:aar", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.runtime:runtime-annotation", + "androidx.compose.runtime:runtime-annotation-android:aar", + "androidx.compose.runtime:runtime-annotation-jvm", + "androidx.compose.runtime:runtime-desktop", + "androidx.compose.runtime:runtime-retain-android:aar", + "androidx.compose.runtime:runtime-retain-desktop", + "androidx.compose.runtime:runtime-retain:aar", + "androidx.compose.runtime:runtime-saveable-android:aar", + "androidx.compose.runtime:runtime-saveable-desktop", + "androidx.compose.runtime:runtime-saveable:aar", + "androidx.compose.runtime:runtime:aar", + "androidx.compose.ui:ui-android:aar", + "androidx.compose.ui:ui-geometry-android:aar", + "androidx.compose.ui:ui-geometry:aar", + "androidx.compose.ui:ui-graphics-android:aar", + "androidx.compose.ui:ui-graphics:aar", + "androidx.compose.ui:ui-test-android:aar", + "androidx.compose.ui:ui-test-junit4-android:aar", + "androidx.compose.ui:ui-test-junit4:aar", + "androidx.compose.ui:ui-test-manifest:aar", + "androidx.compose.ui:ui-test:aar", + "androidx.compose.ui:ui-text-android:aar", + "androidx.compose.ui:ui-text:aar", + "androidx.compose.ui:ui-tooling-preview-android:aar", + "androidx.compose.ui:ui-tooling-preview:aar", + "androidx.compose.ui:ui-unit-android:aar", + "androidx.compose.ui:ui-unit:aar", + "androidx.compose.ui:ui-util-android:aar", + "androidx.compose.ui:ui-util:aar", + "androidx.compose.ui:ui:aar", + "androidx.concurrent:concurrent-futures", + "androidx.concurrent:concurrent-futures-ktx", + "androidx.core:core-ktx:aar", + "androidx.core:core-remoteviews:aar", + "androidx.core:core-viewtree:aar", + "androidx.core:core:aar", + "androidx.cursoradapter:cursoradapter:aar", + "androidx.customview:customview-poolingcontainer:aar", + "androidx.customview:customview:aar", + "androidx.datastore:datastore-core", + "androidx.datastore:datastore-preferences-core", + "androidx.datastore:datastore-preferences:aar", + "androidx.datastore:datastore:aar", + "androidx.documentfile:documentfile:aar", + "androidx.drawerlayout:drawerlayout:aar", + "androidx.dynamicanimation:dynamicanimation:aar", + "androidx.emoji2:emoji2-views-helper:aar", + "androidx.emoji2:emoji2:aar", + "androidx.exifinterface:exifinterface:aar", + "androidx.fragment:fragment-ktx:aar", + "androidx.fragment:fragment:aar", + "androidx.glance:glance-appwidget-external-protobuf", + "androidx.glance:glance-appwidget-proto", + "androidx.glance:glance-appwidget-testing:aar", + "androidx.glance:glance-appwidget:aar", + "androidx.glance:glance-material3:aar", + "androidx.glance:glance-testing:aar", + "androidx.glance:glance:aar", + "androidx.graphics:graphics-path:aar", + "androidx.interpolator:interpolator:aar", + "androidx.legacy:legacy-support-core-utils:aar", + "androidx.lifecycle:lifecycle-common", + "androidx.lifecycle:lifecycle-common-java8", + "androidx.lifecycle:lifecycle-common-jvm", + "androidx.lifecycle:lifecycle-livedata-core-ktx:aar", + "androidx.lifecycle:lifecycle-livedata-core:aar", + "androidx.lifecycle:lifecycle-livedata:aar", + "androidx.lifecycle:lifecycle-process:aar", + "androidx.lifecycle:lifecycle-runtime-android:aar", + "androidx.lifecycle:lifecycle-runtime-compose-android:aar", + "androidx.lifecycle:lifecycle-runtime-compose-desktop", + "androidx.lifecycle:lifecycle-runtime-compose:aar", + "androidx.lifecycle:lifecycle-runtime-desktop", + "androidx.lifecycle:lifecycle-runtime-ktx-android:aar", + "androidx.lifecycle:lifecycle-runtime-ktx:aar", + "androidx.lifecycle:lifecycle-runtime:aar", + "androidx.lifecycle:lifecycle-service:aar", + "androidx.lifecycle:lifecycle-viewmodel-android:aar", + "androidx.lifecycle:lifecycle-viewmodel-compose-android:aar", + "androidx.lifecycle:lifecycle-viewmodel-compose:aar", + "androidx.lifecycle:lifecycle-viewmodel-desktop", + "androidx.lifecycle:lifecycle-viewmodel-ktx:aar", + "androidx.lifecycle:lifecycle-viewmodel-savedstate-android:aar", + "androidx.lifecycle:lifecycle-viewmodel-savedstate-desktop", + "androidx.lifecycle:lifecycle-viewmodel-savedstate:aar", + "androidx.lifecycle:lifecycle-viewmodel:aar", + "androidx.loader:loader:aar", + "androidx.localbroadcastmanager:localbroadcastmanager:aar", + "androidx.metrics:metrics-performance:aar", + "androidx.navigationevent:navigationevent-android:aar", + "androidx.navigationevent:navigationevent-desktop", + "androidx.navigationevent:navigationevent:aar", + "androidx.print:print:aar", + "androidx.profileinstaller:profileinstaller:aar", + "androidx.resourceinspection:resourceinspection-annotation", + "androidx.room:room-common", + "androidx.room:room-ktx:aar", + "androidx.room:room-runtime:aar", + "androidx.savedstate:savedstate-android:aar", + "androidx.savedstate:savedstate-compose-android:aar", + "androidx.savedstate:savedstate-compose-desktop", + "androidx.savedstate:savedstate-compose:aar", + "androidx.savedstate:savedstate-desktop", + "androidx.savedstate:savedstate-ktx:aar", + "androidx.savedstate:savedstate:aar", + "androidx.security:security-crypto:aar", + "androidx.sqlite:sqlite-android:aar", + "androidx.sqlite:sqlite-framework-android:aar", + "androidx.sqlite:sqlite-framework:aar", + "androidx.sqlite:sqlite:aar", + "androidx.startup:startup-runtime:aar", + "androidx.test.espresso:espresso-core:aar", + "androidx.test.espresso:espresso-idling-resource:aar", + "androidx.test.ext:junit:aar", + "androidx.test.services:storage:aar", + "androidx.test:core:aar", + "androidx.test:monitor:aar", + "androidx.test:rules:aar", + "androidx.test:runner:aar", + "androidx.tracing:tracing-android:aar", + "androidx.tracing:tracing-ktx:aar", + "androidx.tracing:tracing:aar", + "androidx.transition:transition:aar", + "androidx.vectordrawable:vectordrawable-animated:aar", + "androidx.vectordrawable:vectordrawable:aar", + "androidx.versionedparcelable:versionedparcelable:aar", + "androidx.viewpager:viewpager:aar", + "androidx.window:window-core", + "androidx.window:window-core-jvm", + "androidx.window:window:aar", + "androidx.work:work-runtime-ktx:aar", + "androidx.work:work-runtime:aar", + "app.cash.sqldelight:android-driver:aar", + "app.cash.sqldelight:async-extensions-jvm", + "app.cash.sqldelight:coroutines-extensions-jvm", + "app.cash.sqldelight:jdbc-driver", + "app.cash.sqldelight:runtime", + "app.cash.sqldelight:runtime-jvm", + "app.cash.sqldelight:sqlite-driver", + "co.touchlab:stately-concurrency-jvm", + "co.touchlab:stately-strict-jvm", + "com.almworks.sqlite4java:sqlite4java", + "com.android.tools:desugar_jdk_libs", + "com.android.tools:desugar_jdk_libs_configuration", + "com.benasher44:uuid-jvm", + "com.fleeksoft.charset:charset-jvm", + "com.fleeksoft.io:io-core-jvm", + "com.fleeksoft.ksoup:ksoup-jvm", + "com.github.mwiede:jsch", + "com.github.requery:sqlite-android:aar", + "com.google.android.datatransport:transport-api:aar", + "com.google.android.datatransport:transport-backend-cct:aar", + "com.google.android.datatransport:transport-runtime:aar", + "com.google.android.gms:play-services-base:aar", + "com.google.android.gms:play-services-basement:aar", + "com.google.android.gms:play-services-mlkit-text-recognition-common:aar", + "com.google.android.gms:play-services-mlkit-text-recognition:aar", + "com.google.android.gms:play-services-tasks:aar", + "com.google.android.odml:image:aar", + "com.google.ar:core:aar", + "com.google.auto.value:auto-value-annotations", + "com.google.code.findbugs:jsr305", + "com.google.code.gson:gson", + "com.google.crypto.tink:tink-android", + "com.google.errorprone:error_prone_annotation", + "com.google.errorprone:error_prone_annotations", + "com.google.firebase:firebase-annotations", + "com.google.firebase:firebase-components:aar", + "com.google.firebase:firebase-encoders", + "com.google.firebase:firebase-encoders-json:aar", + "com.google.guava:failureaccess", + "com.google.guava:guava", + "com.google.guava:listenablefuture", + "com.google.j2objc:j2objc-annotations", + "com.google.mlkit:common:aar", + "com.google.mlkit:genai-common:aar", + "com.google.mlkit:genai-prompt:aar", + "com.google.mlkit:image-labeling-common:aar", + "com.google.mlkit:image-labeling-default-common:aar", + "com.google.mlkit:image-labeling:aar", + "com.google.mlkit:text-recognition-bundled-common:aar", + "com.google.mlkit:text-recognition:aar", + "com.google.mlkit:vision-common:aar", + "com.google.mlkit:vision-interfaces:aar", + "com.google.mlkit:vision-internal-vkp:aar", + "com.google.testparameterinjector:test-parameter-injector", + "com.google.truth:truth", + "com.googlecode.java-diff-utils:diffutils", + "com.googlecode.javaewah:JavaEWAH", + "com.ibm.icu:icu4j", + "com.jcraft:jsch", + "com.jcraft:jzlib", + "com.juul.kable:core-android:aar", + "com.juul.kable:exceptions-jvm", + "com.juul.tuulbox:collections-jvm", + "com.juul.tuulbox:coroutines-android:aar", + "com.microsoft.onnxruntime:onnxruntime-android:aar", + "com.squareup.okhttp3:okhttp", + "com.squareup.okhttp3:okhttp-sse", + "com.squareup.okio:okio", + "com.squareup.okio:okio-jvm", + "com.tom-roush:pdfbox-android:aar", + "commons-codec:commons-codec", + "commons-logging:commons-logging", + "io.arrow-kt:arrow-annotations-jvm", + "io.arrow-kt:arrow-atomic-jvm", + "io.arrow-kt:arrow-autoclose-jvm", + "io.arrow-kt:arrow-core-jvm", + "io.arrow-kt:arrow-exception-utils-jvm", + "io.arrow-kt:arrow-fx-coroutines-jvm", + "io.arrow-kt:arrow-optics-jvm", + "io.arrow-kt:arrow-resilience-jvm", + "io.coil-kt.coil3:coil-compose-core-jvm", + "io.coil-kt.coil3:coil-compose-jvm", + "io.coil-kt.coil3:coil-core-jvm", + "io.coil-kt.coil3:coil-jvm", + "io.coil-kt.coil3:coil-network-core-jvm", + "io.coil-kt.coil3:coil-network-ktor3-jvm", + "io.github.petertrr:kotlin-multiplatform-diff-jvm", + "io.ktor:ktor-client-content-negotiation-jvm", + "io.ktor:ktor-client-core-jvm", + "io.ktor:ktor-client-mock-jvm", + "io.ktor:ktor-client-okhttp-jvm", + "io.ktor:ktor-events-jvm", + "io.ktor:ktor-http-cio-jvm", + "io.ktor:ktor-http-jvm", + "io.ktor:ktor-io-jvm", + "io.ktor:ktor-network-jvm", + "io.ktor:ktor-serialization-jvm", + "io.ktor:ktor-serialization-kotlinx-json-jvm", + "io.ktor:ktor-serialization-kotlinx-jvm", + "io.ktor:ktor-sse-jvm", + "io.ktor:ktor-utils-jvm", + "io.ktor:ktor-websocket-serialization-jvm", + "io.ktor:ktor-websockets-jvm", + "io.opentelemetry:opentelemetry-api", + "io.opentelemetry:opentelemetry-api-incubator", + "io.opentelemetry:opentelemetry-context", + "io.opentelemetry:opentelemetry-exporter-logging", + "io.opentelemetry:opentelemetry-sdk", + "io.opentelemetry:opentelemetry-sdk-common", + "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi", + "io.opentelemetry:opentelemetry-sdk-logs", + "io.opentelemetry:opentelemetry-sdk-metrics", + "io.opentelemetry:opentelemetry-sdk-trace", + "io.projectreactor.tools:blockhound", + "javax.annotation:javax.annotation-api", + "javax.inject:javax.inject", + "junit:junit", + "org.apache.pdfbox:fontbox", + "org.apache.pdfbox:pdfbox", + "org.apache.pdfbox:pdfbox-io", + "org.apache.sshd:sshd-osgi", + "org.apache.sshd:sshd-sftp", + "org.bouncycastle:bcpkix-jdk15to18", + "org.bouncycastle:bcprov-jdk15to18", + "org.bouncycastle:bcprov-jdk18on", + "org.bouncycastle:bcutil-jdk15to18", + "org.checkerframework:checker-compat-qual", + "org.checkerframework:checker-qual", + "org.conscrypt:conscrypt-openjdk-uber", + "org.eclipse.jgit:org.eclipse.jgit", + "org.eclipse.jgit:org.eclipse.jgit.ssh.apache", + "org.eclipse.jgit:org.eclipse.jgit.ssh.jsch", + "org.hamcrest:hamcrest-core", + "org.hamcrest:hamcrest-library", + "org.jetbrains.androidx.lifecycle:lifecycle-common", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose-desktop", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-savedstate", + "org.jetbrains.androidx.savedstate:savedstate", + "org.jetbrains.androidx.savedstate:savedstate-compose", + "org.jetbrains.androidx.savedstate:savedstate-compose-desktop", + "org.jetbrains.compose.animation:animation", + "org.jetbrains.compose.animation:animation-core", + "org.jetbrains.compose.animation:animation-core-desktop", + "org.jetbrains.compose.animation:animation-desktop", + "org.jetbrains.compose.annotation-internal:annotation", + "org.jetbrains.compose.collection-internal:collection", + "org.jetbrains.compose.components:components-resources-desktop", + "org.jetbrains.compose.desktop:desktop", + "org.jetbrains.compose.desktop:desktop-jvm-linux-x64:pom", + "org.jetbrains.compose.foundation:foundation", + "org.jetbrains.compose.foundation:foundation-desktop", + "org.jetbrains.compose.foundation:foundation-layout", + "org.jetbrains.compose.foundation:foundation-layout-desktop", + "org.jetbrains.compose.material3:material3-desktop", + "org.jetbrains.compose.material:material", + "org.jetbrains.compose.material:material-icons-core-desktop", + "org.jetbrains.compose.material:material-icons-extended-desktop", + "org.jetbrains.compose.material:material-ripple", + "org.jetbrains.compose.material:material-ripple-desktop", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.compose.runtime:runtime-saveable", + "org.jetbrains.compose.runtime:runtime-saveable-desktop", + "org.jetbrains.compose.ui:ui", + "org.jetbrains.compose.ui:ui-backhandler", + "org.jetbrains.compose.ui:ui-backhandler-desktop", + "org.jetbrains.compose.ui:ui-desktop", + "org.jetbrains.compose.ui:ui-geometry", + "org.jetbrains.compose.ui:ui-geometry-desktop", + "org.jetbrains.compose.ui:ui-graphics", + "org.jetbrains.compose.ui:ui-graphics-desktop", + "org.jetbrains.compose.ui:ui-test-desktop", + "org.jetbrains.compose.ui:ui-test-junit4-desktop", + "org.jetbrains.compose.ui:ui-text", + "org.jetbrains.compose.ui:ui-text-desktop", + "org.jetbrains.compose.ui:ui-tooling-preview", + "org.jetbrains.compose.ui:ui-uikit", + "org.jetbrains.compose.ui:ui-unit", + "org.jetbrains.compose.ui:ui-unit-desktop", + "org.jetbrains.compose.ui:ui-util", + "org.jetbrains.compose.ui:ui-util-desktop", + "org.jetbrains.kotlin:kotlin-android-extensions-runtime", + "org.jetbrains.kotlin:kotlin-compose-compiler-plugin-embeddable", + "org.jetbrains.kotlin:kotlin-parcelize-runtime", + "org.jetbrains.kotlin:kotlin-reflect", + "org.jetbrains.kotlin:kotlin-serialization-compiler-plugin-embeddable", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlin:kotlin-stdlib-common", + "org.jetbrains.kotlin:kotlin-stdlib-jdk7", + "org.jetbrains.kotlin:kotlin-stdlib-jdk8", + "org.jetbrains.kotlin:kotlin-test", + "org.jetbrains.kotlin:kotlin-test-junit", + "org.jetbrains.kotlinx:atomicfu", + "org.jetbrains.kotlinx:atomicfu-jvm", + "org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm", + "org.jetbrains.kotlinx:kotlinx-coroutines-android", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.jetbrains.kotlinx:kotlinx-coroutines-guava", + "org.jetbrains.kotlinx:kotlinx-coroutines-reactive", + "org.jetbrains.kotlinx:kotlinx-coroutines-slf4j", + "org.jetbrains.kotlinx:kotlinx-coroutines-swing", + "org.jetbrains.kotlinx:kotlinx-coroutines-test", + "org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm", + "org.jetbrains.kotlinx:kotlinx-datetime-jvm", + "org.jetbrains.kotlinx:kotlinx-io-bytestring-jvm", + "org.jetbrains.kotlinx:kotlinx-io-core-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-core", + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-json-io-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-json-jvm", + "org.jetbrains.runtime:jbr-api", + "org.jetbrains.skiko:skiko", + "org.jetbrains.skiko:skiko-awt", + "org.jetbrains.skiko:skiko-awt-runtime-linux-x64", + "org.jetbrains.skiko:skiko-awt-runtime-macos-arm64", + "org.jetbrains.skiko:skiko-awt-runtime-macos-x64", + "org.jetbrains.skiko:skiko-awt-runtime-windows-x64", + "org.jetbrains:annotations", + "org.jetbrains:markdown-jvm", + "org.jspecify:jspecify", + "org.mockito:mockito-core", + "org.objenesis:objenesis", + "org.ow2.asm:asm", + "org.ow2.asm:asm-commons", + "org.ow2.asm:asm-tree", + "org.reactivestreams:reactive-streams", + "org.robolectric:annotations", + "org.robolectric:junit", + "org.robolectric:nativeruntime", + "org.robolectric:nativeruntime-dist-compat", + "org.robolectric:pluginapi", + "org.robolectric:plugins-maven-dependency-resolver", + "org.robolectric:resources", + "org.robolectric:robolectric", + "org.robolectric:sandbox", + "org.robolectric:shadowapi", + "org.robolectric:shadows-framework", + "org.robolectric:utils", + "org.robolectric:utils-reflector", + "org.slf4j:jcl-over-slf4j", + "org.slf4j:slf4j-api", + "org.xerial:sqlite-jdbc", + "org.yaml:snakeyaml" + ], + "https://maven.pkg.jetbrains.space/public/p/compose/dev/": [ + "androidx.activity:activity-compose:aar", + "androidx.activity:activity-ktx:aar", + "androidx.activity:activity:aar", + "androidx.annotation:annotation", + "androidx.annotation:annotation-experimental:aar", + "androidx.annotation:annotation-jvm", + "androidx.appcompat:appcompat-resources:aar", + "androidx.appcompat:appcompat:aar", + "androidx.arch.core:core-common", + "androidx.arch.core:core-runtime:aar", + "androidx.arch.core:core-testing:aar", + "androidx.autofill:autofill:aar", + "androidx.camera:camera-camera2:aar", + "androidx.camera:camera-core:aar", + "androidx.camera:camera-lifecycle:aar", + "androidx.collection:collection", + "androidx.collection:collection-jvm", + "androidx.collection:collection-ktx", + "androidx.compose.animation:animation-android:aar", + "androidx.compose.animation:animation-core-android:aar", + "androidx.compose.animation:animation-core:aar", + "androidx.compose.animation:animation:aar", + "androidx.compose.foundation:foundation-android:aar", + "androidx.compose.foundation:foundation-layout-android:aar", + "androidx.compose.foundation:foundation-layout:aar", + "androidx.compose.foundation:foundation:aar", + "androidx.compose.material3:material3-android:aar", + "androidx.compose.material3:material3:aar", + "androidx.compose.material:material-android:aar", + "androidx.compose.material:material-icons-core-android:aar", + "androidx.compose.material:material-icons-core:aar", + "androidx.compose.material:material-icons-extended-android:aar", + "androidx.compose.material:material-icons-extended:aar", + "androidx.compose.material:material-ripple-android:aar", + "androidx.compose.material:material-ripple:aar", + "androidx.compose.material:material:aar", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.runtime:runtime-annotation", + "androidx.compose.runtime:runtime-annotation-android:aar", + "androidx.compose.runtime:runtime-annotation-jvm", + "androidx.compose.runtime:runtime-desktop", + "androidx.compose.runtime:runtime-retain-android:aar", + "androidx.compose.runtime:runtime-retain-desktop", + "androidx.compose.runtime:runtime-retain:aar", + "androidx.compose.runtime:runtime-saveable-android:aar", + "androidx.compose.runtime:runtime-saveable-desktop", + "androidx.compose.runtime:runtime-saveable:aar", + "androidx.compose.runtime:runtime:aar", + "androidx.compose.ui:ui-android:aar", + "androidx.compose.ui:ui-geometry-android:aar", + "androidx.compose.ui:ui-geometry:aar", + "androidx.compose.ui:ui-graphics-android:aar", + "androidx.compose.ui:ui-graphics:aar", + "androidx.compose.ui:ui-test-android:aar", + "androidx.compose.ui:ui-test-junit4-android:aar", + "androidx.compose.ui:ui-test-junit4:aar", + "androidx.compose.ui:ui-test-manifest:aar", + "androidx.compose.ui:ui-test:aar", + "androidx.compose.ui:ui-text-android:aar", + "androidx.compose.ui:ui-text:aar", + "androidx.compose.ui:ui-tooling-preview-android:aar", + "androidx.compose.ui:ui-tooling-preview:aar", + "androidx.compose.ui:ui-unit-android:aar", + "androidx.compose.ui:ui-unit:aar", + "androidx.compose.ui:ui-util-android:aar", + "androidx.compose.ui:ui-util:aar", + "androidx.compose.ui:ui:aar", + "androidx.concurrent:concurrent-futures", + "androidx.concurrent:concurrent-futures-ktx", + "androidx.core:core-ktx:aar", + "androidx.core:core-remoteviews:aar", + "androidx.core:core-viewtree:aar", + "androidx.core:core:aar", + "androidx.cursoradapter:cursoradapter:aar", + "androidx.customview:customview-poolingcontainer:aar", + "androidx.customview:customview:aar", + "androidx.datastore:datastore-core", + "androidx.datastore:datastore-preferences-core", + "androidx.datastore:datastore-preferences:aar", + "androidx.datastore:datastore:aar", + "androidx.documentfile:documentfile:aar", + "androidx.drawerlayout:drawerlayout:aar", + "androidx.dynamicanimation:dynamicanimation:aar", + "androidx.emoji2:emoji2-views-helper:aar", + "androidx.emoji2:emoji2:aar", + "androidx.exifinterface:exifinterface:aar", + "androidx.fragment:fragment-ktx:aar", + "androidx.fragment:fragment:aar", + "androidx.glance:glance-appwidget-external-protobuf", + "androidx.glance:glance-appwidget-proto", + "androidx.glance:glance-appwidget-testing:aar", + "androidx.glance:glance-appwidget:aar", + "androidx.glance:glance-material3:aar", + "androidx.glance:glance-testing:aar", + "androidx.glance:glance:aar", + "androidx.graphics:graphics-path:aar", + "androidx.interpolator:interpolator:aar", + "androidx.legacy:legacy-support-core-utils:aar", + "androidx.lifecycle:lifecycle-common", + "androidx.lifecycle:lifecycle-common-java8", + "androidx.lifecycle:lifecycle-common-jvm", + "androidx.lifecycle:lifecycle-livedata-core-ktx:aar", + "androidx.lifecycle:lifecycle-livedata-core:aar", + "androidx.lifecycle:lifecycle-livedata:aar", + "androidx.lifecycle:lifecycle-process:aar", + "androidx.lifecycle:lifecycle-runtime-android:aar", + "androidx.lifecycle:lifecycle-runtime-compose-android:aar", + "androidx.lifecycle:lifecycle-runtime-compose-desktop", + "androidx.lifecycle:lifecycle-runtime-compose:aar", + "androidx.lifecycle:lifecycle-runtime-desktop", + "androidx.lifecycle:lifecycle-runtime-ktx-android:aar", + "androidx.lifecycle:lifecycle-runtime-ktx:aar", + "androidx.lifecycle:lifecycle-runtime:aar", + "androidx.lifecycle:lifecycle-service:aar", + "androidx.lifecycle:lifecycle-viewmodel-android:aar", + "androidx.lifecycle:lifecycle-viewmodel-compose-android:aar", + "androidx.lifecycle:lifecycle-viewmodel-compose:aar", + "androidx.lifecycle:lifecycle-viewmodel-desktop", + "androidx.lifecycle:lifecycle-viewmodel-ktx:aar", + "androidx.lifecycle:lifecycle-viewmodel-savedstate-android:aar", + "androidx.lifecycle:lifecycle-viewmodel-savedstate-desktop", + "androidx.lifecycle:lifecycle-viewmodel-savedstate:aar", + "androidx.lifecycle:lifecycle-viewmodel:aar", + "androidx.loader:loader:aar", + "androidx.localbroadcastmanager:localbroadcastmanager:aar", + "androidx.metrics:metrics-performance:aar", + "androidx.navigationevent:navigationevent-android:aar", + "androidx.navigationevent:navigationevent-desktop", + "androidx.navigationevent:navigationevent:aar", + "androidx.print:print:aar", + "androidx.profileinstaller:profileinstaller:aar", + "androidx.resourceinspection:resourceinspection-annotation", + "androidx.room:room-common", + "androidx.room:room-ktx:aar", + "androidx.room:room-runtime:aar", + "androidx.savedstate:savedstate-android:aar", + "androidx.savedstate:savedstate-compose-android:aar", + "androidx.savedstate:savedstate-compose-desktop", + "androidx.savedstate:savedstate-compose:aar", + "androidx.savedstate:savedstate-desktop", + "androidx.savedstate:savedstate-ktx:aar", + "androidx.savedstate:savedstate:aar", + "androidx.security:security-crypto:aar", + "androidx.sqlite:sqlite-android:aar", + "androidx.sqlite:sqlite-framework-android:aar", + "androidx.sqlite:sqlite-framework:aar", + "androidx.sqlite:sqlite:aar", + "androidx.startup:startup-runtime:aar", + "androidx.test.espresso:espresso-core:aar", + "androidx.test.espresso:espresso-idling-resource:aar", + "androidx.test.ext:junit:aar", + "androidx.test.services:storage:aar", + "androidx.test:core:aar", + "androidx.test:monitor:aar", + "androidx.test:rules:aar", + "androidx.test:runner:aar", + "androidx.tracing:tracing-android:aar", + "androidx.tracing:tracing-ktx:aar", + "androidx.tracing:tracing:aar", + "androidx.transition:transition:aar", + "androidx.vectordrawable:vectordrawable-animated:aar", + "androidx.vectordrawable:vectordrawable:aar", + "androidx.versionedparcelable:versionedparcelable:aar", + "androidx.viewpager:viewpager:aar", + "androidx.window:window-core", + "androidx.window:window-core-jvm", + "androidx.window:window:aar", + "androidx.work:work-runtime-ktx:aar", + "androidx.work:work-runtime:aar", + "app.cash.sqldelight:android-driver:aar", + "app.cash.sqldelight:async-extensions-jvm", + "app.cash.sqldelight:coroutines-extensions-jvm", + "app.cash.sqldelight:jdbc-driver", + "app.cash.sqldelight:runtime", + "app.cash.sqldelight:runtime-jvm", + "app.cash.sqldelight:sqlite-driver", + "co.touchlab:stately-concurrency-jvm", + "co.touchlab:stately-strict-jvm", + "com.almworks.sqlite4java:sqlite4java", + "com.android.tools:desugar_jdk_libs", + "com.android.tools:desugar_jdk_libs_configuration", + "com.benasher44:uuid-jvm", + "com.fleeksoft.charset:charset-jvm", + "com.fleeksoft.io:io-core-jvm", + "com.fleeksoft.ksoup:ksoup-jvm", + "com.github.mwiede:jsch", + "com.github.requery:sqlite-android:aar", + "com.google.android.datatransport:transport-api:aar", + "com.google.android.datatransport:transport-backend-cct:aar", + "com.google.android.datatransport:transport-runtime:aar", + "com.google.android.gms:play-services-base:aar", + "com.google.android.gms:play-services-basement:aar", + "com.google.android.gms:play-services-mlkit-text-recognition-common:aar", + "com.google.android.gms:play-services-mlkit-text-recognition:aar", + "com.google.android.gms:play-services-tasks:aar", + "com.google.android.odml:image:aar", + "com.google.ar:core:aar", + "com.google.auto.value:auto-value-annotations", + "com.google.code.findbugs:jsr305", + "com.google.code.gson:gson", + "com.google.crypto.tink:tink-android", + "com.google.errorprone:error_prone_annotation", + "com.google.errorprone:error_prone_annotations", + "com.google.firebase:firebase-annotations", + "com.google.firebase:firebase-components:aar", + "com.google.firebase:firebase-encoders", + "com.google.firebase:firebase-encoders-json:aar", + "com.google.guava:failureaccess", + "com.google.guava:guava", + "com.google.guava:listenablefuture", + "com.google.j2objc:j2objc-annotations", + "com.google.mlkit:common:aar", + "com.google.mlkit:genai-common:aar", + "com.google.mlkit:genai-prompt:aar", + "com.google.mlkit:image-labeling-common:aar", + "com.google.mlkit:image-labeling-default-common:aar", + "com.google.mlkit:image-labeling:aar", + "com.google.mlkit:text-recognition-bundled-common:aar", + "com.google.mlkit:text-recognition:aar", + "com.google.mlkit:vision-common:aar", + "com.google.mlkit:vision-interfaces:aar", + "com.google.mlkit:vision-internal-vkp:aar", + "com.google.testparameterinjector:test-parameter-injector", + "com.google.truth:truth", + "com.googlecode.java-diff-utils:diffutils", + "com.googlecode.javaewah:JavaEWAH", + "com.ibm.icu:icu4j", + "com.jcraft:jsch", + "com.jcraft:jzlib", + "com.juul.kable:core-android:aar", + "com.juul.kable:exceptions-jvm", + "com.juul.tuulbox:collections-jvm", + "com.juul.tuulbox:coroutines-android:aar", + "com.microsoft.onnxruntime:onnxruntime-android:aar", + "com.squareup.okhttp3:okhttp", + "com.squareup.okhttp3:okhttp-sse", + "com.squareup.okio:okio", + "com.squareup.okio:okio-jvm", + "com.tom-roush:pdfbox-android:aar", + "commons-codec:commons-codec", + "commons-logging:commons-logging", + "io.arrow-kt:arrow-annotations-jvm", + "io.arrow-kt:arrow-atomic-jvm", + "io.arrow-kt:arrow-autoclose-jvm", + "io.arrow-kt:arrow-core-jvm", + "io.arrow-kt:arrow-exception-utils-jvm", + "io.arrow-kt:arrow-fx-coroutines-jvm", + "io.arrow-kt:arrow-optics-jvm", + "io.arrow-kt:arrow-resilience-jvm", + "io.coil-kt.coil3:coil-compose-core-jvm", + "io.coil-kt.coil3:coil-compose-jvm", + "io.coil-kt.coil3:coil-core-jvm", + "io.coil-kt.coil3:coil-jvm", + "io.coil-kt.coil3:coil-network-core-jvm", + "io.coil-kt.coil3:coil-network-ktor3-jvm", + "io.github.petertrr:kotlin-multiplatform-diff-jvm", + "io.ktor:ktor-client-content-negotiation-jvm", + "io.ktor:ktor-client-core-jvm", + "io.ktor:ktor-client-mock-jvm", + "io.ktor:ktor-client-okhttp-jvm", + "io.ktor:ktor-events-jvm", + "io.ktor:ktor-http-cio-jvm", + "io.ktor:ktor-http-jvm", + "io.ktor:ktor-io-jvm", + "io.ktor:ktor-network-jvm", + "io.ktor:ktor-serialization-jvm", + "io.ktor:ktor-serialization-kotlinx-json-jvm", + "io.ktor:ktor-serialization-kotlinx-jvm", + "io.ktor:ktor-sse-jvm", + "io.ktor:ktor-utils-jvm", + "io.ktor:ktor-websocket-serialization-jvm", + "io.ktor:ktor-websockets-jvm", + "io.opentelemetry:opentelemetry-api", + "io.opentelemetry:opentelemetry-api-incubator", + "io.opentelemetry:opentelemetry-context", + "io.opentelemetry:opentelemetry-exporter-logging", + "io.opentelemetry:opentelemetry-sdk", + "io.opentelemetry:opentelemetry-sdk-common", + "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi", + "io.opentelemetry:opentelemetry-sdk-logs", + "io.opentelemetry:opentelemetry-sdk-metrics", + "io.opentelemetry:opentelemetry-sdk-trace", + "io.projectreactor.tools:blockhound", + "javax.annotation:javax.annotation-api", + "javax.inject:javax.inject", + "junit:junit", + "org.apache.pdfbox:fontbox", + "org.apache.pdfbox:pdfbox", + "org.apache.pdfbox:pdfbox-io", + "org.apache.sshd:sshd-osgi", + "org.apache.sshd:sshd-sftp", + "org.bouncycastle:bcpkix-jdk15to18", + "org.bouncycastle:bcprov-jdk15to18", + "org.bouncycastle:bcprov-jdk18on", + "org.bouncycastle:bcutil-jdk15to18", + "org.checkerframework:checker-compat-qual", + "org.checkerframework:checker-qual", + "org.conscrypt:conscrypt-openjdk-uber", + "org.eclipse.jgit:org.eclipse.jgit", + "org.eclipse.jgit:org.eclipse.jgit.ssh.apache", + "org.eclipse.jgit:org.eclipse.jgit.ssh.jsch", + "org.hamcrest:hamcrest-core", + "org.hamcrest:hamcrest-library", + "org.jetbrains.androidx.lifecycle:lifecycle-common", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose-desktop", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-savedstate", + "org.jetbrains.androidx.savedstate:savedstate", + "org.jetbrains.androidx.savedstate:savedstate-compose", + "org.jetbrains.androidx.savedstate:savedstate-compose-desktop", + "org.jetbrains.compose.animation:animation", + "org.jetbrains.compose.animation:animation-core", + "org.jetbrains.compose.animation:animation-core-desktop", + "org.jetbrains.compose.animation:animation-desktop", + "org.jetbrains.compose.annotation-internal:annotation", + "org.jetbrains.compose.collection-internal:collection", + "org.jetbrains.compose.components:components-resources-desktop", + "org.jetbrains.compose.desktop:desktop", + "org.jetbrains.compose.desktop:desktop-jvm-linux-x64:pom", + "org.jetbrains.compose.foundation:foundation", + "org.jetbrains.compose.foundation:foundation-desktop", + "org.jetbrains.compose.foundation:foundation-layout", + "org.jetbrains.compose.foundation:foundation-layout-desktop", + "org.jetbrains.compose.material3:material3-desktop", + "org.jetbrains.compose.material:material", + "org.jetbrains.compose.material:material-icons-core-desktop", + "org.jetbrains.compose.material:material-icons-extended-desktop", + "org.jetbrains.compose.material:material-ripple", + "org.jetbrains.compose.material:material-ripple-desktop", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.compose.runtime:runtime-saveable", + "org.jetbrains.compose.runtime:runtime-saveable-desktop", + "org.jetbrains.compose.ui:ui", + "org.jetbrains.compose.ui:ui-backhandler", + "org.jetbrains.compose.ui:ui-backhandler-desktop", + "org.jetbrains.compose.ui:ui-desktop", + "org.jetbrains.compose.ui:ui-geometry", + "org.jetbrains.compose.ui:ui-geometry-desktop", + "org.jetbrains.compose.ui:ui-graphics", + "org.jetbrains.compose.ui:ui-graphics-desktop", + "org.jetbrains.compose.ui:ui-test-desktop", + "org.jetbrains.compose.ui:ui-test-junit4-desktop", + "org.jetbrains.compose.ui:ui-text", + "org.jetbrains.compose.ui:ui-text-desktop", + "org.jetbrains.compose.ui:ui-tooling-preview", + "org.jetbrains.compose.ui:ui-uikit", + "org.jetbrains.compose.ui:ui-unit", + "org.jetbrains.compose.ui:ui-unit-desktop", + "org.jetbrains.compose.ui:ui-util", + "org.jetbrains.compose.ui:ui-util-desktop", + "org.jetbrains.kotlin:kotlin-android-extensions-runtime", + "org.jetbrains.kotlin:kotlin-compose-compiler-plugin-embeddable", + "org.jetbrains.kotlin:kotlin-parcelize-runtime", + "org.jetbrains.kotlin:kotlin-reflect", + "org.jetbrains.kotlin:kotlin-serialization-compiler-plugin-embeddable", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlin:kotlin-stdlib-common", + "org.jetbrains.kotlin:kotlin-stdlib-jdk7", + "org.jetbrains.kotlin:kotlin-stdlib-jdk8", + "org.jetbrains.kotlin:kotlin-test", + "org.jetbrains.kotlin:kotlin-test-junit", + "org.jetbrains.kotlinx:atomicfu", + "org.jetbrains.kotlinx:atomicfu-jvm", + "org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm", + "org.jetbrains.kotlinx:kotlinx-coroutines-android", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.jetbrains.kotlinx:kotlinx-coroutines-guava", + "org.jetbrains.kotlinx:kotlinx-coroutines-reactive", + "org.jetbrains.kotlinx:kotlinx-coroutines-slf4j", + "org.jetbrains.kotlinx:kotlinx-coroutines-swing", + "org.jetbrains.kotlinx:kotlinx-coroutines-test", + "org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm", + "org.jetbrains.kotlinx:kotlinx-datetime-jvm", + "org.jetbrains.kotlinx:kotlinx-io-bytestring-jvm", + "org.jetbrains.kotlinx:kotlinx-io-core-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-core", + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-json-io-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-json-jvm", + "org.jetbrains.runtime:jbr-api", + "org.jetbrains.skiko:skiko", + "org.jetbrains.skiko:skiko-awt", + "org.jetbrains.skiko:skiko-awt-runtime-linux-x64", + "org.jetbrains.skiko:skiko-awt-runtime-macos-arm64", + "org.jetbrains.skiko:skiko-awt-runtime-macos-x64", + "org.jetbrains.skiko:skiko-awt-runtime-windows-x64", + "org.jetbrains:annotations", + "org.jetbrains:markdown-jvm", + "org.jspecify:jspecify", + "org.mockito:mockito-core", + "org.objenesis:objenesis", + "org.ow2.asm:asm", + "org.ow2.asm:asm-commons", + "org.ow2.asm:asm-tree", + "org.reactivestreams:reactive-streams", + "org.robolectric:annotations", + "org.robolectric:junit", + "org.robolectric:nativeruntime", + "org.robolectric:nativeruntime-dist-compat", + "org.robolectric:pluginapi", + "org.robolectric:plugins-maven-dependency-resolver", + "org.robolectric:resources", + "org.robolectric:robolectric", + "org.robolectric:sandbox", + "org.robolectric:shadowapi", + "org.robolectric:shadows-framework", + "org.robolectric:utils", + "org.robolectric:utils-reflector", + "org.slf4j:jcl-over-slf4j", + "org.slf4j:slf4j-api", + "org.xerial:sqlite-jdbc", + "org.yaml:snakeyaml" + ], + "https://oss.sonatype.org/content/repositories/snapshots/": [ + "androidx.activity:activity-compose:aar", + "androidx.activity:activity-ktx:aar", + "androidx.activity:activity:aar", + "androidx.annotation:annotation", + "androidx.annotation:annotation-experimental:aar", + "androidx.annotation:annotation-jvm", + "androidx.appcompat:appcompat-resources:aar", + "androidx.appcompat:appcompat:aar", + "androidx.arch.core:core-common", + "androidx.arch.core:core-runtime:aar", + "androidx.arch.core:core-testing:aar", + "androidx.autofill:autofill:aar", + "androidx.camera:camera-camera2:aar", + "androidx.camera:camera-core:aar", + "androidx.camera:camera-lifecycle:aar", + "androidx.collection:collection", + "androidx.collection:collection-jvm", + "androidx.collection:collection-ktx", + "androidx.compose.animation:animation-android:aar", + "androidx.compose.animation:animation-core-android:aar", + "androidx.compose.animation:animation-core:aar", + "androidx.compose.animation:animation:aar", + "androidx.compose.foundation:foundation-android:aar", + "androidx.compose.foundation:foundation-layout-android:aar", + "androidx.compose.foundation:foundation-layout:aar", + "androidx.compose.foundation:foundation:aar", + "androidx.compose.material3:material3-android:aar", + "androidx.compose.material3:material3:aar", + "androidx.compose.material:material-android:aar", + "androidx.compose.material:material-icons-core-android:aar", + "androidx.compose.material:material-icons-core:aar", + "androidx.compose.material:material-icons-extended-android:aar", + "androidx.compose.material:material-icons-extended:aar", + "androidx.compose.material:material-ripple-android:aar", + "androidx.compose.material:material-ripple:aar", + "androidx.compose.material:material:aar", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.runtime:runtime-annotation", + "androidx.compose.runtime:runtime-annotation-android:aar", + "androidx.compose.runtime:runtime-annotation-jvm", + "androidx.compose.runtime:runtime-desktop", + "androidx.compose.runtime:runtime-retain-android:aar", + "androidx.compose.runtime:runtime-retain-desktop", + "androidx.compose.runtime:runtime-retain:aar", + "androidx.compose.runtime:runtime-saveable-android:aar", + "androidx.compose.runtime:runtime-saveable-desktop", + "androidx.compose.runtime:runtime-saveable:aar", + "androidx.compose.runtime:runtime:aar", + "androidx.compose.ui:ui-android:aar", + "androidx.compose.ui:ui-geometry-android:aar", + "androidx.compose.ui:ui-geometry:aar", + "androidx.compose.ui:ui-graphics-android:aar", + "androidx.compose.ui:ui-graphics:aar", + "androidx.compose.ui:ui-test-android:aar", + "androidx.compose.ui:ui-test-junit4-android:aar", + "androidx.compose.ui:ui-test-junit4:aar", + "androidx.compose.ui:ui-test-manifest:aar", + "androidx.compose.ui:ui-test:aar", + "androidx.compose.ui:ui-text-android:aar", + "androidx.compose.ui:ui-text:aar", + "androidx.compose.ui:ui-tooling-preview-android:aar", + "androidx.compose.ui:ui-tooling-preview:aar", + "androidx.compose.ui:ui-unit-android:aar", + "androidx.compose.ui:ui-unit:aar", + "androidx.compose.ui:ui-util-android:aar", + "androidx.compose.ui:ui-util:aar", + "androidx.compose.ui:ui:aar", + "androidx.concurrent:concurrent-futures", + "androidx.concurrent:concurrent-futures-ktx", + "androidx.core:core-ktx:aar", + "androidx.core:core-remoteviews:aar", + "androidx.core:core-viewtree:aar", + "androidx.core:core:aar", + "androidx.cursoradapter:cursoradapter:aar", + "androidx.customview:customview-poolingcontainer:aar", + "androidx.customview:customview:aar", + "androidx.datastore:datastore-core", + "androidx.datastore:datastore-preferences-core", + "androidx.datastore:datastore-preferences:aar", + "androidx.datastore:datastore:aar", + "androidx.documentfile:documentfile:aar", + "androidx.drawerlayout:drawerlayout:aar", + "androidx.dynamicanimation:dynamicanimation:aar", + "androidx.emoji2:emoji2-views-helper:aar", + "androidx.emoji2:emoji2:aar", + "androidx.exifinterface:exifinterface:aar", + "androidx.fragment:fragment-ktx:aar", + "androidx.fragment:fragment:aar", + "androidx.glance:glance-appwidget-external-protobuf", + "androidx.glance:glance-appwidget-proto", + "androidx.glance:glance-appwidget-testing:aar", + "androidx.glance:glance-appwidget:aar", + "androidx.glance:glance-material3:aar", + "androidx.glance:glance-testing:aar", + "androidx.glance:glance:aar", + "androidx.graphics:graphics-path:aar", + "androidx.interpolator:interpolator:aar", + "androidx.legacy:legacy-support-core-utils:aar", + "androidx.lifecycle:lifecycle-common", + "androidx.lifecycle:lifecycle-common-java8", + "androidx.lifecycle:lifecycle-common-jvm", + "androidx.lifecycle:lifecycle-livedata-core-ktx:aar", + "androidx.lifecycle:lifecycle-livedata-core:aar", + "androidx.lifecycle:lifecycle-livedata:aar", + "androidx.lifecycle:lifecycle-process:aar", + "androidx.lifecycle:lifecycle-runtime-android:aar", + "androidx.lifecycle:lifecycle-runtime-compose-android:aar", + "androidx.lifecycle:lifecycle-runtime-compose-desktop", + "androidx.lifecycle:lifecycle-runtime-compose:aar", + "androidx.lifecycle:lifecycle-runtime-desktop", + "androidx.lifecycle:lifecycle-runtime-ktx-android:aar", + "androidx.lifecycle:lifecycle-runtime-ktx:aar", + "androidx.lifecycle:lifecycle-runtime:aar", + "androidx.lifecycle:lifecycle-service:aar", + "androidx.lifecycle:lifecycle-viewmodel-android:aar", + "androidx.lifecycle:lifecycle-viewmodel-compose-android:aar", + "androidx.lifecycle:lifecycle-viewmodel-compose:aar", + "androidx.lifecycle:lifecycle-viewmodel-desktop", + "androidx.lifecycle:lifecycle-viewmodel-ktx:aar", + "androidx.lifecycle:lifecycle-viewmodel-savedstate-android:aar", + "androidx.lifecycle:lifecycle-viewmodel-savedstate-desktop", + "androidx.lifecycle:lifecycle-viewmodel-savedstate:aar", + "androidx.lifecycle:lifecycle-viewmodel:aar", + "androidx.loader:loader:aar", + "androidx.localbroadcastmanager:localbroadcastmanager:aar", + "androidx.metrics:metrics-performance:aar", + "androidx.navigationevent:navigationevent-android:aar", + "androidx.navigationevent:navigationevent-desktop", + "androidx.navigationevent:navigationevent:aar", + "androidx.print:print:aar", + "androidx.profileinstaller:profileinstaller:aar", + "androidx.resourceinspection:resourceinspection-annotation", + "androidx.room:room-common", + "androidx.room:room-ktx:aar", + "androidx.room:room-runtime:aar", + "androidx.savedstate:savedstate-android:aar", + "androidx.savedstate:savedstate-compose-android:aar", + "androidx.savedstate:savedstate-compose-desktop", + "androidx.savedstate:savedstate-compose:aar", + "androidx.savedstate:savedstate-desktop", + "androidx.savedstate:savedstate-ktx:aar", + "androidx.savedstate:savedstate:aar", + "androidx.security:security-crypto:aar", + "androidx.sqlite:sqlite-android:aar", + "androidx.sqlite:sqlite-framework-android:aar", + "androidx.sqlite:sqlite-framework:aar", + "androidx.sqlite:sqlite:aar", + "androidx.startup:startup-runtime:aar", + "androidx.test.espresso:espresso-core:aar", + "androidx.test.espresso:espresso-idling-resource:aar", + "androidx.test.ext:junit:aar", + "androidx.test.services:storage:aar", + "androidx.test:core:aar", + "androidx.test:monitor:aar", + "androidx.test:rules:aar", + "androidx.test:runner:aar", + "androidx.tracing:tracing-android:aar", + "androidx.tracing:tracing-ktx:aar", + "androidx.tracing:tracing:aar", + "androidx.transition:transition:aar", + "androidx.vectordrawable:vectordrawable-animated:aar", + "androidx.vectordrawable:vectordrawable:aar", + "androidx.versionedparcelable:versionedparcelable:aar", + "androidx.viewpager:viewpager:aar", + "androidx.window:window-core", + "androidx.window:window-core-jvm", + "androidx.window:window:aar", + "androidx.work:work-runtime-ktx:aar", + "androidx.work:work-runtime:aar", + "app.cash.sqldelight:android-driver:aar", + "app.cash.sqldelight:async-extensions-jvm", + "app.cash.sqldelight:coroutines-extensions-jvm", + "app.cash.sqldelight:jdbc-driver", + "app.cash.sqldelight:runtime", + "app.cash.sqldelight:runtime-jvm", + "app.cash.sqldelight:sqlite-driver", + "co.touchlab:stately-concurrency-jvm", + "co.touchlab:stately-strict-jvm", + "com.almworks.sqlite4java:sqlite4java", + "com.android.tools:desugar_jdk_libs", + "com.android.tools:desugar_jdk_libs_configuration", + "com.benasher44:uuid-jvm", + "com.fleeksoft.charset:charset-jvm", + "com.fleeksoft.io:io-core-jvm", + "com.fleeksoft.ksoup:ksoup-jvm", + "com.github.mwiede:jsch", + "com.github.requery:sqlite-android:aar", + "com.google.android.datatransport:transport-api:aar", + "com.google.android.datatransport:transport-backend-cct:aar", + "com.google.android.datatransport:transport-runtime:aar", + "com.google.android.gms:play-services-base:aar", + "com.google.android.gms:play-services-basement:aar", + "com.google.android.gms:play-services-mlkit-text-recognition-common:aar", + "com.google.android.gms:play-services-mlkit-text-recognition:aar", + "com.google.android.gms:play-services-tasks:aar", + "com.google.android.odml:image:aar", + "com.google.ar:core:aar", + "com.google.auto.value:auto-value-annotations", + "com.google.code.findbugs:jsr305", + "com.google.code.gson:gson", + "com.google.crypto.tink:tink-android", + "com.google.errorprone:error_prone_annotation", + "com.google.errorprone:error_prone_annotations", + "com.google.firebase:firebase-annotations", + "com.google.firebase:firebase-components:aar", + "com.google.firebase:firebase-encoders", + "com.google.firebase:firebase-encoders-json:aar", + "com.google.guava:failureaccess", + "com.google.guava:guava", + "com.google.guava:listenablefuture", + "com.google.j2objc:j2objc-annotations", + "com.google.mlkit:common:aar", + "com.google.mlkit:genai-common:aar", + "com.google.mlkit:genai-prompt:aar", + "com.google.mlkit:image-labeling-common:aar", + "com.google.mlkit:image-labeling-default-common:aar", + "com.google.mlkit:image-labeling:aar", + "com.google.mlkit:text-recognition-bundled-common:aar", + "com.google.mlkit:text-recognition:aar", + "com.google.mlkit:vision-common:aar", + "com.google.mlkit:vision-interfaces:aar", + "com.google.mlkit:vision-internal-vkp:aar", + "com.google.testparameterinjector:test-parameter-injector", + "com.google.truth:truth", + "com.googlecode.java-diff-utils:diffutils", + "com.googlecode.javaewah:JavaEWAH", + "com.ibm.icu:icu4j", + "com.jcraft:jsch", + "com.jcraft:jzlib", + "com.juul.kable:core-android:aar", + "com.juul.kable:exceptions-jvm", + "com.juul.tuulbox:collections-jvm", + "com.juul.tuulbox:coroutines-android:aar", + "com.microsoft.onnxruntime:onnxruntime-android:aar", + "com.squareup.okhttp3:okhttp", + "com.squareup.okhttp3:okhttp-sse", + "com.squareup.okio:okio", + "com.squareup.okio:okio-jvm", + "com.tom-roush:pdfbox-android:aar", + "commons-codec:commons-codec", + "commons-logging:commons-logging", + "io.arrow-kt:arrow-annotations-jvm", + "io.arrow-kt:arrow-atomic-jvm", + "io.arrow-kt:arrow-autoclose-jvm", + "io.arrow-kt:arrow-core-jvm", + "io.arrow-kt:arrow-exception-utils-jvm", + "io.arrow-kt:arrow-fx-coroutines-jvm", + "io.arrow-kt:arrow-optics-jvm", + "io.arrow-kt:arrow-resilience-jvm", + "io.coil-kt.coil3:coil-compose-core-jvm", + "io.coil-kt.coil3:coil-compose-jvm", + "io.coil-kt.coil3:coil-core-jvm", + "io.coil-kt.coil3:coil-jvm", + "io.coil-kt.coil3:coil-network-core-jvm", + "io.coil-kt.coil3:coil-network-ktor3-jvm", + "io.github.petertrr:kotlin-multiplatform-diff-jvm", + "io.ktor:ktor-client-content-negotiation-jvm", + "io.ktor:ktor-client-core-jvm", + "io.ktor:ktor-client-mock-jvm", + "io.ktor:ktor-client-okhttp-jvm", + "io.ktor:ktor-events-jvm", + "io.ktor:ktor-http-cio-jvm", + "io.ktor:ktor-http-jvm", + "io.ktor:ktor-io-jvm", + "io.ktor:ktor-network-jvm", + "io.ktor:ktor-serialization-jvm", + "io.ktor:ktor-serialization-kotlinx-json-jvm", + "io.ktor:ktor-serialization-kotlinx-jvm", + "io.ktor:ktor-sse-jvm", + "io.ktor:ktor-utils-jvm", + "io.ktor:ktor-websocket-serialization-jvm", + "io.ktor:ktor-websockets-jvm", + "io.opentelemetry:opentelemetry-api", + "io.opentelemetry:opentelemetry-api-incubator", + "io.opentelemetry:opentelemetry-context", + "io.opentelemetry:opentelemetry-exporter-logging", + "io.opentelemetry:opentelemetry-sdk", + "io.opentelemetry:opentelemetry-sdk-common", + "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi", + "io.opentelemetry:opentelemetry-sdk-logs", + "io.opentelemetry:opentelemetry-sdk-metrics", + "io.opentelemetry:opentelemetry-sdk-trace", + "io.projectreactor.tools:blockhound", + "javax.annotation:javax.annotation-api", + "javax.inject:javax.inject", + "junit:junit", + "org.apache.pdfbox:fontbox", + "org.apache.pdfbox:pdfbox", + "org.apache.pdfbox:pdfbox-io", + "org.apache.sshd:sshd-osgi", + "org.apache.sshd:sshd-sftp", + "org.bouncycastle:bcpkix-jdk15to18", + "org.bouncycastle:bcprov-jdk15to18", + "org.bouncycastle:bcprov-jdk18on", + "org.bouncycastle:bcutil-jdk15to18", + "org.checkerframework:checker-compat-qual", + "org.checkerframework:checker-qual", + "org.conscrypt:conscrypt-openjdk-uber", + "org.eclipse.jgit:org.eclipse.jgit", + "org.eclipse.jgit:org.eclipse.jgit.ssh.apache", + "org.eclipse.jgit:org.eclipse.jgit.ssh.jsch", + "org.hamcrest:hamcrest-core", + "org.hamcrest:hamcrest-library", + "org.jetbrains.androidx.lifecycle:lifecycle-common", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose-desktop", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-savedstate", + "org.jetbrains.androidx.savedstate:savedstate", + "org.jetbrains.androidx.savedstate:savedstate-compose", + "org.jetbrains.androidx.savedstate:savedstate-compose-desktop", + "org.jetbrains.compose.animation:animation", + "org.jetbrains.compose.animation:animation-core", + "org.jetbrains.compose.animation:animation-core-desktop", + "org.jetbrains.compose.animation:animation-desktop", + "org.jetbrains.compose.annotation-internal:annotation", + "org.jetbrains.compose.collection-internal:collection", + "org.jetbrains.compose.components:components-resources-desktop", + "org.jetbrains.compose.desktop:desktop", + "org.jetbrains.compose.desktop:desktop-jvm-linux-x64:pom", + "org.jetbrains.compose.foundation:foundation", + "org.jetbrains.compose.foundation:foundation-desktop", + "org.jetbrains.compose.foundation:foundation-layout", + "org.jetbrains.compose.foundation:foundation-layout-desktop", + "org.jetbrains.compose.material3:material3-desktop", + "org.jetbrains.compose.material:material", + "org.jetbrains.compose.material:material-icons-core-desktop", + "org.jetbrains.compose.material:material-icons-extended-desktop", + "org.jetbrains.compose.material:material-ripple", + "org.jetbrains.compose.material:material-ripple-desktop", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.compose.runtime:runtime-saveable", + "org.jetbrains.compose.runtime:runtime-saveable-desktop", + "org.jetbrains.compose.ui:ui", + "org.jetbrains.compose.ui:ui-backhandler", + "org.jetbrains.compose.ui:ui-backhandler-desktop", + "org.jetbrains.compose.ui:ui-desktop", + "org.jetbrains.compose.ui:ui-geometry", + "org.jetbrains.compose.ui:ui-geometry-desktop", + "org.jetbrains.compose.ui:ui-graphics", + "org.jetbrains.compose.ui:ui-graphics-desktop", + "org.jetbrains.compose.ui:ui-test-desktop", + "org.jetbrains.compose.ui:ui-test-junit4-desktop", + "org.jetbrains.compose.ui:ui-text", + "org.jetbrains.compose.ui:ui-text-desktop", + "org.jetbrains.compose.ui:ui-tooling-preview", + "org.jetbrains.compose.ui:ui-uikit", + "org.jetbrains.compose.ui:ui-unit", + "org.jetbrains.compose.ui:ui-unit-desktop", + "org.jetbrains.compose.ui:ui-util", + "org.jetbrains.compose.ui:ui-util-desktop", + "org.jetbrains.kotlin:kotlin-android-extensions-runtime", + "org.jetbrains.kotlin:kotlin-compose-compiler-plugin-embeddable", + "org.jetbrains.kotlin:kotlin-parcelize-runtime", + "org.jetbrains.kotlin:kotlin-reflect", + "org.jetbrains.kotlin:kotlin-serialization-compiler-plugin-embeddable", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlin:kotlin-stdlib-common", + "org.jetbrains.kotlin:kotlin-stdlib-jdk7", + "org.jetbrains.kotlin:kotlin-stdlib-jdk8", + "org.jetbrains.kotlin:kotlin-test", + "org.jetbrains.kotlin:kotlin-test-junit", + "org.jetbrains.kotlinx:atomicfu", + "org.jetbrains.kotlinx:atomicfu-jvm", + "org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm", + "org.jetbrains.kotlinx:kotlinx-coroutines-android", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.jetbrains.kotlinx:kotlinx-coroutines-guava", + "org.jetbrains.kotlinx:kotlinx-coroutines-reactive", + "org.jetbrains.kotlinx:kotlinx-coroutines-slf4j", + "org.jetbrains.kotlinx:kotlinx-coroutines-swing", + "org.jetbrains.kotlinx:kotlinx-coroutines-test", + "org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm", + "org.jetbrains.kotlinx:kotlinx-datetime-jvm", + "org.jetbrains.kotlinx:kotlinx-io-bytestring-jvm", + "org.jetbrains.kotlinx:kotlinx-io-core-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-core", + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-json-io-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-json-jvm", + "org.jetbrains.runtime:jbr-api", + "org.jetbrains.skiko:skiko", + "org.jetbrains.skiko:skiko-awt", + "org.jetbrains.skiko:skiko-awt-runtime-linux-x64", + "org.jetbrains.skiko:skiko-awt-runtime-macos-arm64", + "org.jetbrains.skiko:skiko-awt-runtime-macos-x64", + "org.jetbrains.skiko:skiko-awt-runtime-windows-x64", + "org.jetbrains:annotations", + "org.jetbrains:markdown-jvm", + "org.jspecify:jspecify", + "org.mockito:mockito-core", + "org.objenesis:objenesis", + "org.ow2.asm:asm", + "org.ow2.asm:asm-commons", + "org.ow2.asm:asm-tree", + "org.reactivestreams:reactive-streams", + "org.robolectric:annotations", + "org.robolectric:junit", + "org.robolectric:nativeruntime", + "org.robolectric:nativeruntime-dist-compat", + "org.robolectric:pluginapi", + "org.robolectric:plugins-maven-dependency-resolver", + "org.robolectric:resources", + "org.robolectric:robolectric", + "org.robolectric:sandbox", + "org.robolectric:shadowapi", + "org.robolectric:shadows-framework", + "org.robolectric:utils", + "org.robolectric:utils-reflector", + "org.slf4j:jcl-over-slf4j", + "org.slf4j:slf4j-api", + "org.xerial:sqlite-jdbc", + "org.yaml:snakeyaml" + ], + "https://repo1.maven.org/maven2/": [ + "androidx.activity:activity-compose:aar", + "androidx.activity:activity-ktx:aar", + "androidx.activity:activity:aar", + "androidx.annotation:annotation", + "androidx.annotation:annotation-experimental:aar", + "androidx.annotation:annotation-jvm", + "androidx.appcompat:appcompat-resources:aar", + "androidx.appcompat:appcompat:aar", + "androidx.arch.core:core-common", + "androidx.arch.core:core-runtime:aar", + "androidx.arch.core:core-testing:aar", + "androidx.autofill:autofill:aar", + "androidx.camera:camera-camera2:aar", + "androidx.camera:camera-core:aar", + "androidx.camera:camera-lifecycle:aar", + "androidx.collection:collection", + "androidx.collection:collection-jvm", + "androidx.collection:collection-ktx", + "androidx.compose.animation:animation-android:aar", + "androidx.compose.animation:animation-core-android:aar", + "androidx.compose.animation:animation-core:aar", + "androidx.compose.animation:animation:aar", + "androidx.compose.foundation:foundation-android:aar", + "androidx.compose.foundation:foundation-layout-android:aar", + "androidx.compose.foundation:foundation-layout:aar", + "androidx.compose.foundation:foundation:aar", + "androidx.compose.material3:material3-android:aar", + "androidx.compose.material3:material3:aar", + "androidx.compose.material:material-android:aar", + "androidx.compose.material:material-icons-core-android:aar", + "androidx.compose.material:material-icons-core:aar", + "androidx.compose.material:material-icons-extended-android:aar", + "androidx.compose.material:material-icons-extended:aar", + "androidx.compose.material:material-ripple-android:aar", + "androidx.compose.material:material-ripple:aar", + "androidx.compose.material:material:aar", + "androidx.compose.runtime:runtime-android:aar", + "androidx.compose.runtime:runtime-annotation", + "androidx.compose.runtime:runtime-annotation-android:aar", + "androidx.compose.runtime:runtime-annotation-jvm", + "androidx.compose.runtime:runtime-desktop", + "androidx.compose.runtime:runtime-retain-android:aar", + "androidx.compose.runtime:runtime-retain-desktop", + "androidx.compose.runtime:runtime-retain:aar", + "androidx.compose.runtime:runtime-saveable-android:aar", + "androidx.compose.runtime:runtime-saveable-desktop", + "androidx.compose.runtime:runtime-saveable:aar", + "androidx.compose.runtime:runtime:aar", + "androidx.compose.ui:ui-android:aar", + "androidx.compose.ui:ui-geometry-android:aar", + "androidx.compose.ui:ui-geometry:aar", + "androidx.compose.ui:ui-graphics-android:aar", + "androidx.compose.ui:ui-graphics:aar", + "androidx.compose.ui:ui-test-android:aar", + "androidx.compose.ui:ui-test-junit4-android:aar", + "androidx.compose.ui:ui-test-junit4:aar", + "androidx.compose.ui:ui-test-manifest:aar", + "androidx.compose.ui:ui-test:aar", + "androidx.compose.ui:ui-text-android:aar", + "androidx.compose.ui:ui-text:aar", + "androidx.compose.ui:ui-tooling-preview-android:aar", + "androidx.compose.ui:ui-tooling-preview:aar", + "androidx.compose.ui:ui-unit-android:aar", + "androidx.compose.ui:ui-unit:aar", + "androidx.compose.ui:ui-util-android:aar", + "androidx.compose.ui:ui-util:aar", + "androidx.compose.ui:ui:aar", + "androidx.concurrent:concurrent-futures", + "androidx.concurrent:concurrent-futures-ktx", + "androidx.core:core-ktx:aar", + "androidx.core:core-remoteviews:aar", + "androidx.core:core-viewtree:aar", + "androidx.core:core:aar", + "androidx.cursoradapter:cursoradapter:aar", + "androidx.customview:customview-poolingcontainer:aar", + "androidx.customview:customview:aar", + "androidx.datastore:datastore-core", + "androidx.datastore:datastore-preferences-core", + "androidx.datastore:datastore-preferences:aar", + "androidx.datastore:datastore:aar", + "androidx.documentfile:documentfile:aar", + "androidx.drawerlayout:drawerlayout:aar", + "androidx.dynamicanimation:dynamicanimation:aar", + "androidx.emoji2:emoji2-views-helper:aar", + "androidx.emoji2:emoji2:aar", + "androidx.exifinterface:exifinterface:aar", + "androidx.fragment:fragment-ktx:aar", + "androidx.fragment:fragment:aar", + "androidx.glance:glance-appwidget-external-protobuf", + "androidx.glance:glance-appwidget-proto", + "androidx.glance:glance-appwidget-testing:aar", + "androidx.glance:glance-appwidget:aar", + "androidx.glance:glance-material3:aar", + "androidx.glance:glance-testing:aar", + "androidx.glance:glance:aar", + "androidx.graphics:graphics-path:aar", + "androidx.interpolator:interpolator:aar", + "androidx.legacy:legacy-support-core-utils:aar", + "androidx.lifecycle:lifecycle-common", + "androidx.lifecycle:lifecycle-common-java8", + "androidx.lifecycle:lifecycle-common-jvm", + "androidx.lifecycle:lifecycle-livedata-core-ktx:aar", + "androidx.lifecycle:lifecycle-livedata-core:aar", + "androidx.lifecycle:lifecycle-livedata:aar", + "androidx.lifecycle:lifecycle-process:aar", + "androidx.lifecycle:lifecycle-runtime-android:aar", + "androidx.lifecycle:lifecycle-runtime-compose-android:aar", + "androidx.lifecycle:lifecycle-runtime-compose-desktop", + "androidx.lifecycle:lifecycle-runtime-compose:aar", + "androidx.lifecycle:lifecycle-runtime-desktop", + "androidx.lifecycle:lifecycle-runtime-ktx-android:aar", + "androidx.lifecycle:lifecycle-runtime-ktx:aar", + "androidx.lifecycle:lifecycle-runtime:aar", + "androidx.lifecycle:lifecycle-service:aar", + "androidx.lifecycle:lifecycle-viewmodel-android:aar", + "androidx.lifecycle:lifecycle-viewmodel-compose-android:aar", + "androidx.lifecycle:lifecycle-viewmodel-compose:aar", + "androidx.lifecycle:lifecycle-viewmodel-desktop", + "androidx.lifecycle:lifecycle-viewmodel-ktx:aar", + "androidx.lifecycle:lifecycle-viewmodel-savedstate-android:aar", + "androidx.lifecycle:lifecycle-viewmodel-savedstate-desktop", + "androidx.lifecycle:lifecycle-viewmodel-savedstate:aar", + "androidx.lifecycle:lifecycle-viewmodel:aar", + "androidx.loader:loader:aar", + "androidx.localbroadcastmanager:localbroadcastmanager:aar", + "androidx.metrics:metrics-performance:aar", + "androidx.navigationevent:navigationevent-android:aar", + "androidx.navigationevent:navigationevent-desktop", + "androidx.navigationevent:navigationevent:aar", + "androidx.print:print:aar", + "androidx.profileinstaller:profileinstaller:aar", + "androidx.resourceinspection:resourceinspection-annotation", + "androidx.room:room-common", + "androidx.room:room-ktx:aar", + "androidx.room:room-runtime:aar", + "androidx.savedstate:savedstate-android:aar", + "androidx.savedstate:savedstate-compose-android:aar", + "androidx.savedstate:savedstate-compose-desktop", + "androidx.savedstate:savedstate-compose:aar", + "androidx.savedstate:savedstate-desktop", + "androidx.savedstate:savedstate-ktx:aar", + "androidx.savedstate:savedstate:aar", + "androidx.security:security-crypto:aar", + "androidx.sqlite:sqlite-android:aar", + "androidx.sqlite:sqlite-framework-android:aar", + "androidx.sqlite:sqlite-framework:aar", + "androidx.sqlite:sqlite:aar", + "androidx.startup:startup-runtime:aar", + "androidx.test.espresso:espresso-core:aar", + "androidx.test.espresso:espresso-idling-resource:aar", + "androidx.test.ext:junit:aar", + "androidx.test.services:storage:aar", + "androidx.test:core:aar", + "androidx.test:monitor:aar", + "androidx.test:rules:aar", + "androidx.test:runner:aar", + "androidx.tracing:tracing-android:aar", + "androidx.tracing:tracing-ktx:aar", + "androidx.tracing:tracing:aar", + "androidx.transition:transition:aar", + "androidx.vectordrawable:vectordrawable-animated:aar", + "androidx.vectordrawable:vectordrawable:aar", + "androidx.versionedparcelable:versionedparcelable:aar", + "androidx.viewpager:viewpager:aar", + "androidx.window:window-core", + "androidx.window:window-core-jvm", + "androidx.window:window:aar", + "androidx.work:work-runtime-ktx:aar", + "androidx.work:work-runtime:aar", + "app.cash.sqldelight:android-driver:aar", + "app.cash.sqldelight:async-extensions-jvm", + "app.cash.sqldelight:coroutines-extensions-jvm", + "app.cash.sqldelight:jdbc-driver", + "app.cash.sqldelight:runtime", + "app.cash.sqldelight:runtime-jvm", + "app.cash.sqldelight:sqlite-driver", + "co.touchlab:stately-concurrency-jvm", + "co.touchlab:stately-strict-jvm", + "com.almworks.sqlite4java:sqlite4java", + "com.android.tools:desugar_jdk_libs", + "com.android.tools:desugar_jdk_libs_configuration", + "com.benasher44:uuid-jvm", + "com.fleeksoft.charset:charset-jvm", + "com.fleeksoft.io:io-core-jvm", + "com.fleeksoft.ksoup:ksoup-jvm", + "com.github.mwiede:jsch", + "com.github.requery:sqlite-android:aar", + "com.google.android.datatransport:transport-api:aar", + "com.google.android.datatransport:transport-backend-cct:aar", + "com.google.android.datatransport:transport-runtime:aar", + "com.google.android.gms:play-services-base:aar", + "com.google.android.gms:play-services-basement:aar", + "com.google.android.gms:play-services-mlkit-text-recognition-common:aar", + "com.google.android.gms:play-services-mlkit-text-recognition:aar", + "com.google.android.gms:play-services-tasks:aar", + "com.google.android.odml:image:aar", + "com.google.ar:core:aar", + "com.google.auto.value:auto-value-annotations", + "com.google.code.findbugs:jsr305", + "com.google.code.gson:gson", + "com.google.crypto.tink:tink-android", + "com.google.errorprone:error_prone_annotation", + "com.google.errorprone:error_prone_annotations", + "com.google.firebase:firebase-annotations", + "com.google.firebase:firebase-components:aar", + "com.google.firebase:firebase-encoders", + "com.google.firebase:firebase-encoders-json:aar", + "com.google.guava:failureaccess", + "com.google.guava:guava", + "com.google.guava:listenablefuture", + "com.google.j2objc:j2objc-annotations", + "com.google.mlkit:common:aar", + "com.google.mlkit:genai-common:aar", + "com.google.mlkit:genai-prompt:aar", + "com.google.mlkit:image-labeling-common:aar", + "com.google.mlkit:image-labeling-default-common:aar", + "com.google.mlkit:image-labeling:aar", + "com.google.mlkit:text-recognition-bundled-common:aar", + "com.google.mlkit:text-recognition:aar", + "com.google.mlkit:vision-common:aar", + "com.google.mlkit:vision-interfaces:aar", + "com.google.mlkit:vision-internal-vkp:aar", + "com.google.testparameterinjector:test-parameter-injector", + "com.google.truth:truth", + "com.googlecode.java-diff-utils:diffutils", + "com.googlecode.javaewah:JavaEWAH", + "com.ibm.icu:icu4j", + "com.jcraft:jsch", + "com.jcraft:jzlib", + "com.juul.kable:core-android:aar", + "com.juul.kable:exceptions-jvm", + "com.juul.tuulbox:collections-jvm", + "com.juul.tuulbox:coroutines-android:aar", + "com.microsoft.onnxruntime:onnxruntime-android:aar", + "com.squareup.okhttp3:okhttp", + "com.squareup.okhttp3:okhttp-sse", + "com.squareup.okio:okio", + "com.squareup.okio:okio-jvm", + "com.tom-roush:pdfbox-android:aar", + "commons-codec:commons-codec", + "commons-logging:commons-logging", + "io.arrow-kt:arrow-annotations-jvm", + "io.arrow-kt:arrow-atomic-jvm", + "io.arrow-kt:arrow-autoclose-jvm", + "io.arrow-kt:arrow-core-jvm", + "io.arrow-kt:arrow-exception-utils-jvm", + "io.arrow-kt:arrow-fx-coroutines-jvm", + "io.arrow-kt:arrow-optics-jvm", + "io.arrow-kt:arrow-resilience-jvm", + "io.coil-kt.coil3:coil-compose-core-jvm", + "io.coil-kt.coil3:coil-compose-jvm", + "io.coil-kt.coil3:coil-core-jvm", + "io.coil-kt.coil3:coil-jvm", + "io.coil-kt.coil3:coil-network-core-jvm", + "io.coil-kt.coil3:coil-network-ktor3-jvm", + "io.github.petertrr:kotlin-multiplatform-diff-jvm", + "io.ktor:ktor-client-content-negotiation-jvm", + "io.ktor:ktor-client-core-jvm", + "io.ktor:ktor-client-mock-jvm", + "io.ktor:ktor-client-okhttp-jvm", + "io.ktor:ktor-events-jvm", + "io.ktor:ktor-http-cio-jvm", + "io.ktor:ktor-http-jvm", + "io.ktor:ktor-io-jvm", + "io.ktor:ktor-network-jvm", + "io.ktor:ktor-serialization-jvm", + "io.ktor:ktor-serialization-kotlinx-json-jvm", + "io.ktor:ktor-serialization-kotlinx-jvm", + "io.ktor:ktor-sse-jvm", + "io.ktor:ktor-utils-jvm", + "io.ktor:ktor-websocket-serialization-jvm", + "io.ktor:ktor-websockets-jvm", + "io.opentelemetry:opentelemetry-api", + "io.opentelemetry:opentelemetry-api-incubator", + "io.opentelemetry:opentelemetry-context", + "io.opentelemetry:opentelemetry-exporter-logging", + "io.opentelemetry:opentelemetry-sdk", + "io.opentelemetry:opentelemetry-sdk-common", + "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi", + "io.opentelemetry:opentelemetry-sdk-logs", + "io.opentelemetry:opentelemetry-sdk-metrics", + "io.opentelemetry:opentelemetry-sdk-trace", + "io.projectreactor.tools:blockhound", + "javax.annotation:javax.annotation-api", + "javax.inject:javax.inject", + "junit:junit", + "org.apache.pdfbox:fontbox", + "org.apache.pdfbox:pdfbox", + "org.apache.pdfbox:pdfbox-io", + "org.apache.sshd:sshd-osgi", + "org.apache.sshd:sshd-sftp", + "org.bouncycastle:bcpkix-jdk15to18", + "org.bouncycastle:bcprov-jdk15to18", + "org.bouncycastle:bcprov-jdk18on", + "org.bouncycastle:bcutil-jdk15to18", + "org.checkerframework:checker-compat-qual", + "org.checkerframework:checker-qual", + "org.conscrypt:conscrypt-openjdk-uber", + "org.eclipse.jgit:org.eclipse.jgit", + "org.eclipse.jgit:org.eclipse.jgit.ssh.apache", + "org.eclipse.jgit:org.eclipse.jgit.ssh.jsch", + "org.hamcrest:hamcrest-core", + "org.hamcrest:hamcrest-library", + "org.jetbrains.androidx.lifecycle:lifecycle-common", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose", + "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose-desktop", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", + "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-savedstate", + "org.jetbrains.androidx.savedstate:savedstate", + "org.jetbrains.androidx.savedstate:savedstate-compose", + "org.jetbrains.androidx.savedstate:savedstate-compose-desktop", + "org.jetbrains.compose.animation:animation", + "org.jetbrains.compose.animation:animation-core", + "org.jetbrains.compose.animation:animation-core-desktop", + "org.jetbrains.compose.animation:animation-desktop", + "org.jetbrains.compose.annotation-internal:annotation", + "org.jetbrains.compose.collection-internal:collection", + "org.jetbrains.compose.components:components-resources-desktop", + "org.jetbrains.compose.desktop:desktop", + "org.jetbrains.compose.desktop:desktop-jvm-linux-x64:pom", + "org.jetbrains.compose.foundation:foundation", + "org.jetbrains.compose.foundation:foundation-desktop", + "org.jetbrains.compose.foundation:foundation-layout", + "org.jetbrains.compose.foundation:foundation-layout-desktop", + "org.jetbrains.compose.material3:material3-desktop", + "org.jetbrains.compose.material:material", + "org.jetbrains.compose.material:material-icons-core-desktop", + "org.jetbrains.compose.material:material-icons-extended-desktop", + "org.jetbrains.compose.material:material-ripple", + "org.jetbrains.compose.material:material-ripple-desktop", + "org.jetbrains.compose.runtime:runtime", + "org.jetbrains.compose.runtime:runtime-desktop", + "org.jetbrains.compose.runtime:runtime-saveable", + "org.jetbrains.compose.runtime:runtime-saveable-desktop", + "org.jetbrains.compose.ui:ui", + "org.jetbrains.compose.ui:ui-backhandler", + "org.jetbrains.compose.ui:ui-backhandler-desktop", + "org.jetbrains.compose.ui:ui-desktop", + "org.jetbrains.compose.ui:ui-geometry", + "org.jetbrains.compose.ui:ui-geometry-desktop", + "org.jetbrains.compose.ui:ui-graphics", + "org.jetbrains.compose.ui:ui-graphics-desktop", + "org.jetbrains.compose.ui:ui-test-desktop", + "org.jetbrains.compose.ui:ui-test-junit4-desktop", + "org.jetbrains.compose.ui:ui-text", + "org.jetbrains.compose.ui:ui-text-desktop", + "org.jetbrains.compose.ui:ui-tooling-preview", + "org.jetbrains.compose.ui:ui-uikit", + "org.jetbrains.compose.ui:ui-unit", + "org.jetbrains.compose.ui:ui-unit-desktop", + "org.jetbrains.compose.ui:ui-util", + "org.jetbrains.compose.ui:ui-util-desktop", + "org.jetbrains.kotlin:kotlin-android-extensions-runtime", + "org.jetbrains.kotlin:kotlin-compose-compiler-plugin-embeddable", + "org.jetbrains.kotlin:kotlin-parcelize-runtime", + "org.jetbrains.kotlin:kotlin-reflect", + "org.jetbrains.kotlin:kotlin-serialization-compiler-plugin-embeddable", + "org.jetbrains.kotlin:kotlin-stdlib", + "org.jetbrains.kotlin:kotlin-stdlib-common", + "org.jetbrains.kotlin:kotlin-stdlib-jdk7", + "org.jetbrains.kotlin:kotlin-stdlib-jdk8", + "org.jetbrains.kotlin:kotlin-test", + "org.jetbrains.kotlin:kotlin-test-junit", + "org.jetbrains.kotlinx:atomicfu", + "org.jetbrains.kotlinx:atomicfu-jvm", + "org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm", + "org.jetbrains.kotlinx:kotlinx-coroutines-android", + "org.jetbrains.kotlinx:kotlinx-coroutines-core", + "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", + "org.jetbrains.kotlinx:kotlinx-coroutines-guava", + "org.jetbrains.kotlinx:kotlinx-coroutines-reactive", + "org.jetbrains.kotlinx:kotlinx-coroutines-slf4j", + "org.jetbrains.kotlinx:kotlinx-coroutines-swing", + "org.jetbrains.kotlinx:kotlinx-coroutines-test", + "org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm", + "org.jetbrains.kotlinx:kotlinx-datetime-jvm", + "org.jetbrains.kotlinx:kotlinx-io-bytestring-jvm", + "org.jetbrains.kotlinx:kotlinx-io-core-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-core", + "org.jetbrains.kotlinx:kotlinx-serialization-core-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-json-io-jvm", + "org.jetbrains.kotlinx:kotlinx-serialization-json-jvm", + "org.jetbrains.runtime:jbr-api", + "org.jetbrains.skiko:skiko", + "org.jetbrains.skiko:skiko-awt", + "org.jetbrains.skiko:skiko-awt-runtime-linux-x64", + "org.jetbrains.skiko:skiko-awt-runtime-macos-arm64", + "org.jetbrains.skiko:skiko-awt-runtime-macos-x64", + "org.jetbrains.skiko:skiko-awt-runtime-windows-x64", + "org.jetbrains:annotations", + "org.jetbrains:markdown-jvm", + "org.jspecify:jspecify", + "org.mockito:mockito-core", + "org.objenesis:objenesis", + "org.ow2.asm:asm", + "org.ow2.asm:asm-commons", + "org.ow2.asm:asm-tree", + "org.reactivestreams:reactive-streams", + "org.robolectric:annotations", + "org.robolectric:junit", + "org.robolectric:nativeruntime", + "org.robolectric:nativeruntime-dist-compat", + "org.robolectric:pluginapi", + "org.robolectric:plugins-maven-dependency-resolver", + "org.robolectric:resources", + "org.robolectric:robolectric", + "org.robolectric:sandbox", + "org.robolectric:shadowapi", + "org.robolectric:shadows-framework", + "org.robolectric:utils", + "org.robolectric:utils-reflector", + "org.slf4j:jcl-over-slf4j", + "org.slf4j:slf4j-api", + "org.xerial:sqlite-jdbc", + "org.yaml:snakeyaml" + ] + }, + "services": { + "io.coil-kt.coil3:coil-network-ktor3-jvm": { + "coil3.util.FetcherServiceLoaderTarget": [ + "coil3.network.ktor3.internal.KtorNetworkFetcherServiceLoaderTarget" + ] + }, + "io.ktor:ktor-client-okhttp-jvm": { + "io.ktor.client.HttpClientEngineContainer": [ + "io.ktor.client.engine.okhttp.OkHttpEngineContainer" + ] + }, + "io.ktor:ktor-serialization-kotlinx-json-jvm": { + "io.ktor.serialization.kotlinx.KotlinxSerializationExtensionProvider": [ + "io.ktor.serialization.kotlinx.json.KotlinxSerializationJsonExtensionProvider" + ] + }, + "io.opentelemetry:opentelemetry-exporter-logging": { + "io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider": [ + "io.opentelemetry.exporter.logging.internal.ConsoleLogRecordExporterComponentProvider", + "io.opentelemetry.exporter.logging.internal.ConsoleMetricExporterComponentProvider", + "io.opentelemetry.exporter.logging.internal.ConsoleSpanExporterComponentProvider" + ], + "io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider": [ + "io.opentelemetry.exporter.logging.internal.ConsoleLogRecordExporterProvider", + "io.opentelemetry.exporter.logging.internal.LoggingLogRecordExporterProvider" + ], + "io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider": [ + "io.opentelemetry.exporter.logging.internal.ConsoleMetricExporterProvider", + "io.opentelemetry.exporter.logging.internal.LoggingMetricExporterProvider" + ], + "io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider": [ + "io.opentelemetry.exporter.logging.internal.ConsoleSpanExporterProvider", + "io.opentelemetry.exporter.logging.internal.LoggingSpanExporterProvider" + ] + }, + "io.projectreactor.tools:blockhound": { + "reactor.blockhound.integration.BlockHoundIntegration": [ + "reactor.blockhound.integration.LoggingIntegration", + "reactor.blockhound.integration.ReactorIntegration", + "reactor.blockhound.integration.RxJava2Integration", + "reactor.blockhound.integration.StandardOutputIntegration" + ] + }, + "org.apache.sshd:sshd-osgi": { + "java.nio.file.spi.FileSystemProvider": [ + "org.apache.sshd.common.file.root.RootedFileSystemProvider" + ] + }, + "org.apache.sshd:sshd-sftp": { + "java.nio.file.spi.FileSystemProvider": [ + "org.apache.sshd.sftp.client.fs.SftpFileSystemProvider" + ], + "org.apache.sshd.server.subsystem.SubsystemFactory": [ + "org.apache.sshd.sftp.server.SftpSubsystemFactory" + ] + }, + "org.bouncycastle:bcprov-jdk18on": { + "java.security.Provider": [ + "org.bouncycastle.jce.provider.BouncyCastleProvider", + "org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider" + ] + }, + "org.eclipse.jgit:org.eclipse.jgit.ssh.apache": { + "org.eclipse.jgit.lib.SignatureVerifierFactory": [ + "org.eclipse.jgit.signing.ssh.SshSignatureVerifierFactory" + ], + "org.eclipse.jgit.lib.SignerFactory": [ + "org.eclipse.jgit.signing.ssh.SshSignerFactory" + ], + "org.eclipse.jgit.transport.SshSessionFactory": [ + "org.eclipse.jgit.transport.sshd.SshdSessionFactory" + ] + }, + "org.eclipse.jgit:org.eclipse.jgit.ssh.jsch": { + "org.eclipse.jgit.transport.SshSessionFactory": [ + "org.eclipse.jgit.transport.JschConfigSessionFactory" + ] + }, + "org.jetbrains.kotlin:kotlin-compose-compiler-plugin-embeddable": { + "org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor": [ + "androidx.compose.compiler.plugins.kotlin.ComposeCommandLineProcessor" + ], + "org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar": [ + "androidx.compose.compiler.plugins.kotlin.ComposePluginRegistrar" + ], + "org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages$Extension": [ + "androidx.compose.compiler.plugins.kotlin.k1.ComposeErrorMessages" + ], + "org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar": [ + "androidx.compose.compiler.plugins.kotlin.k2.ComposeFirExtensionRegistrar" + ] + }, + "org.jetbrains.kotlin:kotlin-reflect": { + "kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoader": [ + "kotlin.reflect.jvm.internal.impl.serialization.deserialization.builtins.BuiltInsLoaderImpl" + ], + "kotlin.reflect.jvm.internal.impl.km.internal.extensions.MetadataExtensions": [ + "kotlin.reflect.jvm.internal.impl.km.jvm.internal.JvmMetadataExtensions" + ], + "kotlin.reflect.jvm.internal.impl.resolve.ExternalOverridabilityCondition": [ + "kotlin.reflect.jvm.internal.impl.load.java.ErasedOverridabilityCondition", + "kotlin.reflect.jvm.internal.impl.load.java.FieldOverridabilityCondition", + "kotlin.reflect.jvm.internal.impl.load.java.JavaIncompatibilityRulesOverridabilityCondition" + ] + }, + "org.jetbrains.kotlin:kotlin-serialization-compiler-plugin-embeddable": { + "org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor": [ + "org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginOptions" + ], + "org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar": [ + "org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationComponentRegistrar" + ] + }, + "org.jetbrains.kotlin:kotlin-test-junit": { + "kotlin.test.AsserterContributor": [ + "kotlin.test.junit.JUnitContributor" + ] + }, + "org.jetbrains.kotlinx:kotlinx-coroutines-android": { + "kotlinx.coroutines.CoroutineExceptionHandler": [ + "kotlinx.coroutines.android.AndroidExceptionPreHandler" + ], + "kotlinx.coroutines.internal.MainDispatcherFactory": [ + "kotlinx.coroutines.android.AndroidDispatcherFactory" + ] + }, + "org.jetbrains.kotlinx:kotlinx-coroutines-swing": { + "kotlinx.coroutines.internal.MainDispatcherFactory": [ + "kotlinx.coroutines.swing.SwingDispatcherFactory" + ] + }, + "org.jetbrains.kotlinx:kotlinx-coroutines-test-jvm": { + "kotlinx.coroutines.CoroutineExceptionHandler": [ + "kotlinx.coroutines.test.internal.ExceptionCollectorAsService" + ], + "kotlinx.coroutines.internal.MainDispatcherFactory": [ + "kotlinx.coroutines.test.internal.TestMainDispatcherFactory" + ] + }, + "org.robolectric:nativeruntime": { + "org.robolectric.pluginapi.NativeRuntimeLoader": [ + "org.robolectric.nativeruntime.DefaultNativeRuntimeLoader" + ] + }, + "org.robolectric:robolectric": { + "androidx.test.internal.platform.ThreadChecker": [ + "org.robolectric.android.internal.RobolectricThreadChecker" + ], + "androidx.test.internal.platform.app.ActivityInvoker": [ + "org.robolectric.android.internal.LocalActivityInvoker" + ], + "androidx.test.internal.platform.content.PermissionGranter": [ + "org.robolectric.android.internal.LocalPermissionGranter" + ], + "androidx.test.internal.platform.os.ControlledLooper": [ + "org.robolectric.android.internal.LocalControlledLooper" + ], + "androidx.test.platform.ui.UiController": [ + "org.robolectric.android.internal.LocalUiController" + ], + "org.robolectric.internal.dependency.DependencyResolver": [ + "org.robolectric.plugins.LegacyDependencyResolver" + ], + "org.robolectric.pluginapi.SdkPicker": [ + "org.robolectric.plugins.DefaultSdkPicker" + ], + "org.robolectric.pluginapi.SdkProvider": [ + "org.robolectric.plugins.DefaultSdkProvider" + ], + "org.robolectric.pluginapi.config.ConfigurationStrategy": [ + "org.robolectric.plugins.HierarchicalConfigurationStrategy" + ], + "org.robolectric.pluginapi.config.Configurer": [ + "org.robolectric.plugins.ConfigConfigurer", + "org.robolectric.plugins.ConscryptModeConfigurer", + "org.robolectric.plugins.GetInstallerPackageNameModeConfigurer", + "org.robolectric.plugins.GraphicsModeConfigurer", + "org.robolectric.plugins.LazyApplicationConfigurer", + "org.robolectric.plugins.LooperModeConfigurer", + "org.robolectric.plugins.ResourcesModeConfigurer", + "org.robolectric.plugins.SQLiteModeConfigurer", + "org.robolectric.plugins.TextLayoutModeConfigurer" + ], + "org.robolectric.pluginapi.config.GlobalConfigProvider": [ + "org.robolectric.RobolectricTestRunner$DeprecatedTestRunnerDefaultConfigProvider" + ] + }, + "org.robolectric:sandbox": { + "org.robolectric.internal.bytecode.ClassHandler": [ + "org.robolectric.internal.bytecode.ShadowWrangler" + ], + "org.robolectric.internal.bytecode.ClassInstrumentor$Decorator": [ + "org.robolectric.internal.bytecode.ShadowDecorator" + ] + }, + "org.robolectric:shadows-framework": { + "org.robolectric.internal.ShadowProvider": [ + "org.robolectric.Shadows" + ] + }, + "org.slf4j:jcl-over-slf4j": { + "org.apache.commons.logging.LogFactory": [ + "org.apache.commons.logging.impl.SLF4JLogFactory" + ] + }, + "org.xerial:sqlite-jdbc": { + "java.sql.Driver": [ + "org.sqlite.JDBC" + ] + } + }, + "version": "2" +} diff --git a/third_party/patches/BUILD.bazel b/third_party/patches/BUILD.bazel new file mode 100644 index 00000000..28add958 --- /dev/null +++ b/third_party/patches/BUILD.bazel @@ -0,0 +1 @@ +exports_files(["rules_kotlin_kmp.patch"]) diff --git a/third_party/patches/rules_kotlin_kmp.patch b/third_party/patches/rules_kotlin_kmp.patch new file mode 100644 index 00000000..3bbdd5f5 --- /dev/null +++ b/third_party/patches/rules_kotlin_kmp.patch @@ -0,0 +1,44 @@ +Add common_srcs attribute to kt_jvm_library for Kotlin Multiplatform (KMP) support. + +When common_srcs is set, sources in that list are passed to the Kotlin compiler +via -Xcommon-sources, which enables expect/actual declarations. All files in +common_srcs must also appear in srcs so they are compiled as part of the same +compilation unit (mirrors how Kotlin Gradle Plugin compiles commonMain + jvmMain). + +diff --git a/kotlin/internal/jvm/jvm.bzl b/kotlin/internal/jvm/jvm.bzl +--- a/kotlin/internal/jvm/jvm.bzl ++++ b/kotlin/internal/jvm/jvm.bzl +@@ -219,6 +219,13 @@ + default = [], + providers = [JavaInfo, _KtJvmInfo], + ), ++ "common_srcs": attr.label_list( ++ doc = """Common source files for Kotlin Multiplatform (KMP) compilation. ++ Files listed here are passed to the compiler with -Xcommon-sources, ++ which enables expect/actual declarations. MUST also appear in srcs.""", ++ allow_files = [".kt"], ++ default = [], ++ ), + "data": attr.label_list( + doc = """The list of files needed by this rule at runtime. See general comments about `data` at + [Attributes common to all build rules](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).""", +diff --git a/kotlin/internal/jvm/compile.bzl b/kotlin/internal/jvm/compile.bzl +--- a/kotlin/internal/jvm/compile.bzl ++++ b/kotlin/internal/jvm/compile.bzl +@@ -580,6 +580,16 @@ + args.add("--build_tools_api", toolchains.kt.experimental_build_tools_api) + args.add_all("--sources", srcs.all_srcs, omit_if_empty = True) + args.add_all("--source_jars", srcs.src_jars + generated_src_jars, omit_if_empty = True) ++ # KMP: pass -Xcommon-sources for expect/actual compilation across source sets ++ _kmp_common_srcs = getattr(ctx.attr, "common_srcs", None) ++ if _kmp_common_srcs: ++ _kmp_common_srcs_files = depset(transitive = [t.files for t in _kmp_common_srcs]) ++ args.add_joined( ++ "--kotlin_passthrough_flags", ++ _kmp_common_srcs_files, ++ join_with = ",", ++ format_joined = "-Xcommon-sources=%s", ++ ) + args.add_all("--deps_artifacts", deps_artifacts, omit_if_empty = True) + args.add_all("--kotlin_friend_paths", compile_deps.associate_jars, omit_if_empty = True) + args.add("--instrument_coverage", ctx.coverage_instrumented()) diff --git a/third_party/unzip.BUILD b/third_party/unzip.BUILD new file mode 100644 index 00000000..c70e874f --- /dev/null +++ b/third_party/unzip.BUILD @@ -0,0 +1,44 @@ +""" +BUILD rules for InfoZip unzip 6.0 — built from source by Bazel. +This file is the build_file for the @unzip_src http_archive in MODULE.bazel. +""" + +load("@rules_cc//cc:defs.bzl", "cc_binary") + +cc_binary( + name = "unzip", + srcs = [ + # Core sources (from unix/Makefile OBJS1-3 + unix platform module) + "unzip.c", + "crc32.c", + "crypt.c", + "envargs.c", + "explode.c", + "extract.c", + "fileio.c", + "globals.c", + "inflate.c", + "list.c", + "match.c", + "process.c", + "ttyio.c", + "ubz2err.c", + "unreduce.c", + "unshrink.c", + "zipinfo.c", + "unix/unix.c", + ] + glob(["*.h", "unix/*.h"]), # all headers needed by the above sources + copts = [ + "-DUNIX", + "-DUSE_ZLIB", + "-DNO_LCHMOD", + # GCC 14+ promotes several pointer-compatibility checks to hard errors. + # Downgrade them to warnings before -w suppresses all warnings. + "-Wno-error=incompatible-pointer-types", + "-Wno-error=implicit-function-declaration", + "-Wno-error=implicit-int", + "-w", # suppress all warnings from third-party C code + ], + linkopts = ["-lz"], + visibility = ["//visibility:public"], +)