mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-23 09:08:32 +02:00
Dynamic plugins (#68)
This commit is contained in:
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
@@ -38,10 +38,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: '1.22'
|
|
||||||
|
|
||||||
- name: install Rust stable
|
- name: install Rust stable
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
with:
|
with:
|
||||||
@@ -81,7 +77,7 @@ jobs:
|
|||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Install yaak CLI
|
- name: Install yaak CLI
|
||||||
run: go install github.com/yaakapp/yaakcli@latest
|
run: npm install -g @yaakapp/cli
|
||||||
|
|
||||||
- name: Run lint
|
- name: Run lint
|
||||||
run: npm run lint
|
run: npm run lint
|
||||||
|
|||||||
96
package-lock.json
generated
96
package-lock.json
generated
@@ -27,7 +27,7 @@
|
|||||||
"@tauri-apps/plugin-log": "^2.0.0-rc.1",
|
"@tauri-apps/plugin-log": "^2.0.0-rc.1",
|
||||||
"@tauri-apps/plugin-os": "^2.0.0-rc.1",
|
"@tauri-apps/plugin-os": "^2.0.0-rc.1",
|
||||||
"@tauri-apps/plugin-shell": "^2.0.0-rc.1",
|
"@tauri-apps/plugin-shell": "^2.0.0-rc.1",
|
||||||
"@yaakapp/api": "^0.1.15",
|
"@yaakapp/api": "^0.1.16",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
"cm6-graphql": "^0.0.9",
|
"cm6-graphql": "^0.0.9",
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
||||||
"@tanstack/react-query-devtools": "^5.45.1",
|
"@tanstack/react-query-devtools": "^5.45.1",
|
||||||
"@tauri-apps/cli": "^2.0.0-rc.2",
|
"@tauri-apps/cli": "^2.0.0-rc.12",
|
||||||
"@types/node": "^18.7.10",
|
"@types/node": "^18.7.10",
|
||||||
"@types/papaparse": "^5.3.7",
|
"@types/papaparse": "^5.3.7",
|
||||||
"@types/parse-color": "^1.0.1",
|
"@types/parse-color": "^1.0.1",
|
||||||
@@ -2354,9 +2354,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli": {
|
"node_modules/@tauri-apps/cli": {
|
||||||
"version": "2.0.0-rc.3",
|
"version": "2.0.0-rc.12",
|
||||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.0.0-rc.3.tgz",
|
"resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.0.0-rc.12.tgz",
|
||||||
"integrity": "sha512-iNF95pieBmverl1EmQyqh+fhcIClS544fN5Ex5lAbYLTiHZ/gm3lOfVBhF6NPaKd/sfLuy7K1tfDXlHztBfANw==",
|
"integrity": "sha512-rNcVSyGHGz8vNk542isYKPk5fEMAsgmzER+1s9YYbGZCH7m4e0rH89p/P9W40I/Z4AZk4ZqjpEeajeS5izDI4g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tauri": "tauri.js"
|
"tauri": "tauri.js"
|
||||||
@@ -2369,22 +2369,22 @@
|
|||||||
"url": "https://opencollective.com/tauri"
|
"url": "https://opencollective.com/tauri"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@tauri-apps/cli-darwin-arm64": "2.0.0-rc.3",
|
"@tauri-apps/cli-darwin-arm64": "2.0.0-rc.12",
|
||||||
"@tauri-apps/cli-darwin-x64": "2.0.0-rc.3",
|
"@tauri-apps/cli-darwin-x64": "2.0.0-rc.12",
|
||||||
"@tauri-apps/cli-linux-arm-gnueabihf": "2.0.0-rc.3",
|
"@tauri-apps/cli-linux-arm-gnueabihf": "2.0.0-rc.12",
|
||||||
"@tauri-apps/cli-linux-arm64-gnu": "2.0.0-rc.3",
|
"@tauri-apps/cli-linux-arm64-gnu": "2.0.0-rc.12",
|
||||||
"@tauri-apps/cli-linux-arm64-musl": "2.0.0-rc.3",
|
"@tauri-apps/cli-linux-arm64-musl": "2.0.0-rc.12",
|
||||||
"@tauri-apps/cli-linux-x64-gnu": "2.0.0-rc.3",
|
"@tauri-apps/cli-linux-x64-gnu": "2.0.0-rc.12",
|
||||||
"@tauri-apps/cli-linux-x64-musl": "2.0.0-rc.3",
|
"@tauri-apps/cli-linux-x64-musl": "2.0.0-rc.12",
|
||||||
"@tauri-apps/cli-win32-arm64-msvc": "2.0.0-rc.3",
|
"@tauri-apps/cli-win32-arm64-msvc": "2.0.0-rc.12",
|
||||||
"@tauri-apps/cli-win32-ia32-msvc": "2.0.0-rc.3",
|
"@tauri-apps/cli-win32-ia32-msvc": "2.0.0-rc.12",
|
||||||
"@tauri-apps/cli-win32-x64-msvc": "2.0.0-rc.3"
|
"@tauri-apps/cli-win32-x64-msvc": "2.0.0-rc.12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-darwin-arm64": {
|
"node_modules/@tauri-apps/cli-darwin-arm64": {
|
||||||
"version": "2.0.0-rc.3",
|
"version": "2.0.0-rc.12",
|
||||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.0.0-rc.3.tgz",
|
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.0.0-rc.12.tgz",
|
||||||
"integrity": "sha512-szYCSr/ChbCF+S6Wnr15TYpI2cZR07d+AQOiFGuScP0preM8Pbsk/sb0hfLwqzepjVFFNVWQba9sG7FEW2Y2XA==",
|
"integrity": "sha512-zYxcAH4reyqKkqCAybggszFWkBvC+ZyZPTWFKXXVQ20MZc1q+e/0UJYC8UKsaumrbi1uptgamvnM8yql56x5QQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -2398,9 +2398,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-darwin-x64": {
|
"node_modules/@tauri-apps/cli-darwin-x64": {
|
||||||
"version": "2.0.0-rc.3",
|
"version": "2.0.0-rc.12",
|
||||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.0.0-rc.3.tgz",
|
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.0.0-rc.12.tgz",
|
||||||
"integrity": "sha512-BJv6EJOY1DJbRzVtfg8CcBAlnS5OjhBAc5YKjh4BT7EyOcop8HStBSxhL6yjWrUP7eLR1iIsW/uSehVJwzYIdQ==",
|
"integrity": "sha512-eme7pQzEzeGCk13V3uxUNRnkVZJukqwHotqEb2RdovXqJWSyESrighBy4PBG5Xn6wNYTOyoquY9+In4TOfJAzw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -2414,9 +2414,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
|
"node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
|
||||||
"version": "2.0.0-rc.3",
|
"version": "2.0.0-rc.12",
|
||||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.0.0-rc.3.tgz",
|
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.0.0-rc.12.tgz",
|
||||||
"integrity": "sha512-fwx805/xL4sF/EdMYqcUHQHzMYwo+OVTBTz5x/JWK8D57rnmLHAP+ZhnfFsZQLRo2QRT2l1Ye3bDyU+QRA1JFA==",
|
"integrity": "sha512-113T2NsLeoy6GXsqc0yjMoozt+KXzkAtUB7DL9Kcvx9IMfA87cUVaTNjnb2GFsoQqpCWGfHei3nr9n1PGEbwMg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -2430,9 +2430,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-linux-arm64-gnu": {
|
"node_modules/@tauri-apps/cli-linux-arm64-gnu": {
|
||||||
"version": "2.0.0-rc.3",
|
"version": "2.0.0-rc.12",
|
||||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.0.0-rc.3.tgz",
|
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.0.0-rc.12.tgz",
|
||||||
"integrity": "sha512-3KauzO1Ls4kuY0nr82S4X8XFxlQAMN+Mqp8LLqvQ+PPMp92XQAkPH7osQdoHIEoW5gsE69U2JaiQ5tHSqNM9og==",
|
"integrity": "sha512-9TrUyNg0vmsYF7IbG+/sybEeiz6ikA1Kjd6JjC4iwfXjRff8fuTR7CIOb06imabxbLzGP79qSAnGAeTXz8E7qA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -2446,9 +2446,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-linux-arm64-musl": {
|
"node_modules/@tauri-apps/cli-linux-arm64-musl": {
|
||||||
"version": "2.0.0-rc.3",
|
"version": "2.0.0-rc.12",
|
||||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.0.0-rc.3.tgz",
|
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.0.0-rc.12.tgz",
|
||||||
"integrity": "sha512-ngHS0foffm1xO5gqnDKGeYMKj8ceGmrFP5dDldoaaMQubw1SyFa0pRUjb7fZSYiO7F4SOSa8NYeMqlF9peZmnQ==",
|
"integrity": "sha512-YvE40+wdkNcXhwUAJNPyhNzJ8YS3saJoxGj7mtNQeNeNrKhxyj6hA5T6gw9KtMkwBOp+HGtqn+eDXiu0X7BBHQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -2462,9 +2462,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-linux-x64-gnu": {
|
"node_modules/@tauri-apps/cli-linux-x64-gnu": {
|
||||||
"version": "2.0.0-rc.3",
|
"version": "2.0.0-rc.12",
|
||||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.0.0-rc.3.tgz",
|
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.0.0-rc.12.tgz",
|
||||||
"integrity": "sha512-0/am9pVvuUHGmz32M8ffz1fpLnc08j3nzcRe5wUdL2AxfT+wKMII+Dn99GtCVgcdDW4jSXDMRUwrBkGocGC2OA==",
|
"integrity": "sha512-q+MJp/lSA5WINs78dCFMlU0/jQeUkGr9GHbKeppcVcpkcY/1vog70b4KhneyvbuklKBn/V8kd0FtIKCn8VP+KQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -2478,9 +2478,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-linux-x64-musl": {
|
"node_modules/@tauri-apps/cli-linux-x64-musl": {
|
||||||
"version": "2.0.0-rc.3",
|
"version": "2.0.0-rc.12",
|
||||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.0.0-rc.3.tgz",
|
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.0.0-rc.12.tgz",
|
||||||
"integrity": "sha512-r7mRi8q8TqTFVjb9kAsU7IgwUgno2s8Ip4xwq9psQhlRE3JGEZQmSEcy1jqTjfl6KFh6lJcDR7l+9/EMhL/D3Q==",
|
"integrity": "sha512-5zodtleH2GFsB9lszDYrzPTLcr+MMqtpQpJWHATC1K03bLEA8ia8zSdBqRwm7u8NraMLl8TE7hc7hwq0uxGEcg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -2494,9 +2494,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-win32-arm64-msvc": {
|
"node_modules/@tauri-apps/cli-win32-arm64-msvc": {
|
||||||
"version": "2.0.0-rc.3",
|
"version": "2.0.0-rc.12",
|
||||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.0.0-rc.3.tgz",
|
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.0.0-rc.12.tgz",
|
||||||
"integrity": "sha512-2J6KjmDIQCw6HF1X6/yPcd+JLl7pxrH2zVMGmNllaoWhHeByvRobqFWnT7gcdHaA3dGTo432CwWvOgTgrINQpQ==",
|
"integrity": "sha512-nSu6VHpuq61DYM2YowLDLDwkK8im7dzYxIHXs+h8/rhkmadTujGhbyUhHPI1STA6hNyITUtSFpo6P2mEbfpAIg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -2510,9 +2510,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-win32-ia32-msvc": {
|
"node_modules/@tauri-apps/cli-win32-ia32-msvc": {
|
||||||
"version": "2.0.0-rc.3",
|
"version": "2.0.0-rc.12",
|
||||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.0.0-rc.3.tgz",
|
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.0.0-rc.12.tgz",
|
||||||
"integrity": "sha512-8q75CsHDSEDdgi6xPwim+BaQZFCswK2Dn/qL38V3Mh9kmVvC8oGJMPC66bC20dF+v3KWeFm2FNNGQqOSXCveHg==",
|
"integrity": "sha512-d/4y57OisMuB+MUkTpZsryQRi9ZQXQ8SsMhrvEgu8sbX8/WRm0iZyGuIZ01RlZZHLIasXbKTkPX+hPQC5Juk8Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@@ -2526,9 +2526,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-win32-x64-msvc": {
|
"node_modules/@tauri-apps/cli-win32-x64-msvc": {
|
||||||
"version": "2.0.0-rc.3",
|
"version": "2.0.0-rc.12",
|
||||||
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.0.0-rc.3.tgz",
|
"resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.0.0-rc.12.tgz",
|
||||||
"integrity": "sha512-qeBRJYalahxEXolekcpZJ/HBrIJacG2NWJBGhhi797mIwnbmlpbHMc8blIJtNNNwVUb2BjXuxKQVfojQ5YYrcg==",
|
"integrity": "sha512-RsPUvsbFza03ysh0nU2nM3P2CVWz9cu7CRHwOEdtXjWWNREHUYCaVpqQKz0tn2sG19yXiNIB40iqrIBUmb/IoA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -2986,9 +2986,9 @@
|
|||||||
"integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ=="
|
"integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ=="
|
||||||
},
|
},
|
||||||
"node_modules/@yaakapp/api": {
|
"node_modules/@yaakapp/api": {
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"resolved": "https://registry.npmjs.org/@yaakapp/api/-/api-0.1.15.tgz",
|
"resolved": "https://registry.npmjs.org/@yaakapp/api/-/api-0.1.16.tgz",
|
||||||
"integrity": "sha512-4nrImM9r4Afih0CcG6PWtGA6Luap/Ki5ZVl56WejWA8WPpy8AhEpC0KErpJChNzzqRjgK9ZEWdQNsBHppzAs8A==",
|
"integrity": "sha512-rWXXb0iUiUk6jtLhZFcbdMRIf6dYXY9wyIvFG9rVpyMxB0LWjim8VpvwF4IK4Y/paxvZ9bjvnaD5PAB4pH6prg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "^22.0.0"
|
"@types/node": "^22.0.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
"@tauri-apps/plugin-log": "^2.0.0-rc.1",
|
"@tauri-apps/plugin-log": "^2.0.0-rc.1",
|
||||||
"@tauri-apps/plugin-os": "^2.0.0-rc.1",
|
"@tauri-apps/plugin-os": "^2.0.0-rc.1",
|
||||||
"@tauri-apps/plugin-shell": "^2.0.0-rc.1",
|
"@tauri-apps/plugin-shell": "^2.0.0-rc.1",
|
||||||
"@yaakapp/api": "^0.1.15",
|
"@yaakapp/api": "^0.1.16",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
"cm6-graphql": "^0.0.9",
|
"cm6-graphql": "^0.0.9",
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
||||||
"@tanstack/react-query-devtools": "^5.45.1",
|
"@tanstack/react-query-devtools": "^5.45.1",
|
||||||
"@tauri-apps/cli": "^2.0.0-rc.2",
|
"@tauri-apps/cli": "^2.0.0-rc.12",
|
||||||
"@types/node": "^18.7.10",
|
"@types/node": "^18.7.10",
|
||||||
"@types/papaparse": "^5.3.7",
|
"@types/papaparse": "^5.3.7",
|
||||||
"@types/parse-color": "^1.0.1",
|
"@types/parse-color": "^1.0.1",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@yaakapp/api",
|
"name": "@yaakapp/api",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"typings": "./lib/index.d.ts",
|
"typings": "./lib/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
import type { GrpcEventType } from "./GrpcEventType";
|
import type { GrpcEventType } from "./GrpcEventType";
|
||||||
|
|
||||||
export type GrpcEvent = { id: string, model: "grpc_event", workspaceId: string, requestId: string, connectionId: string, createdAt: string, content: string, eventType: GrpcEventType, metadata: { [key: string]: string }, status: number | null, error: string | null, };
|
export type GrpcEvent = { id: string, model: "grpc_event", workspaceId: string, requestId: string, connectionId: string, createdAt: string, updatedAt: string, content: string, eventType: GrpcEventType, metadata: { [key: string]: string }, status: number | null, error: string | null, };
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
import type { BootRequest } from "./BootRequest";
|
|
||||||
import type { BootResponse } from "./BootResponse";
|
|
||||||
import type { CallHttpRequestActionRequest } from "./CallHttpRequestActionRequest";
|
import type { CallHttpRequestActionRequest } from "./CallHttpRequestActionRequest";
|
||||||
import type { CallTemplateFunctionRequest } from "./CallTemplateFunctionRequest";
|
import type { CallTemplateFunctionRequest } from "./CallTemplateFunctionRequest";
|
||||||
import type { CallTemplateFunctionResponse } from "./CallTemplateFunctionResponse";
|
import type { CallTemplateFunctionResponse } from "./CallTemplateFunctionResponse";
|
||||||
@@ -19,10 +17,12 @@ import type { GetHttpRequestByIdResponse } from "./GetHttpRequestByIdResponse";
|
|||||||
import type { GetTemplateFunctionsResponse } from "./GetTemplateFunctionsResponse";
|
import type { GetTemplateFunctionsResponse } from "./GetTemplateFunctionsResponse";
|
||||||
import type { ImportRequest } from "./ImportRequest";
|
import type { ImportRequest } from "./ImportRequest";
|
||||||
import type { ImportResponse } from "./ImportResponse";
|
import type { ImportResponse } from "./ImportResponse";
|
||||||
|
import type { PluginBootRequest } from "./PluginBootRequest";
|
||||||
|
import type { PluginBootResponse } from "./PluginBootResponse";
|
||||||
import type { RenderHttpRequestRequest } from "./RenderHttpRequestRequest";
|
import type { RenderHttpRequestRequest } from "./RenderHttpRequestRequest";
|
||||||
import type { RenderHttpRequestResponse } from "./RenderHttpRequestResponse";
|
import type { RenderHttpRequestResponse } from "./RenderHttpRequestResponse";
|
||||||
import type { SendHttpRequestRequest } from "./SendHttpRequestRequest";
|
import type { SendHttpRequestRequest } from "./SendHttpRequestRequest";
|
||||||
import type { SendHttpRequestResponse } from "./SendHttpRequestResponse";
|
import type { SendHttpRequestResponse } from "./SendHttpRequestResponse";
|
||||||
import type { ShowToastRequest } from "./ShowToastRequest";
|
import type { ShowToastRequest } from "./ShowToastRequest";
|
||||||
|
|
||||||
export type InternalEventPayload = { "type": "boot_request" } & BootRequest | { "type": "boot_response" } & BootResponse | { "type": "import_request" } & ImportRequest | { "type": "import_response" } & ImportResponse | { "type": "filter_request" } & FilterRequest | { "type": "filter_response" } & FilterResponse | { "type": "export_http_request_request" } & ExportHttpRequestRequest | { "type": "export_http_request_response" } & ExportHttpRequestResponse | { "type": "send_http_request_request" } & SendHttpRequestRequest | { "type": "send_http_request_response" } & SendHttpRequestResponse | { "type": "get_http_request_actions_request" } & GetHttpRequestActionsRequest | { "type": "get_http_request_actions_response" } & GetHttpRequestActionsResponse | { "type": "call_http_request_action_request" } & CallHttpRequestActionRequest | { "type": "get_template_functions_request" } | { "type": "get_template_functions_response" } & GetTemplateFunctionsResponse | { "type": "call_template_function_request" } & CallTemplateFunctionRequest | { "type": "call_template_function_response" } & CallTemplateFunctionResponse | { "type": "copy_text_request" } & CopyTextRequest | { "type": "render_http_request_request" } & RenderHttpRequestRequest | { "type": "render_http_request_response" } & RenderHttpRequestResponse | { "type": "show_toast_request" } & ShowToastRequest | { "type": "get_http_request_by_id_request" } & GetHttpRequestByIdRequest | { "type": "get_http_request_by_id_response" } & GetHttpRequestByIdResponse | { "type": "find_http_responses_request" } & FindHttpResponsesRequest | { "type": "find_http_responses_response" } & FindHttpResponsesResponse | { "type": "empty_response" } & EmptyResponse;
|
export type InternalEventPayload = { "type": "boot_request" } & PluginBootRequest | { "type": "boot_response" } & PluginBootResponse | { "type": "import_request" } & ImportRequest | { "type": "import_response" } & ImportResponse | { "type": "filter_request" } & FilterRequest | { "type": "filter_response" } & FilterResponse | { "type": "export_http_request_request" } & ExportHttpRequestRequest | { "type": "export_http_request_response" } & ExportHttpRequestResponse | { "type": "send_http_request_request" } & SendHttpRequestRequest | { "type": "send_http_request_response" } & SendHttpRequestResponse | { "type": "get_http_request_actions_request" } & GetHttpRequestActionsRequest | { "type": "get_http_request_actions_response" } & GetHttpRequestActionsResponse | { "type": "call_http_request_action_request" } & CallHttpRequestActionRequest | { "type": "get_template_functions_request" } | { "type": "get_template_functions_response" } & GetTemplateFunctionsResponse | { "type": "call_template_function_request" } & CallTemplateFunctionRequest | { "type": "call_template_function_response" } & CallTemplateFunctionResponse | { "type": "copy_text_request" } & CopyTextRequest | { "type": "render_http_request_request" } & RenderHttpRequestRequest | { "type": "render_http_request_response" } & RenderHttpRequestResponse | { "type": "show_toast_request" } & ShowToastRequest | { "type": "get_http_request_by_id_request" } & GetHttpRequestByIdRequest | { "type": "get_http_request_by_id_response" } & GetHttpRequestByIdResponse | { "type": "find_http_responses_request" } & FindHttpResponsesRequest | { "type": "find_http_responses_response" } & FindHttpResponsesResponse | { "type": "empty_response" } & EmptyResponse;
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ import type { GrpcRequest } from "./GrpcRequest";
|
|||||||
import type { HttpRequest } from "./HttpRequest";
|
import type { HttpRequest } from "./HttpRequest";
|
||||||
import type { HttpResponse } from "./HttpResponse";
|
import type { HttpResponse } from "./HttpResponse";
|
||||||
import type { KeyValue } from "./KeyValue";
|
import type { KeyValue } from "./KeyValue";
|
||||||
|
import type { Plugin } from "./Plugin";
|
||||||
import type { Settings } from "./Settings";
|
import type { Settings } from "./Settings";
|
||||||
import type { Workspace } from "./Workspace";
|
import type { Workspace } from "./Workspace";
|
||||||
|
|
||||||
export type Model = Environment | Folder | GrpcConnection | GrpcEvent | GrpcRequest | HttpRequest | HttpResponse | KeyValue | Workspace | CookieJar | Settings;
|
export type Model = Environment | Folder | GrpcConnection | GrpcEvent | GrpcRequest | HttpRequest | HttpResponse | KeyValue | Workspace | CookieJar | Settings | Plugin;
|
||||||
|
|||||||
3
plugin-runtime-types/src/gen/Plugin.ts
Normal file
3
plugin-runtime-types/src/gen/Plugin.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
|
||||||
|
export type Plugin = { id: string, model: "plugin", createdAt: string, updatedAt: string, checkedAt: string | null, name: string, version: string, uri: string, enabled: boolean, };
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
|
||||||
export type BootRequest = { dir: string, };
|
export type PluginBootRequest = { dir: string, };
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
|
||||||
export type BootResponse = { name: string, version: string, capabilities: Array<string>, };
|
export type PluginBootResponse = { name: string, version: string, capabilities: Array<string>, };
|
||||||
@@ -2,8 +2,6 @@ export type * from './plugins';
|
|||||||
export type * from './themes';
|
export type * from './themes';
|
||||||
|
|
||||||
// TODO: The next ts-rs release includes the ability to put everything in 1 file!
|
// TODO: The next ts-rs release includes the ability to put everything in 1 file!
|
||||||
export * from './gen/BootRequest';
|
|
||||||
export * from './gen/BootResponse';
|
|
||||||
export * from './gen/CallHttpRequestActionArgs';
|
export * from './gen/CallHttpRequestActionArgs';
|
||||||
export * from './gen/CallHttpRequestActionRequest';
|
export * from './gen/CallHttpRequestActionRequest';
|
||||||
export * from './gen/CallTemplateFunctionRequest';
|
export * from './gen/CallTemplateFunctionRequest';
|
||||||
@@ -63,3 +61,4 @@ export * from './gen/TemplateFunctionSelectOption';
|
|||||||
export * from './gen/TemplateFunctionTextArg';
|
export * from './gen/TemplateFunctionTextArg';
|
||||||
export * from './gen/ToastVariant';
|
export * from './gen/ToastVariant';
|
||||||
export * from './gen/Workspace';
|
export * from './gen/Workspace';
|
||||||
|
export * from './gen/Plugin';
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export type { Context } from './Context';
|
|||||||
/**
|
/**
|
||||||
* The global structure of a Yaak plugin
|
* The global structure of a Yaak plugin
|
||||||
*/
|
*/
|
||||||
export type Plugin = {
|
export type PluginDefinition = {
|
||||||
importer?: ImporterPlugin;
|
importer?: ImporterPlugin;
|
||||||
theme?: ThemePlugin;
|
theme?: ThemePlugin;
|
||||||
filter?: FilterPlugin;
|
filter?: FilterPlugin;
|
||||||
|
|||||||
12
src-tauri/migrations/20240829131004_plugins.sql
Normal file
12
src-tauri/migrations/20240829131004_plugins.sql
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
CREATE TABLE plugins
|
||||||
|
(
|
||||||
|
id TEXT NOT NULL
|
||||||
|
PRIMARY KEY,
|
||||||
|
model TEXT DEFAULT 'plugin' NOT NULL,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||||
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||||
|
checked_at DATETIME NULL,
|
||||||
|
enabled BOOLEAN NOT NULL,
|
||||||
|
directory TEXT NULL NOT NULL,
|
||||||
|
url TEXT NULL
|
||||||
|
);
|
||||||
@@ -28,6 +28,7 @@ pub enum AnalyticsResource {
|
|||||||
HttpRequest,
|
HttpRequest,
|
||||||
HttpResponse,
|
HttpResponse,
|
||||||
KeyValue,
|
KeyValue,
|
||||||
|
Plugin,
|
||||||
Setting,
|
Setting,
|
||||||
Sidebar,
|
Sidebar,
|
||||||
Theme,
|
Theme,
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ use crate::updates::{UpdateMode, YaakUpdater};
|
|||||||
use crate::window_menu::app_menu;
|
use crate::window_menu::app_menu;
|
||||||
use yaak_models::models::{
|
use yaak_models::models::{
|
||||||
CookieJar, Environment, EnvironmentVariable, Folder, GrpcConnection, GrpcEvent, GrpcEventType,
|
CookieJar, Environment, EnvironmentVariable, Folder, GrpcConnection, GrpcEvent, GrpcEventType,
|
||||||
GrpcRequest, HttpRequest, HttpResponse, KeyValue, ModelType, Settings, Workspace,
|
GrpcRequest, HttpRequest, HttpResponse, KeyValue, ModelType, Plugin, Settings, Workspace,
|
||||||
};
|
};
|
||||||
use yaak_models::queries::{
|
use yaak_models::queries::{
|
||||||
cancel_pending_grpc_connections, cancel_pending_responses, create_default_http_response,
|
cancel_pending_grpc_connections, cancel_pending_responses, create_default_http_response,
|
||||||
@@ -49,16 +49,17 @@ use yaak_models::queries::{
|
|||||||
delete_http_response, delete_workspace, duplicate_grpc_request, duplicate_http_request,
|
delete_http_response, delete_workspace, duplicate_grpc_request, duplicate_http_request,
|
||||||
generate_model_id, get_cookie_jar, get_environment, get_folder, get_grpc_connection,
|
generate_model_id, get_cookie_jar, get_environment, get_folder, get_grpc_connection,
|
||||||
get_grpc_request, get_http_request, get_http_response, get_key_value_raw,
|
get_grpc_request, get_http_request, get_http_response, get_key_value_raw,
|
||||||
get_or_create_settings, get_workspace, list_cookie_jars, list_environments, list_folders,
|
get_or_create_settings, get_plugin, get_workspace, list_cookie_jars, list_environments,
|
||||||
list_grpc_connections, list_grpc_events, list_grpc_requests, list_http_requests,
|
list_folders, list_grpc_connections, list_grpc_events, list_grpc_requests, list_http_requests,
|
||||||
list_http_responses, list_workspaces, set_key_value_raw, update_response_if_id,
|
list_http_responses, list_plugins, list_workspaces, set_key_value_raw, update_response_if_id,
|
||||||
update_settings, upsert_cookie_jar, upsert_environment, upsert_folder, upsert_grpc_connection,
|
update_settings, upsert_cookie_jar, upsert_environment, upsert_folder, upsert_grpc_connection,
|
||||||
upsert_grpc_event, upsert_grpc_request, upsert_http_request, upsert_workspace,
|
upsert_grpc_event, upsert_grpc_request, upsert_http_request, upsert_plugin, upsert_workspace,
|
||||||
};
|
};
|
||||||
use yaak_plugin_runtime::events::{
|
use yaak_plugin_runtime::events::{
|
||||||
CallHttpRequestActionRequest, FilterResponse, FindHttpResponsesResponse,
|
CallHttpRequestActionRequest, FilterResponse, FindHttpResponsesResponse,
|
||||||
GetHttpRequestActionsResponse, GetHttpRequestByIdResponse, GetTemplateFunctionsResponse,
|
GetHttpRequestActionsResponse, GetHttpRequestByIdResponse, GetTemplateFunctionsResponse,
|
||||||
InternalEvent, InternalEventPayload, RenderHttpRequestResponse, SendHttpRequestResponse,
|
InternalEvent, InternalEventPayload, PluginBootResponse, RenderHttpRequestResponse,
|
||||||
|
SendHttpRequestResponse,
|
||||||
};
|
};
|
||||||
use yaak_templates::{Parser, Tokens};
|
use yaak_templates::{Parser, Tokens};
|
||||||
|
|
||||||
@@ -77,6 +78,9 @@ mod window_menu;
|
|||||||
const DEFAULT_WINDOW_WIDTH: f64 = 1100.0;
|
const DEFAULT_WINDOW_WIDTH: f64 = 1100.0;
|
||||||
const DEFAULT_WINDOW_HEIGHT: f64 = 600.0;
|
const DEFAULT_WINDOW_HEIGHT: f64 = 600.0;
|
||||||
|
|
||||||
|
const MIN_WINDOW_WIDTH: f64 = 300.0;
|
||||||
|
const MIN_WINDOW_HEIGHT: f64 = 300.0;
|
||||||
|
|
||||||
#[derive(serde::Serialize)]
|
#[derive(serde::Serialize)]
|
||||||
#[serde(default, rename_all = "camelCase")]
|
#[serde(default, rename_all = "camelCase")]
|
||||||
struct AppMetaData {
|
struct AppMetaData {
|
||||||
@@ -1165,6 +1169,20 @@ async fn cmd_create_workspace(name: &str, w: WebviewWindow) -> Result<Workspace,
|
|||||||
.map_err(|e| e.to_string())
|
.map_err(|e| e.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
async fn cmd_create_plugin(directory: &str, url: Option<String>, w: WebviewWindow) -> Result<Plugin, String> {
|
||||||
|
upsert_plugin(
|
||||||
|
&w,
|
||||||
|
Plugin {
|
||||||
|
directory: directory.into(),
|
||||||
|
url,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn cmd_update_cookie_jar(
|
async fn cmd_update_cookie_jar(
|
||||||
cookie_jar: CookieJar,
|
cookie_jar: CookieJar,
|
||||||
@@ -1408,10 +1426,9 @@ async fn cmd_list_grpc_requests(
|
|||||||
workspace_id: &str,
|
workspace_id: &str,
|
||||||
w: WebviewWindow,
|
w: WebviewWindow,
|
||||||
) -> Result<Vec<GrpcRequest>, String> {
|
) -> Result<Vec<GrpcRequest>, String> {
|
||||||
let requests = list_grpc_requests(&w, workspace_id)
|
list_grpc_requests(&w, workspace_id)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())
|
||||||
Ok(requests)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@@ -1419,11 +1436,9 @@ async fn cmd_list_http_requests(
|
|||||||
workspace_id: &str,
|
workspace_id: &str,
|
||||||
w: WebviewWindow,
|
w: WebviewWindow,
|
||||||
) -> Result<Vec<HttpRequest>, String> {
|
) -> Result<Vec<HttpRequest>, String> {
|
||||||
let requests = list_http_requests(&w, workspace_id)
|
list_http_requests(&w, workspace_id)
|
||||||
.await
|
.await
|
||||||
.expect("Failed to find requests");
|
.map_err(|e| e.to_string())
|
||||||
// .map_err(|e| e.to_string())
|
|
||||||
Ok(requests)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@@ -1431,11 +1446,27 @@ async fn cmd_list_environments(
|
|||||||
workspace_id: &str,
|
workspace_id: &str,
|
||||||
w: WebviewWindow,
|
w: WebviewWindow,
|
||||||
) -> Result<Vec<Environment>, String> {
|
) -> Result<Vec<Environment>, String> {
|
||||||
let environments = list_environments(&w, workspace_id)
|
list_environments(&w, workspace_id)
|
||||||
.await
|
.await
|
||||||
.expect("Failed to find environments");
|
.map_err(|e| e.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
Ok(environments)
|
#[tauri::command]
|
||||||
|
async fn cmd_list_plugins(w: WebviewWindow) -> Result<Vec<Plugin>, String> {
|
||||||
|
list_plugins(&w).await.map_err(|e| e.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
async fn cmd_plugin_info(
|
||||||
|
id: &str,
|
||||||
|
w: WebviewWindow,
|
||||||
|
plugin_manager: State<'_, PluginManager>,
|
||||||
|
) -> Result<PluginBootResponse, String> {
|
||||||
|
let plugin = get_plugin(&w, id).await.map_err(|e| e.to_string())?;
|
||||||
|
plugin_manager
|
||||||
|
.get_plugin_info(plugin.directory.as_str())
|
||||||
|
.await
|
||||||
|
.ok_or("Failed to find plugin info".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@@ -1689,6 +1720,7 @@ pub fn run() {
|
|||||||
cmd_create_folder,
|
cmd_create_folder,
|
||||||
cmd_create_grpc_request,
|
cmd_create_grpc_request,
|
||||||
cmd_create_http_request,
|
cmd_create_http_request,
|
||||||
|
cmd_create_plugin,
|
||||||
cmd_create_workspace,
|
cmd_create_workspace,
|
||||||
cmd_curl_to_request,
|
cmd_curl_to_request,
|
||||||
cmd_delete_all_grpc_connections,
|
cmd_delete_all_grpc_connections,
|
||||||
@@ -1730,6 +1762,8 @@ pub fn run() {
|
|||||||
cmd_list_grpc_requests,
|
cmd_list_grpc_requests,
|
||||||
cmd_list_http_requests,
|
cmd_list_http_requests,
|
||||||
cmd_list_http_responses,
|
cmd_list_http_responses,
|
||||||
|
cmd_list_plugins,
|
||||||
|
cmd_plugin_info,
|
||||||
cmd_list_workspaces,
|
cmd_list_workspaces,
|
||||||
cmd_metadata,
|
cmd_metadata,
|
||||||
cmd_new_nested_window,
|
cmd_new_nested_window,
|
||||||
@@ -1831,6 +1865,7 @@ fn create_nested_window(
|
|||||||
.title(title)
|
.title(title)
|
||||||
.parent(&window)
|
.parent(&window)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
.min_inner_size(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT)
|
||||||
.inner_size(DEFAULT_WINDOW_WIDTH * 0.7, DEFAULT_WINDOW_HEIGHT * 0.9);
|
.inner_size(DEFAULT_WINDOW_WIDTH * 0.7, DEFAULT_WINDOW_HEIGHT * 0.9);
|
||||||
|
|
||||||
// Add macOS-only things
|
// Add macOS-only things
|
||||||
@@ -1841,7 +1876,7 @@ fn create_nested_window(
|
|||||||
.title_bar_style(TitleBarStyle::Overlay);
|
.title_bar_style(TitleBarStyle::Overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add non-MacOS things
|
// Add non-macOS things
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
{
|
{
|
||||||
win_builder = win_builder.decorations(false);
|
win_builder = win_builder.decorations(false);
|
||||||
@@ -1874,7 +1909,7 @@ fn create_window(handle: &AppHandle, url: &str) -> WebviewWindow {
|
|||||||
100.0 + random::<f64>() * 30.0,
|
100.0 + random::<f64>() * 30.0,
|
||||||
100.0 + random::<f64>() * 30.0,
|
100.0 + random::<f64>() * 30.0,
|
||||||
)
|
)
|
||||||
.min_inner_size(300.0, 300.0)
|
.min_inner_size(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT)
|
||||||
.title(handle.package_info().name.to_string());
|
.title(handle.package_info().name.to_string());
|
||||||
|
|
||||||
// Add macOS-only things
|
// Add macOS-only things
|
||||||
@@ -1900,7 +1935,8 @@ fn create_window(handle: &AppHandle, url: &str) -> WebviewWindow {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match event.id().0.as_str() {
|
let event_id = event.id().0.as_str();
|
||||||
|
match event_id {
|
||||||
"quit" => exit(0),
|
"quit" => exit(0),
|
||||||
"close" => w.close().unwrap(),
|
"close" => w.close().unwrap(),
|
||||||
"zoom_reset" => w.emit("zoom_reset", true).unwrap(),
|
"zoom_reset" => w.emit("zoom_reset", true).unwrap(),
|
||||||
@@ -1971,7 +2007,7 @@ fn monitor_plugin_events<R: Runtime>(app_handle: &AppHandle<R>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_plugin_event<R: Runtime>(app_handle: &AppHandle<R>, event: &InternalEvent) {
|
async fn handle_plugin_event<R: Runtime>(app_handle: &AppHandle<R>, event: &InternalEvent) {
|
||||||
info!("Got event to app {}", event.id);
|
// info!("Got event to app {}", event.id);
|
||||||
let response_event: Option<InternalEventPayload> = match event.clone().payload {
|
let response_event: Option<InternalEventPayload> = match event.clone().payload {
|
||||||
InternalEventPayload::CopyTextRequest(req) => {
|
InternalEventPayload::CopyTextRequest(req) => {
|
||||||
app_handle
|
app_handle
|
||||||
|
|||||||
@@ -655,6 +655,7 @@ pub struct GrpcEvent {
|
|||||||
pub request_id: String,
|
pub request_id: String,
|
||||||
pub connection_id: String,
|
pub connection_id: String,
|
||||||
pub created_at: NaiveDateTime,
|
pub created_at: NaiveDateTime,
|
||||||
|
pub updated_at: NaiveDateTime,
|
||||||
pub content: String,
|
pub content: String,
|
||||||
pub event_type: GrpcEventType,
|
pub event_type: GrpcEventType,
|
||||||
pub metadata: HashMap<String, String>,
|
pub metadata: HashMap<String, String>,
|
||||||
@@ -693,6 +694,7 @@ impl<'s> TryFrom<&Row<'s>> for GrpcEvent {
|
|||||||
request_id: r.get("request_id")?,
|
request_id: r.get("request_id")?,
|
||||||
connection_id: r.get("connection_id")?,
|
connection_id: r.get("connection_id")?,
|
||||||
created_at: r.get("created_at")?,
|
created_at: r.get("created_at")?,
|
||||||
|
updated_at: r.get("updated_at")?,
|
||||||
content: r.get("content")?,
|
content: r.get("content")?,
|
||||||
event_type: serde_json::from_str(event_type.as_str()).unwrap_or_default(),
|
event_type: serde_json::from_str(event_type.as_str()).unwrap_or_default(),
|
||||||
metadata: serde_json::from_str(metadata.as_str()).unwrap_or_default(),
|
metadata: serde_json::from_str(metadata.as_str()).unwrap_or_default(),
|
||||||
@@ -702,6 +704,51 @@ impl<'s> TryFrom<&Row<'s>> for GrpcEvent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
pub struct Plugin {
|
||||||
|
pub id: String,
|
||||||
|
#[ts(type = "\"plugin\"")]
|
||||||
|
pub model: String,
|
||||||
|
pub created_at: NaiveDateTime,
|
||||||
|
pub updated_at: NaiveDateTime,
|
||||||
|
pub checked_at: Option<NaiveDateTime>,
|
||||||
|
pub directory: String,
|
||||||
|
pub url: Option<String>,
|
||||||
|
pub enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Iden)]
|
||||||
|
pub enum PluginIden {
|
||||||
|
#[iden = "plugins"]
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
Model,
|
||||||
|
CreatedAt,
|
||||||
|
UpdatedAt,
|
||||||
|
CheckedAt,
|
||||||
|
Directory,
|
||||||
|
Url,
|
||||||
|
Enabled,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'s> TryFrom<&Row<'s>> for Plugin {
|
||||||
|
type Error = rusqlite::Error;
|
||||||
|
|
||||||
|
fn try_from(r: &Row<'s>) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Plugin {
|
||||||
|
id: r.get("id")?,
|
||||||
|
model: r.get("model")?,
|
||||||
|
created_at: r.get("created_at")?,
|
||||||
|
updated_at: r.get("updated_at")?,
|
||||||
|
checked_at: r.get("checked_at")?,
|
||||||
|
url: r.get("url")?,
|
||||||
|
directory: r.get("directory")?,
|
||||||
|
enabled: r.get("enabled")?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)]
|
||||||
#[serde(default, rename_all = "camelCase")]
|
#[serde(default, rename_all = "camelCase")]
|
||||||
pub struct KeyValue {
|
pub struct KeyValue {
|
||||||
@@ -758,6 +805,7 @@ pub enum ModelType {
|
|||||||
TypeGrpcRequest,
|
TypeGrpcRequest,
|
||||||
TypeHttpRequest,
|
TypeHttpRequest,
|
||||||
TypeHttpResponse,
|
TypeHttpResponse,
|
||||||
|
TypePlugin,
|
||||||
TypeWorkspace,
|
TypeWorkspace,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -772,6 +820,7 @@ impl ModelType {
|
|||||||
ModelType::TypeGrpcRequest => "gr",
|
ModelType::TypeGrpcRequest => "gr",
|
||||||
ModelType::TypeHttpRequest => "rq",
|
ModelType::TypeHttpRequest => "rq",
|
||||||
ModelType::TypeHttpResponse => "rs",
|
ModelType::TypeHttpResponse => "rs",
|
||||||
|
ModelType::TypePlugin => "pg",
|
||||||
ModelType::TypeWorkspace => "wk",
|
ModelType::TypeWorkspace => "wk",
|
||||||
}
|
}
|
||||||
.to_string()
|
.to_string()
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::models::{
|
use crate::models::{CookieJar, CookieJarIden, Environment, EnvironmentIden, Folder, FolderIden, GrpcConnection, GrpcConnectionIden, GrpcEvent, GrpcEventIden, GrpcRequest, GrpcRequestIden, HttpRequest, HttpRequestIden, HttpResponse, HttpResponseHeader, HttpResponseIden, KeyValue, KeyValueIden, ModelType, Plugin, PluginIden, Settings, SettingsIden, Workspace, WorkspaceIden};
|
||||||
CookieJar, CookieJarIden, Environment, EnvironmentIden, Folder, FolderIden, GrpcConnection,
|
|
||||||
GrpcConnectionIden, GrpcEvent, GrpcEventIden, GrpcRequest, GrpcRequestIden, HttpRequest,
|
|
||||||
HttpRequestIden, HttpResponse, HttpResponseHeader, HttpResponseIden, KeyValue, KeyValueIden,
|
|
||||||
ModelType, Settings, SettingsIden, Workspace, WorkspaceIden,
|
|
||||||
};
|
|
||||||
use crate::plugin::SqliteConnection;
|
use crate::plugin::SqliteConnection;
|
||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
use rand::distributions::{Alphanumeric, DistString};
|
use rand::distributions::{Alphanumeric, DistString};
|
||||||
@@ -848,7 +843,7 @@ pub async fn upsert_environment<R: Runtime>(
|
|||||||
serde_json::to_string(&environment.variables)?.into(),
|
serde_json::to_string(&environment.variables)?.into(),
|
||||||
])
|
])
|
||||||
.on_conflict(
|
.on_conflict(
|
||||||
OnConflict::column(GrpcEventIden::Id)
|
OnConflict::column(EnvironmentIden::Id)
|
||||||
.update_columns([
|
.update_columns([
|
||||||
EnvironmentIden::UpdatedAt,
|
EnvironmentIden::UpdatedAt,
|
||||||
EnvironmentIden::Name,
|
EnvironmentIden::Name,
|
||||||
@@ -877,6 +872,88 @@ pub async fn get_environment<R: Runtime>(mgr: &impl Manager<R>, id: &str) -> Res
|
|||||||
Ok(stmt.query_row(&*params.as_params(), |row| row.try_into())?)
|
Ok(stmt.query_row(&*params.as_params(), |row| row.try_into())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_plugin<R: Runtime>(
|
||||||
|
mgr: &impl Manager<R>,
|
||||||
|
id: &str
|
||||||
|
) -> Result<Plugin> {
|
||||||
|
let dbm = &*mgr.state::<SqliteConnection>();
|
||||||
|
let db = dbm.0.lock().await.get().unwrap();
|
||||||
|
|
||||||
|
let (sql, params) = Query::select()
|
||||||
|
.from(PluginIden::Table)
|
||||||
|
.column(Asterisk)
|
||||||
|
.cond_where(Expr::col(EnvironmentIden::Id).eq(id))
|
||||||
|
.build_rusqlite(SqliteQueryBuilder);
|
||||||
|
let mut stmt = db.prepare(sql.as_str())?;
|
||||||
|
Ok(stmt.query_row(&*params.as_params(), |row| row.try_into())?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn list_plugins<R: Runtime>(
|
||||||
|
mgr: &impl Manager<R>,
|
||||||
|
) -> Result<Vec<Plugin>> {
|
||||||
|
let dbm = &*mgr.state::<SqliteConnection>();
|
||||||
|
let db = dbm.0.lock().await.get().unwrap();
|
||||||
|
|
||||||
|
let (sql, params) = Query::select()
|
||||||
|
.from(PluginIden::Table)
|
||||||
|
.column(Asterisk)
|
||||||
|
.order_by(PluginIden::CreatedAt, Order::Desc)
|
||||||
|
.build_rusqlite(SqliteQueryBuilder);
|
||||||
|
let mut stmt = db.prepare(sql.as_str())?;
|
||||||
|
let items = stmt.query_map(&*params.as_params(), |row| row.try_into())?;
|
||||||
|
Ok(items.map(|v| v.unwrap()).collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn upsert_plugin<R: Runtime>(
|
||||||
|
window: &WebviewWindow<R>,
|
||||||
|
plugin: Plugin,
|
||||||
|
) -> Result<Plugin> {
|
||||||
|
let id = match plugin.id.as_str() {
|
||||||
|
"" => generate_model_id(ModelType::TypePlugin),
|
||||||
|
_ => plugin.id.to_string(),
|
||||||
|
};
|
||||||
|
let dbm = &*window.app_handle().state::<SqliteConnection>();
|
||||||
|
let db = dbm.0.lock().await.get().unwrap();
|
||||||
|
|
||||||
|
let (sql, params) = Query::insert()
|
||||||
|
.into_table(PluginIden::Table)
|
||||||
|
.columns([
|
||||||
|
PluginIden::Id,
|
||||||
|
PluginIden::CreatedAt,
|
||||||
|
PluginIden::UpdatedAt,
|
||||||
|
PluginIden::CheckedAt,
|
||||||
|
PluginIden::Directory,
|
||||||
|
PluginIden::Url,
|
||||||
|
PluginIden::Enabled,
|
||||||
|
])
|
||||||
|
.values_panic([
|
||||||
|
id.as_str().into(),
|
||||||
|
CurrentTimestamp.into(),
|
||||||
|
CurrentTimestamp.into(),
|
||||||
|
plugin.checked_at.into(),
|
||||||
|
plugin.directory.into(),
|
||||||
|
plugin.url.into(),
|
||||||
|
plugin.enabled.into(),
|
||||||
|
])
|
||||||
|
.on_conflict(
|
||||||
|
OnConflict::column(PluginIden::Id)
|
||||||
|
.update_columns([
|
||||||
|
PluginIden::UpdatedAt,
|
||||||
|
PluginIden::CheckedAt,
|
||||||
|
PluginIden::Directory,
|
||||||
|
PluginIden::Url,
|
||||||
|
PluginIden::Enabled,
|
||||||
|
])
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.returning_all()
|
||||||
|
.build_rusqlite(SqliteQueryBuilder);
|
||||||
|
|
||||||
|
let mut stmt = db.prepare(sql.as_str())?;
|
||||||
|
let m = stmt.query_row(&*params.as_params(), |row| row.try_into())?;
|
||||||
|
Ok(emit_upserted_model(window, m))
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_folder<R: Runtime>(mgr: &impl Manager<R>, id: &str) -> Result<Folder> {
|
pub async fn get_folder<R: Runtime>(mgr: &impl Manager<R>, id: &str) -> Result<Folder> {
|
||||||
let dbm = &*mgr.state::<SqliteConnection>();
|
let dbm = &*mgr.state::<SqliteConnection>();
|
||||||
let db = dbm.0.lock().await.get().unwrap();
|
let db = dbm.0.lock().await.get().unwrap();
|
||||||
|
|||||||
@@ -2,10 +2,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use ts_rs::TS;
|
use ts_rs::TS;
|
||||||
|
|
||||||
use yaak_models::models::{
|
use yaak_models::models::{CookieJar, Environment, Folder, GrpcConnection, GrpcEvent, GrpcRequest, HttpRequest, HttpResponse, KeyValue, Plugin, Settings, Workspace};
|
||||||
CookieJar, Environment, Folder, GrpcConnection, GrpcEvent, GrpcRequest, HttpRequest,
|
|
||||||
HttpResponse, KeyValue, Settings, Workspace,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
@@ -21,8 +18,8 @@ pub struct InternalEvent {
|
|||||||
#[serde(rename_all = "snake_case", tag = "type")]
|
#[serde(rename_all = "snake_case", tag = "type")]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
pub enum InternalEventPayload {
|
pub enum InternalEventPayload {
|
||||||
BootRequest(BootRequest),
|
BootRequest(PluginBootRequest),
|
||||||
BootResponse(BootResponse),
|
BootResponse(PluginBootResponse),
|
||||||
|
|
||||||
ImportRequest(ImportRequest),
|
ImportRequest(ImportRequest),
|
||||||
ImportResponse(ImportResponse),
|
ImportResponse(ImportResponse),
|
||||||
@@ -71,14 +68,14 @@ pub struct EmptyResponse {}
|
|||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
#[serde(default, rename_all = "camelCase")]
|
#[serde(default, rename_all = "camelCase")]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
pub struct BootRequest {
|
pub struct PluginBootRequest {
|
||||||
pub dir: String,
|
pub dir: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
#[serde(default, rename_all = "camelCase")]
|
#[serde(default, rename_all = "camelCase")]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
pub struct BootResponse {
|
pub struct PluginBootResponse {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub version: String,
|
pub version: String,
|
||||||
pub capabilities: Vec<String>,
|
pub capabilities: Vec<String>,
|
||||||
@@ -401,4 +398,5 @@ pub enum Model {
|
|||||||
Workspace(Workspace),
|
Workspace(Workspace),
|
||||||
CookieJar(CookieJar),
|
CookieJar(CookieJar),
|
||||||
Settings(Settings),
|
Settings(Settings),
|
||||||
|
Plugin(Plugin),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::events::{
|
use crate::events::{
|
||||||
CallHttpRequestActionRequest, CallTemplateFunctionArgs, RenderPurpose,
|
PluginBootResponse, CallHttpRequestActionRequest, CallTemplateFunctionArgs,
|
||||||
CallTemplateFunctionRequest, CallTemplateFunctionResponse, FilterRequest, FilterResponse,
|
CallTemplateFunctionRequest, CallTemplateFunctionResponse, FilterRequest, FilterResponse,
|
||||||
GetHttpRequestActionsRequest, GetHttpRequestActionsResponse, GetTemplateFunctionsResponse,
|
GetHttpRequestActionsRequest, GetHttpRequestActionsResponse, GetTemplateFunctionsResponse,
|
||||||
ImportRequest, ImportResponse, InternalEvent, InternalEventPayload,
|
ImportRequest, ImportResponse, InternalEvent, InternalEventPayload, RenderPurpose,
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
@@ -64,6 +64,10 @@ impl PluginManager {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_plugin_info(&self, dir: &str) -> Option<PluginBootResponse> {
|
||||||
|
self.server.plugin_by_dir(dir).await.ok()?.info().await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_http_request_actions(&self) -> Result<Vec<GetHttpRequestActionsResponse>> {
|
pub async fn get_http_request_actions(&self) -> Result<Vec<GetHttpRequestActionsResponse>> {
|
||||||
let reply_events = self
|
let reply_events = self
|
||||||
.server
|
.server
|
||||||
@@ -155,7 +159,9 @@ impl PluginManager {
|
|||||||
});
|
});
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
None => Err(PluginErr("No importers found for file contents".to_string())),
|
None => Err(PluginErr(
|
||||||
|
"No importers found for file contents".to_string(),
|
||||||
|
)),
|
||||||
Some((resp, ref_id)) => {
|
Some((resp, ref_id)) => {
|
||||||
let plugin = self.server.plugin_by_ref_id(ref_id.as_str()).await?;
|
let plugin = self.server.plugin_by_ref_id(ref_id.as_str()).await?;
|
||||||
let plugin_name = plugin.name().await;
|
let plugin_name = plugin.name().await;
|
||||||
|
|||||||
@@ -15,21 +15,30 @@ use tokio::fs::read_dir;
|
|||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
use tonic::codegen::tokio_stream;
|
use tonic::codegen::tokio_stream;
|
||||||
use tonic::transport::Server;
|
use tonic::transport::Server;
|
||||||
|
use yaak_models::queries::list_plugins;
|
||||||
|
|
||||||
pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||||
Builder::new("yaak_plugin_runtime")
|
Builder::new("yaak_plugin_runtime")
|
||||||
.setup(|app, _| {
|
.setup(|app_handle, _| {
|
||||||
let plugins_dir = app
|
let plugins_dir = app_handle
|
||||||
.path()
|
.path()
|
||||||
.resolve("plugins", BaseDirectory::Resource)
|
.resolve("plugins", BaseDirectory::Resource)
|
||||||
.expect("failed to resolve plugin directory resource");
|
.expect("failed to resolve plugin directory resource");
|
||||||
|
|
||||||
tauri::async_runtime::block_on(async move {
|
tauri::async_runtime::block_on(async move {
|
||||||
let plugin_dirs = read_plugins_dir(&plugins_dir)
|
let bundled_plugin_dirs = read_plugins_dir(&plugins_dir)
|
||||||
.await
|
.await
|
||||||
.expect(format!("Failed to read plugins dir: {:?}", plugins_dir).as_str());
|
.expect(format!("Failed to read plugins dir: {:?}", plugins_dir).as_str());
|
||||||
let manager = PluginManager::new(&app, plugin_dirs).await;
|
|
||||||
app.manage(manager);
|
let plugins = list_plugins(app_handle).await.unwrap_or_default();
|
||||||
|
let installed_plugin_dirs = plugins
|
||||||
|
.iter()
|
||||||
|
.map(|p| p.directory.to_owned())
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
|
||||||
|
let plugin_dirs = [installed_plugin_dirs, bundled_plugin_dirs].concat();
|
||||||
|
let manager = PluginManager::new(&app_handle, plugin_dirs).await;
|
||||||
|
app_handle.manage(manager);
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use log::info;
|
|
||||||
use rand::distributions::{Alphanumeric, DistString};
|
use rand::distributions::{Alphanumeric, DistString};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
@@ -11,7 +10,7 @@ use tonic::{Request, Response, Status, Streaming};
|
|||||||
|
|
||||||
use crate::error::Error::PluginNotFoundErr;
|
use crate::error::Error::PluginNotFoundErr;
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::events::{BootRequest, BootResponse, InternalEvent, InternalEventPayload};
|
use crate::events::{PluginBootRequest, PluginBootResponse, InternalEvent, InternalEventPayload};
|
||||||
use crate::server::plugin_runtime::plugin_runtime_server::PluginRuntime;
|
use crate::server::plugin_runtime::plugin_runtime_server::PluginRuntime;
|
||||||
use plugin_runtime::EventStreamEvent;
|
use plugin_runtime::EventStreamEvent;
|
||||||
use yaak_models::queries::generate_id;
|
use yaak_models::queries::generate_id;
|
||||||
@@ -28,7 +27,7 @@ pub struct PluginHandle {
|
|||||||
dir: String,
|
dir: String,
|
||||||
to_plugin_tx: Arc<Mutex<mpsc::Sender<tonic::Result<EventStreamEvent>>>>,
|
to_plugin_tx: Arc<Mutex<mpsc::Sender<tonic::Result<EventStreamEvent>>>>,
|
||||||
ref_id: String,
|
ref_id: String,
|
||||||
boot_resp: Arc<Mutex<Option<BootResponse>>>,
|
boot_resp: Arc<Mutex<Option<PluginBootResponse>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PluginHandle {
|
impl PluginHandle {
|
||||||
@@ -38,6 +37,11 @@ impl PluginHandle {
|
|||||||
Some(r) => r.name.to_owned(),
|
Some(r) => r.name.to_owned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn info(&self) -> Option<PluginBootResponse> {
|
||||||
|
let resp = &*self.boot_resp.lock().await;
|
||||||
|
resp.clone()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build_event_to_send(
|
pub fn build_event_to_send(
|
||||||
&self,
|
&self,
|
||||||
@@ -53,11 +57,11 @@ impl PluginHandle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send(&self, event: &InternalEvent) -> Result<()> {
|
pub async fn send(&self, event: &InternalEvent) -> Result<()> {
|
||||||
info!(
|
// info!(
|
||||||
"Sending event to plugin {} {:?}",
|
// "Sending event to plugin {} {:?}",
|
||||||
event.id,
|
// event.id,
|
||||||
self.name().await
|
// self.name().await
|
||||||
);
|
// );
|
||||||
self.to_plugin_tx
|
self.to_plugin_tx
|
||||||
.lock()
|
.lock()
|
||||||
.await
|
.await
|
||||||
@@ -68,7 +72,7 @@ impl PluginHandle {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn boot(&self, resp: &BootResponse) {
|
pub async fn boot(&self, resp: &PluginBootResponse) {
|
||||||
let mut boot_resp = self.boot_resp.lock().await;
|
let mut boot_resp = self.boot_resp.lock().await;
|
||||||
*boot_resp = Some(resp.clone());
|
*boot_resp = Some(resp.clone());
|
||||||
}
|
}
|
||||||
@@ -120,7 +124,7 @@ impl PluginRuntimeGrpcServer {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn boot_plugin(&self, id: &str, resp: &BootResponse) {
|
pub async fn boot_plugin(&self, id: &str, resp: &PluginBootResponse) {
|
||||||
match self.plugin_ref_to_plugin.lock().await.get(id) {
|
match self.plugin_ref_to_plugin.lock().await.get(id) {
|
||||||
None => {
|
None => {
|
||||||
println!("Tried booting non-existing plugin {}", id);
|
println!("Tried booting non-existing plugin {}", id);
|
||||||
@@ -151,61 +155,27 @@ impl PluginRuntimeGrpcServer {
|
|||||||
plugin_handle
|
plugin_handle
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub async fn callback(
|
|
||||||
// &self,
|
|
||||||
// source_event: InternalEvent,
|
|
||||||
// payload: InternalEventPayload,
|
|
||||||
// ) -> Result<InternalEvent> {
|
|
||||||
// let reply_id = match source_event.clone().reply_id {
|
|
||||||
// None => {
|
|
||||||
// let msg = format!("Source event missing reply Id {:?}", source_event.clone());
|
|
||||||
// return Err(MissingCallbackIdErr(msg));
|
|
||||||
// }
|
|
||||||
// Some(id) => id,
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// let callbacks = self.callbacks.lock().await;
|
|
||||||
// let plugin_name = match callbacks.get(reply_id.as_str()) {
|
|
||||||
// None => {
|
|
||||||
// let msg = format!("Callback not found {:?}", source_event);
|
|
||||||
// return Err(MissingCallbackErr(msg));
|
|
||||||
// }
|
|
||||||
// Some(n) => n,
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// let plugins = self.plugins.lock().await;
|
|
||||||
// let plugin = match plugins.get(plugin_name) {
|
|
||||||
// None => {
|
|
||||||
// let msg = format!(
|
|
||||||
// "Plugin not found {plugin_name}. Choices were {:?}",
|
|
||||||
// plugins.keys()
|
|
||||||
// );
|
|
||||||
// return Err(UnknownPluginErr(msg));
|
|
||||||
// }
|
|
||||||
// Some(n) => n,
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// plugin.send(&payload, Some(reply_id)).await
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub async fn plugin_by_ref_id(&self, ref_id: &str) -> Result<PluginHandle> {
|
pub async fn plugin_by_ref_id(&self, ref_id: &str) -> Result<PluginHandle> {
|
||||||
let plugins = self.plugin_ref_to_plugin.lock().await;
|
let plugins = self.plugin_ref_to_plugin.lock().await;
|
||||||
if plugins.is_empty() {
|
|
||||||
return Err(PluginNotFoundErr(ref_id.into()));
|
|
||||||
}
|
|
||||||
|
|
||||||
match plugins.get(ref_id) {
|
match plugins.get(ref_id) {
|
||||||
None => Err(PluginNotFoundErr(ref_id.into())),
|
None => Err(PluginNotFoundErr(ref_id.into())),
|
||||||
Some(p) => Ok(p.to_owned()),
|
Some(p) => Ok(p.to_owned()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn plugin_by_dir(&self, dir: &str) -> Result<PluginHandle> {
|
||||||
|
let plugins = self.plugin_ref_to_plugin.lock().await;
|
||||||
|
for p in plugins.values() {
|
||||||
|
if p.dir == dir {
|
||||||
|
return Ok(p.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(PluginNotFoundErr(dir.into()))
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn plugin_by_name(&self, plugin_name: &str) -> Result<PluginHandle> {
|
pub async fn plugin_by_name(&self, plugin_name: &str) -> Result<PluginHandle> {
|
||||||
let plugins = self.plugin_ref_to_plugin.lock().await;
|
let plugins = self.plugin_ref_to_plugin.lock().await;
|
||||||
if plugins.is_empty() {
|
|
||||||
return Err(PluginNotFoundErr(plugin_name.into()));
|
|
||||||
}
|
|
||||||
|
|
||||||
for p in plugins.values() {
|
for p in plugins.values() {
|
||||||
if p.name().await == plugin_name {
|
if p.name().await == plugin_name {
|
||||||
return Ok(p.to_owned());
|
return Ok(p.to_owned());
|
||||||
@@ -341,7 +311,7 @@ impl PluginRuntimeGrpcServer {
|
|||||||
plugin_ids.push(plugin.clone().ref_id);
|
plugin_ids.push(plugin.clone().ref_id);
|
||||||
|
|
||||||
let event = plugin.build_event_to_send(
|
let event = plugin.build_event_to_send(
|
||||||
&InternalEventPayload::BootRequest(BootRequest {
|
&InternalEventPayload::BootRequest(PluginBootRequest {
|
||||||
dir: dir.to_string(),
|
dir: dir.to_string(),
|
||||||
}),
|
}),
|
||||||
None,
|
None,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { httpResponsesQueryKey } from '../hooks/useHttpResponses';
|
|||||||
import { keyValueQueryKey } from '../hooks/useKeyValue';
|
import { keyValueQueryKey } from '../hooks/useKeyValue';
|
||||||
import { useListenToTauriEvent } from '../hooks/useListenToTauriEvent';
|
import { useListenToTauriEvent } from '../hooks/useListenToTauriEvent';
|
||||||
import { useNotificationToast } from '../hooks/useNotificationToast';
|
import { useNotificationToast } from '../hooks/useNotificationToast';
|
||||||
|
import { pluginsAtom } from '../hooks/usePlugins';
|
||||||
import { useRecentCookieJars } from '../hooks/useRecentCookieJars';
|
import { useRecentCookieJars } from '../hooks/useRecentCookieJars';
|
||||||
import { useRecentEnvironments } from '../hooks/useRecentEnvironments';
|
import { useRecentEnvironments } from '../hooks/useRecentEnvironments';
|
||||||
import { useRecentRequests } from '../hooks/useRecentRequests';
|
import { useRecentRequests } from '../hooks/useRecentRequests';
|
||||||
@@ -67,6 +68,7 @@ export function GlobalHooks() {
|
|||||||
|
|
||||||
const setSettings = useSetAtom(settingsAtom);
|
const setSettings = useSetAtom(settingsAtom);
|
||||||
const setWorkspaces = useSetAtom(workspacesAtom);
|
const setWorkspaces = useSetAtom(workspacesAtom);
|
||||||
|
const setPlugins = useSetAtom(pluginsAtom);
|
||||||
const setHttpRequests = useSetAtom(httpRequestsAtom);
|
const setHttpRequests = useSetAtom(httpRequestsAtom);
|
||||||
const setGrpcRequests = useSetAtom(grpcRequestsAtom);
|
const setGrpcRequests = useSetAtom(grpcRequestsAtom);
|
||||||
const setEnvironments = useSetAtom(environmentsAtom);
|
const setEnvironments = useSetAtom(environmentsAtom);
|
||||||
@@ -100,6 +102,8 @@ export function GlobalHooks() {
|
|||||||
|
|
||||||
if (model.model === 'workspace') {
|
if (model.model === 'workspace') {
|
||||||
setWorkspaces(updateModelList(model, pushToFront));
|
setWorkspaces(updateModelList(model, pushToFront));
|
||||||
|
} else if (model.model === 'plugin') {
|
||||||
|
setPlugins(updateModelList(model, pushToFront));
|
||||||
} else if (model.model === 'http_request') {
|
} else if (model.model === 'http_request') {
|
||||||
setHttpRequests(updateModelList(model, pushToFront));
|
setHttpRequests(updateModelList(model, pushToFront));
|
||||||
} else if (model.model === 'grpc_request') {
|
} else if (model.model === 'grpc_request') {
|
||||||
@@ -129,6 +133,8 @@ export function GlobalHooks() {
|
|||||||
|
|
||||||
if (model.model === 'workspace') {
|
if (model.model === 'workspace') {
|
||||||
setWorkspaces(removeById(model));
|
setWorkspaces(removeById(model));
|
||||||
|
} else if (model.model === 'plugin') {
|
||||||
|
setPlugins(removeById(model));
|
||||||
} else if (model.model === 'http_request') {
|
} else if (model.model === 'http_request') {
|
||||||
setHttpRequests(removeById(model));
|
setHttpRequests(removeById(model));
|
||||||
} else if (model.model === 'http_response') {
|
} else if (model.model === 'http_response') {
|
||||||
|
|||||||
@@ -9,20 +9,31 @@ import { HStack } from './core/Stacks';
|
|||||||
type Props = ButtonProps & {
|
type Props = ButtonProps & {
|
||||||
onChange: (value: { filePath: string | null; contentType: string | null }) => void;
|
onChange: (value: { filePath: string | null; contentType: string | null }) => void;
|
||||||
filePath: string | null;
|
filePath: string | null;
|
||||||
|
directory?: boolean;
|
||||||
inline?: boolean;
|
inline?: boolean;
|
||||||
|
noun?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Special character to insert ltr text in rtl element
|
// Special character to insert ltr text in rtl element
|
||||||
const rtlEscapeChar = <>‎</>;
|
const rtlEscapeChar = <>‎</>;
|
||||||
|
|
||||||
export function SelectFile({ onChange, filePath, inline, className }: Props) {
|
export function SelectFile({
|
||||||
|
onChange,
|
||||||
|
filePath,
|
||||||
|
inline,
|
||||||
|
className,
|
||||||
|
directory,
|
||||||
|
noun,
|
||||||
|
size = 'sm',
|
||||||
|
...props
|
||||||
|
}: Props) {
|
||||||
const handleClick = async () => {
|
const handleClick = async () => {
|
||||||
const filePath = await open({
|
const filePath = await open({
|
||||||
title: 'Select File',
|
title: 'Select File',
|
||||||
multiple: false,
|
multiple: false,
|
||||||
|
directory,
|
||||||
});
|
});
|
||||||
if (filePath == null) return;
|
if (filePath == null) return;
|
||||||
|
|
||||||
const contentType = filePath ? mime.getType(filePath) : null;
|
const contentType = filePath ? mime.getType(filePath) : null;
|
||||||
onChange({ filePath, contentType });
|
onChange({ filePath, contentType });
|
||||||
};
|
};
|
||||||
@@ -31,31 +42,41 @@ export function SelectFile({ onChange, filePath, inline, className }: Props) {
|
|||||||
onChange({ filePath: null, contentType: null });
|
onChange({ filePath: null, contentType: null });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const itemLabel = noun ?? (directory ? 'Folder' : 'File');
|
||||||
|
const selectOrChange = (filePath ? 'Change ' : 'Select ') + itemLabel;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HStack space={1.5} className="group relative justify-stretch">
|
<HStack space={1.5} className="group relative justify-stretch overflow-hidden">
|
||||||
<Button
|
<Button
|
||||||
className={classNames(className, 'font-mono text-xs rtl', inline && 'w-full')}
|
className={classNames(className, 'font-mono text-xs rtl', inline && 'w-full')}
|
||||||
color="secondary"
|
color="secondary"
|
||||||
size="sm"
|
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
|
size={size}
|
||||||
|
{...props}
|
||||||
>
|
>
|
||||||
{rtlEscapeChar}
|
{rtlEscapeChar}
|
||||||
{inline ? <>{filePath || 'Select File'}</> : <>Select File</>}
|
{inline ? filePath || selectOrChange : selectOrChange}
|
||||||
</Button>
|
</Button>
|
||||||
{!inline && (
|
{!inline && (
|
||||||
<>
|
<>
|
||||||
{filePath && (
|
{filePath && (
|
||||||
<IconButton
|
<IconButton
|
||||||
size="sm"
|
size={size}
|
||||||
variant="border"
|
variant="border"
|
||||||
icon="x"
|
icon="x"
|
||||||
title="Unset File"
|
title={'Unset ' + itemLabel}
|
||||||
onClick={handleClear}
|
onClick={handleClear}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div className="text-sm font-mono truncate rtl pr-3 text">
|
<div
|
||||||
|
className={classNames(
|
||||||
|
'font-mono truncate rtl pl-1.5 pr-3 text-text',
|
||||||
|
size === 'xs' && 'text-xs',
|
||||||
|
size === 'sm' && 'text-sm',
|
||||||
|
)}
|
||||||
|
>
|
||||||
{rtlEscapeChar}
|
{rtlEscapeChar}
|
||||||
{filePath ?? 'No file selected'}
|
{filePath ?? `No ${itemLabel.toLowerCase()} selected`}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -10,13 +10,15 @@ import { HeaderSize } from '../HeaderSize';
|
|||||||
import { WindowControls } from '../WindowControls';
|
import { WindowControls } from '../WindowControls';
|
||||||
import { SettingsAppearance } from './SettingsAppearance';
|
import { SettingsAppearance } from './SettingsAppearance';
|
||||||
import { SettingsGeneral } from './SettingsGeneral';
|
import { SettingsGeneral } from './SettingsGeneral';
|
||||||
|
import { SettingsPlugins } from './SettingsPlugins';
|
||||||
|
|
||||||
enum Tab {
|
enum Tab {
|
||||||
General = 'general',
|
General = 'general',
|
||||||
Appearance = 'appearance',
|
Appearance = 'appearance',
|
||||||
|
Plugins = 'plugins',
|
||||||
}
|
}
|
||||||
|
|
||||||
const tabs = [Tab.General, Tab.Appearance];
|
const tabs = [Tab.General, Tab.Appearance, Tab.Plugins];
|
||||||
|
|
||||||
export const Settings = () => {
|
export const Settings = () => {
|
||||||
const osInfo = useOsInfo();
|
const osInfo = useOsInfo();
|
||||||
@@ -58,6 +60,9 @@ export const Settings = () => {
|
|||||||
<TabContent value={Tab.Appearance} className="pt-3 overflow-y-auto h-full px-4">
|
<TabContent value={Tab.Appearance} className="pt-3 overflow-y-auto h-full px-4">
|
||||||
<SettingsAppearance />
|
<SettingsAppearance />
|
||||||
</TabContent>
|
</TabContent>
|
||||||
|
<TabContent value={Tab.Plugins} className="pt-3 overflow-y-auto h-full px-4">
|
||||||
|
<SettingsPlugins />
|
||||||
|
</TabContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
95
src-web/components/Settings/SettingsPlugins.tsx
Normal file
95
src-web/components/Settings/SettingsPlugins.tsx
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
import type { Plugin } from '@yaakapp/api';
|
||||||
|
import React from 'react';
|
||||||
|
import { useCreatePlugin } from '../../hooks/useCreatePlugin';
|
||||||
|
import { usePluginInfo } from '../../hooks/usePluginInfo';
|
||||||
|
import { usePlugins, useRefreshPlugins } from '../../hooks/usePlugins';
|
||||||
|
import { Button } from '../core/Button';
|
||||||
|
import { Checkbox } from '../core/Checkbox';
|
||||||
|
import { IconButton } from '../core/IconButton';
|
||||||
|
import { InlineCode } from '../core/InlineCode';
|
||||||
|
import { HStack } from '../core/Stacks';
|
||||||
|
import { SelectFile } from '../SelectFile';
|
||||||
|
|
||||||
|
export function SettingsPlugins() {
|
||||||
|
const [directory, setDirectory] = React.useState<string | null>(null);
|
||||||
|
const plugins = usePlugins();
|
||||||
|
const createPlugin = useCreatePlugin();
|
||||||
|
const refreshPlugins = useRefreshPlugins();
|
||||||
|
return (
|
||||||
|
<div className="grid grid-rows-[minmax(0,1fr)_auto] h-full">
|
||||||
|
<table className="w-full text-sm mb-auto min-w-full max-w-full divide-y divide-surface-highlight">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th className="py-2 text-left">Plugin</th>
|
||||||
|
<th className="py-2 text-right">Version</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="divide-y divide-surface-highlight">
|
||||||
|
{plugins.map((p) => (
|
||||||
|
<PluginInfo key={p.id} plugin={p} />
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (directory == null) return;
|
||||||
|
createPlugin.mutate(directory);
|
||||||
|
setDirectory(null);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<footer className="grid grid-cols-[minmax(0,1fr)_auto] -mx-4 py-2 px-4 border-t bg-surface-highlight border-border-subtle min-w-0">
|
||||||
|
<SelectFile
|
||||||
|
size="xs"
|
||||||
|
noun="Plugin"
|
||||||
|
directory
|
||||||
|
onChange={({ filePath }) => setDirectory(filePath)}
|
||||||
|
filePath={directory}
|
||||||
|
/>
|
||||||
|
<HStack>
|
||||||
|
{directory && (
|
||||||
|
<Button size="xs" type="submit" color="primary" className="ml-auto">
|
||||||
|
Add Plugin
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
<IconButton
|
||||||
|
size="sm"
|
||||||
|
icon="refresh"
|
||||||
|
title="Reload plugins"
|
||||||
|
spin={refreshPlugins.isPending}
|
||||||
|
onClick={() => refreshPlugins.mutate()}
|
||||||
|
/>
|
||||||
|
</HStack>
|
||||||
|
</footer>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function PluginInfo({ plugin }: { plugin: Plugin }) {
|
||||||
|
const pluginInfo = usePluginInfo(plugin.id);
|
||||||
|
if (pluginInfo.data == null) return null;
|
||||||
|
return (
|
||||||
|
<tr className="group">
|
||||||
|
<td className="pr-2">
|
||||||
|
<Checkbox hideLabel checked={true} title="foo" onChange={() => null} />
|
||||||
|
</td>
|
||||||
|
<td className="py-2 select-text cursor-text w-full">
|
||||||
|
<InlineCode>{pluginInfo.data?.name}</InlineCode>
|
||||||
|
</td>
|
||||||
|
<td className="py-2 select-text cursor-text text-right">
|
||||||
|
<InlineCode>{pluginInfo.data?.version}</InlineCode>
|
||||||
|
</td>
|
||||||
|
<td className="py-2 select-text cursor-text pl-2">
|
||||||
|
<IconButton
|
||||||
|
size="sm"
|
||||||
|
icon="trash"
|
||||||
|
title="Uninstall plugin"
|
||||||
|
className="text-text-subtlest"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -73,7 +73,7 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button
|
|||||||
size === 'md' && 'h-md px-3 rounded-md',
|
size === 'md' && 'h-md px-3 rounded-md',
|
||||||
size === 'sm' && 'h-sm px-2.5 rounded-md',
|
size === 'sm' && 'h-sm px-2.5 rounded-md',
|
||||||
size === 'xs' && 'h-xs px-2 text-sm rounded-md',
|
size === 'xs' && 'h-xs px-2 text-sm rounded-md',
|
||||||
size === '2xs' && 'h-5 px-1 text-xs rounded',
|
size === '2xs' && 'h-2xs px-1 text-xs rounded',
|
||||||
|
|
||||||
// Solids
|
// Solids
|
||||||
variant === 'solid' && 'border-transparent',
|
variant === 'solid' && 'border-transparent',
|
||||||
|
|||||||
@@ -58,9 +58,9 @@ export const IconButton = forwardRef<HTMLButtonElement, Props>(function IconButt
|
|||||||
'!px-0',
|
'!px-0',
|
||||||
color === 'custom' && 'text-text-subtle',
|
color === 'custom' && 'text-text-subtle',
|
||||||
color === 'default' && 'text-text-subtle',
|
color === 'default' && 'text-text-subtle',
|
||||||
size === 'md' && 'w-9',
|
size === 'md' && 'w-md',
|
||||||
size === 'sm' && 'w-8',
|
size === 'sm' && 'w-sm',
|
||||||
size === 'xs' && 'w-6',
|
size === 'xs' && 'w-xs',
|
||||||
size === '2xs' && 'w-5',
|
size === '2xs' && 'w-5',
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export function InlineCode({ className, ...props }: HTMLAttributes<HTMLSpanEleme
|
|||||||
<code
|
<code
|
||||||
className={classNames(
|
className={classNames(
|
||||||
className,
|
className,
|
||||||
|
'select-text cursor-text',
|
||||||
'font-mono text-shrink bg-surface-highlight border border-border-subtle',
|
'font-mono text-shrink bg-surface-highlight border border-border-subtle',
|
||||||
'px-1.5 py-0.5 rounded text shadow-inner break-words',
|
'px-1.5 py-0.5 rounded text shadow-inner break-words',
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -14,9 +14,11 @@ export function useActiveWorkspaceChangedToast() {
|
|||||||
|
|
||||||
setId(activeWorkspace?.id ?? null);
|
setId(activeWorkspace?.id ?? null);
|
||||||
|
|
||||||
// Don't notify on first load
|
// Don't notify on the first load
|
||||||
if (id === null) return;
|
if (id === null) return;
|
||||||
|
|
||||||
|
console.log('HELLO?', activeWorkspace?.id, id, window.location);
|
||||||
|
|
||||||
toast.show({
|
toast.show({
|
||||||
id: 'workspace-changed',
|
id: 'workspace-changed',
|
||||||
timeout: 3000,
|
timeout: 3000,
|
||||||
|
|||||||
13
src-web/hooks/useCreatePlugin.ts
Normal file
13
src-web/hooks/useCreatePlugin.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { useMutation } from '@tanstack/react-query';
|
||||||
|
import { trackEvent } from '../lib/analytics';
|
||||||
|
import { invokeCmd } from '../lib/tauri';
|
||||||
|
|
||||||
|
export function useCreatePlugin() {
|
||||||
|
return useMutation<void, unknown, string>({
|
||||||
|
mutationKey: ['create_plugin'],
|
||||||
|
mutationFn: async (directory: string) => {
|
||||||
|
await invokeCmd('cmd_create_plugin', { directory });
|
||||||
|
},
|
||||||
|
onSettled: () => trackEvent('plugin', 'create'),
|
||||||
|
});
|
||||||
|
}
|
||||||
13
src-web/hooks/usePluginInfo.ts
Normal file
13
src-web/hooks/usePluginInfo.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import type { BootResponse } from '@yaakapp/api';
|
||||||
|
import { invokeCmd } from '../lib/tauri';
|
||||||
|
|
||||||
|
export function usePluginInfo(id: string) {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ['plugin_info', id],
|
||||||
|
queryFn: async () => {
|
||||||
|
const info = (await invokeCmd('cmd_plugin_info', { id })) as BootResponse;
|
||||||
|
return info;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
23
src-web/hooks/usePlugins.ts
Normal file
23
src-web/hooks/usePlugins.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { useMutation } from '@tanstack/react-query';
|
||||||
|
import type { Plugin } from '@yaakapp/api';
|
||||||
|
import { atom, useAtomValue, useSetAtom } from 'jotai';
|
||||||
|
import { minPromiseMillis } from '../lib/minPromiseMillis';
|
||||||
|
import { listPlugins } from '../lib/store';
|
||||||
|
|
||||||
|
const plugins = await listPlugins();
|
||||||
|
export const pluginsAtom = atom<Plugin[]>(plugins);
|
||||||
|
|
||||||
|
export function usePlugins() {
|
||||||
|
return useAtomValue(pluginsAtom);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useRefreshPlugins() {
|
||||||
|
const setPlugins = useSetAtom(pluginsAtom);
|
||||||
|
return useMutation({
|
||||||
|
mutationKey: ['refresh_plugins'],
|
||||||
|
mutationFn: async () => {
|
||||||
|
const plugins = await minPromiseMillis(listPlugins());
|
||||||
|
setPlugins(plugins);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ export type TrackResource =
|
|||||||
| 'http_request'
|
| 'http_request'
|
||||||
| 'http_response'
|
| 'http_response'
|
||||||
| 'key_value'
|
| 'key_value'
|
||||||
|
| 'plugin'
|
||||||
| 'setting'
|
| 'setting'
|
||||||
| 'sidebar'
|
| 'sidebar'
|
||||||
| 'theme'
|
| 'theme'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { sleep } from './sleep';
|
import { sleep } from './sleep';
|
||||||
|
|
||||||
/** Ensures a promise takes at least a certain number of milliseconds to resolve */
|
/** Ensures a promise takes at least a certain number of milliseconds to resolve */
|
||||||
export async function minPromiseMillis<T>(promise: Promise<T>, millis: number) {
|
export async function minPromiseMillis<T>(promise: Promise<T>, millis = 300) {
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
let result;
|
let result;
|
||||||
let err;
|
let err;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type {
|
|||||||
Folder,
|
Folder,
|
||||||
GrpcRequest,
|
GrpcRequest,
|
||||||
HttpRequest,
|
HttpRequest,
|
||||||
|
Plugin,
|
||||||
Settings,
|
Settings,
|
||||||
Workspace,
|
Workspace,
|
||||||
} from '@yaakapp/api';
|
} from '@yaakapp/api';
|
||||||
@@ -63,6 +64,11 @@ export async function listWorkspaces(): Promise<Workspace[]> {
|
|||||||
return workspaces;
|
return workspaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function listPlugins(): Promise<Plugin[]> {
|
||||||
|
const plugins: Plugin[] = (await invokeCmd('cmd_list_plugins')) ?? [];
|
||||||
|
return plugins;
|
||||||
|
}
|
||||||
|
|
||||||
export async function getCookieJar(id: string | null): Promise<CookieJar | null> {
|
export async function getCookieJar(id: string | null): Promise<CookieJar | null> {
|
||||||
if (id === null) return null;
|
if (id === null) return null;
|
||||||
const cookieJar: CookieJar = (await invokeCmd('cmd_get_cookie_jar', { id })) ?? null;
|
const cookieJar: CookieJar = (await invokeCmd('cmd_get_cookie_jar', { id })) ?? null;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ type TauriCmd =
|
|||||||
| 'cmd_check_for_updates'
|
| 'cmd_check_for_updates'
|
||||||
| 'cmd_create_cookie_jar'
|
| 'cmd_create_cookie_jar'
|
||||||
| 'cmd_create_environment'
|
| 'cmd_create_environment'
|
||||||
|
| 'cmd_create_plugin'
|
||||||
| 'cmd_template_tokens_to_string'
|
| 'cmd_template_tokens_to_string'
|
||||||
| 'cmd_create_folder'
|
| 'cmd_create_folder'
|
||||||
| 'cmd_create_grpc_request'
|
| 'cmd_create_grpc_request'
|
||||||
@@ -47,11 +48,13 @@ type TauriCmd =
|
|||||||
| 'cmd_list_grpc_requests'
|
| 'cmd_list_grpc_requests'
|
||||||
| 'cmd_list_http_requests'
|
| 'cmd_list_http_requests'
|
||||||
| 'cmd_list_http_responses'
|
| 'cmd_list_http_responses'
|
||||||
|
| 'cmd_list_plugins'
|
||||||
| 'cmd_list_workspaces'
|
| 'cmd_list_workspaces'
|
||||||
| 'cmd_metadata'
|
| 'cmd_metadata'
|
||||||
| 'cmd_new_nested_window'
|
| 'cmd_new_nested_window'
|
||||||
| 'cmd_new_window'
|
| 'cmd_new_window'
|
||||||
| 'cmd_parse_template'
|
| 'cmd_parse_template'
|
||||||
|
| 'cmd_plugin_info'
|
||||||
| 'cmd_render_template'
|
| 'cmd_render_template'
|
||||||
| 'cmd_save_response'
|
| 'cmd_save_response'
|
||||||
| 'cmd_send_ephemeral_request'
|
| 'cmd_send_ephemeral_request'
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const plugin = require('tailwindcss/plugin');
|
const plugin = require('tailwindcss/plugin');
|
||||||
|
|
||||||
const height = {
|
const sizes = {
|
||||||
|
'2xs': '1.25rem',
|
||||||
xs: '1.8rem',
|
xs: '1.8rem',
|
||||||
sm: '2.0rem',
|
sm: '2.0rem',
|
||||||
md: '2.5rem',
|
md: '2.5rem',
|
||||||
@@ -18,8 +19,10 @@ module.exports = {
|
|||||||
fontSize: {
|
fontSize: {
|
||||||
xs: '0.8rem',
|
xs: '0.8rem',
|
||||||
},
|
},
|
||||||
height,
|
height: sizes,
|
||||||
minHeight: height,
|
width: sizes,
|
||||||
|
minHeight: sizes,
|
||||||
|
minWidth: sizes,
|
||||||
lineHeight: {
|
lineHeight: {
|
||||||
// HACK: Minus 2 to account for borders inside inputs
|
// HACK: Minus 2 to account for borders inside inputs
|
||||||
xs: 'calc(1.75rem - 2px)',
|
xs: 'calc(1.75rem - 2px)',
|
||||||
|
|||||||
Reference in New Issue
Block a user