From bb9a46935c248e0da6d0fad5303eb46375a07a8c Mon Sep 17 00:00:00 2001 From: Huakun Date: Tue, 1 Apr 2025 06:15:10 -0400 Subject: [PATCH] Feature: add drizzle (#264) * feat: add drizzle orm * feat: update drizzle configuration and schema management - Added a check for DB_FILE_NAME in drizzle.config.ts to ensure it's set. - Updated package.json to change the package name to @kksh/drizzle and added exports for schema and relations. - Enhanced README.md with instructions for using the schema generation. - Refactored schema.ts for improved readability and organization of imports. * add tauri-plugin-sql * feat: add database select and execute commands - Introduced `select` and `execute` functions in the database module to facilitate querying and executing SQL commands. - Updated the Tauri plugin to expose these commands, allowing for database interactions from the frontend. - Added corresponding permissions for the new commands in the permissions configuration. - Enhanced the database library with JSON value handling for query parameters. * fix: sqlite select command * drizzle ORM verified working * refactor: clean up database module by removing unused SelectQueryResult type and disabling eslint for explicit any usage * pnpm lock update * Update enum definition for type safety - Changed enum to use 'as const' for better type inference - Ensured more robust handling of extension publish sources * reimplemented most db command functions with ORM (migrate from tauri command invoke * fixed searchExtensionData orm function * Refactor ORM commands and searchExtensionData function for improved readability and consistency - Reformatted import statements for better organization. - Cleaned up whitespace and indentation in searchExtensionData function. - Enhanced readability of SQL conditions and query building logic. - Disabled eslint for explicit any usage in the troubleshooters page. * Fix test assertions in database module to use array indexing for results format rust code * update deno lock * move drizzle from desktop to drizzle package * update pnpm version and lock * refactor: migrate db tauri commands to drizzle * refactor: remove unused extension and command CRUD operations from db module --- Cargo.lock | 385 ++++++ apps/desktop/package.json | 5 +- apps/desktop/src-tauri/Cargo.toml | 1 + apps/desktop/src-tauri/src/lib.rs | 5 + apps/desktop/src/lib/cmds/builtin.ts | 17 + apps/desktop/src/lib/cmds/ext.ts | 3 +- apps/desktop/src/lib/orm/cmds.ts | 0 apps/desktop/src/lib/orm/database.ts | 60 + apps/desktop/src/lib/stores/extensions.ts | 2 +- apps/desktop/src/routes/+error.svelte | 1 + apps/desktop/src/routes/app/+page.svelte | 3 + .../app/extension/clipboard/+page.svelte | 3 +- .../clipboard/content-preview.svelte | 2 +- .../app/extension/ui-iframe/+page.svelte | 2 +- .../routes/app/extension/ui-iframe/+page.ts | 3 +- .../app/extension/ui-worker/+page.svelte | 2 +- .../routes/app/extension/ui-worker/+page.ts | 4 +- .../extension-loading/+page.svelte | 2 +- .../app/troubleshooters/orm/+page.svelte | 124 ++ .../routes/app/troubleshooters/sidebar.svelte | 6 + deno.lock | 534 +++++++- package.json | 2 +- packages/api/src/api/client.ts | 36 +- packages/api/src/commands/db.ts | 437 ------ packages/api/src/commands/index.ts | 3 +- packages/api/src/commands/sql.ts | 30 + packages/api/src/models/extension.ts | 3 +- packages/api/src/models/server.ts | 2 +- packages/api/src/models/sql.ts | 13 +- packages/db/Cargo.toml | 4 +- packages/db/src/lib.rs | 160 +++ packages/drizzle/.gitignore | 34 + packages/drizzle/README.md | 35 + packages/drizzle/drizzle.config.ts | 15 + .../drizzle/drizzle/0000_colossal_jocasta.sql | 71 + .../drizzle/drizzle/meta/0000_snapshot.json | 405 ++++++ packages/drizzle/drizzle/meta/_journal.json | 13 + packages/drizzle/drizzle/relations.ts | 21 + packages/drizzle/drizzle/schema.ts | 88 ++ packages/drizzle/index.ts | 3 + packages/drizzle/package.json | 26 + packages/drizzle/src/apis.ts | 616 +++++++++ packages/drizzle/src/proxy.ts | 55 + packages/drizzle/tsconfig.json | 28 + packages/extension/package.json | 1 + packages/extension/src/db.ts | 15 +- packages/extension/src/install.ts | 3 +- packages/extension/src/load.ts | 4 +- packages/tauri-plugins/jarvis/Cargo.toml | 2 +- packages/tauri-plugins/jarvis/build.rs | 36 +- .../tauri-plugins/jarvis/permissions/all.toml | 2 + .../autogenerated/commands/execute.toml | 13 + .../autogenerated/commands/select.toml | 13 + .../permissions/autogenerated/reference.md | 52 + .../jarvis/permissions/schemas/schema.json | 20 + .../tauri-plugins/jarvis/src/commands/db.rs | 222 +-- packages/tauri-plugins/jarvis/src/lib.rs | 19 +- .../jarvis/src/model/app_state.rs | 1 - .../jarvis/src/server/grpc/kunkun.rs | 5 +- .../tauri-plugins/jarvis/src/server/http.rs | 3 +- .../tauri-plugins/jarvis/src/server/rest.rs | 6 +- packages/ui/package.json | 2 +- .../error/raw-error-json-preset.svelte | 2 - pnpm-lock.yaml | 1187 +++++++++++++++-- vendors/tauri-plugin-network | 2 +- vendors/tauri-plugin-user-input | 2 +- 66 files changed, 3966 insertions(+), 910 deletions(-) create mode 100644 apps/desktop/src/lib/orm/cmds.ts create mode 100644 apps/desktop/src/lib/orm/database.ts create mode 100644 apps/desktop/src/routes/app/troubleshooters/orm/+page.svelte delete mode 100644 packages/api/src/commands/db.ts create mode 100644 packages/api/src/commands/sql.ts create mode 100644 packages/drizzle/.gitignore create mode 100644 packages/drizzle/README.md create mode 100644 packages/drizzle/drizzle.config.ts create mode 100644 packages/drizzle/drizzle/0000_colossal_jocasta.sql create mode 100644 packages/drizzle/drizzle/meta/0000_snapshot.json create mode 100644 packages/drizzle/drizzle/meta/_journal.json create mode 100644 packages/drizzle/drizzle/relations.ts create mode 100644 packages/drizzle/drizzle/schema.ts create mode 100644 packages/drizzle/index.ts create mode 100644 packages/drizzle/package.json create mode 100644 packages/drizzle/src/apis.ts create mode 100644 packages/drizzle/src/proxy.ts create mode 100644 packages/drizzle/tsconfig.json create mode 100644 packages/tauri-plugins/jarvis/permissions/autogenerated/commands/execute.toml create mode 100644 packages/tauri-plugins/jarvis/permissions/autogenerated/commands/select.toml diff --git a/Cargo.lock b/Cargo.lock index 9f60b90..9c07cc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -479,6 +479,15 @@ dependencies = [ "system-deps", ] +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -1869,6 +1878,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", + "pem-rfc7468", "zeroize", ] @@ -2081,6 +2091,12 @@ dependencies = [ "const-random", ] +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + [[package]] name = "downcast-rs" version = "1.2.1" @@ -2166,6 +2182,9 @@ name = "either" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +dependencies = [ + "serde", +] [[package]] name = "elliptic-curve" @@ -2347,6 +2366,17 @@ version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + [[package]] name = "event-listener" version = "5.3.1" @@ -2625,6 +2655,17 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + [[package]] name = "futures-io" version = "0.3.31" @@ -4014,6 +4055,7 @@ dependencies = [ "tauri-plugin-shell", "tauri-plugin-shellx", "tauri-plugin-single-instance", + "tauri-plugin-sql", "tauri-plugin-store", "tauri-plugin-stronghold", "tauri-plugin-svelte", @@ -4032,6 +4074,9 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] [[package]] name = "lazycell" @@ -4139,6 +4184,12 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + [[package]] name = "libredox" version = "0.1.3" @@ -4356,6 +4407,16 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + [[package]] name = "mdns-sd" version = "0.11.5" @@ -4734,6 +4795,23 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "smallvec", + "zeroize", +] + [[package]] name = "num-complex" version = "0.4.6" @@ -4809,6 +4887,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -5327,6 +5406,15 @@ dependencies = [ "hmac", ] +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -5520,6 +5608,17 @@ dependencies = [ "futures-io", ] +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + [[package]] name = "pkcs8" version = "0.10.2" @@ -6361,6 +6460,26 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422" +[[package]] +name = "rsa" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "signature", + "spki", + "subtle", + "zeroize", +] + [[package]] name = "rusqlite" version = "0.31.0" @@ -7006,6 +7125,9 @@ name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +dependencies = [ + "serde", +] [[package]] name = "socket2" @@ -7084,6 +7206,211 @@ dependencies = [ "der", ] +[[package]] +name = "sqlformat" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" +dependencies = [ + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27144619c6e5802f1380337a209d2ac1c431002dd74c6e60aebff3c506dc4f0c" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a999083c1af5b5d6c071d34a708a19ba3e02106ad82ef7bbd69f5e48266b613b" +dependencies = [ + "atoi", + "byteorder", + "bytes", + "crc", + "crossbeam-queue", + "either", + "event-listener", + "futures-channel", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashbrown 0.14.5", + "hashlink", + "hex", + "indexmap 2.6.0", + "log", + "memchr", + "once_cell", + "paste", + "percent-encoding", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlformat", + "thiserror 1.0.66", + "time", + "tracing", + "url", +] + +[[package]] +name = "sqlx-macros" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23217eb7d86c584b8cbe0337b9eacf12ab76fe7673c513141ec42565698bb88" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 2.0.87", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a099220ae541c5db479c6424bdf1b200987934033c2584f79a0e1693601e776" +dependencies = [ + "dotenvy", + "either", + "heck 0.5.0", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", + "syn 2.0.87", + "tempfile", + "url", +] + +[[package]] +name = "sqlx-mysql" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5afe4c38a9b417b6a9a5eeffe7235d0a106716495536e7727d1c7f4b1ff3eba6" +dependencies = [ + "atoi", + "base64 0.22.1", + "bitflags 2.6.0", + "byteorder", + "bytes", + "crc", + "digest", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac", + "itoa 1.0.11", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand 0.8.5", + "rsa", + "serde", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 1.0.66", + "time", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1dbb157e65f10dbe01f729339c06d239120221c9ad9fa0ba8408c4cc18ecf21" +dependencies = [ + "atoi", + "base64 0.22.1", + "bitflags 2.6.0", + "byteorder", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "hex", + "hkdf", + "hmac", + "home", + "itoa 1.0.11", + "log", + "md-5", + "memchr", + "once_cell", + "rand 0.8.5", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 1.0.66", + "time", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2cdd83c008a622d94499c0006d8ee5f821f36c89b7d625c900e5dc30b5c5ee" +dependencies = [ + "atoi", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "serde_urlencoded", + "sqlx-core", + "time", + "tracing", + "url", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -7139,6 +7466,17 @@ dependencies = [ "quote", ] +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + [[package]] name = "strip-ansi-escapes" version = "0.2.0" @@ -7989,6 +8327,25 @@ dependencies = [ "zbus", ] +[[package]] +name = "tauri-plugin-sql" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6ccca89ded6bd2ff49fdad9a5b34bcd624aa223fdfddbab83c85706ee3a4948" +dependencies = [ + "futures-core", + "indexmap 2.6.0", + "log", + "serde", + "serde_json", + "sqlx", + "tauri", + "tauri-plugin", + "thiserror 2.0.3", + "time", + "tokio", +] + [[package]] name = "tauri-plugin-store" version = "2.2.0" @@ -8854,12 +9211,24 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + [[package]] name = "unicode-segmentation" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + [[package]] name = "universal-hash" version = "0.5.1" @@ -9082,6 +9451,12 @@ dependencies = [ "wit-bindgen-rt", ] +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" version = "0.2.95" @@ -9339,6 +9714,16 @@ dependencies = [ "rustix", ] +[[package]] +name = "whoami" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" +dependencies = [ + "redox_syscall", + "wasite", +] + [[package]] name = "widestring" version = "0.4.3" diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 5ad660f..1649263 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -17,6 +17,7 @@ "dependencies": { "@formkit/auto-animate": "^0.8.2", "@inlang/paraglide-sveltekit": "0.16.0", + "@kksh/drizzle": "workspace:*", "@kksh/extension": "workspace:*", "@kksh/svelte5": "^0.1.15", "@kksh/ui": "workspace:*", @@ -27,9 +28,11 @@ "@tauri-apps/api": "^2.3.0", "@tauri-apps/plugin-autostart": "^2.2.0", "@tauri-apps/plugin-shell": "^2.2.0", + "@tauri-apps/plugin-sql": "^2.2.0", "@tauri-apps/plugin-stronghold": "^2.2.0", "@tauri-store/svelte": "^2.1.1", "dompurify": "^3.2.4", + "drizzle-orm": "^0.40.1", "eslint": "^9.21.0", "fuse.js": "^7.1.0", "gsap": "^3.12.7", @@ -37,7 +40,7 @@ "lz-string": "^1.5.0", "pretty-bytes": "^6.1.1", "semver": "^7.7.1", - "svelte-inspect-value": "^0.3.0", + "svelte-inspect-value": "^0.5.0", "svelte-sonner": "^0.3.28", "sveltekit-superforms": "^2.23.1", "tauri-plugin-clipboard-api": "^2.1.11", diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml index 902bb98..d532862 100644 --- a/apps/desktop/src-tauri/Cargo.toml +++ b/apps/desktop/src-tauri/Cargo.toml @@ -58,6 +58,7 @@ uuid = "1.14.0" obfstr = { workspace = true } base64 = { workspace = true } tauri-plugin-stronghold = "2.2.0" +tauri-plugin-sql = "2" [target."cfg(target_os = \"macos\")".dependencies] diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs index dff6f45..55181ed 100644 --- a/apps/desktop/src-tauri/src/lib.rs +++ b/apps/desktop/src-tauri/src/lib.rs @@ -108,6 +108,11 @@ pub fn run() { .build(), ) .plugin(tauri_plugin_cli::init()) + .plugin( + tauri_plugin_sql::Builder::default() + // .add_migrations("sqlite:mydatabase.db", migrations) + .build(), + ) .plugin(tauri_plugin_user_input::init()) .plugin(tauri_plugin_deep_link::init()) .plugin(tauri_plugin_shell::init()) diff --git a/apps/desktop/src/lib/cmds/builtin.ts b/apps/desktop/src/lib/cmds/builtin.ts index 57015db..40f54da 100644 --- a/apps/desktop/src/lib/cmds/builtin.ts +++ b/apps/desktop/src/lib/cmds/builtin.ts @@ -242,6 +242,23 @@ export const rawBuiltinCmds: BuiltinCmd[] = [ }, keywords: ["extension", "troubleshooter"] }, + { + name: "ORM Troubleshooter", + icon: { + type: IconEnum.Iconify, + value: "material-symbols:database" + }, + description: "", + flags: { + developer: true, + dev: true + }, + function: async () => { + appState.clearSearchTerm() + goto(i18n.resolveRoute("/app/troubleshooters/orm")) + }, + keywords: ["extension", "troubleshooter", "database", "orm"] + }, { name: "Create Quicklink", icon: { diff --git a/apps/desktop/src/lib/cmds/ext.ts b/apps/desktop/src/lib/cmds/ext.ts index ff2c17c..21db8d6 100644 --- a/apps/desktop/src/lib/cmds/ext.ts +++ b/apps/desktop/src/lib/cmds/ext.ts @@ -7,10 +7,11 @@ import { decideKkrpcSerialization } from "@/utils/kkrpc" import { sleep } from "@/utils/time" import { trimSlash } from "@/utils/url" import { constructExtensionSupportDir } from "@kksh/api" -import { db, spawnExtensionFileServer } from "@kksh/api/commands" +import { spawnExtensionFileServer } from "@kksh/api/commands" import type { HeadlessCommand } from "@kksh/api/headless" import { CustomUiCmd, ExtPackageJsonExtra, HeadlessCmd, TemplateUiCmd } from "@kksh/api/models" import { constructJarvisServerAPIWithPermissions, type IApp } from "@kksh/api/ui" +import { db } from "@kksh/drizzle" import { launchNewExtWindow, loadExtensionManifestFromDisk } from "@kksh/extension" import type { IKunkunFullServerAPI } from "@kunkunapi/src/api/server" import { convertFileSrc } from "@tauri-apps/api/core" diff --git a/apps/desktop/src/lib/orm/cmds.ts b/apps/desktop/src/lib/orm/cmds.ts new file mode 100644 index 0000000..e69de29 diff --git a/apps/desktop/src/lib/orm/database.ts b/apps/desktop/src/lib/orm/database.ts new file mode 100644 index 0000000..031c5d6 --- /dev/null +++ b/apps/desktop/src/lib/orm/database.ts @@ -0,0 +1,60 @@ +// /* eslint-disable @typescript-eslint/no-explicit-any */ +// import { db as dbCmd } from "@kksh/api/commands" +// import * as schema from "@kksh/drizzle/schema" +// import { error } from "@tauri-apps/plugin-log" +// import { drizzle } from "drizzle-orm/sqlite-proxy" + +// /** +// * Loads the sqlite database via the Tauri Proxy. +// */ +// // export const sqlite = await Database.load("sqlite:test.db"); + +// /** +// * The drizzle database instance. +// */ +// export const db = drizzle( +// async (sql, params, method) => { +// let rows: any = [] +// let results = [] +// console.log({ +// sql, +// params, +// method +// }) +// console.log(sql) +// // If the query is a SELECT, use the select method +// if (isSelectQuery(sql)) { +// rows = await dbCmd.select(sql, params).catch((e) => { +// error("SQL Error:", e) +// return [] +// }) +// } else { +// // Otherwise, use the execute method +// rows = await dbCmd.execute(sql, params).catch((e) => { +// error("SQL Error:", e) +// return [] +// }) +// return { rows: [] } +// } + +// rows = rows.map((row: any) => { +// return Object.values(row) +// }) + +// // If the method is "all", return all rows +// results = method === "all" ? rows : rows[0] +// return { rows: results } +// }, +// // Pass the schema to the drizzle instance +// { schema: schema, logger: true } +// ) + +// /** +// * Checks if the given SQL query is a SELECT query. +// * @param sql The SQL query to check. +// * @returns True if the query is a SELECT query, false otherwise. +// */ +// function isSelectQuery(sql: string): boolean { +// const selectRegex = /^\s*SELECT\b/i +// return selectRegex.test(sql) +// } diff --git a/apps/desktop/src/lib/stores/extensions.ts b/apps/desktop/src/lib/stores/extensions.ts index 96b1c5f..2180154 100644 --- a/apps/desktop/src/lib/stores/extensions.ts +++ b/apps/desktop/src/lib/stores/extensions.ts @@ -1,5 +1,5 @@ -import { db } from "@kksh/api/commands" import type { CustomUiCmd, ExtPackageJsonExtra, HeadlessCmd, TemplateUiCmd } from "@kksh/api/models" +import { db } from "@kksh/drizzle" import * as extAPI from "@kksh/extension" import * as path from "@tauri-apps/api/path" import Fuse from "fuse.js" diff --git a/apps/desktop/src/routes/+error.svelte b/apps/desktop/src/routes/+error.svelte index a4ae1af..176af5b 100644 --- a/apps/desktop/src/routes/+error.svelte +++ b/apps/desktop/src/routes/+error.svelte @@ -12,6 +12,7 @@ +
--> + import { cn } from "@/utils" - import { db } from "@kksh/api/commands" import type { ExtData } from "@kksh/api/models" + import { db } from "@kksh/drizzle" import { Resizable, Separator } from "@kksh/svelte5" import { convertFileSrc } from "@tauri-apps/api/core" import DOMPurify from "dompurify" diff --git a/apps/desktop/src/routes/app/extension/ui-iframe/+page.svelte b/apps/desktop/src/routes/app/extension/ui-iframe/+page.svelte index 8674f6d..fdbf957 100644 --- a/apps/desktop/src/routes/app/extension/ui-iframe/+page.svelte +++ b/apps/desktop/src/routes/app/extension/ui-iframe/+page.svelte @@ -10,7 +10,6 @@ import { positionToCssStyleString, positionToTailwindClasses } from "@/utils/style" import { sleep } from "@/utils/time" import { isInMainWindow } from "@/utils/window" - import { db } from "@kksh/api/commands" import { CustomPosition, ThemeColor, type Position } from "@kksh/api/models" import { constructJarvisServerAPIWithPermissions, @@ -19,6 +18,7 @@ type IUiCustom } from "@kksh/api/ui" import { toast, type IUiCustomServer1, type IUiCustomServer2 } from "@kksh/api/ui/custom" + import { db } from "@kksh/drizzle" import { Button } from "@kksh/svelte5" import { cn } from "@kksh/ui/utils" import type { IKunkunFullServerAPI } from "@kunkunapi/src/api/server" diff --git a/apps/desktop/src/routes/app/extension/ui-iframe/+page.ts b/apps/desktop/src/routes/app/extension/ui-iframe/+page.ts index 5f13d44..25da688 100644 --- a/apps/desktop/src/routes/app/extension/ui-iframe/+page.ts +++ b/apps/desktop/src/routes/app/extension/ui-iframe/+page.ts @@ -1,8 +1,7 @@ import { KunkunIframeExtParams } from "@/cmds/ext" import { i18n } from "@/i18n" -import { appState } from "@/stores/appState" -import { db, unregisterExtensionWindow } from "@kksh/api/commands" import type { Ext as ExtInfoInDB, ExtPackageJsonExtra } from "@kksh/api/models" +import { db } from "@kksh/drizzle" import { loadExtensionManifestFromDisk } from "@kksh/extension" import { error as svError } from "@sveltejs/kit" import { join } from "@tauri-apps/api/path" diff --git a/apps/desktop/src/routes/app/extension/ui-worker/+page.svelte b/apps/desktop/src/routes/app/extension/ui-worker/+page.svelte index 3afe712..68637ec 100644 --- a/apps/desktop/src/routes/app/extension/ui-worker/+page.svelte +++ b/apps/desktop/src/routes/app/extension/ui-worker/+page.svelte @@ -13,7 +13,6 @@ } from "@/utils/tauri-events.js" import { sleep } from "@/utils/time.js" import { isInMainWindow } from "@/utils/window.js" - import { db } from "@kksh/api/commands" import { constructJarvisServerAPIWithPermissions, type IApp, @@ -29,6 +28,7 @@ type IComponent, type TemplateUiCommand } from "@kksh/api/ui/template" + import { db } from "@kksh/drizzle" import { Button, Form } from "@kksh/svelte5" import { LoadingBar } from "@kksh/ui" import { Templates } from "@kksh/ui/extension" diff --git a/apps/desktop/src/routes/app/extension/ui-worker/+page.ts b/apps/desktop/src/routes/app/extension/ui-worker/+page.ts index 7bfa7ea..98dbfb8 100644 --- a/apps/desktop/src/routes/app/extension/ui-worker/+page.ts +++ b/apps/desktop/src/routes/app/extension/ui-worker/+page.ts @@ -1,7 +1,7 @@ import { KunkunTemplateExtParams } from "@/cmds/ext" import { i18n } from "@/i18n" -import { db, unregisterExtensionWindow } from "@kksh/api/commands" -import type { Ext as ExtInfoInDB, ExtPackageJsonExtra } from "@kksh/api/models" +import type { ExtPackageJsonExtra } from "@kksh/api/models" +import { db } from "@kksh/drizzle" import { loadExtensionManifestFromDisk } from "@kksh/extension" import { error as sbError, error as svError } from "@sveltejs/kit" import { join } from "@tauri-apps/api/path" diff --git a/apps/desktop/src/routes/app/troubleshooters/extension-loading/+page.svelte b/apps/desktop/src/routes/app/troubleshooters/extension-loading/+page.svelte index 83020ba..e7c4417 100644 --- a/apps/desktop/src/routes/app/troubleshooters/extension-loading/+page.svelte +++ b/apps/desktop/src/routes/app/troubleshooters/extension-loading/+page.svelte @@ -1,6 +1,6 @@ + +
+ + + + + + +
{ + e.preventDefault() + const _data = await searchExtensionData({ + extId: 1, + searchMode: SearchModeEnum.FTS, + searchText: searchText, + orderByCreatedAt: SQLSortOrderEnum.Desc, + limit: 10, + fields: ["search_text", "data"] + }) + console.log(_data) + data = _data + inspectTitle = "Search Results" + }} + > + + +
+ +
diff --git a/apps/desktop/src/routes/app/troubleshooters/sidebar.svelte b/apps/desktop/src/routes/app/troubleshooters/sidebar.svelte index ce429e0..ab276f8 100644 --- a/apps/desktop/src/routes/app/troubleshooters/sidebar.svelte +++ b/apps/desktop/src/routes/app/troubleshooters/sidebar.svelte @@ -6,6 +6,7 @@ import { Constants } from "@kksh/ui" import { ArrowLeftIcon } from "lucide-svelte" import AppWindow from "lucide-svelte/icons/app-window" + import DB from "lucide-svelte/icons/database" import Loader from "lucide-svelte/icons/loader" import Network from "lucide-svelte/icons/network" @@ -25,6 +26,11 @@ title: m.troubleshooters_sidebar_mdns_debugger_title(), url: i18n.resolveRoute("/app/troubleshooters/mdns-debugger"), icon: Network + }, + { + title: "ORM", + url: i18n.resolveRoute("/app/troubleshooters/orm"), + icon: DB } ] let currentItem = $state(items.find((item) => window.location.pathname === item.url)) diff --git a/deno.lock b/deno.lock index 90645c5..6fdc767 100644 --- a/deno.lock +++ b/deno.lock @@ -10,6 +10,7 @@ "npm:@formkit/auto-animate@~0.8.2": "0.8.2", "npm:@grpc/grpc-js@^1.12.2": "1.12.5", "npm:@grpc/proto-loader@~0.7.13": "0.7.13", + "npm:@hey-api/client-fetch@~0.8.3": "0.8.3", "npm:@huakunshen/jsr-client@~0.1.5": "0.1.5_typescript@5.6.3_zod@3.24.1_react@18.3.1", "npm:@ianvs/prettier-plugin-sort-imports@^4.4.0": "4.4.1_prettier@3.4.2", "npm:@ianvs/prettier-plugin-sort-imports@^4.4.1": "4.4.1_prettier@3.4.2", @@ -24,9 +25,11 @@ "npm:@jsr/std__semver@^1.0.3": "1.0.3", "npm:@jsr/std__semver@^1.0.4": "1.0.4", "npm:@kksh/react@0.1.1": "0.1.1_react@18.3.1_react-dom@18.3.1__react@18.3.1_react-hook-form@7.54.2__react@18.3.1_@types+react@18.3.18_@types+react-dom@18.3.5__@types+react@18.3.18_date-fns@3.6.0_tailwindcss@3.4.17__postcss@8.5.1", - "npm:@kksh/svelte5@0.1.15": "0.1.15_lucide-svelte@0.469.0__svelte@5.19.6___acorn@8.14.0_svelte@5.19.6__acorn@8.14.0_svelte-sonner@0.3.28__svelte@5.19.6___acorn@8.14.0_typescript@5.6.3_sveltekit-superforms@2.24.0__@sveltejs+kit@2.17.3___@sveltejs+vite-plugin-svelte@5.0.3____svelte@5.19.6_____acorn@8.14.0____vite@6.0.11_____@types+node@20.17.16_____jiti@2.4.2____@types+node@20.17.16___svelte@5.19.6____acorn@8.14.0___vite@5.4.14____@types+node@20.17.16___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__valibot@1.0.0-rc.4___typescript@5.6.3__zod@3.24.2__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__vite@5.4.14___@types+node@20.17.16__typescript@5.6.3__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_@sveltejs+kit@2.17.3__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__vite@5.4.14___@types+node@20.17.16__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_valibot@1.0.0-rc.4__typescript@5.6.3_zod@3.24.2_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_vite@5.4.14__@types+node@20.17.16_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16", + "npm:@kksh/sdk@^0.0.3": "0.0.3_@hey-api+client-fetch@0.8.3_typescript@5.6.3", + "npm:@kksh/svelte5@0.1.15": "0.1.15_lucide-svelte@0.469.0__svelte@5.19.6___acorn@8.14.0_svelte@5.19.6__acorn@8.14.0_svelte-sonner@0.3.28__svelte@5.19.6___acorn@8.14.0_typescript@5.6.3_sveltekit-superforms@2.24.0__@sveltejs+kit@2.17.3___@sveltejs+vite-plugin-svelte@5.0.3____svelte@5.19.6_____acorn@8.14.0____vite@6.0.11_____@types+node@20.17.16_____jiti@2.4.2____@types+node@20.17.16___svelte@5.19.6____acorn@8.14.0___vite@5.4.14____@types+node@20.17.16___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__valibot@1.0.0-rc.4___typescript@5.6.3__zod@3.24.2__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__vite@5.4.14___@types+node@20.17.16__typescript@5.6.3__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16__tsx@4.19.3_@sveltejs+kit@2.17.3__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__vite@5.4.14___@types+node@20.17.16__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_valibot@1.0.0-rc.4__typescript@5.6.3_zod@3.24.2_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_vite@5.4.14__@types+node@20.17.16_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16_tsx@4.19.3", "npm:@kksh/svelte5@~0.1.15": "0.1.16_lucide-svelte@0.469.0__svelte@5.19.6___acorn@8.14.0_svelte@5.19.6__acorn@8.14.0_svelte-sonner@0.3.28__svelte@5.19.6___acorn@8.14.0_typescript@5.6.3", "npm:@kksh/vue@0.1.3": "0.1.3_vue@3.5.13__typescript@5.6.3_nanostores@0.10.3_@unovis+ts@1.5.0_zod@3.24.1_tailwindcss@3.4.17__postcss@8.5.1_radix-vue@1.9.13__vue@3.5.13___typescript@5.6.3__typescript@5.6.3_typescript@5.6.3", + "npm:@libsql/client@0.15": "0.15.0", "npm:@nuxtjs/tailwindcss@6.12.1": "6.12.1_postcss@8.5.1_tailwindcss@3.4.17__postcss@8.5.1_rollup@4.34.0", "npm:@octokit/rest@^21.1.0": "21.1.0_@octokit+core@6.1.3", "npm:@radix-icons/vue@1": "1.0.0_vue@3.5.13__typescript@5.6.3_typescript@5.6.3", @@ -39,7 +42,6 @@ "npm:@shikijs/langs@^2.3.2": "2.3.2", "npm:@shikijs/rehype@^3.2.1": "3.2.1", "npm:@shikijs/themes@^2.3.2": "2.3.2", - "npm:@supabase/ssr@~0.5.2": "0.5.2_@supabase+supabase-js@2.48.1", "npm:@supabase/supabase-js@^2.48.0": "2.48.1", "npm:@supabase/supabase-js@^2.49.1": "2.49.1", "npm:@sveltejs/adapter-auto@^3.3.1": "3.3.1_@sveltejs+kit@2.17.3__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__vite@5.4.14___@types+node@20.17.16__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_svelte@5.19.6__acorn@8.14.0_vite@5.4.14__@types+node@20.17.16_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16", @@ -72,6 +74,7 @@ "npm:@tauri-apps/plugin-os@^2.2.0": "2.2.0", "npm:@tauri-apps/plugin-process@2.2.0": "2.2.0", "npm:@tauri-apps/plugin-shell@^2.2.0": "2.2.0", + "npm:@tauri-apps/plugin-sql@^2.2.0": "2.2.0", "npm:@tauri-apps/plugin-store@^2.2.0": "2.2.0", "npm:@tauri-apps/plugin-stronghold@^2.2.0": "2.2.0", "npm:@tauri-apps/plugin-updater@^2.3.0": "2.5.1", @@ -99,7 +102,7 @@ "npm:@typescript-eslint/parser@^7.15.0": "7.18.0_eslint@8.57.1_typescript@5.6.3", "npm:@typescript-eslint/parser@^8.20.0": "8.22.0_eslint@8.57.1_typescript@5.6.3", "npm:@typescript-eslint/parser@^8.25.0": "8.25.0_eslint@8.57.1_typescript@5.6.3", - "npm:@valibot/to-json-schema@1.0.0-beta.4": "1.0.0-beta.4_valibot@1.0.0-beta.14__typescript@5.6.3_typescript@5.6.3", + "npm:@valibot/to-json-schema@1.0.0": "1.0.0_valibot@1.0.0__typescript@5.6.3_typescript@5.6.3", "npm:@vitejs/plugin-react@^4.3.1": "4.3.4_vite@5.4.14__@types+node@20.17.16_@babel+core@7.26.7_@types+node@20.17.16", "npm:@vitejs/plugin-vue@^5.1.4": "5.2.1_vite@5.4.14__@types+node@20.17.16_vue@3.5.13__typescript@5.6.3_@types+node@20.17.16_typescript@5.6.3", "npm:autoprefixer@^10.4.19": "10.4.20_postcss@8.5.1", @@ -118,6 +121,9 @@ "npm:debug@^4.4.0": "4.4.0", "npm:dompurify@^3.2.3": "3.2.4", "npm:dompurify@^3.2.4": "3.2.4", + "npm:dotenv@^16.4.7": "16.4.7", + "npm:drizzle-kit@~0.30.5": "0.30.5_esbuild@0.19.12", + "npm:drizzle-orm@~0.40.1": "0.40.1_@libsql+client@0.15.0", "npm:eslint-config-next@15.0.3": "15.0.3_eslint@8.57.1_typescript@5.6.3_@typescript-eslint+parser@8.22.0__eslint@8.57.1__typescript@5.6.3_eslint-plugin-import@2.31.0__eslint@8.57.1", "npm:eslint-config-prettier@^10.0.1": "10.0.1_eslint@8.57.1", "npm:eslint-config-prettier@^9.1.0": "9.1.0_eslint@8.57.1", @@ -130,7 +136,7 @@ "npm:eslint@^8.57.0": "8.57.1", "npm:eslint@^9.17.0": "9.19.0", "npm:eslint@^9.21.0": "9.21.0", - "npm:formsnap@2.0.0-next.1": "2.0.0-next.1_svelte@5.19.6__acorn@8.14.0_sveltekit-superforms@2.24.0__@sveltejs+kit@2.17.3___@sveltejs+vite-plugin-svelte@5.0.3____svelte@5.19.6_____acorn@8.14.0____vite@6.0.11_____@types+node@20.17.16_____jiti@2.4.2____@types+node@20.17.16___svelte@5.19.6____acorn@8.14.0___vite@5.4.14____@types+node@20.17.16___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__valibot@1.0.0-rc.4___typescript@5.6.3__zod@3.24.2__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__vite@5.4.14___@types+node@20.17.16__typescript@5.6.3__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_@sveltejs+kit@2.17.3__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__vite@5.4.14___@types+node@20.17.16__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_valibot@1.0.0-rc.4__typescript@5.6.3_zod@3.24.2_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_vite@5.4.14__@types+node@20.17.16_typescript@5.6.3_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16", + "npm:formsnap@2.0.0-next.1": "2.0.0-next.1_svelte@5.19.6__acorn@8.14.0_sveltekit-superforms@2.24.0__@sveltejs+kit@2.17.3___@sveltejs+vite-plugin-svelte@5.0.3____svelte@5.19.6_____acorn@8.14.0____vite@6.0.11_____@types+node@20.17.16_____jiti@2.4.2____@types+node@20.17.16___svelte@5.19.6____acorn@8.14.0___vite@5.4.14____@types+node@20.17.16___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__valibot@1.0.0-rc.4___typescript@5.6.3__zod@3.24.2__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__vite@5.4.14___@types+node@20.17.16__typescript@5.6.3__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16__tsx@4.19.3_@sveltejs+kit@2.17.3__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__vite@5.4.14___@types+node@20.17.16__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_valibot@1.0.0-rc.4__typescript@5.6.3_zod@3.24.2_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_vite@5.4.14__@types+node@20.17.16_typescript@5.6.3_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16_tsx@4.19.3", "npm:fs-extra@^11.2.0": "11.3.0", "npm:fuse.js@^7.1.0": "7.1.0", "npm:get-folder-size@5": "5.0.0", @@ -186,14 +192,14 @@ "npm:svelte-check@^4.1.1": "4.1.4_svelte@5.19.6__acorn@8.14.0_typescript@5.6.3", "npm:svelte-check@^4.1.4": "4.1.4_svelte@5.19.6__acorn@8.14.0_typescript@5.6.3", "npm:svelte-exmarkdown@^4.0.3": "4.0.3_svelte@5.19.6__acorn@8.14.0", - "npm:svelte-inspect-value@0.3": "0.3.0_svelte@5.19.6__acorn@8.14.0", + "npm:svelte-inspect-value@0.5": "0.5.0_svelte@5.19.6__acorn@8.14.0", "npm:svelte-motion@~0.12.2": "0.12.2_svelte@5.19.6__acorn@8.14.0", "npm:svelte-radix@^2.0.1": "2.0.1_svelte@5.19.6__acorn@8.14.0", "npm:svelte-sonner@~0.3.28": "0.3.28_svelte@5.19.6__acorn@8.14.0", "npm:svelte@^5.16.6": "5.19.6_acorn@8.14.0", "npm:svelte@^5.20.5": "5.20.5_acorn@8.14.0", - "npm:sveltekit-superforms@^2.22.1": "2.24.0_@sveltejs+kit@2.17.3__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__vite@5.4.14___@types+node@20.17.16__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_svelte@5.19.6__acorn@8.14.0_valibot@1.0.0-rc.4__typescript@5.6.3_zod@3.24.2_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_vite@5.4.14__@types+node@20.17.16_typescript@5.6.3_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16", - "npm:sveltekit-superforms@^2.23.1": "2.24.0_@sveltejs+kit@2.17.3__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__vite@5.4.14___@types+node@20.17.16__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_svelte@5.19.6__acorn@8.14.0_valibot@1.0.0-rc.4__typescript@5.6.3_zod@3.24.2_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_vite@5.4.14__@types+node@20.17.16_typescript@5.6.3_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16", + "npm:sveltekit-superforms@^2.22.1": "2.24.0_@sveltejs+kit@2.17.3__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__vite@5.4.14___@types+node@20.17.16__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_svelte@5.19.6__acorn@8.14.0_valibot@1.0.0-rc.4__typescript@5.6.3_zod@3.24.2_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_vite@5.4.14__@types+node@20.17.16_typescript@5.6.3_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16_tsx@4.19.3", + "npm:sveltekit-superforms@^2.23.1": "2.24.0_@sveltejs+kit@2.17.3__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__vite@5.4.14___@types+node@20.17.16__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_svelte@5.19.6__acorn@8.14.0_valibot@1.0.0-rc.4__typescript@5.6.3_zod@3.24.2_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_vite@5.4.14__@types+node@20.17.16_typescript@5.6.3_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16_tsx@4.19.3", "npm:tailwind-merge@^2.4.0": "2.6.0", "npm:tailwind-merge@^2.5.5": "2.6.0", "npm:tailwind-merge@^2.6.0": "2.6.0", @@ -214,6 +220,7 @@ "npm:tauri-plugin-system-info-api@2.0.8": "2.0.8_typescript@5.6.3", "npm:ts-proto@^2.3.0": "2.6.1", "npm:tslib@^2.8.1": "2.8.1", + "npm:tsx@^4.19.3": "4.19.3", "npm:turbo@^2.4.4": "2.4.4", "npm:typedoc@~0.27.5": "0.27.6_typescript@5.6.3", "npm:typedoc@~0.27.6": "0.27.6_typescript@5.6.3", @@ -229,6 +236,7 @@ "npm:typescript@~5.7.2": "5.7.3", "npm:uuid@^11.0.3": "11.0.5", "npm:uuid@^11.1.0": "11.1.0", + "npm:valibot@1": "1.0.0_typescript@5.6.3", "npm:valibot@^1.0.0-beta.10": "1.0.0-beta.14_typescript@5.6.3", "npm:valibot@^1.0.0-beta.11": "1.0.0-beta.14_typescript@5.6.3", "npm:valibot@^1.0.0-rc.4": "1.0.0-rc.4_typescript@5.6.3", @@ -1253,6 +1261,9 @@ "node-source-walk" ] }, + "@drizzle-team/brocli@0.10.2": { + "integrity": "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==" + }, "@emotion/babel-plugin@11.13.5": { "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", "dependencies": [ @@ -1317,6 +1328,23 @@ "@emotion/weak-memoize@0.4.0": { "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==" }, + "@esbuild-kit/core-utils@3.3.2": { + "integrity": "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==", + "dependencies": [ + "esbuild@0.18.20", + "source-map-support" + ] + }, + "@esbuild-kit/esm-loader@2.6.5": { + "integrity": "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==", + "dependencies": [ + "@esbuild-kit/core-utils", + "get-tsconfig" + ] + }, + "@esbuild/aix-ppc64@0.19.12": { + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==" + }, "@esbuild/aix-ppc64@0.21.5": { "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==" }, @@ -1326,6 +1354,12 @@ "@esbuild/aix-ppc64@0.25.0": { "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==" }, + "@esbuild/android-arm64@0.18.20": { + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==" + }, + "@esbuild/android-arm64@0.19.12": { + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==" + }, "@esbuild/android-arm64@0.21.5": { "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==" }, @@ -1335,6 +1369,12 @@ "@esbuild/android-arm64@0.25.0": { "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==" }, + "@esbuild/android-arm@0.18.20": { + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==" + }, + "@esbuild/android-arm@0.19.12": { + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==" + }, "@esbuild/android-arm@0.21.5": { "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==" }, @@ -1344,6 +1384,12 @@ "@esbuild/android-arm@0.25.0": { "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==" }, + "@esbuild/android-x64@0.18.20": { + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==" + }, + "@esbuild/android-x64@0.19.12": { + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==" + }, "@esbuild/android-x64@0.21.5": { "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==" }, @@ -1353,6 +1399,12 @@ "@esbuild/android-x64@0.25.0": { "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==" }, + "@esbuild/darwin-arm64@0.18.20": { + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==" + }, + "@esbuild/darwin-arm64@0.19.12": { + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==" + }, "@esbuild/darwin-arm64@0.21.5": { "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==" }, @@ -1362,6 +1414,12 @@ "@esbuild/darwin-arm64@0.25.0": { "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==" }, + "@esbuild/darwin-x64@0.18.20": { + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==" + }, + "@esbuild/darwin-x64@0.19.12": { + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==" + }, "@esbuild/darwin-x64@0.21.5": { "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==" }, @@ -1371,6 +1429,12 @@ "@esbuild/darwin-x64@0.25.0": { "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==" }, + "@esbuild/freebsd-arm64@0.18.20": { + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==" + }, + "@esbuild/freebsd-arm64@0.19.12": { + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==" + }, "@esbuild/freebsd-arm64@0.21.5": { "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==" }, @@ -1380,6 +1444,12 @@ "@esbuild/freebsd-arm64@0.25.0": { "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==" }, + "@esbuild/freebsd-x64@0.18.20": { + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==" + }, + "@esbuild/freebsd-x64@0.19.12": { + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==" + }, "@esbuild/freebsd-x64@0.21.5": { "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==" }, @@ -1389,6 +1459,12 @@ "@esbuild/freebsd-x64@0.25.0": { "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==" }, + "@esbuild/linux-arm64@0.18.20": { + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==" + }, + "@esbuild/linux-arm64@0.19.12": { + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==" + }, "@esbuild/linux-arm64@0.21.5": { "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==" }, @@ -1398,6 +1474,12 @@ "@esbuild/linux-arm64@0.25.0": { "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==" }, + "@esbuild/linux-arm@0.18.20": { + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==" + }, + "@esbuild/linux-arm@0.19.12": { + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==" + }, "@esbuild/linux-arm@0.21.5": { "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==" }, @@ -1407,6 +1489,12 @@ "@esbuild/linux-arm@0.25.0": { "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==" }, + "@esbuild/linux-ia32@0.18.20": { + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==" + }, + "@esbuild/linux-ia32@0.19.12": { + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==" + }, "@esbuild/linux-ia32@0.21.5": { "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==" }, @@ -1416,6 +1504,12 @@ "@esbuild/linux-ia32@0.25.0": { "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==" }, + "@esbuild/linux-loong64@0.18.20": { + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==" + }, + "@esbuild/linux-loong64@0.19.12": { + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==" + }, "@esbuild/linux-loong64@0.21.5": { "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==" }, @@ -1425,6 +1519,12 @@ "@esbuild/linux-loong64@0.25.0": { "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==" }, + "@esbuild/linux-mips64el@0.18.20": { + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==" + }, + "@esbuild/linux-mips64el@0.19.12": { + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==" + }, "@esbuild/linux-mips64el@0.21.5": { "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==" }, @@ -1434,6 +1534,12 @@ "@esbuild/linux-mips64el@0.25.0": { "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==" }, + "@esbuild/linux-ppc64@0.18.20": { + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==" + }, + "@esbuild/linux-ppc64@0.19.12": { + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==" + }, "@esbuild/linux-ppc64@0.21.5": { "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==" }, @@ -1443,6 +1549,12 @@ "@esbuild/linux-ppc64@0.25.0": { "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==" }, + "@esbuild/linux-riscv64@0.18.20": { + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==" + }, + "@esbuild/linux-riscv64@0.19.12": { + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==" + }, "@esbuild/linux-riscv64@0.21.5": { "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==" }, @@ -1452,6 +1564,12 @@ "@esbuild/linux-riscv64@0.25.0": { "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==" }, + "@esbuild/linux-s390x@0.18.20": { + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==" + }, + "@esbuild/linux-s390x@0.19.12": { + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==" + }, "@esbuild/linux-s390x@0.21.5": { "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==" }, @@ -1461,6 +1579,12 @@ "@esbuild/linux-s390x@0.25.0": { "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==" }, + "@esbuild/linux-x64@0.18.20": { + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==" + }, + "@esbuild/linux-x64@0.19.12": { + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==" + }, "@esbuild/linux-x64@0.21.5": { "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==" }, @@ -1476,6 +1600,12 @@ "@esbuild/netbsd-arm64@0.25.0": { "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==" }, + "@esbuild/netbsd-x64@0.18.20": { + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==" + }, + "@esbuild/netbsd-x64@0.19.12": { + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==" + }, "@esbuild/netbsd-x64@0.21.5": { "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==" }, @@ -1491,6 +1621,12 @@ "@esbuild/openbsd-arm64@0.25.0": { "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==" }, + "@esbuild/openbsd-x64@0.18.20": { + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==" + }, + "@esbuild/openbsd-x64@0.19.12": { + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==" + }, "@esbuild/openbsd-x64@0.21.5": { "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==" }, @@ -1500,6 +1636,12 @@ "@esbuild/openbsd-x64@0.25.0": { "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==" }, + "@esbuild/sunos-x64@0.18.20": { + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==" + }, + "@esbuild/sunos-x64@0.19.12": { + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==" + }, "@esbuild/sunos-x64@0.21.5": { "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==" }, @@ -1509,6 +1651,12 @@ "@esbuild/sunos-x64@0.25.0": { "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==" }, + "@esbuild/win32-arm64@0.18.20": { + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==" + }, + "@esbuild/win32-arm64@0.19.12": { + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==" + }, "@esbuild/win32-arm64@0.21.5": { "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==" }, @@ -1518,6 +1666,12 @@ "@esbuild/win32-arm64@0.25.0": { "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==" }, + "@esbuild/win32-ia32@0.18.20": { + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==" + }, + "@esbuild/win32-ia32@0.19.12": { + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==" + }, "@esbuild/win32-ia32@0.21.5": { "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==" }, @@ -1527,6 +1681,12 @@ "@esbuild/win32-ia32@0.25.0": { "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==" }, + "@esbuild/win32-x64@0.18.20": { + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==" + }, + "@esbuild/win32-x64@0.19.12": { + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==" + }, "@esbuild/win32-x64@0.21.5": { "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==" }, @@ -1722,6 +1882,9 @@ "@hey-api/client-fetch@0.6.0": { "integrity": "sha512-FlhFsVeH8RxJe/nq8xUzxNbiOpe+GadxlD2pfvDyOyLdCTU4o/LRv46ZVWstaW7DgF4nxhI328chy3+AulwVXw==" }, + "@hey-api/client-fetch@0.8.3": { + "integrity": "sha512-EBVa8wwUMyBSeQ32PtCz6u5bFQZIMAufvwCT1ZtpjqT3caJQEza4NokbGU50q1ZVrMsM5Ot6GuDNJOF3TMo26Q==" + }, "@hookform/resolvers@3.10.0_react-hook-form@7.54.2__react@18.3.1_react@18.3.1": { "integrity": "sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag==", "dependencies": [ @@ -1734,7 +1897,7 @@ "@huakunshen/jsr-client@0.1.5_typescript@5.6.3_zod@3.24.1_react@18.3.1": { "integrity": "sha512-iLm7OuGNetejByzEx7Z3B4KnFot3uP42IMYGmj15tpi4hWaO6iw5AkQ+bqhEnf/LpH6qxK6lBqkALjcDWdGY2g==", "dependencies": [ - "@hey-api/client-fetch", + "@hey-api/client-fetch@0.6.0", "@zodios/core", "openapi-fetch", "openapi-typescript-helpers", @@ -2440,7 +2603,14 @@ "zod@3.24.1" ] }, - "@kksh/svelte5@0.1.15_lucide-svelte@0.469.0__svelte@5.19.6___acorn@8.14.0_svelte@5.19.6__acorn@8.14.0_svelte-sonner@0.3.28__svelte@5.19.6___acorn@8.14.0_typescript@5.6.3_sveltekit-superforms@2.24.0__@sveltejs+kit@2.17.3___@sveltejs+vite-plugin-svelte@5.0.3____svelte@5.19.6_____acorn@8.14.0____vite@6.0.11_____@types+node@20.17.16_____jiti@2.4.2____@types+node@20.17.16___svelte@5.19.6____acorn@8.14.0___vite@5.4.14____@types+node@20.17.16___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__valibot@1.0.0-rc.4___typescript@5.6.3__zod@3.24.2__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__vite@5.4.14___@types+node@20.17.16__typescript@5.6.3__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_@sveltejs+kit@2.17.3__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__vite@5.4.14___@types+node@20.17.16__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_valibot@1.0.0-rc.4__typescript@5.6.3_zod@3.24.2_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_vite@5.4.14__@types+node@20.17.16_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16": { + "@kksh/sdk@0.0.3_@hey-api+client-fetch@0.8.3_typescript@5.6.3": { + "integrity": "sha512-he5/VSiIfEuXQlGWGxoIurrq/wbddbvZiHbKIGAFTS1DljCHjnAjEajueCkz9M3sbn+WGylS8VSVAFSCWdCfPg==", + "dependencies": [ + "@hey-api/client-fetch@0.8.3", + "typescript@5.6.3" + ] + }, + "@kksh/svelte5@0.1.15_lucide-svelte@0.469.0__svelte@5.19.6___acorn@8.14.0_svelte@5.19.6__acorn@8.14.0_svelte-sonner@0.3.28__svelte@5.19.6___acorn@8.14.0_typescript@5.6.3_sveltekit-superforms@2.24.0__@sveltejs+kit@2.17.3___@sveltejs+vite-plugin-svelte@5.0.3____svelte@5.19.6_____acorn@8.14.0____vite@6.0.11_____@types+node@20.17.16_____jiti@2.4.2____@types+node@20.17.16___svelte@5.19.6____acorn@8.14.0___vite@5.4.14____@types+node@20.17.16___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__valibot@1.0.0-rc.4___typescript@5.6.3__zod@3.24.2__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__vite@5.4.14___@types+node@20.17.16__typescript@5.6.3__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16__tsx@4.19.3_@sveltejs+kit@2.17.3__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__vite@5.4.14___@types+node@20.17.16__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_valibot@1.0.0-rc.4__typescript@5.6.3_zod@3.24.2_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_vite@5.4.14__@types+node@20.17.16_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16_tsx@4.19.3": { "integrity": "sha512-Cr/gSWsnRtQIQLpQAkGBODujWn5g4LlhDp865skRV95tkrOuAwbbWGjG5+oWx1fK+fiDu+rhe2UCqw61SW2B/Q==", "dependencies": [ "@tanstack/table-core", @@ -2520,6 +2690,62 @@ "@kwsites/promise-deferred@1.1.1": { "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" }, + "@libsql/client@0.15.0": { + "integrity": "sha512-AkJg9mxnAVCtHAVndZ8YwxqG43nSYVNZHAEX55MZ0R06rBcCoYLwjAr8grxC02/tNZpf4KMJj+BVPqNnQOD8ZQ==", + "dependencies": [ + "@libsql/core", + "@libsql/hrana-client", + "js-base64", + "libsql", + "promise-limit" + ] + }, + "@libsql/core@0.15.0": { + "integrity": "sha512-8SReMzkCPmqoDl1tkAa9FCmoxDmiiuDM2eM8cTlKnMD6xG2jUczvckYM/x7VCWy0O9zu0LR/u7sEYEd2CPPTJA==", + "dependencies": [ + "js-base64" + ] + }, + "@libsql/darwin-arm64@0.5.1": { + "integrity": "sha512-ETWRV8+h2l1P4/BB+ct1yWoBJMokUfCLe8W7TEbGo/9mAqk4NWkacVlAJgRdVIFQsA+3/vrQF7LyaIQOSEELTg==" + }, + "@libsql/darwin-x64@0.5.1": { + "integrity": "sha512-zB1Sid7vTBt/PiiLyQmw9AXZZv3MziNRx/rJ6xc/HTUYG7c2QHwOMikVuad1Lafvvf3OyGYSAPHKg9hdvNFP9A==" + }, + "@libsql/hrana-client@0.7.0": { + "integrity": "sha512-OF8fFQSkbL7vJY9rfuegK1R7sPgQ6kFMkDamiEccNUvieQ+3urzfDFI616oPl8V7T9zRmnTkSjMOImYCAVRVuw==", + "dependencies": [ + "@libsql/isomorphic-fetch", + "@libsql/isomorphic-ws", + "js-base64", + "node-fetch@3.3.2" + ] + }, + "@libsql/isomorphic-fetch@0.3.1": { + "integrity": "sha512-6kK3SUK5Uu56zPq/Las620n5aS9xJq+jMBcNSOmjhNf/MUvdyji4vrMTqD7ptY7/4/CAVEAYDeotUz60LNQHtw==" + }, + "@libsql/isomorphic-ws@0.1.5": { + "integrity": "sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==", + "dependencies": [ + "@types/ws", + "ws@8.18.1" + ] + }, + "@libsql/linux-arm64-gnu@0.5.1": { + "integrity": "sha512-RbDc3fcRH5gjg2UUsMTPncSMCqTZ6re59t4jhNFpaLb3n2raD8S3XfvMq9LFqirzK+JDKHhxRPTow0E+QLaLJQ==" + }, + "@libsql/linux-arm64-musl@0.5.1": { + "integrity": "sha512-JwK6Ne8dmtt+D+0zESwKvrjnylSDHNN7Mt9gb+TbWZZVvmro8n/ApvRVJh8ZO3R7dH32rUJoc2cQmKD6B691sA==" + }, + "@libsql/linux-x64-gnu@0.5.1": { + "integrity": "sha512-9U1yo0H8OaxGsVPQFDm/SrQjhyMFUHinmfPOwQcLjcnWwv1GqfNdYlGnp2ZfdJr2QOx7k5klouJjJgy8KzhY4g==" + }, + "@libsql/linux-x64-musl@0.5.1": { + "integrity": "sha512-2TEX6SJqi88wPbv1ZHiTHtqaWOf+Mj7L8jOSgQY/aMoPzV5VFtDFF68ApIUNR6L+4eMwlD28NpahwJf8ilWYIw==" + }, + "@libsql/win32-x64-msvc@0.5.1": { + "integrity": "sha512-rOtBBJhLuCeSgXBWIRNTLADdSLfwsII6za/ci5+XJKSiSi0STO4bcGEfVKLEJ6HDqdCJ2zdH1WGc9rTwhsUB0g==" + }, "@liuli-util/fs-extra@0.1.0": { "integrity": "sha512-eaAyDyMGT23QuRGbITVY3SOJff3G9ekAAyGqB9joAnTBmqvFN+9a1FazOdO70G6IUqgpKV451eBHYSRcOJ/FNQ==", "dependencies": [ @@ -2623,6 +2849,9 @@ "vue" ] }, + "@neon-rs/load@0.0.4": { + "integrity": "sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==" + }, "@netlify/functions@2.8.2": { "integrity": "sha512-DeoAQh8LuNPvBE4qsKlezjKj0PyXDryOFJfJKo3Z1qZLKzQ21sT314KQKPVjfvw6knqijj+IO+0kHXy/TJiqNA==", "dependencies": [ @@ -3474,6 +3703,9 @@ "node-addon-api" ] }, + "@petamoriken/float16@3.9.2": { + "integrity": "sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog==" + }, "@pkgjs/parseargs@0.11.0": { "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==" }, @@ -5082,14 +5314,6 @@ "ws@8.18.0" ] }, - "@supabase/ssr@0.5.2_@supabase+supabase-js@2.48.1": { - "integrity": "sha512-n3plRhr2Bs8Xun1o4S3k1CDv17iH5QY9YcoEvXX3bxV1/5XSasA0mNXYycFmADIdtdE6BG9MRjP5CGIs8qxC8A==", - "dependencies": [ - "@supabase/supabase-js@2.48.1", - "@types/cookie", - "cookie@0.7.2" - ] - }, "@supabase/storage-js@2.7.1": { "integrity": "sha512-asYHcyDR1fKqrMpytAS1zjyEfvxuOIp1CIXX7ji4lHHcJKqyk+sLl/Vxgm4sN6u8zvuUtae9e4kDxQP2qrwWBA==", "dependencies": [ @@ -5136,7 +5360,7 @@ "dependencies": [ "@sveltejs/vite-plugin-svelte@5.0.3_svelte@5.19.6__acorn@8.14.0_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16_svelte@5.20.5__acorn@8.14.0", "@types/cookie", - "cookie@0.6.0", + "cookie", "devalue@5.1.1", "esm-env", "import-meta-resolve", @@ -5155,7 +5379,26 @@ "dependencies": [ "@sveltejs/vite-plugin-svelte@5.0.3_svelte@5.19.6__acorn@8.14.0_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16", "@types/cookie", - "cookie@0.6.0", + "cookie", + "devalue@5.1.1", + "esm-env", + "import-meta-resolve", + "kleur@4.1.5", + "magic-string", + "mrmime", + "sade", + "set-cookie-parser", + "sirv", + "svelte@5.19.6_acorn@8.14.0", + "vite@5.4.14_@types+node@20.17.16" + ] + }, + "@sveltejs/kit@2.17.3_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_svelte@5.19.6__acorn@8.14.0_vite@5.4.14__@types+node@20.17.16_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16_tsx@4.19.3": { + "integrity": "sha512-GcNaPDr0ti4O/TonPewkML2DG7UVXkSxPN3nPMlpmx0Rs4b2kVP4gymz98WEHlfzPXdd4uOOT1Js26DtieTNBQ==", + "dependencies": [ + "@sveltejs/vite-plugin-svelte@5.0.3_svelte@5.19.6__acorn@8.14.0_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2__tsx@4.19.3_tsx@4.19.3", + "@types/cookie", + "cookie", "devalue@5.1.1", "esm-env", "import-meta-resolve", @@ -5174,7 +5417,7 @@ "dependencies": [ "@sveltejs/vite-plugin-svelte@5.0.3_svelte@5.19.6__acorn@8.14.0_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_svelte@5.20.5__acorn@8.14.0_@types+node@20.17.16", "@types/cookie", - "cookie@0.6.0", + "cookie", "devalue@5.1.1", "esm-env", "import-meta-resolve", @@ -5215,6 +5458,15 @@ "vite@6.0.11_@types+node@20.17.16_jiti@2.4.2" ] }, + "@sveltejs/vite-plugin-svelte-inspector@4.0.1_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_svelte@5.19.6__acorn@8.14.0_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2___tsx@4.19.3__tsx@4.19.3_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2__tsx@4.19.3_tsx@4.19.3": { + "integrity": "sha512-J/Nmb2Q2y7mck2hyCX4ckVHcR5tu2J+MtBEQqpDrrgELZ2uvraQcK/ioCV61AqkdXFgriksOKIceDcQmqnGhVw==", + "dependencies": [ + "@sveltejs/vite-plugin-svelte@5.0.3_svelte@5.19.6__acorn@8.14.0_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2__tsx@4.19.3_tsx@4.19.3", + "debug@4.4.0", + "svelte@5.19.6_acorn@8.14.0", + "vite@6.0.11_@types+node@20.17.16_jiti@2.4.2_tsx@4.19.3" + ] + }, "@sveltejs/vite-plugin-svelte@5.0.3_svelte@5.19.6__acorn@8.14.0_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16": { "integrity": "sha512-MCFS6CrQDu1yGwspm4qtli0e63vaPCehf6V7pIMP15AsWgMKrqDGCPFF/0kn4SP0ii4aySu4Pa62+fIRGFMjgw==", "dependencies": [ @@ -5225,7 +5477,7 @@ "magic-string", "svelte@5.19.6_acorn@8.14.0", "vite@6.0.11_@types+node@20.17.16_jiti@2.4.2", - "vitefu" + "vitefu@1.0.6_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16" ] }, "@sveltejs/vite-plugin-svelte@5.0.3_svelte@5.19.6__acorn@8.14.0_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16_svelte@5.20.5__acorn@8.14.0": { @@ -5238,7 +5490,20 @@ "magic-string", "svelte@5.20.5_acorn@8.14.0", "vite@6.0.11_@types+node@20.17.16_jiti@2.4.2", - "vitefu" + "vitefu@1.0.6_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16" + ] + }, + "@sveltejs/vite-plugin-svelte@5.0.3_svelte@5.19.6__acorn@8.14.0_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2__tsx@4.19.3_tsx@4.19.3": { + "integrity": "sha512-MCFS6CrQDu1yGwspm4qtli0e63vaPCehf6V7pIMP15AsWgMKrqDGCPFF/0kn4SP0ii4aySu4Pa62+fIRGFMjgw==", + "dependencies": [ + "@sveltejs/vite-plugin-svelte-inspector@4.0.1_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_svelte@5.19.6__acorn@8.14.0_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2___tsx@4.19.3__tsx@4.19.3_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2__tsx@4.19.3_tsx@4.19.3", + "debug@4.4.0", + "deepmerge", + "kleur@4.1.5", + "magic-string", + "svelte@5.19.6_acorn@8.14.0", + "vite@6.0.11_@types+node@20.17.16_jiti@2.4.2_tsx@4.19.3", + "vitefu@1.0.6_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2__tsx@4.19.3_tsx@4.19.3" ] }, "@sveltejs/vite-plugin-svelte@5.0.3_svelte@5.19.6__acorn@8.14.0_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_svelte@5.20.5__acorn@8.14.0_@types+node@20.17.16": { @@ -5251,7 +5516,7 @@ "magic-string", "svelte@5.20.5_acorn@8.14.0", "vite@6.0.11_@types+node@20.17.16_jiti@2.4.2", - "vitefu" + "vitefu@1.0.6_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16" ] }, "@swc/counter@0.1.3": { @@ -5487,6 +5752,12 @@ "@tauri-apps/api@2.2.0" ] }, + "@tauri-apps/plugin-sql@2.2.0": { + "integrity": "sha512-yGdybpaMENe/p6lTXslvDHYNNvD9qB7palaBBF5fJHdYSkwd3vrLiYU9dFfLwUAwnsBylND55EiivWsjhazejA==", + "dependencies": [ + "@tauri-apps/api@2.3.0" + ] + }, "@tauri-apps/plugin-store@2.2.0": { "integrity": "sha512-hJTRtuJis4w5fW1dkcgftsYxKXK0+DbAqurZ3CURHG5WkAyyZgbxpeYctw12bbzF9ZbZREXZklPq8mocCC3Sgg==", "dependencies": [ @@ -6390,10 +6661,10 @@ "vue" ] }, - "@valibot/to-json-schema@1.0.0-beta.4_valibot@1.0.0-beta.14__typescript@5.6.3_typescript@5.6.3": { - "integrity": "sha512-wXBdCyoqec+NLCl5ihitXzZXD4JAjPK3+HfskSXzfhiNFvKje0A/v1LygqKidUgIbaJtREmq/poJGbaS/0MKuQ==", + "@valibot/to-json-schema@1.0.0_valibot@1.0.0__typescript@5.6.3_typescript@5.6.3": { + "integrity": "sha512-/9crJgPptVsGCL6X+JPDQyaJwkalSZ/52WuF8DiRUxJgcmpNdzYRfZ+gqMEP8W3CTVfuMWPqqvIgfwJ97f9Etw==", "dependencies": [ - "valibot@1.0.0-beta.14_typescript@5.6.3" + "valibot@1.0.0_typescript@5.6.3" ] }, "@vee-validate/zod@4.15.0_zod@3.24.1_vue@3.5.13__typescript@5.6.3_typescript@5.6.3": { @@ -7626,9 +7897,6 @@ "cookie@0.6.0": { "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==" }, - "cookie@0.7.2": { - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==" - }, "cookies@0.9.1": { "integrity": "sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==", "dependencies": [ @@ -8218,6 +8486,9 @@ "detect-libc@1.0.3": { "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==" }, + "detect-libc@2.0.2": { + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==" + }, "detect-libc@2.0.3": { "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==" }, @@ -8397,6 +8668,22 @@ "detect-libc@1.0.3" ] }, + "drizzle-kit@0.30.5_esbuild@0.19.12": { + "integrity": "sha512-l6dMSE100u7sDaTbLczibrQZjA35jLsHNqIV+jmhNVO3O8jzM6kywMOmV9uOz9ZVSCMPQhAZEFjL/qDPVrqpUA==", + "dependencies": [ + "@drizzle-team/brocli", + "@esbuild-kit/esm-loader", + "esbuild@0.19.12", + "esbuild-register", + "gel" + ] + }, + "drizzle-orm@0.40.1_@libsql+client@0.15.0": { + "integrity": "sha512-aPNhtiJiPfm3qxz1czrnIDkfvkSdKGXYeZkpG55NPTVI186LmK2fBLMi4dsHpPHlJrZeQ92D322YFPHADBALew==", + "dependencies": [ + "@libsql/client" + ] + }, "dunder-proto@1.0.1": { "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "dependencies": [ @@ -8509,6 +8796,9 @@ "env-paths@2.2.1": { "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" }, + "env-paths@3.0.0": { + "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==" + }, "err-code@2.0.3": { "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" }, @@ -8639,6 +8929,13 @@ "is-symbol" ] }, + "esbuild-register@3.6.0_esbuild@0.19.12": { + "integrity": "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==", + "dependencies": [ + "debug@4.4.0", + "esbuild@0.19.12" + ] + }, "esbuild-runner@2.2.2_esbuild@0.25.0": { "integrity": "sha512-fRFVXcmYVmSmtYm2mL8RlUASt2TDkGh3uRcvHFOKNr/T58VrfVeKD9uT9nlgxk96u0LS0ehS/GY7Da/bXWKkhw==", "dependencies": [ @@ -8647,6 +8944,61 @@ "tslib@2.4.0" ] }, + "esbuild@0.18.20": { + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dependencies": [ + "@esbuild/android-arm@0.18.20", + "@esbuild/android-arm64@0.18.20", + "@esbuild/android-x64@0.18.20", + "@esbuild/darwin-arm64@0.18.20", + "@esbuild/darwin-x64@0.18.20", + "@esbuild/freebsd-arm64@0.18.20", + "@esbuild/freebsd-x64@0.18.20", + "@esbuild/linux-arm@0.18.20", + "@esbuild/linux-arm64@0.18.20", + "@esbuild/linux-ia32@0.18.20", + "@esbuild/linux-loong64@0.18.20", + "@esbuild/linux-mips64el@0.18.20", + "@esbuild/linux-ppc64@0.18.20", + "@esbuild/linux-riscv64@0.18.20", + "@esbuild/linux-s390x@0.18.20", + "@esbuild/linux-x64@0.18.20", + "@esbuild/netbsd-x64@0.18.20", + "@esbuild/openbsd-x64@0.18.20", + "@esbuild/sunos-x64@0.18.20", + "@esbuild/win32-arm64@0.18.20", + "@esbuild/win32-ia32@0.18.20", + "@esbuild/win32-x64@0.18.20" + ] + }, + "esbuild@0.19.12": { + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dependencies": [ + "@esbuild/aix-ppc64@0.19.12", + "@esbuild/android-arm@0.19.12", + "@esbuild/android-arm64@0.19.12", + "@esbuild/android-x64@0.19.12", + "@esbuild/darwin-arm64@0.19.12", + "@esbuild/darwin-x64@0.19.12", + "@esbuild/freebsd-arm64@0.19.12", + "@esbuild/freebsd-x64@0.19.12", + "@esbuild/linux-arm@0.19.12", + "@esbuild/linux-arm64@0.19.12", + "@esbuild/linux-ia32@0.19.12", + "@esbuild/linux-loong64@0.19.12", + "@esbuild/linux-mips64el@0.19.12", + "@esbuild/linux-ppc64@0.19.12", + "@esbuild/linux-riscv64@0.19.12", + "@esbuild/linux-s390x@0.19.12", + "@esbuild/linux-x64@0.19.12", + "@esbuild/netbsd-x64@0.19.12", + "@esbuild/openbsd-x64@0.19.12", + "@esbuild/sunos-x64@0.19.12", + "@esbuild/win32-arm64@0.19.12", + "@esbuild/win32-ia32@0.19.12", + "@esbuild/win32-x64@0.19.12" + ] + }, "esbuild@0.21.5": { "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dependencies": [ @@ -9394,7 +9746,7 @@ "fetch-blob" ] }, - "formsnap@2.0.0-next.1_svelte@5.19.6__acorn@8.14.0_sveltekit-superforms@2.24.0__@sveltejs+kit@2.17.3___@sveltejs+vite-plugin-svelte@5.0.3____svelte@5.19.6_____acorn@8.14.0____vite@6.0.11_____@types+node@20.17.16_____jiti@2.4.2____@types+node@20.17.16___svelte@5.19.6____acorn@8.14.0___vite@5.4.14____@types+node@20.17.16___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__valibot@1.0.0-rc.4___typescript@5.6.3__zod@3.24.2__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__vite@5.4.14___@types+node@20.17.16__typescript@5.6.3__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_@sveltejs+kit@2.17.3__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__vite@5.4.14___@types+node@20.17.16__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_valibot@1.0.0-rc.4__typescript@5.6.3_zod@3.24.2_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_vite@5.4.14__@types+node@20.17.16_typescript@5.6.3_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16": { + "formsnap@2.0.0-next.1_svelte@5.19.6__acorn@8.14.0_sveltekit-superforms@2.24.0__@sveltejs+kit@2.17.3___@sveltejs+vite-plugin-svelte@5.0.3____svelte@5.19.6_____acorn@8.14.0____vite@6.0.11_____@types+node@20.17.16_____jiti@2.4.2____@types+node@20.17.16___svelte@5.19.6____acorn@8.14.0___vite@5.4.14____@types+node@20.17.16___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__valibot@1.0.0-rc.4___typescript@5.6.3__zod@3.24.2__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__vite@5.4.14___@types+node@20.17.16__typescript@5.6.3__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16__tsx@4.19.3_@sveltejs+kit@2.17.3__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__vite@5.4.14___@types+node@20.17.16__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_valibot@1.0.0-rc.4__typescript@5.6.3_zod@3.24.2_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_vite@5.4.14__@types+node@20.17.16_typescript@5.6.3_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16_tsx@4.19.3": { "integrity": "sha512-ha8r9eMmsGEGMY+ljV3FEyTtB72E7dt95y9HHUbCcaDnjbz3Q6n00BHLz7dfBZ9rqyaMeIO200EmP1IcYMExeg==", "dependencies": [ "svelte@5.19.6_acorn@8.14.0", @@ -9496,6 +9848,17 @@ "fuse.js@7.1.0": { "integrity": "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==" }, + "gel@2.0.1": { + "integrity": "sha512-gfem3IGvqKqXwEq7XseBogyaRwGsQGuE7Cw/yQsjLGdgiyqX92G1xENPCE0ltunPGcsJIa6XBOTx/PK169mOqw==", + "dependencies": [ + "@petamoriken/float16", + "debug@4.4.0", + "env-paths@3.0.0", + "semver@7.7.1", + "shell-quote", + "which@4.0.0" + ] + }, "gensync@1.0.0-beta.2": { "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" }, @@ -10576,6 +10939,9 @@ "react" ] }, + "js-base64@3.7.7": { + "integrity": "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==" + }, "js-levenshtein@1.1.6": { "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==" }, @@ -10938,6 +11304,20 @@ "semver@7.7.0" ] }, + "libsql@0.5.1": { + "integrity": "sha512-ePnm5zj6T//GKiTY/v5b0a272NX73hqdRORmD8gzz1nUui9051dtTt6t0XCrIqxwJAHSmQiZcfAx3YSASn9Y+A==", + "dependencies": [ + "@libsql/darwin-arm64", + "@libsql/darwin-x64", + "@libsql/linux-arm64-gnu", + "@libsql/linux-arm64-musl", + "@libsql/linux-x64-gnu", + "@libsql/linux-x64-musl", + "@libsql/win32-x64-msvc", + "@neon-rs/load", + "detect-libc@2.0.2" + ] + }, "lilconfig@2.1.0": { "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==" }, @@ -12010,7 +12390,7 @@ "node-gyp@11.0.0": { "integrity": "sha512-zQS+9MTTeCMgY0F3cWPyJyRFAkVltQ1uXm+xXu/ES6KFgC6Czo1Seb9vQW2wNxSX2OrDTiqL0ojtkFxBQ0ypIw==", "dependencies": [ - "env-paths", + "env-paths@2.2.1", "exponential-backoff", "glob@10.4.5", "graceful-fs", @@ -13266,6 +13646,9 @@ "promise-inflight@1.0.1": { "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==" }, + "promise-limit@2.7.0": { + "integrity": "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw==" + }, "promise-retry@2.0.1": { "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "dependencies": [ @@ -14613,8 +14996,8 @@ "unified" ] }, - "svelte-inspect-value@0.3.0_svelte@5.19.6__acorn@8.14.0": { - "integrity": "sha512-nHv+7+FRePs86sgL2I8jlbSrs8/uJmHJ2uxnMk9tVipWdZYYcmGhsmU+7U8lm/1RAZFS63/xSKdceMDyE09y0A==", + "svelte-inspect-value@0.5.0_svelte@5.19.6__acorn@8.14.0": { + "integrity": "sha512-ZWbu/TZl/gGAPe8Xjmg0YvERSpEC+q07HV8m0xhp51auTNh8mjaf07bcmcl0coBb0wnJqcAB4uWJ1GDdtGQrQw==", "dependencies": [ "esm-env", "fast-deep-equal", @@ -14706,11 +15089,11 @@ "zimmerframe" ] }, - "sveltekit-superforms@2.24.0_@sveltejs+kit@2.17.3__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__vite@5.4.14___@types+node@20.17.16__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_svelte@5.19.6__acorn@8.14.0_valibot@1.0.0-rc.4__typescript@5.6.3_zod@3.24.2_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_vite@5.4.14__@types+node@20.17.16_typescript@5.6.3_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16": { + "sveltekit-superforms@2.24.0_@sveltejs+kit@2.17.3__@sveltejs+vite-plugin-svelte@5.0.3___svelte@5.19.6____acorn@8.14.0___vite@6.0.11____@types+node@20.17.16____jiti@2.4.2___@types+node@20.17.16__svelte@5.19.6___acorn@8.14.0__vite@5.4.14___@types+node@20.17.16__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_svelte@5.19.6__acorn@8.14.0_valibot@1.0.0-rc.4__typescript@5.6.3_zod@3.24.2_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_vite@5.4.14__@types+node@20.17.16_typescript@5.6.3_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16_tsx@4.19.3": { "integrity": "sha512-JuuaaPDn9OHUKc0Uy8jzv1jUZNfO4AHUE0JLcXjiuJNRokYLqC+RsPDL4/jUkqia97aZzrfTgB/meQ8iS5nNJg==", "dependencies": [ "@gcornut/valibot-json-schema", - "@sveltejs/kit@2.17.3_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_svelte@5.19.6__acorn@8.14.0_vite@5.4.14__@types+node@20.17.16_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16", + "@sveltejs/kit@2.17.3_@sveltejs+vite-plugin-svelte@5.0.3__svelte@5.19.6___acorn@8.14.0__vite@6.0.11___@types+node@20.17.16___jiti@2.4.2__@types+node@20.17.16_svelte@5.19.6__acorn@8.14.0_vite@5.4.14__@types+node@20.17.16_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16_tsx@4.19.3", "devalue@5.1.1", "json-schema-to-ts", "memoize-weak", @@ -15150,6 +15533,14 @@ "tsscmp@1.0.6": { "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==" }, + "tsx@4.19.3": { + "integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==", + "dependencies": [ + "esbuild@0.25.0", + "fsevents", + "get-tsconfig" + ] + }, "tuf-js@3.0.1": { "integrity": "sha512-+68OP1ZzSF84rTckf3FA95vJ1Zlx/uaXyiiKyPd1pA4rZNkpEvDAKmsu1xUSmbF/chCRYgZ6UZkDwC7PmzmAyA==", "dependencies": [ @@ -15664,6 +16055,12 @@ "typescript@5.6.3" ] }, + "valibot@1.0.0_typescript@5.6.3": { + "integrity": "sha512-1Hc0ihzWxBar6NGeZv7fPLY0QuxFMyxwYR2sF1Blu7Wq7EnremwY2W02tit2ij2VJT8HcSkHAQqmFfl77f73Yw==", + "dependencies": [ + "typescript@5.6.3" + ] + }, "validate-npm-package-license@3.0.4": { "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dependencies": [ @@ -15860,6 +16257,18 @@ "rollup" ] }, + "vite@6.0.11_@types+node@20.17.16_jiti@2.4.2_tsx@4.19.3": { + "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==", + "dependencies": [ + "@types/node@20.17.16", + "esbuild@0.24.2", + "fsevents", + "jiti@2.4.2", + "postcss@8.5.1", + "rollup", + "tsx" + ] + }, "vite@6.2.0_@types+node@20.17.16": { "integrity": "sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==", "dependencies": [ @@ -15876,6 +16285,12 @@ "vite@6.0.11_@types+node@20.17.16_jiti@2.4.2" ] }, + "vitefu@1.0.6_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2_@types+node@20.17.16_vite@6.0.11__@types+node@20.17.16__jiti@2.4.2__tsx@4.19.3_tsx@4.19.3": { + "integrity": "sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA==", + "dependencies": [ + "vite@6.0.11_@types+node@20.17.16_jiti@2.4.2_tsx@4.19.3" + ] + }, "vitest@2.1.9_@types+node@20.17.16_vite@5.4.14__@types+node@20.17.16": { "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==", "dependencies": [ @@ -16250,8 +16665,10 @@ "packageJson": { "dependencies": [ "npm:@changesets/cli@^2.28.1", + "npm:@hey-api/client-fetch@~0.8.3", "npm:@ianvs/prettier-plugin-sort-imports@^4.4.1", "npm:@iconify/svelte@^4.2.0", + "npm:@kksh/sdk@^0.0.3", "npm:@supabase/supabase-js@^2.49.1", "npm:@tauri-apps/api@^2.3.0", "npm:@tauri-apps/cli@^2.3.1", @@ -16275,7 +16692,7 @@ "npm:svelte@^5.20.5", "npm:turbo@^2.4.4", "npm:typescript@5", - "npm:valibot@^1.0.0-rc.4", + "npm:valibot@1", "npm:verify-package-export@^0.0.3", "npm:zod@^3.24.2" ] @@ -16295,7 +16712,7 @@ "npm:debug@^4.4.0", "npm:fs-extra@^11.2.0", "npm:inquirer@^10.1.2", - "npm:valibot@^1.0.0-rc.4" + "npm:valibot@1" ] } }, @@ -16311,7 +16728,7 @@ "npm:get-folder-size@5", "npm:handlebars@^4.7.8", "npm:tar@^7.4.3", - "npm:valibot@^1.0.0-rc.4", + "npm:valibot@1", "npm:vitest@^2.1.9" ] } @@ -16338,6 +16755,7 @@ "npm:@tauri-apps/cli@^2.3.1", "npm:@tauri-apps/plugin-autostart@^2.2.0", "npm:@tauri-apps/plugin-shell@^2.2.0", + "npm:@tauri-apps/plugin-sql@^2.2.0", "npm:@tauri-apps/plugin-stronghold@^2.2.0", "npm:@types/bun@latest", "npm:@types/semver@^7.5.8", @@ -16347,6 +16765,7 @@ "npm:bits-ui@1.0.0-next.86", "npm:clsx@^2.1.1", "npm:dompurify@^3.2.4", + "npm:drizzle-orm@~0.40.1", "npm:eslint-config-prettier@^9.1.0", "npm:eslint-plugin-svelte@^2.46.1", "npm:eslint@^9.21.0", @@ -16359,7 +16778,7 @@ "npm:prettier@^3.5.2", "npm:pretty-bytes@^6.1.1", "npm:semver@^7.7.1", - "npm:svelte-inspect-value@0.3", + "npm:svelte-inspect-value@0.5", "npm:svelte-radix@^2.0.1", "npm:svelte-sonner@~0.3.28", "npm:sveltekit-superforms@^2.23.1", @@ -16417,7 +16836,7 @@ "npm:tauri-plugin-system-info-api@2.0.8", "npm:typedoc@~0.27.6", "npm:typescript@5", - "npm:valibot@^1.0.0-rc.4", + "npm:valibot@1", "npm:verify-package-export@^0.0.3" ] } @@ -16440,13 +16859,27 @@ ] } }, + "packages/drizzle": { + "packageJson": { + "dependencies": [ + "npm:@libsql/client@0.15", + "npm:@types/bun@latest", + "npm:dotenv@^16.4.7", + "npm:drizzle-kit@~0.30.5", + "npm:drizzle-orm@~0.40.1", + "npm:tsx@^4.19.3" + ] + } + }, "packages/extension": { "packageJson": { "dependencies": [ - "npm:@jsr/std__semver@^1.0.3", + "npm:@jsr/std__semver@^1.0.4", "npm:@tauri-apps/plugin-upload@^2.2.1", "npm:@types/bun@latest", - "npm:uuid@^11.0.3" + "npm:@types/semver@^7.5.8", + "npm:semver@^7.7.1", + "npm:uuid@^11.1.0" ] } }, @@ -16533,17 +16966,8 @@ "npm:@aws-sdk/client-s3@^3.583.0", "npm:@supabase/supabase-js@^2.48.0", "npm:@types/bun@latest", - "npm:@valibot/to-json-schema@1.0.0-beta.4", - "npm:valibot@^1.0.0-rc.4" - ] - } - }, - "packages/supabase": { - "packageJson": { - "dependencies": [ - "npm:@supabase/ssr@~0.5.2", - "npm:@supabase/supabase-js@^2.48.0", - "npm:@types/bun@latest" + "npm:@valibot/to-json-schema@1.0.0", + "npm:valibot@1" ] } }, @@ -16761,7 +17185,7 @@ "npm:shiki-magic-move@~0.5.2", "npm:shiki@^1.27.2", "npm:svelte-exmarkdown@^4.0.3", - "npm:svelte-inspect-value@0.3", + "npm:svelte-inspect-value@0.5", "npm:svelte-motion@~0.12.2", "npm:svelte-radix@^2.0.1", "npm:svelte-sonner@~0.3.28", @@ -16772,7 +17196,7 @@ "npm:tailwindcss@^3.4.17", "npm:tauri-plugin-shellx-api@^2.0.16", "npm:typescript-eslint@^8.20.0", - "npm:valibot@^1.0.0-rc.4", + "npm:valibot@1", "npm:zod@^3.24.1" ] } diff --git a/package.json b/package.json index 15d46c3..68c426a 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "typescript": "^5.0.0", "verify-package-export": "^0.0.3" }, - "packageManager": "pnpm@9.15.2", + "packageManager": "pnpm@10.7.0", "engines": { "node": ">=22" }, diff --git a/packages/api/src/api/client.ts b/packages/api/src/api/client.ts index 07e8f7d..962a40c 100644 --- a/packages/api/src/api/client.ts +++ b/packages/api/src/api/client.ts @@ -20,9 +20,10 @@ import type { IPath as ITauriPath } from "tauri-api-adapter" import * as v from "valibot" -import { KV, type JarvisExtDB } from "../commands/db" import type { fileSearch } from "../commands/fileSearch" import { type AppInfo } from "../models/apps" +import { type ExtData } from "../models/extension" +import { ExtDataField, SearchMode, SQLSortOrder } from "../models/sql" import type { LightMode, Position, Radius, ThemeColor } from "../models/styles" import type { DenoSysOptions } from "../permissions/schema" @@ -154,23 +155,34 @@ export interface IUiCustom { } export interface IDb { - add: typeof JarvisExtDB.prototype.add - delete: typeof JarvisExtDB.prototype.delete - search: typeof JarvisExtDB.prototype.search - retrieveAll: typeof JarvisExtDB.prototype.retrieveAll - retrieveAllByType: typeof JarvisExtDB.prototype.retrieveAllByType - deleteAll: typeof JarvisExtDB.prototype.deleteAll - update: typeof JarvisExtDB.prototype.update + add: (data: { data: string; dataType?: string; searchText?: string }) => Promise + delete: (dataId: number) => Promise + search: (searchParams: { + dataId?: number + searchMode?: SearchMode + dataType?: string + searchText?: string + afterCreatedAt?: Date + beforeCreatedAt?: Date + limit?: number + orderByCreatedAt?: SQLSortOrder + orderByUpdatedAt?: SQLSortOrder + fields?: ExtDataField[] + }) => Promise + retrieveAll: (options: { fields?: ExtDataField[] }) => Promise + retrieveAllByType: (dataType: string) => Promise + deleteAll: () => Promise + update: (data: { dataId: number; data: string; searchText?: string }) => Promise } /** * A key-value store built on top of the Database API (based on sqlite) */ export interface IKV { - get: typeof KV.prototype.get - set: typeof KV.prototype.set - exists: typeof KV.prototype.exists - delete: typeof KV.prototype.delete + get: (key: string) => Promise + set: (key: string, value: string) => Promise + exists: (key: string) => Promise + delete: (key: string) => Promise } export interface IFs { diff --git a/packages/api/src/commands/db.ts b/packages/api/src/commands/db.ts deleted file mode 100644 index eb421f8..0000000 --- a/packages/api/src/commands/db.ts +++ /dev/null @@ -1,437 +0,0 @@ -import { invoke } from "@tauri-apps/api/core" -import { array, literal, optional, parse, safeParse, union, type InferOutput } from "valibot" -import { KUNKUN_EXT_IDENTIFIER } from "../constants" -import { CmdType, Ext, ExtCmd, ExtData } from "../models/extension" -import { convertDateToSqliteString, SearchMode, SearchModeEnum, SQLSortOrder } from "../models/sql" -import { generateJarvisPluginCommand } from "./common" - -/* -------------------------------------------------------------------------- */ -/* Extension CRUD */ -/* -------------------------------------------------------------------------- */ -export function createExtension(ext: { - identifier: string - version: string - enabled?: boolean - path?: string - data?: any -}) { - return invoke(generateJarvisPluginCommand("create_extension"), ext) -} - -export function getAllExtensions() { - return invoke(generateJarvisPluginCommand("get_all_extensions")) -} - -export function getUniqueExtensionByIdentifier(identifier: string) { - return invoke( - generateJarvisPluginCommand("get_unique_extension_by_identifier"), - { - identifier - } - ) -} - -export function getUniqueExtensionByPath(path: string) { - return invoke(generateJarvisPluginCommand("get_unique_extension_by_path"), { - path - }) -} - -export function getAllExtensionsByIdentifier(identifier: string) { - return invoke(generateJarvisPluginCommand("get_all_extensions_by_identifier"), { - identifier - }) -} - -/** - * Use this function when you expect the extension to exist. Such as builtin extensions. - * @param identifier - * @returns - */ -export function getExtensionByIdentifierExpectExists(identifier: string): Promise { - return getUniqueExtensionByIdentifier(identifier).then((ext) => { - if (!ext) { - throw new Error(`Unexpexted Error: Extension ${identifier} not found`) - } - return ext - }) -} - -// TODO: clean this up -// export function deleteExtensionByIdentifier(identifier: string) { -// return invoke(generateJarvisPluginCommand("delete_extension_by_identifier"), { identifier }) -// } - -export function deleteExtensionByPath(path: string) { - return invoke(generateJarvisPluginCommand("delete_extension_by_path"), { - path - }) -} - -export function deleteExtensionByExtId(extId: string) { - return invoke(generateJarvisPluginCommand("delete_extension_by_ext_id"), { extId }) -} - -/* -------------------------------------------------------------------------- */ -/* Extension Command CRUD */ -/* -------------------------------------------------------------------------- */ -export function createCommand(data: { - extId: number - name: string - cmdType: CmdType - data: string - alias?: string - hotkey?: string - enabled?: boolean -}) { - return invoke(generateJarvisPluginCommand("create_command"), { - ...data, - enabled: data.enabled ?? false - }) -} - -export function getCommandById(cmdId: number) { - return invoke(generateJarvisPluginCommand("get_command_by_id"), { cmdId }) -} - -export function getCommandsByExtId(extId: number) { - return invoke(generateJarvisPluginCommand("get_commands_by_ext_id"), { extId }) -} - -export function deleteCommandById(cmdId: number) { - return invoke(generateJarvisPluginCommand("delete_command_by_id"), { - cmdId - }) -} - -export function updateCommandById(data: { - cmdId: number - name: string - cmdType: CmdType - data: string - alias?: string - hotkey?: string - enabled: boolean -}) { - return invoke(generateJarvisPluginCommand("update_command_by_id"), data) -} - -/* -------------------------------------------------------------------------- */ -/* Extension Data CRUD */ -/* -------------------------------------------------------------------------- */ -export const ExtDataField = union([literal("data"), literal("search_text")]) -export type ExtDataField = InferOutput - -function convertRawExtDataToExtData(rawData?: { - createdAt: string - updatedAt: string - data: null | string - searchText: null | string -}): ExtData | undefined { - if (!rawData) { - return rawData - } - const parsedRes = safeParse(ExtData, { - ...rawData, - createdAt: new Date(rawData.createdAt), - updatedAt: new Date(rawData.updatedAt), - data: rawData.data ?? undefined, - searchText: rawData.searchText ?? undefined - }) - if (parsedRes.success) { - return parsedRes.output - } else { - console.error("Extension Data Parse Failure", parsedRes.issues) - throw new Error("Fail to parse extension data") - } -} - -export function createExtensionData(data: { - extId: number - dataType: string - data: string - searchText?: string -}) { - return invoke(generateJarvisPluginCommand("create_extension_data"), data) -} - -export function getExtensionDataById(dataId: number, fields?: ExtDataField[]) { - return invoke< - | (ExtData & { - createdAt: string - updatedAt: string - data: null | string - searchText: null | string - }) - | undefined - >(generateJarvisPluginCommand("get_extension_data_by_id"), { - dataId, - fields - }).then(convertRawExtDataToExtData) -} - -/** - * Fields option can be used to select optional fields. By default, if left empty, data and searchText are not returned. - * This is because data and searchText can be large and we don't want to return them by default. - * If you just want to get data ids in order to delete them, retrieving all data is not necessary. - * @param searchParams - */ -export async function searchExtensionData(searchParams: { - extId: number - searchMode: SearchMode - dataId?: number - dataType?: string - searchText?: string - afterCreatedAt?: string - beforeCreatedAt?: string - limit?: number - offset?: number - orderByCreatedAt?: SQLSortOrder - orderByUpdatedAt?: SQLSortOrder - fields?: ExtDataField[] -}): Promise { - const fields = parse(optional(array(ExtDataField), []), searchParams.fields) - let items = await invoke< - (ExtData & { - createdAt: string - updatedAt: string - data: null | string - searchText: null | string - })[] - >(generateJarvisPluginCommand("search_extension_data"), { - searchQuery: { - ...searchParams, - fields - } - }) - - return items.map(convertRawExtDataToExtData).filter((item) => item) as ExtData[] -} - -export function deleteExtensionDataById(dataId: number) { - return invoke(generateJarvisPluginCommand("delete_extension_data_by_id"), { dataId }) -} - -export function updateExtensionDataById(data: { - dataId: number - data: string - searchText?: string -}) { - return invoke(generateJarvisPluginCommand("update_extension_data_by_id"), data) -} - -/* -------------------------------------------------------------------------- */ -/* Built-in Extensions */ -/* -------------------------------------------------------------------------- */ -export function getExtClipboard() { - return getExtensionByIdentifierExpectExists(KUNKUN_EXT_IDENTIFIER.KUNKUN_CLIPBOARD_EXT_IDENTIFIER) -} -export function getExtQuickLinks() { - return getExtensionByIdentifierExpectExists( - KUNKUN_EXT_IDENTIFIER.KUNKUN_QUICK_LINKS_EXT_IDENTIFIER - ) -} -export function getExtRemote() { - return getExtensionByIdentifierExpectExists(KUNKUN_EXT_IDENTIFIER.KUNKUN_REMOTE_EXT_IDENTIFIER) -} -export function getExtScriptCmd() { - return getExtensionByIdentifierExpectExists( - KUNKUN_EXT_IDENTIFIER.KUNKUN_SCRIPT_CMD_EXT_IDENTIFIER - ) -} -export function getExtDev() { - return getExtensionByIdentifierExpectExists(KUNKUN_EXT_IDENTIFIER.KUNKUN_DEV_EXT_IDENTIFIER) -} - -/** - * Database API for extensions. - * Extensions shouldn't have full access to the database, they can only access their own data. - * When an extension is loaded, the main thread will create an instance of this class and - * expose it to the extension. - */ -export class JarvisExtDB { - extId: number - - constructor(extId: number) { - this.extId = extId - } - - async add(data: { data: string; dataType?: string; searchText?: string }) { - return createExtensionData({ - data: data.data, - dataType: data.dataType ?? "default", - searchText: data.searchText, - extId: this.extId - }) - } - - async delete(dataId: number): Promise { - // Verify if this data belongs to this extension - const d = await getExtensionDataById(dataId) - if (!d || d.extId !== this.extId) { - throw new Error("Extension Data not found") - } - return await deleteExtensionDataById(dataId) - } - - async search(searchParams: { - dataId?: number - searchMode?: SearchMode - dataType?: string - searchText?: string - afterCreatedAt?: Date - beforeCreatedAt?: Date - limit?: number - orderByCreatedAt?: SQLSortOrder - orderByUpdatedAt?: SQLSortOrder - fields?: ExtDataField[] - }): Promise { - const beforeCreatedAt = searchParams.beforeCreatedAt - ? convertDateToSqliteString(searchParams.beforeCreatedAt) - : undefined - const afterCreatedAt = searchParams.afterCreatedAt - ? convertDateToSqliteString(searchParams.afterCreatedAt) - : undefined - return searchExtensionData({ - ...searchParams, - searchMode: searchParams.searchMode ?? SearchModeEnum.FTS, - extId: this.extId, - beforeCreatedAt, - afterCreatedAt - }) - } - - /** - * Retrieve all data of this extension. - * Use `search()` method for more advanced search. - * @param options optional fields to retrieve. By default, data and searchText are not returned. - * @returns - */ - retrieveAll(options: { fields?: ExtDataField[] }): Promise { - return this.search({ fields: options.fields }) - } - - /** - * Retrieve all data of this extension by type. - * Use `search()` method for more advanced search. - * @param dataType - * @returns - */ - retrieveAllByType(dataType: string): Promise { - return this.search({ dataType }) - } - - /** - * Delete all data of this extension. - */ - deleteAll(): Promise { - return this.search({}) - .then((items) => { - return Promise.all(items.map((item) => this.delete(item.dataId))) - }) - .then(() => {}) - } - - /** - * Update data and searchText of this extension. - * @param dataId unique id of the data - * @param data - * @param searchText - * @returns - */ - async update(data: { dataId: number; data: string; searchText?: string }): Promise { - const d = await getExtensionDataById(data.dataId) - if (!d || d.extId !== this.extId) { - throw new Error("Extension Data not found") - } - return updateExtensionDataById(data) - } -} - -export class KV { - extId: number - db: JarvisExtDB - private DataType: string = "kunkun_kv" - - constructor(extId: number) { - this.extId = extId - this.db = new JarvisExtDB(extId) - } - - get(key: string): Promise { - return this.db - .search({ - dataType: this.DataType, - searchText: key, - searchMode: SearchModeEnum.ExactMatch, - fields: ["search_text", "data"] - }) - .then((items) => { - if (items.length === 0) { - return null - } else if (items.length > 1) { - throw new Error("Multiple KVs with the same key") - } - return items[0].data ? (JSON.parse(items[0].data).value as T) : null - }) - .catch((err) => { - console.warn(err) - return null - }) - } - - set(key: string, value: string): Promise { - return this.db - .search({ - dataType: this.DataType, - searchText: key, - searchMode: SearchModeEnum.ExactMatch - }) - .then((items) => { - if (items.length === 0) { - return this.db.add({ - data: JSON.stringify({ value: value }), - dataType: this.DataType, - searchText: key - }) - } else if (items.length === 1) { - return this.db.update({ - dataId: items[0].dataId, - data: JSON.stringify({ value: value }), - searchText: key - }) - } else { - return Promise.all(items.map((item) => this.db.delete(item.dataId))).then(() => - Promise.resolve() - ) - } - }) - } - - delete(key: string): Promise { - return this.db - .search({ - dataType: this.DataType, - searchText: key, - searchMode: SearchModeEnum.ExactMatch - }) - .then((items) => { - return Promise.all(items.map((item) => this.db.delete(item.dataId))).then(() => - Promise.resolve() - ) - }) - } - - exists(key: string): Promise { - return this.db - .search({ - dataType: this.DataType, - searchText: key, - searchMode: SearchModeEnum.ExactMatch, - fields: [] - }) - .then((items) => { - return items.length > 0 - }) - } -} diff --git a/packages/api/src/commands/index.ts b/packages/api/src/commands/index.ts index be6154c..25b2c1a 100644 --- a/packages/api/src/commands/index.ts +++ b/packages/api/src/commands/index.ts @@ -5,8 +5,7 @@ export * from "./tools" export * from "./extension" export * from "./system" export * from "./store" -export * as db from "./db" -export { JarvisExtDB } from "./db" +export * as sql from "./sql" export * from "./clipboard" export * from "./fileSearch" export * from "./utils" diff --git a/packages/api/src/commands/sql.ts b/packages/api/src/commands/sql.ts new file mode 100644 index 0000000..ae7eb4c --- /dev/null +++ b/packages/api/src/commands/sql.ts @@ -0,0 +1,30 @@ +import { invoke } from "@tauri-apps/api/core" +import { generateJarvisPluginCommand } from "./common" + +export interface QueryResult { + /** The number of rows affected by the query. */ + rowsAffected: number + /** + * The last inserted `id`. + * + * This value is not set for Postgres databases. If the + * last inserted id is required on Postgres, the `select` function + * must be used, with a `RETURNING` clause + * (`INSERT INTO todos (title) VALUES ($1) RETURNING id`). + */ + lastInsertId?: number +} + +export function select(query: string, values: any[]) { + return invoke(generateJarvisPluginCommand("select"), { + query, + values + }) +} + +export function execute(query: string, values: any[]) { + return invoke(generateJarvisPluginCommand("execute"), { + query, + values + }) +} diff --git a/packages/api/src/models/extension.ts b/packages/api/src/models/extension.ts index 0b8a7d9..1db196d 100644 --- a/packages/api/src/models/extension.ts +++ b/packages/api/src/models/extension.ts @@ -19,7 +19,7 @@ export const Ext = v.object({ identifier: v.string(), version: v.string(), enabled: v.boolean(), - installed_at: v.string(), + installedAt: v.string(), path: v.optional(v.nullable(v.string())), data: v.optional(v.any()) }) @@ -48,6 +48,7 @@ export const ExtCmd = v.object({ hotkey: v.optional(v.nullable(v.string())), enabled: v.boolean() }) + export type ExtCmd = v.InferOutput export const QuickLinkCmd = v.object({ diff --git a/packages/api/src/models/server.ts b/packages/api/src/models/server.ts index 3dd9dd3..87ef50c 100644 --- a/packages/api/src/models/server.ts +++ b/packages/api/src/models/server.ts @@ -5,7 +5,7 @@ import { ExtPackageJson, KunkunExtManifest } from "./manifest" export const ExtPublishSourceTypeEnum = { jsr: "jsr", npm: "npm" -} +} as const export const ExtPublishMetadata = v.object({ source: v.optional(v.string("Source of the extension (e.g. url to package)")), diff --git a/packages/api/src/models/sql.ts b/packages/api/src/models/sql.ts index eddb49f..a1d6719 100644 --- a/packages/api/src/models/sql.ts +++ b/packages/api/src/models/sql.ts @@ -1,12 +1,12 @@ -import { enum_, type InferOutput } from "valibot" +import * as v from "valibot" export enum SQLSortOrderEnum { Asc = "ASC", Desc = "DESC" } -export const SQLSortOrder = enum_(SQLSortOrderEnum) -export type SQLSortOrder = InferOutput +export const SQLSortOrder = v.enum_(SQLSortOrderEnum) +export type SQLSortOrder = v.InferOutput export enum SearchModeEnum { ExactMatch = "exact_match", @@ -14,8 +14,8 @@ export enum SearchModeEnum { FTS = "fts" } -export const SearchMode = enum_(SearchModeEnum) -export type SearchMode = InferOutput +export const SearchMode = v.enum_(SearchModeEnum) +export type SearchMode = v.InferOutput export function convertDateToSqliteString(date: Date) { const pad = (num: number) => num.toString().padStart(2, "0") @@ -29,3 +29,6 @@ export function convertDateToSqliteString(date: Date) { return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` } + +export const ExtDataField = v.union([v.literal("data"), v.literal("search_text")]) +export type ExtDataField = v.InferOutput diff --git a/packages/db/Cargo.toml b/packages/db/Cargo.toml index e7d9e9b..74b86c6 100644 --- a/packages/db/Cargo.toml +++ b/packages/db/Cargo.toml @@ -4,7 +4,9 @@ version = "0.1.0" edition = "2021" [dependencies] -rusqlite = { version = "0.31.0", features = ["bundled-sqlcipher-vendored-openssl"] } +rusqlite = { version = "0.31.0", features = [ + "bundled-sqlcipher-vendored-openssl", +] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } tempfile = "3.10.1" diff --git a/packages/db/src/lib.rs b/packages/db/src/lib.rs index 5f4d27c..5cd3d4a 100644 --- a/packages/db/src/lib.rs +++ b/packages/db/src/lib.rs @@ -2,6 +2,7 @@ pub mod models; pub mod schema; use models::{CmdType, ExtDataField, ExtDataSearchQuery, SearchMode}; use rusqlite::{params, params_from_iter, Connection, Result, ToSql}; +use serde_json::Value as JsonValue; use serde_json::{json, Value}; use std::path::Path; @@ -122,6 +123,97 @@ impl JarvisDB { Ok(()) } + pub fn select(&self, query: String, values: Vec) -> Result> { + println!("DB selecting: {}", query); + println!("DB selecting values: {:?}", values); + let mut stmt = self.conn.prepare(&query)?; + + // Convert JsonValue parameters to appropriate types for rusqlite + let mut params: Vec> = Vec::new(); + for value in values { + if value.is_null() { + params.push(Box::new(Option::::None)); + } else if value.is_string() { + params.push(Box::new(value.as_str().unwrap().to_owned())); + } else if let Some(number) = value.as_number() { + if number.is_i64() { + params.push(Box::new(number.as_i64().unwrap())); + } else if number.is_u64() { + params.push(Box::new(number.as_u64().unwrap() as i64)); + } else { + params.push(Box::new(number.as_f64().unwrap())); + } + } else { + params.push(Box::new(value.to_string())); + } + } + + // Get column names from statement + let column_names: Vec = (0..stmt.column_count()) + .map(|i| stmt.column_name(i).unwrap().to_string()) + .collect(); + + // Execute the query with the converted parameters and map results + let rows = stmt.query_map(params_from_iter(params.iter().map(|p| p.as_ref())), |row| { + let mut result = Vec::new(); + for i in 0..column_names.len() { + let value: Value = match row.get_ref(i)? { + rusqlite::types::ValueRef::Null => Value::Null, + rusqlite::types::ValueRef::Integer(i) => Value::Number(i.into()), + rusqlite::types::ValueRef::Real(r) => Value::Number( + serde_json::Number::from_f64(r).unwrap_or(serde_json::Number::from(0)), + ), + rusqlite::types::ValueRef::Text(t) => { + Value::String(String::from_utf8_lossy(t).into_owned()) + } + rusqlite::types::ValueRef::Blob(b) => { + Value::String(String::from_utf8_lossy(b).into_owned()) + } + }; + result.push(value); + } + Ok(Value::Array(result)) + })?; + + let mut results = Vec::new(); + for row in rows { + results.push(row?); + } + Ok(results) + } + + pub fn execute(&self, query: &str, values: Vec) -> Result<(u64, i64)> { + let mut stmt = self.conn.prepare(query)?; + + // Convert JsonValue parameters to appropriate types for rusqlite + let mut params: Vec> = Vec::new(); + for value in values { + if value.is_null() { + params.push(Box::new(Option::::None)); + } else if value.is_string() { + params.push(Box::new(value.as_str().unwrap().to_owned())); + } else if let Some(number) = value.as_number() { + if number.is_i64() { + params.push(Box::new(number.as_i64().unwrap())); + } else if number.is_u64() { + params.push(Box::new(number.as_u64().unwrap() as i64)); + } else { + params.push(Box::new(number.as_f64().unwrap())); + } + } else { + params.push(Box::new(value.to_string())); + } + } + + // Execute the query with the converted parameters + let rows_affected = stmt.execute(params_from_iter(params.iter().map(|p| p.as_ref())))?; + + // Get the last insert rowid + let last_insert_id = self.conn.last_insert_rowid(); + + Ok((rows_affected as u64, last_insert_id)) + } + pub fn get_all_extensions(&self) -> Result> { let mut stmt = self.conn.prepare( "SELECT ext_id, identifier, path, data, version, enabled, installed_at FROM extensions", @@ -983,4 +1075,72 @@ mod tests { fs::remove_file(&db_path).unwrap(); } + + #[test] + fn test_select_and_execute() { + let dir = tempdir().unwrap(); + let db_path = dir.path().join("test.db"); + let db = JarvisDB::new(&db_path, None).unwrap(); + db.init().unwrap(); + + // Create a simple todo table + db.execute( + "CREATE TABLE todos (id INTEGER PRIMARY KEY, title TEXT, completed BOOLEAN)", + vec![], + ) + .unwrap(); + + // Test execute with INSERT + let (rows_affected, last_id) = db + .execute( + "INSERT INTO todos (title, completed) VALUES (?1, ?2)", + vec![json!("Buy groceries"), json!(false)], + ) + .unwrap(); + assert_eq!(rows_affected, 1); + assert_eq!(last_id, 1); + + // Test select with basic query + let results = db + .select( + "SELECT title, completed FROM todos WHERE id = ?1".to_string(), + vec![json!(1)], + ) + .unwrap(); + assert_eq!(results.len(), 1); + assert_eq!(results[0][0], "Buy groceries"); + assert_eq!(results[0][1], "false"); + + // Test execute with UPDATE + let (rows_affected, _) = db + .execute( + "UPDATE todos SET completed = ?1 WHERE id = ?2", + vec![json!(true), json!(1)], + ) + .unwrap(); + assert_eq!(rows_affected, 1); + + // Verify the update with select + let results = db + .select( + "SELECT completed FROM todos WHERE id = ?1".to_string(), + vec![json!(1)], + ) + .unwrap(); + assert_eq!(results[0][0], "true"); + + // Test execute with DELETE + let (rows_affected, _) = db + .execute("DELETE FROM todos WHERE id = ?1", vec![json!(1)]) + .unwrap(); + assert_eq!(rows_affected, 1); + + // Verify the deletion + let results = db + .select("SELECT COUNT(*) as count FROM todos".to_string(), vec![]) + .unwrap(); + assert_eq!(results[0][0], 0); + + fs::remove_file(&db_path).unwrap(); + } } diff --git a/packages/drizzle/.gitignore b/packages/drizzle/.gitignore new file mode 100644 index 0000000..a14702c --- /dev/null +++ b/packages/drizzle/.gitignore @@ -0,0 +1,34 @@ +# dependencies (bun install) +node_modules + +# output +out +dist +*.tgz + +# code coverage +coverage +*.lcov + +# logs +logs +_.log +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# caches +.eslintcache +.cache +*.tsbuildinfo + +# IntelliJ based IDEs +.idea + +# Finder (MacOS) folder config +.DS_Store diff --git a/packages/drizzle/README.md b/packages/drizzle/README.md new file mode 100644 index 0000000..9ce0c45 --- /dev/null +++ b/packages/drizzle/README.md @@ -0,0 +1,35 @@ +# drizzle + +- Only use `pull` to generate the schema from existing database. +- Don't `migrate` or `push`. + +```bash +export DB_FILE_NAME="~/Library/Application Support/sh.kunkun.desktop/kk.dev.sqlite" +bunx drizzle-kit pull +``` + +We are using sqlite with fts5, which drizzle doesn't support yet, so pushing the schema will destroy the existing schema. + +We only use pulled schema to generate sql queries. + +## Update Schema + +After `drizzle-kit pull` the schema may have problem with JSON type and boolean type. + +Will need to manually update the following + +### JSON + +```diff lang="ts" ++ data: text({ mode: "json" }).notNull(), ++ metadata: text({ mode: "json" }), +- data: numeric().notNull(), +- metadata: numeric(), +``` + +### Boolean + +```diff lang="ts" ++ enabled: integer({ mode: "boolean" }), +- enabled: numeric().default(sql`(TRUE)`), +``` diff --git a/packages/drizzle/drizzle.config.ts b/packages/drizzle/drizzle.config.ts new file mode 100644 index 0000000..c7ec2f3 --- /dev/null +++ b/packages/drizzle/drizzle.config.ts @@ -0,0 +1,15 @@ +import "dotenv/config" +import { defineConfig } from "drizzle-kit" + +if (!process.env.DB_FILE_NAME) { + throw new Error("DB_FILE_NAME is not set") +} + +export default defineConfig({ + out: "./drizzle", + // schema: "./src/db/schema.ts", + dialect: "sqlite", + dbCredentials: { + url: process.env.DB_FILE_NAME + } +}) diff --git a/packages/drizzle/drizzle/0000_colossal_jocasta.sql b/packages/drizzle/drizzle/0000_colossal_jocasta.sql new file mode 100644 index 0000000..007c393 --- /dev/null +++ b/packages/drizzle/drizzle/0000_colossal_jocasta.sql @@ -0,0 +1,71 @@ +-- Current sql file was generated after introspecting the database +-- If you want to run this migration please uncomment this code before executing migrations +/* +CREATE TABLE `schema_version` ( + `version` integer NOT NULL +); +--> statement-breakpoint +CREATE TABLE `extensions` ( + `ext_id` integer PRIMARY KEY AUTOINCREMENT, + `identifier` text NOT NULL, + `version` text NOT NULL, + `enabled` numeric DEFAULT (TRUE), + `path` text, + `data` numeric, + `installed_at` numeric DEFAULT (CURRENT_TIMESTAMP) +); +--> statement-breakpoint +CREATE TABLE `commands` ( + `cmd_id` integer PRIMARY KEY AUTOINCREMENT, + `ext_id` integer NOT NULL, + `name` text NOT NULL, + `enabled` numeric DEFAULT (TRUE), + `alias` text, + `hotkey` text, + `type` text NOT NULL, + `data` numeric, + FOREIGN KEY (`ext_id`) REFERENCES `extensions`(`ext_id`) ON UPDATE no action ON DELETE cascade +); +--> statement-breakpoint +CREATE TABLE `extension_data` ( + `data_id` integer PRIMARY KEY AUTOINCREMENT, + `ext_id` integer NOT NULL, + `data_type` text NOT NULL, + `data` numeric NOT NULL, + `metadata` numeric, + `search_text` text, + `created_at` numeric DEFAULT (CURRENT_TIMESTAMP), + `updated_at` numeric DEFAULT (CURRENT_TIMESTAMP), + FOREIGN KEY (`ext_id`) REFERENCES `extensions`(`ext_id`) ON UPDATE no action ON DELETE cascade +); +--> statement-breakpoint +CREATE TABLE `extension_data_fts` ( + `data_id` numeric, + `search_text` numeric, + `extension_data_fts` numeric, + `rank` numeric +); +--> statement-breakpoint +CREATE TABLE `extension_data_fts_data` ( + `id` integer PRIMARY KEY, + `block` blob +); +--> statement-breakpoint +CREATE TABLE `extension_data_fts_idx` ( + `segid` numeric NOT NULL, + `term` numeric NOT NULL, + `pgno` numeric, + PRIMARY KEY(`segid`, `term`) +); +--> statement-breakpoint +CREATE TABLE `extension_data_fts_docsize` ( + `id` integer PRIMARY KEY, + `sz` blob +); +--> statement-breakpoint +CREATE TABLE `extension_data_fts_config` ( + `k` numeric PRIMARY KEY NOT NULL, + `v` numeric +); + +*/ \ No newline at end of file diff --git a/packages/drizzle/drizzle/meta/0000_snapshot.json b/packages/drizzle/drizzle/meta/0000_snapshot.json new file mode 100644 index 0000000..6bc517c --- /dev/null +++ b/packages/drizzle/drizzle/meta/0000_snapshot.json @@ -0,0 +1,405 @@ +{ + "id": "00000000-0000-0000-0000-000000000000", + "prevId": "", + "version": "6", + "dialect": "sqlite", + "tables": { + "schema_version": { + "name": "schema_version", + "columns": { + "version": { + "autoincrement": false, + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "extensions": { + "name": "extensions", + "columns": { + "ext_id": { + "autoincrement": true, + "name": "ext_id", + "type": "integer", + "primaryKey": true, + "notNull": false + }, + "identifier": { + "autoincrement": false, + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version": { + "autoincrement": false, + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "default": "(TRUE)", + "autoincrement": false, + "name": "enabled", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "path": { + "autoincrement": false, + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "data": { + "autoincrement": false, + "name": "data", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "installed_at": { + "default": "(CURRENT_TIMESTAMP)", + "autoincrement": false, + "name": "installed_at", + "type": "numeric", + "primaryKey": false, + "notNull": false + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "commands": { + "name": "commands", + "columns": { + "cmd_id": { + "autoincrement": true, + "name": "cmd_id", + "type": "integer", + "primaryKey": true, + "notNull": false + }, + "ext_id": { + "autoincrement": false, + "name": "ext_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "name": { + "autoincrement": false, + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "default": "(TRUE)", + "autoincrement": false, + "name": "enabled", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "alias": { + "autoincrement": false, + "name": "alias", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "hotkey": { + "autoincrement": false, + "name": "hotkey", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "autoincrement": false, + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "data": { + "autoincrement": false, + "name": "data", + "type": "numeric", + "primaryKey": false, + "notNull": false + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": { + "commands_ext_id_extensions_ext_id_fk": { + "name": "commands_ext_id_extensions_ext_id_fk", + "tableFrom": "commands", + "tableTo": "extensions", + "columnsFrom": [ + "ext_id" + ], + "columnsTo": [ + "ext_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "extension_data": { + "name": "extension_data", + "columns": { + "data_id": { + "autoincrement": true, + "name": "data_id", + "type": "integer", + "primaryKey": true, + "notNull": false + }, + "ext_id": { + "autoincrement": false, + "name": "ext_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "data_type": { + "autoincrement": false, + "name": "data_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "data": { + "autoincrement": false, + "name": "data", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "autoincrement": false, + "name": "metadata", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "search_text": { + "autoincrement": false, + "name": "search_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "default": "(CURRENT_TIMESTAMP)", + "autoincrement": false, + "name": "created_at", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "default": "(CURRENT_TIMESTAMP)", + "autoincrement": false, + "name": "updated_at", + "type": "numeric", + "primaryKey": false, + "notNull": false + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": { + "extension_data_ext_id_extensions_ext_id_fk": { + "name": "extension_data_ext_id_extensions_ext_id_fk", + "tableFrom": "extension_data", + "tableTo": "extensions", + "columnsFrom": [ + "ext_id" + ], + "columnsTo": [ + "ext_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "extension_data_fts": { + "name": "extension_data_fts", + "columns": { + "data_id": { + "autoincrement": false, + "name": "data_id", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "search_text": { + "autoincrement": false, + "name": "search_text", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "extension_data_fts": { + "autoincrement": false, + "name": "extension_data_fts", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "rank": { + "autoincrement": false, + "name": "rank", + "type": "numeric", + "primaryKey": false, + "notNull": false + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "extension_data_fts_data": { + "name": "extension_data_fts_data", + "columns": { + "id": { + "autoincrement": false, + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": false + }, + "block": { + "autoincrement": false, + "name": "block", + "type": "blob", + "primaryKey": false, + "notNull": false + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "extension_data_fts_idx": { + "name": "extension_data_fts_idx", + "columns": { + "segid": { + "autoincrement": false, + "name": "segid", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "term": { + "autoincrement": false, + "name": "term", + "type": "numeric", + "primaryKey": false, + "notNull": true + }, + "pgno": { + "autoincrement": false, + "name": "pgno", + "type": "numeric", + "primaryKey": false, + "notNull": false + } + }, + "compositePrimaryKeys": { + "extension_data_fts_idx_segid_term_pk": { + "columns": [ + "segid", + "term" + ], + "name": "extension_data_fts_idx_segid_term_pk" + } + }, + "indexes": {}, + "foreignKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "extension_data_fts_docsize": { + "name": "extension_data_fts_docsize", + "columns": { + "id": { + "autoincrement": false, + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": false + }, + "sz": { + "autoincrement": false, + "name": "sz", + "type": "blob", + "primaryKey": false, + "notNull": false + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "extension_data_fts_config": { + "name": "extension_data_fts_config", + "columns": { + "k": { + "autoincrement": false, + "name": "k", + "type": "numeric", + "primaryKey": true, + "notNull": true + }, + "v": { + "autoincrement": false, + "name": "v", + "type": "numeric", + "primaryKey": false, + "notNull": false + } + }, + "compositePrimaryKeys": {}, + "indexes": {}, + "foreignKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/packages/drizzle/drizzle/meta/_journal.json b/packages/drizzle/drizzle/meta/_journal.json new file mode 100644 index 0000000..ce42543 --- /dev/null +++ b/packages/drizzle/drizzle/meta/_journal.json @@ -0,0 +1,13 @@ +{ + "version": "7", + "dialect": "sqlite", + "entries": [ + { + "idx": 0, + "version": "6", + "when": 1742544246324, + "tag": "0000_colossal_jocasta", + "breakpoints": true + } + ] +} \ No newline at end of file diff --git a/packages/drizzle/drizzle/relations.ts b/packages/drizzle/drizzle/relations.ts new file mode 100644 index 0000000..e1e2387 --- /dev/null +++ b/packages/drizzle/drizzle/relations.ts @@ -0,0 +1,21 @@ +import { relations } from "drizzle-orm/relations" +import { commands, extensionData, extensions } from "./schema" + +export const commandsRelations = relations(commands, ({ one }) => ({ + extension: one(extensions, { + fields: [commands.extId], + references: [extensions.extId] + }) +})) + +export const extensionsRelations = relations(extensions, ({ many }) => ({ + commands: many(commands), + extensionData: many(extensionData) +})) + +export const extensionDataRelations = relations(extensionData, ({ one }) => ({ + extension: one(extensions, { + fields: [extensionData.extId], + references: [extensions.extId] + }) +})) diff --git a/packages/drizzle/drizzle/schema.ts b/packages/drizzle/drizzle/schema.ts new file mode 100644 index 0000000..bf7a0b4 --- /dev/null +++ b/packages/drizzle/drizzle/schema.ts @@ -0,0 +1,88 @@ +import { sql } from "drizzle-orm" +import { + blob, + foreignKey, + integer, + numeric, + primaryKey, + sqliteTable, + text +} from "drizzle-orm/sqlite-core" + +export const schemaVersion = sqliteTable("schema_version", { + version: integer().notNull() +}) + +export const extensions = sqliteTable("extensions", { + extId: integer("ext_id").primaryKey({ autoIncrement: true }), + identifier: text().notNull(), + version: text().notNull(), + // enabled: numeric().default(sql`(TRUE)`), + enabled: integer({ mode: "boolean" }), + path: text(), + data: numeric(), + installedAt: numeric("installed_at").default(sql`(CURRENT_TIMESTAMP)`) +}) + +export const commands = sqliteTable("commands", { + cmdId: integer("cmd_id").primaryKey({ autoIncrement: true }), + extId: integer("ext_id") + .notNull() + .references(() => extensions.extId, { onDelete: "cascade" }), + name: text().notNull(), + enabled: integer({ mode: "boolean" }), + // enabled: numeric().default(sql`(TRUE)`), + alias: text(), + hotkey: text(), + type: text().notNull(), + data: numeric() +}) + +export const extensionData = sqliteTable("extension_data", { + dataId: integer("data_id").primaryKey({ autoIncrement: true }), + extId: integer("ext_id") + .notNull() + .references(() => extensions.extId, { onDelete: "cascade" }), + dataType: text("data_type").notNull(), + // data: text({ mode: "json" }).notNull(), + // metadata: text({ mode: "json" }), + data: text("data").notNull(), + metadata: text("metadata"), + searchText: text("search_text"), + createdAt: numeric("created_at").default(sql`(CURRENT_TIMESTAMP)`), + updatedAt: numeric("updated_at").default(sql`(CURRENT_TIMESTAMP)`) +}) + +export const extensionDataFts = sqliteTable("extension_data_fts", { + dataId: numeric("data_id"), + searchText: numeric("search_text"), + extensionDataFts: numeric("extension_data_fts"), + rank: numeric() +}) + +export const extensionDataFtsData = sqliteTable("extension_data_fts_data", { + id: integer().primaryKey(), + block: blob() +}) + +export const extensionDataFtsIdx = sqliteTable( + "extension_data_fts_idx", + { + segid: numeric().notNull(), + term: numeric().notNull(), + pgno: numeric() + }, + (table) => [ + primaryKey({ columns: [table.segid, table.term], name: "extension_data_fts_idx_segid_term_pk" }) + ] +) + +export const extensionDataFtsDocsize = sqliteTable("extension_data_fts_docsize", { + id: integer().primaryKey(), + sz: blob() +}) + +export const extensionDataFtsConfig = sqliteTable("extension_data_fts_config", { + k: numeric().primaryKey().notNull(), + v: numeric() +}) diff --git a/packages/drizzle/index.ts b/packages/drizzle/index.ts new file mode 100644 index 0000000..7be6aab --- /dev/null +++ b/packages/drizzle/index.ts @@ -0,0 +1,3 @@ +export * as schema from "./drizzle/schema" +export * as relations from "./drizzle/relations" +export * as db from "./src/apis" diff --git a/packages/drizzle/package.json b/packages/drizzle/package.json new file mode 100644 index 0000000..630ad3a --- /dev/null +++ b/packages/drizzle/package.json @@ -0,0 +1,26 @@ +{ + "name": "@kksh/drizzle", + "type": "module", + "private": true, + "exports": { + ".": "./index.ts", + "./api": "./src/apis.ts", + "./schema": "./drizzle/schema.ts", + "./relations": "./drizzle/relations.ts" + }, + "devDependencies": { + "@types/bun": "latest", + "drizzle-kit": "^0.30.5", + "tsx": "^4.19.3" + }, + "peerDependencies": { + "typescript": "^5" + }, + "dependencies": { + "@kksh/api": "workspace:*", + "@libsql/client": "^0.15.1", + "@tauri-apps/plugin-log": "^2.3.1", + "dotenv": "^16.4.7", + "drizzle-orm": "^0.41.0" + } +} diff --git a/packages/drizzle/src/apis.ts b/packages/drizzle/src/apis.ts new file mode 100644 index 0000000..c70e043 --- /dev/null +++ b/packages/drizzle/src/apis.ts @@ -0,0 +1,616 @@ +import { KUNKUN_EXT_IDENTIFIER, type IDb, type IKV } from "@kksh/api" +import { + CmdType, + convertDateToSqliteString, + Ext, + ExtCmd, + ExtData, + SearchMode, + SearchModeEnum, + SQLSortOrder, + SQLSortOrderEnum +} from "@kksh/api/models" +import * as relations from "@kksh/drizzle/relations" +import * as orm from "drizzle-orm" +import type { SelectedFields } from "drizzle-orm/sqlite-core" +import * as v from "valibot" +import * as schema from "../drizzle/schema" +import { db } from "./proxy" + +/* -------------------------------------------------------------------------- */ +/* Built-in Extensions */ +/* -------------------------------------------------------------------------- */ +export function getExtClipboard(): Promise { + return getExtensionByIdentifierExpectExists(KUNKUN_EXT_IDENTIFIER.KUNKUN_CLIPBOARD_EXT_IDENTIFIER) +} +export function getExtQuickLinks(): Promise { + return getExtensionByIdentifierExpectExists( + KUNKUN_EXT_IDENTIFIER.KUNKUN_QUICK_LINKS_EXT_IDENTIFIER + ) +} +export function getExtRemote(): Promise { + return getExtensionByIdentifierExpectExists(KUNKUN_EXT_IDENTIFIER.KUNKUN_REMOTE_EXT_IDENTIFIER) +} +export function getExtScriptCmd(): Promise { + return getExtensionByIdentifierExpectExists( + KUNKUN_EXT_IDENTIFIER.KUNKUN_SCRIPT_CMD_EXT_IDENTIFIER + ) +} +export function getExtDev(): Promise { + return getExtensionByIdentifierExpectExists(KUNKUN_EXT_IDENTIFIER.KUNKUN_DEV_EXT_IDENTIFIER) +} + +/* -------------------------------------------------------------------------- */ +/* Extension CRUD */ +/* -------------------------------------------------------------------------- */ +export function createExtension(ext: { + identifier: string + version: string + enabled?: boolean + path?: string + data?: any +}) { + return db + .insert(schema.extensions) + .values({ + identifier: ext.identifier, + version: ext.version, + enabled: ext.enabled, + path: ext.path, + data: ext.data + }) + .run() +} + +export async function getUniqueExtensionByIdentifier(identifier: string): Promise { + const ext = await db + .select() + .from(schema.extensions) + .where(orm.eq(schema.extensions.identifier, identifier)) + .get() + const result = v.safeParse(v.optional(Ext), ext) + if (!result.success) { + console.error("Failed to parse extension:", v.flatten(result.issues)) + return undefined + } + const parsed = result.output + return parsed +} + +/** + * Use this function when you expect the extension to exist. Such as builtin extensions. + * @param identifier + * @returns + */ +export function getExtensionByIdentifierExpectExists(identifier: string): Promise { + return getUniqueExtensionByIdentifier(identifier).then((ext) => { + if (!ext) { + throw new Error(`Unexpexted Error: Extension ${identifier} not found`) + } + return ext + }) +} + +export async function getAllExtensions(): Promise { + const exts = await db.select().from(schema.extensions).all() + return v.parse(v.array(Ext), exts) +} + +/** + * There can be duplicate extensions with the same identifier. Store and Dev extensions can have the same identifier. + * But install path must be unique. + * @param path + */ +export async function getUniqueExtensionByPath(path: string) { + const ext = await db + .select() + .from(schema.extensions) + .where(orm.eq(schema.extensions.path, path)) + .get() + return v.parse(Ext, ext) +} + +export function getAllExtensionsByIdentifier(identifier: string): Promise { + return db + .select() + .from(schema.extensions) + .where(orm.eq(schema.extensions.identifier, identifier)) + .all() + .then((exts) => v.parse(v.array(Ext), exts)) +} + +export function deleteExtensionByPath(path: string): Promise { + return db + .delete(schema.extensions) + .where(orm.eq(schema.extensions.path, path)) + .run() + .then(() => undefined) +} + +export function deleteExtensionByExtId(extId: number): Promise { + return db + .delete(schema.extensions) + .where(orm.eq(schema.extensions.extId, extId)) + .run() + .then(() => undefined) +} + +/* -------------------------------------------------------------------------- */ +/* Extension Command CRUD */ +/* -------------------------------------------------------------------------- */ +export function createCommand(data: { + extId: number + name: string + cmdType: CmdType + data: string + alias?: string + hotkey?: string + enabled?: boolean +}) { + return db + .insert(schema.commands) + .values({ + extId: data.extId, + name: data.name, + type: data.cmdType, + data: data.data, + alias: data.alias, + hotkey: data.hotkey, + enabled: data.enabled ?? true + }) + .run() + .then(() => undefined) +} + +export async function getCmdById(cmdId: number): Promise { + const cmd = await db + .select() + .from(schema.commands) + .where(orm.eq(schema.commands.cmdId, cmdId)) + .get() + return v.parse(ExtCmd, cmd) +} + +export async function getAllCmds(): Promise { + const cmds = await db.select().from(schema.commands).all() + return v.parse(v.array(ExtCmd), cmds) +} + +export function getCommandsByExtId(extId: number) { + return db + .select() + .from(schema.commands) + .where(orm.eq(schema.commands.extId, extId)) + .all() + .then((cmds) => v.parse(v.array(ExtCmd), cmds)) +} + +export function deleteCmdById(cmdId: number) { + return db + .delete(schema.commands) + .where(orm.eq(schema.commands.cmdId, cmdId)) + .run() + .then(() => undefined) +} + +export function updateCmdByID(data: { + cmdId: number + name: string + cmdType: CmdType + data: string + alias?: string + hotkey?: string + enabled: boolean +}) { + return db + .update(schema.commands) + .set({ + name: data.name, + type: data.cmdType, + data: data.data, + alias: data.alias, // optional + hotkey: data.hotkey, // optional + enabled: data.enabled + // in drizzle schema, use integer({ mode: 'boolean' }) for boolean sqlite + // enabled: data.enabled ? String(data.enabled) : undefined + }) + .where(orm.eq(schema.commands.cmdId, data.cmdId)) + .run() + .then(() => undefined) +} + +/* -------------------------------------------------------------------------- */ +/* Extension Data CRUD */ +/* -------------------------------------------------------------------------- */ +export const ExtDataField = v.union([v.literal("data"), v.literal("search_text")]) +export type ExtDataField = v.InferOutput + +function convertRawExtDataToExtData(rawData?: { + createdAt: string + updatedAt: string + data: null | string + searchText?: null | string + dataId: number + extId: number + dataType: string +}): ExtData | undefined { + if (!rawData) { + return rawData + } + const parsedRes = v.safeParse(ExtData, { + ...rawData, + createdAt: new Date(rawData.createdAt), + updatedAt: new Date(rawData.updatedAt), + data: rawData.data ?? undefined, + searchText: rawData.searchText ?? undefined + }) + if (parsedRes.success) { + return parsedRes.output + } else { + console.error("Extension Data Parse Failure", parsedRes.issues) + throw new Error("Fail to parse extension data") + } +} + +export function createExtensionData(data: { + extId: number + dataType: string + data: string + searchText?: string +}) { + return db.insert(schema.extensionData).values(data).run() +} + +export function getExtensionDataById(dataId: number, fields?: ExtDataField[]) { + const _fields = fields ?? [] + const selectQuery: SelectedFields = { + dataId: schema.extensionData.dataId, + extId: schema.extensionData.extId, + dataType: schema.extensionData.dataType, + metadata: schema.extensionData.metadata, + createdAt: schema.extensionData.createdAt, + updatedAt: schema.extensionData.updatedAt + // data: schema.extensionData.data, + // searchText: schema.extensionData.searchText + } + if (_fields.includes("data")) { + selectQuery["data"] = schema.extensionData.data + } + if (_fields.includes("search_text")) { + selectQuery["searchText"] = schema.extensionData.searchText + } + return db + .select(selectQuery) + .from(schema.extensionData) + .where(orm.eq(schema.extensionData.dataId, dataId)) + .get() + .then((rawData) => { + console.log("Raw Data", rawData) + // @ts-expect-error - rawData is unknown, but will be safe parsed with valibot + return convertRawExtDataToExtData(rawData) + }) +} + +export async function searchExtensionData(searchParams: { + extId: number + searchMode: SearchMode + dataId?: number + dataType?: string + searchText?: string + afterCreatedAt?: string + beforeCreatedAt?: string + limit?: number + offset?: number + orderByCreatedAt?: SQLSortOrder + orderByUpdatedAt?: SQLSortOrder + fields?: ExtDataField[] +}): Promise { + const fields = v.parse(v.optional(v.array(ExtDataField), []), searchParams.fields) + const _fields = fields ?? [] + + // Build the select query based on fields + const selectQuery: SelectedFields = { + dataId: schema.extensionData.dataId, + extId: schema.extensionData.extId, + dataType: schema.extensionData.dataType, + createdAt: schema.extensionData.createdAt, + updatedAt: schema.extensionData.updatedAt + } + + if (_fields.includes("data")) { + selectQuery["data"] = schema.extensionData.data + } + if (_fields.includes("search_text")) { + selectQuery["searchText"] = schema.extensionData.searchText + } + + // Build the query + let baseQuery = db.select(selectQuery).from(schema.extensionData) + + // Add FTS join if needed + if (searchParams.searchMode === SearchModeEnum.FTS && searchParams.searchText) { + // @ts-expect-error - The join type is correct but TypeScript can't infer it properly + baseQuery = baseQuery.innerJoin( + schema.extensionDataFts, + orm.eq(schema.extensionData.dataId, schema.extensionDataFts.dataId) + ) + } + + // Add conditions + const conditions = [orm.eq(schema.extensionData.extId, searchParams.extId)] + + if (searchParams.dataId) { + conditions.push(orm.eq(schema.extensionData.dataId, searchParams.dataId)) + } + + if (searchParams.dataType) { + conditions.push(orm.eq(schema.extensionData.dataType, searchParams.dataType)) + } + + if (searchParams.searchText) { + switch (searchParams.searchMode) { + case SearchModeEnum.ExactMatch: + conditions.push(orm.eq(schema.extensionData.searchText, searchParams.searchText)) + break + case SearchModeEnum.Like: + conditions.push(orm.like(schema.extensionData.searchText, `%${searchParams.searchText}%`)) + break + case SearchModeEnum.FTS: + conditions.push( + orm.sql`${schema.extensionDataFts.searchText} MATCH ${searchParams.searchText}` + ) + break + } + } + + if (searchParams.afterCreatedAt) { + conditions.push(orm.gt(schema.extensionData.createdAt, searchParams.afterCreatedAt)) + } + + if (searchParams.beforeCreatedAt) { + conditions.push(orm.lt(schema.extensionData.createdAt, searchParams.beforeCreatedAt)) + } + + // Build the final query with all conditions and modifiers + const query = baseQuery + .where(orm.and(...conditions)) + .orderBy( + searchParams.orderByCreatedAt + ? searchParams.orderByCreatedAt === SQLSortOrderEnum.Asc + ? orm.asc(schema.extensionData.createdAt) + : orm.desc(schema.extensionData.createdAt) + : searchParams.orderByUpdatedAt + ? searchParams.orderByUpdatedAt === SQLSortOrderEnum.Asc + ? orm.asc(schema.extensionData.updatedAt) + : orm.desc(schema.extensionData.updatedAt) + : orm.asc(schema.extensionData.createdAt) // Default ordering + ) + .limit(searchParams.limit ?? 100) // Default limit + .offset(searchParams.offset ?? 0) // Default offset + + // Execute query and convert results + const results = await query.all() + return results + .map((rawData) => { + // @ts-expect-error - rawData is unknown, but will be safe parsed with valibot + return convertRawExtDataToExtData(rawData) + }) + .filter((item): item is ExtData => item !== undefined) +} + +export function deleteExtensionDataById(dataId: number) { + return db + .delete(schema.extensionData) + .where(orm.eq(schema.extensionData.dataId, dataId)) + .run() + .then(() => undefined) +} + +export function updateExtensionDataById(data: { + dataId: number + data: string + searchText?: string +}): Promise { + return db + .update(schema.extensionData) + .set({ + data: data.data, + searchText: data.searchText + }) + .where(orm.eq(schema.extensionData.dataId, data.dataId)) + .run() + .then(() => undefined) +} + +/** + * Database API for extensions. + * Extensions shouldn't have full access to the database, they can only access their own data. + * When an extension is loaded, the main thread will create an instance of this class and + * expose it to the extension. + */ +export class JarvisExtDB implements IDb { + extId: number + + constructor(extId: number) { + this.extId = extId + } + + async add(data: { data: string; dataType?: string; searchText?: string }): Promise { + return createExtensionData({ + data: data.data, + dataType: data.dataType ?? "default", + searchText: data.searchText, + extId: this.extId + }).then(() => undefined) + } + + async delete(dataId: number): Promise { + // Verify if this data belongs to this extension + const d = await getExtensionDataById(dataId) + if (!d || d.extId !== this.extId) { + throw new Error("Extension Data not found") + } + return await deleteExtensionDataById(dataId) + } + + async search(searchParams: { + dataId?: number + searchMode?: SearchMode + dataType?: string + searchText?: string + afterCreatedAt?: Date + beforeCreatedAt?: Date + limit?: number + orderByCreatedAt?: SQLSortOrder + orderByUpdatedAt?: SQLSortOrder + fields?: ExtDataField[] + }): Promise { + const beforeCreatedAt = searchParams.beforeCreatedAt + ? convertDateToSqliteString(searchParams.beforeCreatedAt) + : undefined + const afterCreatedAt = searchParams.afterCreatedAt + ? convertDateToSqliteString(searchParams.afterCreatedAt) + : undefined + return searchExtensionData({ + ...searchParams, + searchMode: searchParams.searchMode ?? SearchModeEnum.FTS, + extId: this.extId, + beforeCreatedAt, + afterCreatedAt + }) + } + + /** + * Retrieve all data of this extension. + * Use `search()` method for more advanced search. + * @param options optional fields to retrieve. By default, data and searchText are not returned. + * @returns + */ + retrieveAll(options: { fields?: ExtDataField[] }): Promise { + return this.search({ fields: options.fields }) + } + + /** + * Retrieve all data of this extension by type. + * Use `search()` method for more advanced search. + * @param dataType + * @returns + */ + retrieveAllByType(dataType: string): Promise { + return this.search({ dataType }) + } + + /** + * Delete all data of this extension. + */ + deleteAll(): Promise { + return this.search({}) + .then((items) => { + return Promise.all(items.map((item) => this.delete(item.dataId))) + }) + .then(() => {}) + } + + /** + * Update data and searchText of this extension. + * @param dataId unique id of the data + * @param data + * @param searchText + * @returns + */ + async update(data: { dataId: number; data: string; searchText?: string }): Promise { + const d = await getExtensionDataById(data.dataId) + if (!d || d.extId !== this.extId) { + throw new Error("Extension Data not found") + } + return updateExtensionDataById(data) + } +} + +export class KV implements IKV { + extId: number + db: JarvisExtDB + private DataType: string = "kunkun_kv" + + constructor(extId: number) { + this.extId = extId + this.db = new JarvisExtDB(extId) + } + + get(key: string): Promise { + return this.db + .search({ + dataType: this.DataType, + searchText: key, + searchMode: SearchModeEnum.ExactMatch, + fields: ["search_text", "data"] + }) + .then((items) => { + if (items.length === 0) { + return null + } else if (items.length > 1) { + throw new Error("Multiple KVs with the same key") + } + return items[0]?.data ? (JSON.parse(items[0].data).value as T) : null + }) + .catch((err) => { + console.warn(err) + return null + }) + } + + set(key: string, value: string): Promise { + return this.db + .search({ + dataType: this.DataType, + searchText: key, + searchMode: SearchModeEnum.ExactMatch + }) + .then((items) => { + if (items.length === 0) { + return this.db.add({ + data: JSON.stringify({ value: value }), + dataType: this.DataType, + searchText: key + }) + } else if (items.length === 1) { + return this.db.update({ + dataId: items[0]!.dataId, + data: JSON.stringify({ value: value }), + searchText: key + }) + } else { + return Promise.all(items.map((item) => this.db.delete(item.dataId))).then(() => + Promise.resolve() + ) + } + }) + } + + delete(key: string): Promise { + return this.db + .search({ + dataType: this.DataType, + searchText: key, + searchMode: SearchModeEnum.ExactMatch + }) + .then((items) => { + return Promise.all(items.map((item) => this.db.delete(item.dataId))).then(() => + Promise.resolve() + ) + }) + } + + exists(key: string): Promise { + return this.db + .search({ + dataType: this.DataType, + searchText: key, + searchMode: SearchModeEnum.ExactMatch, + fields: [] + }) + .then((items) => { + return items.length > 0 + }) + } +} diff --git a/packages/drizzle/src/proxy.ts b/packages/drizzle/src/proxy.ts new file mode 100644 index 0000000..2514b2f --- /dev/null +++ b/packages/drizzle/src/proxy.ts @@ -0,0 +1,55 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { sql } from "@kksh/api/commands" +import { error } from "@tauri-apps/plugin-log" +import { drizzle } from "drizzle-orm/sqlite-proxy" +import * as schema from "../drizzle/schema" + +/** + * The drizzle database instance. + */ +export const db = drizzle( + async (sqlQuery, params, method) => { + let rows: any = [] + let results = [] + console.log({ + sql: sqlQuery, + params, + method + }) + console.log(sqlQuery) + // If the query is a SELECT, use the select method + if (isSelectQuery(sqlQuery)) { + rows = await sql.select(sqlQuery, params).catch((e) => { + error("SQL Error:", e) + return [] + }) + } else { + // Otherwise, use the execute method + rows = await sql.execute(sqlQuery, params).catch((e) => { + error("SQL Error:", e) + return [] + }) + return { rows: [] } + } + + rows = rows.map((row: any) => { + return Object.values(row) + }) + + // If the method is "all", return all rows + results = method === "all" ? rows : rows[0] + return { rows: results } + }, + // Pass the schema to the drizzle instance + { schema: schema, logger: true } +) + +/** + * Checks if the given SQL query is a SELECT query. + * @param sql The SQL query to check. + * @returns True if the query is a SELECT query, false otherwise. + */ +function isSelectQuery(sql: string): boolean { + const selectRegex = /^\s*SELECT\b/i + return selectRegex.test(sql) +} diff --git a/packages/drizzle/tsconfig.json b/packages/drizzle/tsconfig.json new file mode 100644 index 0000000..ab0f0b0 --- /dev/null +++ b/packages/drizzle/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + // Environment setup & latest features + "lib": ["esnext"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedIndexedAccess": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + } +} diff --git a/packages/extension/package.json b/packages/extension/package.json index c04c2f9..7ade252 100644 --- a/packages/extension/package.json +++ b/packages/extension/package.json @@ -16,6 +16,7 @@ }, "dependencies": { "@kksh/api": "workspace:*", + "@kksh/drizzle": "workspace:*", "@std/semver": "npm:@jsr/std__semver@^1.0.4", "@tauri-apps/plugin-upload": "^2.2.1", "semver": "^7.7.1", diff --git a/packages/extension/src/db.ts b/packages/extension/src/db.ts index fabc869..0b2f458 100644 --- a/packages/extension/src/db.ts +++ b/packages/extension/src/db.ts @@ -1,14 +1,6 @@ -import { db } from "@kksh/api/commands" -import { - CmdTypeEnum, - ExtCmd, - ExtPackageJson, - ExtPackageJsonExtra, - Icon, - QuickLinkCmd -} from "@kksh/api/models" +import { CmdTypeEnum, ExtPackageJson, Icon, QuickLinkCmd } from "@kksh/api/models" +import { db } from "@kksh/drizzle" import * as v from "valibot" -import { isExtPathInDev } from "./utils" export async function upsertExtension(extPkgJson: ExtPackageJson, extFullPath: string) { const extInDb = await db.getUniqueExtensionByIdentifier(extPkgJson.kunkun.identifier) @@ -39,7 +31,7 @@ export async function createQuickLinkCommand(name: string, link: string, icon: I export async function getAllQuickLinkCommands(): Promise { const extension = await db.getExtQuickLinks() const cmds = await db.getCommandsByExtId(extension.extId) - return cmds + const parsedCmds = cmds .map((cmd) => { try { cmd.data = JSON.parse(cmd.data) @@ -55,4 +47,5 @@ export async function getAllQuickLinkCommands(): Promise { } }) .filter((cmd) => cmd !== null) + return parsedCmds } diff --git a/packages/extension/src/install.ts b/packages/extension/src/install.ts index 9ab6c8f..4b17f42 100644 --- a/packages/extension/src/install.ts +++ b/packages/extension/src/install.ts @@ -3,8 +3,9 @@ * including install, uninstall, upgrade, check app-extension compatibility, etc. */ import { isCompatible } from "@kksh/api" -import { copy_dir_all, db, decompressTarball } from "@kksh/api/commands" +import { copy_dir_all, decompressTarball } from "@kksh/api/commands" import type { ExtensionStoreListItem, ExtPackageJsonExtra } from "@kksh/api/models" +import { db } from "@kksh/drizzle" import { greaterThan, parse as parseSemver } from "@std/semver" import * as path from "@tauri-apps/api/path" import * as dialog from "@tauri-apps/plugin-dialog" diff --git a/packages/extension/src/load.ts b/packages/extension/src/load.ts index 5af4543..1f4e88d 100644 --- a/packages/extension/src/load.ts +++ b/packages/extension/src/load.ts @@ -1,5 +1,5 @@ -import { db } from "@kksh/api/commands" import { ExtPackageJson, ExtPackageJsonExtra, License } from "@kksh/api/models" +import { db } from "@kksh/drizzle" import { basename, dirname, join } from "@tauri-apps/api/path" import { readDir, readTextFile } from "@tauri-apps/plugin-fs" import { debug, error } from "@tauri-apps/plugin-log" @@ -77,7 +77,7 @@ export function loadAllExtensionsFromDisk( * @returns loaded extensions */ export async function loadAllExtensionsFromDb(): Promise { - const allDbExts = await (await db.getAllExtensions()).filter((ext) => ext.path) + const allDbExts = (await db.getAllExtensions()).filter((ext) => ext.path) const results: ExtPackageJsonExtra[] = [] for (const ext of allDbExts) { if (!ext.path) continue diff --git a/packages/tauri-plugins/jarvis/Cargo.toml b/packages/tauri-plugins/jarvis/Cargo.toml index 103e7b8..5358e8f 100644 --- a/packages/tauri-plugins/jarvis/Cargo.toml +++ b/packages/tauri-plugins/jarvis/Cargo.toml @@ -69,6 +69,6 @@ ico = "0.3.0" [build-dependencies] -tauri-plugin = { version = "2.0.3", features = ["build"] } +tauri-plugin = { version = "2", features = ["build"] } tonic-build = "0.11" base64 = { workspace = true } diff --git a/packages/tauri-plugins/jarvis/build.rs b/packages/tauri-plugins/jarvis/build.rs index f3bcbc4..ae9bb8b 100644 --- a/packages/tauri-plugins/jarvis/build.rs +++ b/packages/tauri-plugins/jarvis/build.rs @@ -81,23 +81,25 @@ const COMMANDS: &[&str] = &[ // "ext_store_wrapper_save", "get_server_port", /* ----------------------------- sqlite database ---------------------------- */ - "create_extension", - "get_all_extensions", - "get_unique_extension_by_identifier", - "get_unique_extension_by_path", - "get_all_extensions_by_identifier", - "delete_extension_by_path", - "delete_extension_by_ext_id", - "create_command", - "get_command_by_id", - "get_commands_by_ext_id", - "delete_command_by_id", - "update_command_by_id", - "create_extension_data", - "get_extension_data_by_id", - "search_extension_data", - "delete_extension_data_by_id", - "update_extension_data_by_id", + // "create_extension", + // "get_all_extensions", + // "get_unique_extension_by_identifier", + // "get_unique_extension_by_path", + // "get_all_extensions_by_identifier", + // "delete_extension_by_path", + // "delete_extension_by_ext_id", + // "create_command", + // "get_command_by_id", + // "get_commands_by_ext_id", + // "delete_command_by_id", + // "update_command_by_id", + // "create_extension_data", + // "get_extension_data_by_id", + // "search_extension_data", + // "delete_extension_data_by_id", + // "update_extension_data_by_id", + "select", + "execute", /* -------------------------------- Clipboard ------------------------------- */ "add_to_history", "get_history", diff --git a/packages/tauri-plugins/jarvis/permissions/all.toml b/packages/tauri-plugins/jarvis/permissions/all.toml index 3e5222d..77fa122 100644 --- a/packages/tauri-plugins/jarvis/permissions/all.toml +++ b/packages/tauri-plugins/jarvis/permissions/all.toml @@ -65,6 +65,8 @@ commands.allow = [ "get_ext_label_map", "get_frontmost_app", # Database + "select", + "execute", "create_extension", "get_all_extensions", "get_unique_extension_by_identifier", diff --git a/packages/tauri-plugins/jarvis/permissions/autogenerated/commands/execute.toml b/packages/tauri-plugins/jarvis/permissions/autogenerated/commands/execute.toml new file mode 100644 index 0000000..d98be89 --- /dev/null +++ b/packages/tauri-plugins/jarvis/permissions/autogenerated/commands/execute.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-execute" +description = "Enables the execute command without any pre-configured scope." +commands.allow = ["execute"] + +[[permission]] +identifier = "deny-execute" +description = "Denies the execute command without any pre-configured scope." +commands.deny = ["execute"] diff --git a/packages/tauri-plugins/jarvis/permissions/autogenerated/commands/select.toml b/packages/tauri-plugins/jarvis/permissions/autogenerated/commands/select.toml new file mode 100644 index 0000000..5a13a02 --- /dev/null +++ b/packages/tauri-plugins/jarvis/permissions/autogenerated/commands/select.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-select" +description = "Enables the select command without any pre-configured scope." +commands.allow = ["select"] + +[[permission]] +identifier = "deny-select" +description = "Denies the select command without any pre-configured scope." +commands.deny = ["select"] diff --git a/packages/tauri-plugins/jarvis/permissions/autogenerated/reference.md b/packages/tauri-plugins/jarvis/permissions/autogenerated/reference.md index 43a78fd..06546b4 100644 --- a/packages/tauri-plugins/jarvis/permissions/autogenerated/reference.md +++ b/packages/tauri-plugins/jarvis/permissions/autogenerated/reference.md @@ -492,6 +492,32 @@ Denies the empty_trash command without any pre-configured scope. +`jarvis:allow-execute` + + + + +Enables the execute command without any pre-configured scope. + + + + + + + +`jarvis:deny-execute` + + + + +Denies the execute command without any pre-configured scope. + + + + + + + `jarvis:allow-file-search` @@ -1610,6 +1636,32 @@ Denies the search_extension_data command without any pre-configured scope. +`jarvis:allow-select` + + + + +Enables the select command without any pre-configured scope. + + + + + + + +`jarvis:deny-select` + + + + +Denies the select command without any pre-configured scope. + + + + + + + `jarvis:allow-server-is-running` diff --git a/packages/tauri-plugins/jarvis/permissions/schemas/schema.json b/packages/tauri-plugins/jarvis/permissions/schemas/schema.json index 32302ff..ac9ff84 100644 --- a/packages/tauri-plugins/jarvis/permissions/schemas/schema.json +++ b/packages/tauri-plugins/jarvis/permissions/schemas/schema.json @@ -479,6 +479,16 @@ "type": "string", "const": "deny-empty-trash" }, + { + "description": "Enables the execute command without any pre-configured scope.", + "type": "string", + "const": "allow-execute" + }, + { + "description": "Denies the execute command without any pre-configured scope.", + "type": "string", + "const": "deny-execute" + }, { "description": "Enables the file_search command without any pre-configured scope.", "type": "string", @@ -909,6 +919,16 @@ "type": "string", "const": "deny-search-extension-data" }, + { + "description": "Enables the select command without any pre-configured scope.", + "type": "string", + "const": "allow-select" + }, + { + "description": "Denies the select command without any pre-configured scope.", + "type": "string", + "const": "deny-select" + }, { "description": "Enables the server_is_running command without any pre-configured scope.", "type": "string", diff --git a/packages/tauri-plugins/jarvis/src/commands/db.rs b/packages/tauri-plugins/jarvis/src/commands/db.rs index f833837..aa7d9a9 100644 --- a/packages/tauri-plugins/jarvis/src/commands/db.rs +++ b/packages/tauri-plugins/jarvis/src/commands/db.rs @@ -2,6 +2,7 @@ use db::{ models::{Cmd, CmdType, Ext, ExtData, ExtDataField, ExtDataSearchQuery, SQLSortOrder}, JarvisDB, }; +use serde_json::{json, Value as JsonValue}; use std::{path::PathBuf, sync::Mutex}; use tauri::State; @@ -21,227 +22,30 @@ impl DBState { } } -/* -------------------------------------------------------------------------- */ -/* Extension CRUD */ -/* -------------------------------------------------------------------------- */ #[tauri::command] -pub async fn create_extension( +pub async fn select( db: State<'_, DBState>, - identifier: &str, - version: &str, - enabled: Option, - path: Option<&str>, - data: Option<&str>, -) -> Result<(), String> { + query: &str, + values: Vec, +) -> Result, String> { db.db .lock() .unwrap() - .create_extension(identifier, version, enabled.unwrap_or(true), path, data) + .select(query.to_string(), values) .map_err(|err| err.to_string()) } #[tauri::command] -pub async fn get_all_extensions(db: State<'_, DBState>) -> Result, String> { - db.db - .lock() - .unwrap() - .get_all_extensions() - .map_err(|err| err.to_string()) -} - -#[tauri::command] -pub async fn get_all_extensions_by_identifier( - identifier: &str, +pub async fn execute( db: State<'_, DBState>, -) -> Result, String> { - db.db - .lock() - .unwrap() - .get_all_extensions_by_identifier(identifier) - .map_err(|err| err.to_string()) -} - -#[tauri::command] -pub async fn get_unique_extension_by_identifier( - identifier: &str, - db: State<'_, DBState>, -) -> Result, String> { - let ext = db + query: &str, + values: Vec, +) -> Result, String> { + let (rows_affected, last_id) = db .db .lock() .unwrap() - .get_unique_extension_by_identifier(identifier) + .execute(query, values) .map_err(|err| err.to_string())?; - Ok(ext) -} - -#[tauri::command] -pub async fn get_unique_extension_by_path( - path: &str, - db: State<'_, DBState>, -) -> Result, String> { - let ext = db - .db - .lock() - .unwrap() - .get_unique_extension_by_path(path) - .map_err(|err| err.to_string())?; - Ok(ext) -} - -#[tauri::command] -pub async fn delete_extension_by_path(path: &str, db: State<'_, DBState>) -> Result<(), String> { - db.db - .lock() - .unwrap() - .delete_extension_by_path(path) - .map_err(|err| err.to_string()) -} - -#[tauri::command] -pub async fn delete_extension_by_ext_id(ext_id: i32, db: State<'_, DBState>) -> Result<(), String> { - db.db - .lock() - .unwrap() - .delete_extension_by_ext_id(ext_id) - .map_err(|err| err.to_string()) -} - -/* -------------------------------------------------------------------------- */ -/* Extension Command CRUD */ -/* -------------------------------------------------------------------------- */ - -#[tauri::command] -pub async fn create_command( - db: State<'_, DBState>, - ext_id: i32, - name: &str, - cmd_type: CmdType, - data: &str, - enabled: bool, - alias: Option<&str>, - hotkey: Option<&str>, -) -> Result<(), String> { - db.db - .lock() - .unwrap() - .create_command(ext_id, name, cmd_type, data, enabled, alias, hotkey) - .map_err(|err| err.to_string()) -} - -#[tauri::command] -pub async fn get_command_by_id(db: State<'_, DBState>, cmd_id: i32) -> Result, String> { - db.db - .lock() - .unwrap() - .get_command_by_id(cmd_id) - .map_err(|err| err.to_string()) -} - -#[tauri::command] -pub async fn get_commands_by_ext_id( - db: State<'_, DBState>, - ext_id: i32, -) -> Result, String> { - db.db - .lock() - .unwrap() - .get_commands_by_ext_id(ext_id) - .map_err(|err| err.to_string()) -} - -#[tauri::command] -pub async fn delete_command_by_id(db: State<'_, DBState>, cmd_id: i32) -> Result<(), String> { - db.db - .lock() - .unwrap() - .delete_command_by_id(cmd_id) - .map_err(|err| err.to_string()) -} - -#[tauri::command] -pub async fn update_command_by_id( - db: State<'_, DBState>, - cmd_id: i32, - name: &str, - cmd_type: CmdType, - data: &str, - enabled: bool, - alias: Option<&str>, - hotkey: Option<&str>, -) -> Result<(), String> { - db.db - .lock() - .unwrap() - .update_command_by_id(cmd_id, name, cmd_type, data, enabled, alias, hotkey) - .map_err(|err| err.to_string()) -} - -/* -------------------------------------------------------------------------- */ -/* Extension Data CRUD */ -/* -------------------------------------------------------------------------- */ -#[tauri::command] -pub async fn create_extension_data( - ext_id: i32, - data_type: &str, - data: &str, - search_text: Option<&str>, - db: State<'_, DBState>, -) -> Result<(), String> { - db.db - .lock() - .unwrap() - .create_extension_data(ext_id, data_type, data, search_text, None) - .map_err(|err| err.to_string()) -} - -#[tauri::command] -pub async fn get_extension_data_by_id( - data_id: i32, - fields: Option>, - db: State<'_, DBState>, -) -> Result, String> { - db.db - .lock() - .unwrap() - .get_extension_data_by_id(data_id, fields) - .map_err(|err| err.to_string()) -} - -#[tauri::command] -pub async fn search_extension_data( - db: State<'_, DBState>, - search_query: ExtDataSearchQuery, -) -> Result, String> { - db.db - .lock() - .unwrap() - .search_extension_data(search_query) - .map_err(|err| err.to_string()) -} - -#[tauri::command] -pub async fn delete_extension_data_by_id( - data_id: i32, - db: State<'_, DBState>, -) -> Result<(), String> { - db.db - .lock() - .unwrap() - .delete_extension_data_by_id(data_id) - .map_err(|err| err.to_string()) -} - -#[tauri::command] -pub async fn update_extension_data_by_id( - data_id: i32, - data: &str, - search_text: Option<&str>, - db: State<'_, DBState>, -) -> Result<(), String> { - db.db - .lock() - .unwrap() - .update_extension_data_by_id(data_id, data, search_text) - .map_err(|err| err.to_string()) + Ok(vec![json!([rows_affected, last_id])]) } diff --git a/packages/tauri-plugins/jarvis/src/lib.rs b/packages/tauri-plugins/jarvis/src/lib.rs index 58da91d..50a20b6 100644 --- a/packages/tauri-plugins/jarvis/src/lib.rs +++ b/packages/tauri-plugins/jarvis/src/lib.rs @@ -140,23 +140,8 @@ pub fn init() -> TauriPlugin { // commands::storage::ext_store_wrapper_load, // commands::storage::ext_store_wrapper_save, /* -------------------------------- database -------------------------------- */ - commands::db::create_extension, - commands::db::get_all_extensions, - commands::db::get_unique_extension_by_identifier, - commands::db::get_unique_extension_by_path, - commands::db::get_all_extensions_by_identifier, - commands::db::delete_extension_by_path, - commands::db::delete_extension_by_ext_id, - commands::db::create_command, - commands::db::get_command_by_id, - commands::db::get_commands_by_ext_id, - commands::db::delete_command_by_id, - commands::db::update_command_by_id, - commands::db::create_extension_data, - commands::db::get_extension_data_by_id, - commands::db::search_extension_data, - commands::db::delete_extension_data_by_id, - commands::db::update_extension_data_by_id, + commands::db::select, + commands::db::execute, /* -------------------------------- Clipboard ------------------------------- */ commands::clipboard::get_history, commands::clipboard::add_to_history, diff --git a/packages/tauri-plugins/jarvis/src/model/app_state.rs b/packages/tauri-plugins/jarvis/src/model/app_state.rs index 995358d..52ba895 100644 --- a/packages/tauri-plugins/jarvis/src/model/app_state.rs +++ b/packages/tauri-plugins/jarvis/src/model/app_state.rs @@ -1,4 +1,3 @@ - pub struct AppState { // pub history: Mutex>, // pub dev_extension_path: Mutex>, diff --git a/packages/tauri-plugins/jarvis/src/server/grpc/kunkun.rs b/packages/tauri-plugins/jarvis/src/server/grpc/kunkun.rs index a23ae34..a49042c 100644 --- a/packages/tauri-plugins/jarvis/src/server/grpc/kunkun.rs +++ b/packages/tauri-plugins/jarvis/src/server/grpc/kunkun.rs @@ -2,10 +2,7 @@ // use hello_world::{HelloReply, HelloRequest}; // use server_info«::server_info_server::ServerInfo; // use server_info::{InfoRequest, InfoResponse}; -use grpc::kunkun::{ - kunkun_server::Kunkun, - Empty, ServerInfoResponse, -}; +use grpc::kunkun::{kunkun_server::Kunkun, Empty, ServerInfoResponse}; use tauri::{AppHandle, Emitter, Manager}; use tonic::{Request, Response, Status}; diff --git a/packages/tauri-plugins/jarvis/src/server/http.rs b/packages/tauri-plugins/jarvis/src/server/http.rs index 9361e70..9ec8f77 100644 --- a/packages/tauri-plugins/jarvis/src/server/http.rs +++ b/packages/tauri-plugins/jarvis/src/server/http.rs @@ -6,8 +6,7 @@ use axum::routing::{get, post}; use axum_server::tls_rustls::RustlsConfig; use base64::prelude::*; use grpc::{ - file_transfer::file_transfer_server::FileTransferServer, - kunkun::kunkun_server::KunkunServer, + file_transfer::file_transfer_server::FileTransferServer, kunkun::kunkun_server::KunkunServer, }; /// This module is responsible for controlling the main server use obfstr::obfstr as s; diff --git a/packages/tauri-plugins/jarvis/src/server/rest.rs b/packages/tauri-plugins/jarvis/src/server/rest.rs index 8391356..1919d11 100644 --- a/packages/tauri-plugins/jarvis/src/server/rest.rs +++ b/packages/tauri-plugins/jarvis/src/server/rest.rs @@ -3,10 +3,8 @@ use super::{ model::{ServerInfo, ServerState}, }; use crate::{ - constants::KUNKUN_REFRESH_WORKER_EXTENSION, - models::FileTransferState, - server::model::FileTransferProgressPayload, - JarvisState, + constants::KUNKUN_REFRESH_WORKER_EXTENSION, models::FileTransferState, + server::model::FileTransferProgressPayload, JarvisState, }; use axum::{ body::StreamBody, diff --git a/packages/ui/package.json b/packages/ui/package.json index 6219ec3..483da1d 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -96,7 +96,7 @@ "remark-math": "^6.0.0", "shiki-magic-move": "^0.5.2", "svelte-exmarkdown": "^4.0.3", - "svelte-inspect-value": "^0.3.0", + "svelte-inspect-value": "^0.5.0", "svelte-motion": "^0.12.2", "valibot": "^1.0.0" } diff --git a/packages/ui/src/components/error/raw-error-json-preset.svelte b/packages/ui/src/components/error/raw-error-json-preset.svelte index c02b244..90fa00b 100644 --- a/packages/ui/src/components/error/raw-error-json-preset.svelte +++ b/packages/ui/src/components/error/raw-error-json-preset.svelte @@ -1,11 +1,9 @@