diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9fb2074..65aa152 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -63,6 +63,7 @@ jobs: TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} VITE_TLDRAW_LICENSE_KEY: ${{ secrets.VITE_TLDRAW_LICENSE_KEY }} + APTABASE_APP_KEY: ${{ secrets.APTABASE_APP_KEY }} with: tagName: v__VERSION__ releaseName: "RelWave v__VERSION__" diff --git a/bridge/package.json b/bridge/package.json index 065662a..352183e 100644 --- a/bridge/package.json +++ b/bridge/package.json @@ -1,6 +1,6 @@ { "name": "relwave-bridge", - "version": "1.0.0", + "version": "1.0.1", "type": "commonjs", "main": "dist/index.cjs", "scripts": { diff --git a/package.json b/package.json index a98a5b3..0f57907 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "relwave", "private": true, - "version": "1.0.0", + "version": "1.0.1", "type": "module", "scripts": { "dev": "vite", @@ -13,6 +13,7 @@ "bridge:package": "node scripts/package-bridge.mjs" }, "dependencies": { + "@aptabase/tauri": "github:aptabase/tauri-plugin-aptabase", "@codemirror/lang-sql": "^6.10.0", "@codemirror/theme-one-dark": "^6.1.3", "@codemirror/view": "^6.39.8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8d58629..64d0887 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@aptabase/tauri': + specifier: github:aptabase/tauri-plugin-aptabase + version: https://codeload.github.com/aptabase/tauri-plugin-aptabase/tar.gz/de6df6b8671568aad53eabaf4b49207a3d6c5622 '@codemirror/lang-sql': specifier: ^6.10.0 version: 6.10.0 @@ -189,6 +192,10 @@ importers: packages: + '@aptabase/tauri@https://codeload.github.com/aptabase/tauri-plugin-aptabase/tar.gz/de6df6b8671568aad53eabaf4b49207a3d6c5622': + resolution: {tarball: https://codeload.github.com/aptabase/tauri-plugin-aptabase/tar.gz/de6df6b8671568aad53eabaf4b49207a3d6c5622} + version: 0.4.2 + '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -1356,79 +1363,66 @@ packages: resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} cpu: [arm] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.59.0': resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} cpu: [arm] os: [linux] - libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.59.0': resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} cpu: [arm64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.59.0': resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} cpu: [arm64] os: [linux] - libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.59.0': resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} cpu: [loong64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.59.0': resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} cpu: [loong64] os: [linux] - libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.59.0': resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} cpu: [ppc64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.59.0': resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} cpu: [ppc64] os: [linux] - libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.59.0': resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} cpu: [riscv64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.59.0': resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} cpu: [riscv64] os: [linux] - libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.59.0': resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} cpu: [s390x] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.59.0': resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} cpu: [x64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-musl@4.59.0': resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} cpu: [x64] os: [linux] - libc: [musl] '@rollup/rollup-openbsd-x64@4.59.0': resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} @@ -1498,28 +1492,24 @@ packages: engines: {node: '>= 20'} cpu: [arm64] os: [linux] - libc: [glibc] '@tailwindcss/oxide-linux-arm64-musl@4.2.1': resolution: {integrity: sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] - libc: [musl] '@tailwindcss/oxide-linux-x64-gnu@4.2.1': resolution: {integrity: sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==} engines: {node: '>= 20'} cpu: [x64] os: [linux] - libc: [glibc] '@tailwindcss/oxide-linux-x64-musl@4.2.1': resolution: {integrity: sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==} engines: {node: '>= 20'} cpu: [x64] os: [linux] - libc: [musl] '@tailwindcss/oxide-wasm32-wasi@4.2.1': resolution: {integrity: sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==} @@ -1588,35 +1578,30 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] - libc: [glibc] '@tauri-apps/cli-linux-arm64-musl@2.10.1': resolution: {integrity: sha512-MIj78PDDGjkg3NqGptDOGgfXks7SYJwhiMh8SBoZS+vfdz7yP5jN18bNaLnDhsVIPARcAhE1TlsZe/8Yxo2zqg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - libc: [musl] '@tauri-apps/cli-linux-riscv64-gnu@2.10.1': resolution: {integrity: sha512-X0lvOVUg8PCVaoEtEAnpxmnkwlE1gcMDTqfhbefICKDnOTJ5Est3qL0SrWxizDackIOKBcvtpejrSiVpuJI1kw==} engines: {node: '>= 10'} cpu: [riscv64] os: [linux] - libc: [glibc] '@tauri-apps/cli-linux-x64-gnu@2.10.1': resolution: {integrity: sha512-2/12bEzsJS9fAKybxgicCDFxYD1WEI9kO+tlDwX5znWG2GwMBaiWcmhGlZ8fi+DMe9CXlcVarMTYc0L3REIRxw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [glibc] '@tauri-apps/cli-linux-x64-musl@2.10.1': resolution: {integrity: sha512-Y8J0ZzswPz50UcGOFuXGEMrxbjwKSPgXftx5qnkuMs2rmwQB5ssvLb6tn54wDSYxe7S6vlLob9vt0VKuNOaCIQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [musl] '@tauri-apps/cli-win32-arm64-msvc@2.10.1': resolution: {integrity: sha512-iSt5B86jHYAPJa/IlYw++SXtFPGnWtFJriHn7X0NFBVunF6zu9+/zOn8OgqIWSl8RgzhLGXQEEtGBdR4wzpVgg==} @@ -2444,28 +2429,24 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] lightningcss-linux-arm64-musl@1.31.1: resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [musl] lightningcss-linux-x64-gnu@1.31.1: resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [glibc] lightningcss-linux-x64-musl@1.31.1: resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [musl] lightningcss-win32-arm64-msvc@1.31.1: resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==} @@ -3135,6 +3116,11 @@ packages: snapshots: + '@aptabase/tauri@https://codeload.github.com/aptabase/tauri-plugin-aptabase/tar.gz/de6df6b8671568aad53eabaf4b49207a3d6c5622': + dependencies: + '@tauri-apps/api': 2.10.1 + tslib: 2.8.1 + '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.28.5 diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 5dfa472..f574247 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -453,6 +453,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.44" @@ -460,8 +466,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ "iana-time-zone", + "js-sys", "num-traits", "serde", + "wasm-bindgen", "windows-link 0.2.1", ] @@ -500,6 +508,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation" version = "0.10.1" @@ -523,9 +541,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" dependencies = [ "bitflags 2.11.0", - "core-foundation", + "core-foundation 0.10.1", "core-graphics-types", - "foreign-types", + "foreign-types 0.5.0", "libc", ] @@ -536,7 +554,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ "bitflags 2.11.0", - "core-foundation", + "core-foundation 0.10.1", "libc", ] @@ -814,6 +832,12 @@ dependencies = [ "tendril 0.5.0", ] +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + [[package]] name = "dpi" version = "0.1.2" @@ -861,7 +885,7 @@ dependencies = [ "rustc_version", "toml 0.9.12+spec-1.1.0", "vswhom", - "winreg", + "winreg 0.55.0", ] [[package]] @@ -870,6 +894,15 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + [[package]] name = "endi" version = "1.1.1" @@ -1015,6 +1048,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared 0.1.1", +] + [[package]] name = "foreign-types" version = "0.5.0" @@ -1022,7 +1064,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ "foreign-types-macros", - "foreign-types-shared", + "foreign-types-shared 0.3.1", ] [[package]] @@ -1036,6 +1078,12 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "foreign-types-shared" version = "0.3.1" @@ -1061,6 +1109,21 @@ dependencies = [ "new_debug_unreachable", ] +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.32" @@ -1068,6 +1131,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -1135,6 +1199,7 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ + "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -1458,6 +1523,44 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "h2" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap 2.13.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.4.0", + "indexmap 2.13.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -1525,6 +1628,17 @@ dependencies = [ "markup5ever 0.38.0", ] +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http" version = "1.4.0" @@ -1535,6 +1649,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + [[package]] name = "http-body" version = "1.0.1" @@ -1542,7 +1667,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http", + "http 1.4.0", ] [[package]] @@ -1553,8 +1678,8 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "pin-project-lite", ] @@ -1564,6 +1689,36 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.5.10", + "tokio", + "tower-service", + "tracing", + "want", +] + [[package]] name = "hyper" version = "1.8.1" @@ -1574,8 +1729,9 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "http", - "http-body", + "h2 0.4.15", + "http 1.4.0", + "http-body 1.0.1", "httparse", "itoa", "pin-project-lite", @@ -1591,8 +1747,8 @@ version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "http", - "hyper", + "http 1.4.0", + "hyper 1.8.1", "hyper-util", "rustls", "rustls-pki-types", @@ -1601,6 +1757,35 @@ dependencies = [ "tower-service", ] +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper 0.14.32", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.8.1", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.20" @@ -1611,17 +1796,19 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http", - "http-body", - "hyper", + "http 1.4.0", + "http-body 1.0.1", + "hyper 1.8.1", "ipnet", "libc", "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.6.3", + "system-configuration 0.7.0", "tokio", "tower-service", "tracing", + "windows-registry", ] [[package]] @@ -2001,9 +2188,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.183" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libloading" @@ -2171,6 +2358,23 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "native-tls" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "ndk" version = "0.9.0" @@ -2207,6 +2411,18 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "nix" +version = "0.31.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" +dependencies = [ + "bitflags 2.11.0", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "nodrop" version = "0.1.14" @@ -2273,6 +2489,27 @@ dependencies = [ "objc2-foundation", ] +[[package]] +name = "objc2-cloud-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" +dependencies = [ + "bitflags 2.11.0", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" +dependencies = [ + "objc2", + "objc2-foundation", +] + [[package]] name = "objc2-core-foundation" version = "0.3.2" @@ -2297,6 +2534,38 @@ dependencies = [ "objc2-io-surface", ] +[[package]] +name = "objc2-core-image" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-location" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-text" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" +dependencies = [ + "bitflags 2.11.0", + "objc2", + "objc2-core-foundation", + "objc2-core-graphics", +] + [[package]] name = "objc2-encode" version = "4.1.0" @@ -2367,8 +2636,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ "bitflags 2.11.0", + "block2", "objc2", + "objc2-cloud-kit", + "objc2-core-data", "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image", + "objc2-core-location", + "objc2-core-text", + "objc2-foundation", + "objc2-quartz-core", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e" +dependencies = [ + "objc2", "objc2-foundation", ] @@ -2404,12 +2692,49 @@ dependencies = [ "pathdiff", ] +[[package]] +name = "openssl" +version = "0.10.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" +dependencies = [ + "bitflags 2.11.0", + "cfg-if", + "foreign-types 0.3.2", + "libc", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "openssl-probe" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" +[[package]] +name = "openssl-sys" +version = "0.9.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -2426,6 +2751,22 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "os_info" +version = "3.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf20a545b305cf1da722b236b5155c9bb35f1d5ceb28c048bd96ca842f41b5b" +dependencies = [ + "android_system_properties", + "log", + "nix", + "objc2", + "objc2-foundation", + "objc2-ui-kit", + "serde", + "windows-sys 0.61.2", +] + [[package]] name = "osakit" version = "0.3.1" @@ -2931,6 +3272,16 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + [[package]] name = "rand_chacha" version = "0.2.2" @@ -2951,6 +3302,16 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + [[package]] name = "rand_core" version = "0.5.1" @@ -2969,6 +3330,15 @@ dependencies = [ "getrandom 0.2.17", ] +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + [[package]] name = "rand_hc" version = "0.2.0" @@ -3075,14 +3445,100 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" name = "relwave" version = "1.0.0" dependencies = [ + "chrono", + "dotenvy", + "reqwest 0.11.27", "serde", "serde_json", "tauri", "tauri-build", + "tauri-plugin-aptabase", "tauri-plugin-dialog", "tauri-plugin-opener", "tauri-plugin-process", "tauri-plugin-updater", + "tokio", + "uuid", +] + +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.32", + "hyper-tls 0.5.0", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 0.1.2", + "system-configuration 0.5.1", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg 0.50.0", +] + +[[package]] +name = "reqwest" +version = "0.12.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-core", + "h2 0.4.15", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.8.1", + "hyper-rustls", + "hyper-tls 0.6.0", + "hyper-util", + "js-sys", + "log", + "mime", + "native-tls", + "percent-encoding", + "pin-project-lite", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 1.0.2", + "tokio", + "tokio-native-tls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", ] [[package]] @@ -3095,10 +3551,10 @@ dependencies = [ "bytes", "futures-core", "futures-util", - "http", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "http-body-util", - "hyper", + "hyper 1.8.1", "hyper-rustls", "hyper-util", "js-sys", @@ -3110,7 +3566,7 @@ dependencies = [ "rustls-platform-verifier", "serde", "serde_json", - "sync_wrapper", + "sync_wrapper 1.0.2", "tokio", "tokio-rustls", "tokio-util", @@ -3216,6 +3672,15 @@ dependencies = [ "security-framework", ] +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + [[package]] name = "rustls-pki-types" version = "1.14.0" @@ -3231,7 +3696,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" dependencies = [ - "core-foundation", + "core-foundation 0.10.1", "core-foundation-sys", "jni", "log", @@ -3269,6 +3734,12 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + [[package]] name = "same-file" version = "1.0.6" @@ -3351,7 +3822,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ "bitflags 2.11.0", - "core-foundation", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -3509,6 +3980,18 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "serde_with" version = "3.18.0" @@ -3638,6 +4121,16 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "socket2" version = "0.6.3" @@ -3796,6 +4289,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "sync_wrapper" version = "1.0.2" @@ -3816,6 +4315,57 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "sys-locale" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" +dependencies = [ + "libc", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "system-configuration-sys 0.5.0", +] + +[[package]] +name = "system-configuration" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" +dependencies = [ + "bitflags 2.11.0", + "core-foundation 0.9.4", + "system-configuration-sys 0.6.0", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "system-deps" version = "6.2.2" @@ -3837,7 +4387,7 @@ checksum = "9103edf55f2da3c82aea4c7fab7c4241032bfeea0e71fa557d98e00e7ce7cc20" dependencies = [ "bitflags 2.11.0", "block2", - "core-foundation", + "core-foundation 0.10.1", "core-graphics", "crossbeam-channel", "dispatch2", @@ -3911,7 +4461,7 @@ dependencies = [ "glob", "gtk", "heck 0.5.0", - "http", + "http 1.4.0", "jni", "libc", "log", @@ -3925,7 +4475,7 @@ dependencies = [ "percent-encoding", "plist", "raw-window-handle", - "reqwest", + "reqwest 0.13.2", "serde", "serde_json", "serde_repr", @@ -4026,6 +4576,26 @@ dependencies = [ "walkdir", ] +[[package]] +name = "tauri-plugin-aptabase" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "075ebe083b5f311bdfbf436f8383d316dfb12267be5fd977b57d7701bdb99987" +dependencies = [ + "futures", + "log", + "os_info", + "rand 0.9.4", + "reqwest 0.12.28", + "serde", + "serde_json", + "sys-locale", + "tauri", + "tauri-plugin", + "time", + "tokio", +] + [[package]] name = "tauri-plugin-dialog" version = "2.6.0" @@ -4108,13 +4678,13 @@ dependencies = [ "dirs", "flate2", "futures-util", - "http", + "http 1.4.0", "infer", "log", "minisign-verify", "osakit", "percent-encoding", - "reqwest", + "reqwest 0.13.2", "rustls", "semver", "serde", @@ -4140,7 +4710,7 @@ dependencies = [ "cookie", "dpi", "gtk", - "http", + "http 1.4.0", "jni", "objc2", "objc2-ui-kit", @@ -4163,7 +4733,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e11ea2e6f801d275fdd890d6c9603736012742a1c33b96d0db788c9cdebf7f9e" dependencies = [ "gtk", - "http", + "http 1.4.0", "jni", "log", "objc2", @@ -4195,7 +4765,7 @@ dependencies = [ "dunce", "glob", "html5ever 0.29.1", - "http", + "http 1.4.0", "infer", "json-patch", "kuchikiki", @@ -4355,11 +4925,35 @@ dependencies = [ "bytes", "libc", "mio", + "parking_lot", "pin-project-lite", - "socket2", + "signal-hook-registry", + "socket2 0.6.3", + "tokio-macros", "windows-sys 0.61.2", ] +[[package]] +name = "tokio-macros" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.4" @@ -4497,7 +5091,7 @@ dependencies = [ "futures-core", "futures-util", "pin-project-lite", - "sync_wrapper", + "sync_wrapper 1.0.2", "tokio", "tower-layer", "tower-service", @@ -4512,8 +5106,8 @@ dependencies = [ "bitflags 2.11.0", "bytes", "futures-util", - "http", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "iri-string", "pin-project-lite", "tower", @@ -4729,6 +5323,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version-compare" version = "0.2.1" @@ -5172,6 +5772,17 @@ dependencies = [ "windows-link 0.1.3", ] +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + [[package]] name = "windows-result" version = "0.3.4" @@ -5217,6 +5828,15 @@ dependencies = [ "windows-targets 0.42.2", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -5268,6 +5888,21 @@ dependencies = [ "windows_x86_64_msvc 0.42.2", ] +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -5325,6 +5960,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -5343,6 +5984,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -5361,6 +6008,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -5391,6 +6044,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -5409,6 +6068,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -5427,6 +6092,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -5445,6 +6116,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -5484,6 +6161,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "winreg" version = "0.55.0" @@ -5604,7 +6291,7 @@ dependencies = [ "dunce", "gdkx11", "gtk", - "http", + "http 1.4.0", "javascriptcore-rs", "jni", "libc", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 06ea145..22d5356 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -20,6 +20,12 @@ tauri-plugin-dialog = "2" tauri-plugin-process = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" +reqwest = { version = "0.11", features = ["json"] } +tokio = { version = "1", features = ["full"] } +uuid = { version = "1.0", features = ["v4"] } +chrono = { version = "0.4", features = ["serde"] } +dotenvy = "0.15" +tauri-plugin-aptabase = "1.0.0" [[bin]] name = "relwave" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 36d1463..a4c4ae6 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -19,6 +19,7 @@ "dialog:default", "process:default", "process:allow-restart", - "process:allow-exit" + "process:allow-exit", + "aptabase:allow-track-event" ] } \ No newline at end of file diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index bbfdedb..ee46a67 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -2,18 +2,59 @@ mod bridge; mod devtools; +mod services; use bridge::{bridge_restart, bridge_kill, bridge_status, bridge_write, BridgeProcess}; use devtools::{close_devtools, is_devtools_open, navigate_back, navigate_forward, open_devtools, reload_webview}; -use tauri::Manager; +use services::analytics::AnalyticsService; +use tauri::{Manager, State}; +use tauri_plugin_aptabase::EventTracker; -fn main() { - tauri::Builder::default() +#[tokio::main] +async fn main() { + let _ = dotenvy::dotenv(); + let _ = dotenvy::from_path("../.env"); + + let mut builder = tauri::Builder::default() .plugin(tauri_plugin_updater::Builder::new().build()) .plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_dialog::init()) - .plugin(tauri_plugin_process::init()) + .plugin(tauri_plugin_process::init()); + + let aptabase_key = option_env!("APTABASE_APP_KEY") + .map(String::from) + .or_else(|| std::env::var("APTABASE_APP_KEY").ok()); + + if let Some(app_key) = aptabase_key.clone() { + if !app_key.is_empty() { + println!("Aptabase analytics enabled"); + builder = builder.plugin( + tauri_plugin_aptabase::Builder::new(&app_key) + .with_options(tauri_plugin_aptabase::InitOptions { + flush_interval: Some(std::time::Duration::from_secs(1)), + ..Default::default() + }) + .build() + ); + } + } else { + println!("APTABASE_APP_KEY not found in environment at build time"); + } + + builder .setup(|app| { + let has_aptabase = option_env!("APTABASE_APP_KEY") + .map(String::from) + .or_else(|| std::env::var("APTABASE_APP_KEY").ok()) + .is_some(); + + if has_aptabase { + let _ = app.track_event("app_started", None); + } + + let analytics = AnalyticsService::new(app.handle()); + app.manage(analytics); + let handle = app.handle().clone(); let child = bridge::init(handle); app.manage(BridgeProcess::new(child)); @@ -29,12 +70,18 @@ fn main() { is_devtools_open, reload_webview, navigate_back, - navigate_forward + navigate_forward, + get_analytics_enabled, + set_analytics_enabled ]) .build(tauri::generate_context!()) .expect("error while building tauri application") .run(|app_handle, event| { if let tauri::RunEvent::Exit = event { + // Track exit event before killing bridge + let _ = app_handle.track_event("app_exited", None); + app_handle.flush_events_blocking(); + // Kill bridge process on app exit to prevent orphaned processes if let Some(state) = app_handle.try_state::() { let mut guard = state.0.lock().unwrap(); @@ -46,3 +93,16 @@ fn main() { } }); } + + + +#[tauri::command] +async fn get_analytics_enabled(analytics: State<'_, AnalyticsService>) -> Result { + Ok(analytics.is_enabled().await) +} + +#[tauri::command] +async fn set_analytics_enabled(enabled: bool, analytics: State<'_, AnalyticsService>) -> Result<(), String> { + analytics.set_enabled(enabled).await; + Ok(()) +} diff --git a/src-tauri/src/services/analytics.rs b/src-tauri/src/services/analytics.rs new file mode 100644 index 0000000..e82249f --- /dev/null +++ b/src-tauri/src/services/analytics.rs @@ -0,0 +1,30 @@ +use std::sync::Arc; +use tauri::AppHandle; +use tokio::sync::RwLock; + +#[derive(Clone)] +pub struct AnalyticsService { + enabled: Arc>, +} + +impl AnalyticsService { + pub fn new(_app: &AppHandle) -> Self { + Self { + enabled: Arc::new(RwLock::new(false)), + } + } + + pub async fn is_enabled(&self) -> bool { + *self.enabled.read().await + } + + pub async fn set_enabled(&self, enabled: bool) { + let mut e = self.enabled.write().await; + *e = enabled; + if enabled { + println!("Analytics have been enabled by the user."); + } else { + println!("Analytics have been disabled by the user."); + } + } +} diff --git a/src-tauri/src/services/mod.rs b/src-tauri/src/services/mod.rs new file mode 100644 index 0000000..6c1d2c4 --- /dev/null +++ b/src-tauri/src/services/mod.rs @@ -0,0 +1 @@ +pub mod analytics; diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 1bf93e7..4d54573 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "RelWave", - "version": "1.0.0", + "version": "1.0.1", "identifier": "tech.relwave.app", "build": { "beforeDevCommand": "vite", diff --git a/src/features/chart/hooks/useChartVisualization.ts b/src/features/chart/hooks/useChartVisualization.ts index a30cb72..22faf74 100644 --- a/src/features/chart/hooks/useChartVisualization.ts +++ b/src/features/chart/hooks/useChartVisualization.ts @@ -4,6 +4,7 @@ import { queryService } from "@/services/bridge/query"; import { toPng, toSvg } from "html-to-image"; import { useEffect, useState } from "react"; import { toast } from "sonner"; +import { analyticsService } from "@/services/analytics"; interface QueryResultRow { @@ -140,6 +141,9 @@ export const useChartVisualization = (selectedTable: SelectedTable, dbId?: strin // Replace data instead of appending to prevent accumulation setRowData(event.detail.rows); setIsExecuting(false); + if (event.detail.rows.length > 0) { + analyticsService.trackChartCreated(); + } }; const handleError = (event: CustomEvent) => { diff --git a/src/features/database/hooks/useDatabaseDetails.ts b/src/features/database/hooks/useDatabaseDetails.ts index f05cebc..8a3b499 100644 --- a/src/features/database/hooks/useDatabaseDetails.ts +++ b/src/features/database/hooks/useDatabaseDetails.ts @@ -4,6 +4,7 @@ import { useDatabase, useTables, useTableData, usePrefetch, useInvalidateCache, import { QueryProgress, SelectedTable, TableInfo, TableRow } from "@/features/database/types"; import { sessionService } from "@/services/bridge/session"; import { queryService } from "@/services/bridge/query"; +import { analyticsService } from "@/services/analytics"; interface UseDatabaseDetailsOptions { dbId: string | undefined; @@ -101,7 +102,7 @@ export function useDatabaseDetails({ const { prefetchNextPage } = usePrefetch(); // Cache invalidation - const { invalidateTable } = useInvalidateCache(); + const { invalidateTable, invalidateDatabase } = useInvalidateCache(); // Derived state from table data query const tableData = tableDataResult?.rows || []; @@ -204,6 +205,7 @@ export function useDatabaseDetails({ setQueryError(null); setHasExecutedQuery(true); setIsExecuting(true); + analyticsService.trackQueryExecuted(); const sessionId = await sessionService.createSession(); setQuerySessionId(sessionId); @@ -248,6 +250,11 @@ export function useDatabaseDetails({ setQuerySessionId(null); setQueryProgress(null); + const isDDL = query.trim().toUpperCase().match(/^(CREATE|DROP|ALTER|TRUNCATE)/); + if (isDDL && dbId && event.detail.status === "success") { + invalidateDatabase(dbId); + } + const { rows, timeMs, status } = event.detail; const statusType = status === "success" ? "success" : "warning"; const message = diff --git a/src/features/home/hooks/useDeleteConnection.ts b/src/features/home/hooks/useDeleteConnection.ts index 6ac080d..567076f 100644 --- a/src/features/home/hooks/useDeleteConnection.ts +++ b/src/features/home/hooks/useDeleteConnection.ts @@ -4,6 +4,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; import { databaseService } from "@/services/bridge/database"; import { bridgeRequest } from "@/services/bridge/bridgeClient"; import { projectKeys } from "@/features/project/hooks/useProjectQueries"; +import { analyticsService } from "@/services/analytics"; type DeleteConnectionDialogProps = { open: boolean; @@ -45,6 +46,7 @@ export function useDeleteConnection(onSuccess?: () => void) { if (!linkedProject) { // 2. No project -> call existing delete directly await deleteDatabaseMutation.mutateAsync(databaseId); + analyticsService.trackDatabaseRemoved(); toast.success("Database removed"); } else { // 3. Project exists -> fetch git remote, open dialog @@ -72,6 +74,7 @@ export function useDeleteConnection(onSuccess?: () => void) { // Delete the DB connection itself await deleteDatabaseMutation.mutateAsync(databaseId); + analyticsService.trackDatabaseRemoved(); toast.success("Database removed"); setDialogOpen(false); } catch (err: any) { diff --git a/src/features/home/hooks/useIndexPage.ts b/src/features/home/hooks/useIndexPage.ts index 960cbaa..148678b 100644 --- a/src/features/home/hooks/useIndexPage.ts +++ b/src/features/home/hooks/useIndexPage.ts @@ -11,6 +11,7 @@ import { useDatabaseStats } from "../../database/hooks/useDatabaseStats"; import { useSelectedDbStats } from "../../database/hooks/useSelectedDbStats"; import { databaseService } from "@/services/bridge/database"; import { projectService } from "@/services/bridge/project"; +import { analyticsService } from "@/services/analytics"; import { useDeleteConnection } from "./useDeleteConnection"; import { DatabaseConnection } from "@/features/database/types"; import { useWelcomeMessage } from "@/features/database/hooks/useWelcomeMessage"; @@ -176,6 +177,11 @@ export const useIndexPage = (bridgeReady: boolean) => { } toast.success("Database connection added"); + analyticsService.trackDatabaseAdded(payload.type); + console.log("Analytics: Database added", payload.type) + if (payload.ssh) { + analyticsService.trackSshConnectionSuccess(); + } setIsDialogOpen(false); await Promise.all([refetchDatabases(), refetchStatus()]); } catch (err: any) { diff --git a/src/features/project/hooks/useProjectsPage.ts b/src/features/project/hooks/useProjectsPage.ts deleted file mode 100644 index bb6cc69..0000000 --- a/src/features/project/hooks/useProjectsPage.ts +++ /dev/null @@ -1,184 +0,0 @@ -// features/project/hooks/useProjectsPage.ts - -import { useState, useMemo } from "react"; -import { toast } from "sonner"; -import { useNavigate } from "react-router-dom"; -import { useQueryClient } from "@tanstack/react-query"; -import { useDatabases, queryKeys } from "@/features/project/hooks/useDbQueries"; -import { - useProjects, - useCreateProject, - useDeleteProject, - useProjectSchema, - useProjectERDiagram, - useProjectQueries, - projectKeys, -} from "@/features/project/hooks/useProjectQueries"; -import { projectService } from "@/services/bridge/project"; -import { ProjectSummary } from "../types"; - - -// ---- Types ---- - -interface CreateProjectInput { - databaseId: string; - name: string; - description?: string; - defaultSchema?: string; -} - -interface ProjectToDelete { - id: string; - name: string; -} - -// ---- Hook ---- - -export const useProjectsPage = () => { - const navigate = useNavigate(); - const queryClient = useQueryClient(); - - // Data - const { data: projects = [], isLoading: projectsLoading } = useProjects(); - const { data: databases = [] } = useDatabases(); - - // Mutations - const createProjectMutation = useCreateProject(); - const deleteProjectMutation = useDeleteProject(); - - // UI State - const [searchQuery, setSearchQuery] = useState(""); - const [selectedProject, setSelectedProject] = useState(null); - const [isCreateOpen, setIsCreateOpen] = useState(false); - const [isImportOpen, setIsImportOpen] = useState(false); - const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); - const [projectToDelete, setProjectToDelete] = useState(null); - - // Sub-resource queries for selected project - const { data: schemaData } = useProjectSchema(selectedProject ?? undefined); - const { data: erData } = useProjectERDiagram(selectedProject ?? undefined); - const { data: queriesData } = useProjectQueries(selectedProject ?? undefined); - - // Derived state - const filteredProjects = useMemo( - () => - projects.filter( - (p: ProjectSummary) => - p.name.toLowerCase().includes(searchQuery.toLowerCase()) || - (p.description ?? "").toLowerCase().includes(searchQuery.toLowerCase()) - ), - [projects, searchQuery] - ); - - const selectedProjectData = useMemo( - () => projects.find((p: ProjectSummary) => p.id === selectedProject) ?? null, - [projects, selectedProject] - ); - - // ---- Bridge Handlers (belong in hook) ---- - - const handleCreate = async (data: CreateProjectInput) => { - try { - const created = await createProjectMutation.mutateAsync(data); - toast.success("Project created", { description: (created as ProjectSummary).name }); - setIsCreateOpen(false); - setSelectedProject((created as ProjectSummary).id); - } catch (err: any) { - toast.error("Failed to create project", { description: err.message }); - } - }; - - const handleDelete = async () => { - if (!projectToDelete) return; - try { - await deleteProjectMutation.mutateAsync(projectToDelete.id); - toast.success("Project deleted"); - setDeleteDialogOpen(false); - setProjectToDelete(null); - if (selectedProject === projectToDelete.id) setSelectedProject(null); - } catch (err: any) { - toast.error("Failed to delete", { description: err.message }); - } - }; - - const handleExport = async (projectId: string) => { - try { - const bundle = await projectService.exportProject(projectId); - if (!bundle) { - toast.error("Project not found"); - return; - } - const blob = new Blob([JSON.stringify(bundle, null, 2)], { - type: "application/json", - }); - const url = URL.createObjectURL(blob); - const a = document.createElement("a"); - a.href = url; - a.download = `${bundle.metadata.name.replace(/\s+/g, "-").toLowerCase()}-export.json`; - a.click(); - setTimeout(() => URL.revokeObjectURL(url), 0); - toast.success("Project exported"); - } catch (err: any) { - toast.error("Export failed", { description: err.message }); - } - }; - - const handleImportComplete = (projectId: string, projectName: string) => { - queryClient.invalidateQueries({ queryKey: projectKeys.all }); - queryClient.invalidateQueries({ queryKey: queryKeys.databases }); - toast.success("Project imported", { description: projectName }); - setSelectedProject(projectId); - }; - - // ---- Navigation Handler (can stay in page but fine here too) ---- - - const handleOpen = (projectId: string) => { - const project = projects.find((p: ProjectSummary) => p.id === projectId); - if (project) navigate(`/${project.databaseId}`); - }; - - // ---- Delete dialog helpers ---- - - const openDeleteDialog = (id: string, name: string) => { - setProjectToDelete({ id, name }); - setDeleteDialogOpen(true); - }; - - return { - // Data - projects, - databases, - filteredProjects, - selectedProjectData, - projectsLoading, - - // Sub-resource data - schemaData, - erData, - queriesData, - - // Mutation states - isCreating: createProjectMutation.isPending, - - // UI state - searchQuery, - setSearchQuery, - selectedProject, - setSelectedProject, - isCreateOpen, - setIsCreateOpen, - isImportOpen, - setIsImportOpen, - deleteDialogOpen, - setDeleteDialogOpen, - projectToDelete, - - // Handlers - handleCreate, - handleDelete, - handleExport, - handleImportComplete, - handleOpen, - openDeleteDialog, - }; -}; \ No newline at end of file diff --git a/src/features/settings/components/AnalyticsSettings.tsx b/src/features/settings/components/AnalyticsSettings.tsx new file mode 100644 index 0000000..b6520c2 --- /dev/null +++ b/src/features/settings/components/AnalyticsSettings.tsx @@ -0,0 +1,83 @@ +import { useEffect, useState } from "react"; +import { analyticsService } from "@/services/analytics"; +import { Switch } from "@/components/ui/switch"; +import { Label } from "@/components/ui/label"; +import { ShieldAlert, Info } from "lucide-react"; + +export default function AnalyticsSettings() { + const [enabled, setEnabled] = useState(false); + const [loading, setLoading] = useState(true); + + useEffect(() => { + analyticsService.isEnabled().then((val) => { + setEnabled(val); + setLoading(false); + }); + }, []); + + const handleToggle = async (checked: boolean) => { + setEnabled(checked); + await analyticsService.setEnabled(checked); + }; + + if (loading) return null; + + return ( +
+
+

Privacy & Analytics

+

+ Manage how anonymous usage data is collected. +

+
+ +
+
+
+ +

+ Help us improve RelWave by sharing completely anonymous usage statistics. + Analytics are disabled by default and strictly respect your privacy. +

+
+ +
+ +
+
+ +
+ What we collect +
    +
  • App launches & updates
  • +
  • Database driver types (e.g. Postgres)
  • +
  • Feature usage (e.g. "Query Executed")
  • +
  • Operating System (Windows/Mac/Linux)
  • +
+
+
+
+ +
+ What we NEVER collect +
    +
  • SQL queries or schema data
  • +
  • Database credentials or hosts
  • +
  • Table/Column names
  • +
  • AI Prompts or Responses
  • +
  • Any PII or IPs
  • +
+
+
+
+
+
+ ); +} diff --git a/src/features/settings/components/SettingsDialog.tsx b/src/features/settings/components/SettingsDialog.tsx index 6abae98..5caf027 100644 --- a/src/features/settings/components/SettingsDialog.tsx +++ b/src/features/settings/components/SettingsDialog.tsx @@ -1,10 +1,10 @@ import { useState } from "react"; -import { AISettings, AIHistoryPanel, CheckForUpdates, ColorVariant, DeveloperMode, ThemeMode, Version } from "@/features/settings/components"; +import { AISettings, AIHistoryPanel, CheckForUpdates, ColorVariant, DeveloperMode, ThemeMode, Version, AnalyticsSettings } from "@/features/settings/components"; import { cn } from "@/lib/utils"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog"; -type TabId = "general" | "ai" | "shortcuts" | "about"; +type TabId = "general" | "ai" | "analytics" | "shortcuts" | "about"; interface Tab { id: TabId; @@ -14,6 +14,7 @@ interface Tab { const TABS: Tab[] = [ { id: "general", label: "General" }, { id: "ai", label: "AI Providers" }, + { id: "analytics", label: "Analytics" }, { id: "shortcuts", label: "Shortcuts" }, { id: "about", label: "About" }, ]; @@ -65,8 +66,6 @@ export function SettingsDialog({ open, onOpenChange }: SettingsDialogProps) { )} - - {activeTab === "ai" && (
@@ -74,6 +73,12 @@ export function SettingsDialog({ open, onOpenChange }: SettingsDialogProps) {
)} + {activeTab === "analytics" && ( +
+ +
+ )} + {activeTab === "shortcuts" && (

Keyboard shortcuts will be available here.

diff --git a/src/features/settings/components/index.tsx b/src/features/settings/components/index.tsx index 6196572..7df7d47 100644 --- a/src/features/settings/components/index.tsx +++ b/src/features/settings/components/index.tsx @@ -2,6 +2,7 @@ export { default as Header } from './Header' export { default as ThemeMode } from './ThemeMode' export { default as ColorVariant } from './ColorVariant' export { default as DeveloperMode } from './DeveloperMode' +export { default as AnalyticsSettings } from './AnalyticsSettings' export { default as CheckForUpdates } from './CheckForUpdates' export { default as Version } from './Version' export { default as AISettings } from './AISettings' diff --git a/src/services/analytics.ts b/src/services/analytics.ts new file mode 100644 index 0000000..799f800 --- /dev/null +++ b/src/services/analytics.ts @@ -0,0 +1,101 @@ +import { invoke } from "@tauri-apps/api/core"; +import { trackEvent as aptabaseTrackEvent } from "@aptabase/tauri"; + +export const analyticsService = { + async trackEvent(eventName: string, props?: Record): Promise { + try { + const enabled = await this.isEnabled(); + if (enabled) { + console.log("Dispatching to Aptabase:", eventName, props); + if (props) { + await aptabaseTrackEvent(eventName, props as any); + } else { + await aptabaseTrackEvent(eventName); + } + } + } catch (e) { + console.warn("Failed to track analytics event:", e); + } + }, + + async isEnabled(): Promise { + try { + return await invoke("get_analytics_enabled"); + } catch (e) { + console.warn("Failed to get analytics status:", e); + return false; + } + }, + + async setEnabled(enabled: boolean): Promise { + try { + await invoke("set_analytics_enabled", { enabled }); + } catch (e) { + console.warn("Failed to set analytics status:", e); + } + }, + + trackDatabaseAdded(type?: string): void { + this.trackEvent("database_added", { type }); + }, + + trackDatabaseConnected(type?: string): void { + this.trackEvent("database_connected", { type }); + }, + + trackDatabaseConnectionFailed(type?: string, error?: string): void { + this.trackEvent("database_connection_failed", { type, error }); + }, + + trackDatabaseRemoved(type?: string): void { + this.trackEvent("database_removed", { type }); + }, + + trackSshConnectionSuccess(): void { + this.trackEvent("ssh_connection_success"); + }, + + trackProjectCreated(): void { + this.trackEvent("project_created"); + }, + + trackProjectOpened(): void { + this.trackEvent("project_opened"); + }, + + trackQueryExecuted(): void { + this.trackEvent("query_executed"); + }, + + trackErDiagramOpened(): void { + this.trackEvent("er_diagram_opened"); + }, + + trackErDiagramExported(format: string): void { + this.trackEvent("er_diagram_exported", { format }); + }, + + trackMigrationCreated(): void { + this.trackEvent("migration_created"); + }, + + trackMigrationApplied(): void { + this.trackEvent("migration_applied"); + }, + + trackGitInitialized(): void { + this.trackEvent("git_initialized"); + }, + + trackGitCommit(): void { + this.trackEvent("git_commit"); + }, + + trackAiChatOpened(): void { + this.trackEvent("ai_chat_opened"); + }, + + trackChartCreated(): void { + this.trackEvent("chart_created"); + } +}; diff --git a/src/services/bridge/ai.ts b/src/services/bridge/ai.ts index 6d5dbb1..d5ebbc9 100644 --- a/src/services/bridge/ai.ts +++ b/src/services/bridge/ai.ts @@ -1,4 +1,5 @@ import { bridgeRequest } from "./bridgeClient"; +import { analyticsService } from "../analytics"; // ── Re-export the types that the frontend needs ─────────────────────────── // (These mirror the bridge types but kept local to avoid importing from bridge) @@ -204,6 +205,7 @@ class AIService { input: SchemaAnalysisInput, opts?: { skipCache?: boolean; datasourceName?: string } ): Promise { + analyticsService.trackAiChatOpened(); const result = await bridgeRequest("ai.analyzeSchema", { settings, input, @@ -225,6 +227,7 @@ class AIService { input: QueryExplanationInput, opts?: { skipCache?: boolean; datasourceName?: string } ): Promise { + analyticsService.trackAiChatOpened(); const result = await bridgeRequest("ai.explainQuery", { settings, input, diff --git a/src/services/bridge/git.ts b/src/services/bridge/git.ts index 5ba0708..1fe655a 100644 --- a/src/services/bridge/git.ts +++ b/src/services/bridge/git.ts @@ -1,5 +1,6 @@ import { GitBranchInfo, GitFileChange, GitLogEntry, GitPushPullResult, GitRemoteInfo, GitStatus } from "@/features/git/types"; import { bridgeRequest } from "./bridgeClient"; +import { analyticsService } from "../analytics"; class GitService { /** @@ -15,6 +16,7 @@ class GitService { */ async gitInit(dir: string, defaultBranch = "main"): Promise { const result = await bridgeRequest("git.init", { dir, defaultBranch }); + analyticsService.trackGitInitialized(); return result?.data; } @@ -52,6 +54,7 @@ class GitService { */ async gitCommit(dir: string, message: string): Promise<{ hash: string }> { const result = await bridgeRequest("git.commit", { dir, message }); + analyticsService.trackGitCommit(); return result?.data; } diff --git a/src/services/bridge/migration.ts b/src/services/bridge/migration.ts index ea818f2..6ccdd44 100644 --- a/src/services/bridge/migration.ts +++ b/src/services/bridge/migration.ts @@ -1,4 +1,5 @@ import { bridgeRequest } from "./bridgeClient"; +import { analyticsService } from "../analytics"; class MigrationService { /** @@ -13,6 +14,7 @@ class MigrationService { }): Promise<{ version: string; filename: string; filepath: string }> { try { const result = await bridgeRequest("migration.generateCreate", params); + analyticsService.trackMigrationCreated(); return result?.data; } catch (error: any) { console.error("Failed to generate create migration:", error); @@ -31,6 +33,7 @@ class MigrationService { }): Promise<{ version: string; filename: string; filepath: string }> { try { const result = await bridgeRequest("migration.generateAlter", params); + analyticsService.trackMigrationCreated(); return result?.data; } catch (error: any) { console.error("Failed to generate alter migration:", error); @@ -49,6 +52,7 @@ class MigrationService { }): Promise<{ version: string; filename: string; filepath: string }> { try { const result = await bridgeRequest("migration.generateDrop", params); + analyticsService.trackMigrationCreated(); return result?.data; } catch (error: any) { console.error("Failed to generate drop migration:", error); @@ -62,6 +66,9 @@ class MigrationService { async applyMigration(dbId: string, version: string): Promise { try { const result = await bridgeRequest("migration.apply", { dbId, version }); + if (result?.ok) { + analyticsService.trackMigrationApplied(); + } return result?.ok === true; } catch (error: any) { console.error("Failed to apply migration:", error); diff --git a/vite.config.ts b/vite.config.ts index 779e44c..40dee63 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -10,9 +10,10 @@ export default defineConfig(async () => ({ plugins: [react(), tailwindcss()], resolve: { - alias: { - "@": path.resolve(__dirname, "./src"), - }, + alias: [ + { find: "@", replacement: path.resolve(__dirname, "./src") }, + { find: /^@tauri-apps\/api$/, replacement: "@tauri-apps/api/core" }, + ], }, // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`