mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-02-17 13:17:46 +01:00
Compare commits
215 Commits
v2024.10.0
...
v2025.1.0-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdb4331032 | ||
|
|
8d645eb8c6 | ||
|
|
592cf38e38 | ||
|
|
ac0ecb342d | ||
|
|
439a29ab46 | ||
|
|
db64b54c79 | ||
|
|
49f5e980de | ||
|
|
658e2179ca | ||
|
|
e7184e4d47 | ||
|
|
6719573b2b | ||
|
|
4479164321 | ||
|
|
4295a09515 | ||
|
|
bb5da84c82 | ||
|
|
72ab3f0a3c | ||
|
|
eea87ac02f | ||
|
|
587667fe79 | ||
|
|
84c3987c34 | ||
|
|
40a77be556 | ||
|
|
d37cfad862 | ||
|
|
34c0449a40 | ||
|
|
ad4d695b75 | ||
|
|
969e1b965d | ||
|
|
88ff7f4300 | ||
|
|
8cd9c031e8 | ||
|
|
806ce2f0ba | ||
|
|
dcb17c3ed4 | ||
|
|
d2936cb022 | ||
|
|
ba330047ca | ||
|
|
295aea4f2e | ||
|
|
476dbc432b | ||
|
|
8dff75ad4f | ||
|
|
88b410bf99 | ||
|
|
3d3ff2824f | ||
|
|
3b56f4e142 | ||
|
|
576340db33 | ||
|
|
bcf5b3db84 | ||
|
|
8b5b66acf0 | ||
|
|
f694456ddc | ||
|
|
0a7257c55a | ||
|
|
328e3db56e | ||
|
|
cbc443075a | ||
|
|
37671a50f2 | ||
|
|
95266a9177 | ||
|
|
eeb66ca28a | ||
|
|
d745e91f80 | ||
|
|
7a9c2e2223 | ||
|
|
1d51bd642a | ||
|
|
1920f720a9 | ||
|
|
81005165f3 | ||
|
|
3cf372c01e | ||
|
|
2f7b66fc92 | ||
|
|
4776bbc753 | ||
|
|
79f668c863 | ||
|
|
a164875104 | ||
|
|
bc50891edb | ||
|
|
806a8eb801 | ||
|
|
ab55c2e0ce | ||
|
|
c2ea2a5fe5 | ||
|
|
c72180bb59 | ||
|
|
17fdd608d1 | ||
|
|
40adce921b | ||
|
|
75ead9cc8a | ||
|
|
609bd4cdea | ||
|
|
68e1b5d746 | ||
|
|
53f5ef3515 | ||
|
|
592c1228f1 | ||
|
|
36cecb2d29 | ||
|
|
31440eea76 | ||
|
|
6ad27c4458 | ||
|
|
0dd09062e3 | ||
|
|
5ebf7dc499 | ||
|
|
42cd4a5f0f | ||
|
|
add39bda6e | ||
|
|
be938a81dc | ||
|
|
4b807f221b | ||
|
|
80119f6574 | ||
|
|
dfca17f9b7 | ||
|
|
135c366e32 | ||
|
|
31f2bff0f6 | ||
|
|
61d094d9fd | ||
|
|
c1d5881167 | ||
|
|
dd8ccfe21f | ||
|
|
b4b29babfd | ||
|
|
ecabe9b6ef | ||
|
|
ec999015ab | ||
|
|
51a11b6495 | ||
|
|
27134a52ad | ||
|
|
42bf016e90 | ||
|
|
833dc7d3f7 | ||
|
|
42d350ef27 | ||
|
|
a81f9d07cb | ||
|
|
cb6e3d4ac8 | ||
|
|
5ff5d6fb1d | ||
|
|
e2253786dc | ||
|
|
20140148bf | ||
|
|
4b9dce26ac | ||
|
|
3b2c2960a9 | ||
|
|
a79578142d | ||
|
|
2b61257e50 | ||
|
|
1f4eea89c5 | ||
|
|
1609e46660 | ||
|
|
28d5a2a019 | ||
|
|
40f0f5387a | ||
|
|
88bcfb9e66 | ||
|
|
2b076c90e4 | ||
|
|
0443fbdfdb | ||
|
|
36d24bdac0 | ||
|
|
d4dfc1c820 | ||
|
|
00178ad197 | ||
|
|
f8efd1a31a | ||
|
|
e1363cf151 | ||
|
|
38e0f5ede7 | ||
|
|
9663018e21 | ||
|
|
80a7c2a9c7 | ||
|
|
4687723176 | ||
|
|
41ce2df00c | ||
|
|
794967904a | ||
|
|
74a7a1a21a | ||
|
|
d9587aa314 | ||
|
|
6b208ef67c | ||
|
|
0cfec0ada6 | ||
|
|
3ecfb15c89 | ||
|
|
23c026126f | ||
|
|
ff9abab547 | ||
|
|
c9c48c77e4 | ||
|
|
83efc58f29 | ||
|
|
632e1ff091 | ||
|
|
40286756b9 | ||
|
|
1050ac5e3c | ||
|
|
6d2c3712c0 | ||
|
|
4a52095033 | ||
|
|
55b12d7329 | ||
|
|
f4240e5229 | ||
|
|
7759649963 | ||
|
|
c5e6d6f2cb | ||
|
|
ec850f2cf0 | ||
|
|
ff52ad5345 | ||
|
|
5de50c70c6 | ||
|
|
94f8949ca2 | ||
|
|
44fc3c8d2d | ||
|
|
57a05d5486 | ||
|
|
e216214085 | ||
|
|
aa7f18a16f | ||
|
|
b9f397e04a | ||
|
|
57c3a86799 | ||
|
|
52ac41b0c6 | ||
|
|
741ccbe741 | ||
|
|
2ecd86da78 | ||
|
|
30e4e7665a | ||
|
|
516dfd1f19 | ||
|
|
0cd08499aa | ||
|
|
c652df82a3 | ||
|
|
c8342fb0a9 | ||
|
|
d0b59a0fb4 | ||
|
|
6f50f35519 | ||
|
|
4e775b2b49 | ||
|
|
e77a9e5d44 | ||
|
|
a381e44d8c | ||
|
|
4acf0969e8 | ||
|
|
30c4178269 | ||
|
|
dffe6e0a16 | ||
|
|
8090e67b9e | ||
|
|
f1beabcb6f | ||
|
|
647b8e2313 | ||
|
|
f5b4697608 | ||
|
|
f201857d51 | ||
|
|
0d982057a5 | ||
|
|
6fb94384b9 | ||
|
|
d754e7233d | ||
|
|
f974a66086 | ||
|
|
250625fc0e | ||
|
|
16e090b520 | ||
|
|
be9fbbcb6e | ||
|
|
8be3c3d0e1 | ||
|
|
c680e15cb5 | ||
|
|
da6baf72f5 | ||
|
|
2ca30bcb31 | ||
|
|
2e2b3128c5 | ||
|
|
4a81818d05 | ||
|
|
0eb98a3882 | ||
|
|
d28100d682 | ||
|
|
0f4d3bdbb5 | ||
|
|
c7eccddac9 | ||
|
|
4b7712df80 | ||
|
|
e5c6c31e02 | ||
|
|
7e62bb6b68 | ||
|
|
3b2ee25d75 | ||
|
|
4a9e2ac9b6 | ||
|
|
d890b8be0a | ||
|
|
bb1ba93676 | ||
|
|
f8c3f71cfe | ||
|
|
c9050bd3bb | ||
|
|
d0fe1beee0 | ||
|
|
e401e8f1cf | ||
|
|
4160e5b1c4 | ||
|
|
89ff25cd54 | ||
|
|
7a941016a9 | ||
|
|
7e4f807f75 | ||
|
|
be60e4648a | ||
|
|
6060ddcd87 | ||
|
|
9915c57817 | ||
|
|
917adcfb2e | ||
|
|
1c5e62a468 | ||
|
|
f5e8c525e9 | ||
|
|
6583615885 | ||
|
|
0f0eba244c | ||
|
|
3911b7b583 | ||
|
|
3634d315ed | ||
|
|
89b85c2e27 | ||
|
|
bbff3f5969 | ||
|
|
eb8f66dca2 | ||
|
|
08531fa1ff | ||
|
|
662bc41cb3 | ||
|
|
974425afee | ||
|
|
9f7f06a142 |
@@ -8,14 +8,15 @@ module.exports = {
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'eslint-config-prettier',
|
||||
],
|
||||
plugins: ['react-refresh'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.json'],
|
||||
},
|
||||
ignorePatterns: [
|
||||
'scripts/**/*',
|
||||
'plugin-runtime/**/*',
|
||||
'plugin-runtime-types/**/*',
|
||||
'packages/plugin-runtime/**/*',
|
||||
'packages/plugin-runtime-types/**/*',
|
||||
'src-tauri/**/*',
|
||||
'src-web/tailwind.config.cjs',
|
||||
'src-web/vite.config.ts',
|
||||
@@ -32,6 +33,7 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'react-refresh/only-export-components': 'error',
|
||||
'jsx-a11y/no-autofocus': 'off',
|
||||
'react/react-in-jsx-scope': 'off',
|
||||
'import/no-unresolved': 'off',
|
||||
|
||||
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
src-tauri/vendored/**/* linguist-generated=true
|
||||
src-tauri/gen/schemas/**/* linguist-generated=true
|
||||
45
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
45
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -1,45 +0,0 @@
|
||||
name: Bug Report
|
||||
description: "Something isn't working properly in Yaak"
|
||||
title: "Short description"
|
||||
labels: ["bug", "needs triage"]
|
||||
assignees:
|
||||
- gschier
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report 🤗
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Also tell us, what did you expect to happen?
|
||||
placeholder: Tell us what you see!
|
||||
value: "A bug happened!"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of our software are you running?
|
||||
placeholder: 2024.8.0
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: os
|
||||
attributes:
|
||||
label: What operating system are you on?
|
||||
multiple: false
|
||||
options:
|
||||
- macOS
|
||||
- Windows
|
||||
- Linux
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
4
.github/ISSUE_TEMPLATE/config.yml
vendored
4
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,5 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Feature Request, Question, etc.
|
||||
- name: Bugs, Feedback, Feature Requests, and Questions
|
||||
url: https://feedback.yaak.app
|
||||
about: Report all non-bugs to the feedback board 👉🏼
|
||||
about: "Please report to Yaak's public feedback board. Issues will be created and linked here when applicable."
|
||||
|
||||
44
.github/workflows/release.yml
vendored
44
.github/workflows/release.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
- platform: 'macos-latest' # for Intel-based Macs.
|
||||
args: '--target x86_64-apple-darwin'
|
||||
yaak_arch: 'x64'
|
||||
- platform: 'ubuntu-22.04' # for Tauri v1, you could replace this with ubuntu-20.04.
|
||||
- platform: 'ubuntu-22.04'
|
||||
args: ''
|
||||
yaak_arch: 'x64'
|
||||
- platform: 'windows-latest'
|
||||
@@ -38,10 +38,6 @@ jobs:
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.22'
|
||||
|
||||
- name: install Rust stable
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
@@ -56,7 +52,7 @@ jobs:
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
target/
|
||||
src-tauri/target/
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
restore-keys: ${{ runner.os }}-cargo-
|
||||
|
||||
@@ -66,15 +62,23 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
|
||||
|
||||
- name: install dependencies (windows only)
|
||||
if: matrix.platform == 'windows-latest'
|
||||
run: cargo install --force trusted-signing-cli
|
||||
|
||||
- name: Install NPM Dependencies
|
||||
run: |
|
||||
npm ci
|
||||
npm install @yaakapp/cli
|
||||
|
||||
- name: Install Protoc for plugin-runtime
|
||||
uses: arduino/setup-protoc@v3
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Run JS build
|
||||
run: npm run build
|
||||
|
||||
- name: Run lint
|
||||
run: npm run lint
|
||||
|
||||
@@ -93,20 +97,32 @@ jobs:
|
||||
env:
|
||||
YAAK_PLUGINS_DIR: ${{ env.YAAK_PLUGINS_DIR }}
|
||||
YAAK_TARGET_ARCH: ${{ matrix.yaak_arch }}
|
||||
|
||||
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
|
||||
# Apple signing stuff
|
||||
APPLE_CERTIFICATE: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
APPLE_ID: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_ID }}
|
||||
APPLE_PASSWORD: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_PASSWORD }}
|
||||
APPLE_SIGNING_IDENTITY: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_SIGNING_IDENTITY }}
|
||||
APPLE_TEAM_ID: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_TEAM_ID }}
|
||||
|
||||
# Windows signing stuff
|
||||
AZURE_CLIENT_ID: ${{ matrix.platform == 'windows-latest' && secrets.AZURE_CLIENT_ID }}
|
||||
AZURE_CLIENT_SECRET: ${{ matrix.platform == 'windows-latest' && secrets.AZURE_CLIENT_SECRET }}
|
||||
AZURE_TENANT_ID: ${{ matrix.platform == 'windows-latest' && secrets.AZURE_TENANT_ID }}
|
||||
with:
|
||||
tagName: 'v__VERSION__'
|
||||
releaseName: 'Release __VERSION__'
|
||||
releaseBody: 'https://yaak.app/blog/__VERSION__'
|
||||
releaseBody: |
|
||||
> [!IMPORTANT]
|
||||
> The Yaak project is open source. However, to fund development, these pre-built binaries require a license for commercial use. Please see the [Pricing Page](https://yaak.app/pricing) for more details.
|
||||
|
||||
You can view the full release notes here → https://yaak.app/blog/2024.13.0
|
||||
releaseDraft: true
|
||||
prerelease: false
|
||||
args: ${{ matrix.args }}
|
||||
|
||||
@@ -1,19 +1,62 @@
|
||||
## Developer Setup
|
||||
# Developer Setup
|
||||
|
||||
Development requires the following tools
|
||||
Yaak is a combined Node.js and Rust monorepo. It is a [Tauri](https://tauri.app) project, so
|
||||
uses Rust and HTML/CSS/JS for the main application but there is also a plugin system powered
|
||||
by a Node.js sidecar that communicates to the app over gRPC.
|
||||
|
||||
Because of the moving parts, there are a few setup steps required before development can
|
||||
begin.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Make sure you have the following tools installed:
|
||||
|
||||
- [Node.js](https://nodejs.org/en/download/package-manager)
|
||||
- [Rust](https://www.rust-lang.org/tools/install)
|
||||
|
||||
Then, you can run the app.
|
||||
Check the installations with the following commands:
|
||||
|
||||
1. Checkout the [plugins](https://github.com/yaakapp/plugins) repository
|
||||
2. Run `YAAK_PLUGINS_DIR="..." npm run bootstrap` to fetch external binaries, build local dependencies, etc.
|
||||
3. Run the desktop app in dev mode `npm start`
|
||||
```shell
|
||||
node -v
|
||||
npm -v
|
||||
rustc --version
|
||||
```
|
||||
|
||||
Install the NPM dependencies:
|
||||
|
||||
```shell
|
||||
npm install
|
||||
```
|
||||
|
||||
Run the `bootstrap` command to do some initial setup:
|
||||
|
||||
```shell
|
||||
npm run bootstrap
|
||||
```
|
||||
|
||||
_NOTE: Run with `YAAK_PLUGINS_DIR=<Path to yaakapp/plugins>` to re-build bundled plugins_
|
||||
|
||||
## Run the App
|
||||
|
||||
After bootstrapping, start the app in development mode:
|
||||
|
||||
```shell
|
||||
npm start
|
||||
```
|
||||
|
||||
_NOTE: If working on bundled plugins, run with `YAAK_PLUGINS_DIR=<Path to yaakapp/plugins>`_
|
||||
|
||||
## SQLite Migrations
|
||||
|
||||
1. From `src-tauri/`, run `sqlx migrate add migration-name`
|
||||
2. Migrate the DB by running the app (may need to `cargo clean` first)
|
||||
New migrations can be created from the `src-tauri/` directory:
|
||||
|
||||
```shell
|
||||
cd src-tauri
|
||||
sqlx migrate add migration-name
|
||||
```
|
||||
|
||||
_Note: Yaak development builds use a separate database location than production releases_
|
||||
Run the app to apply the migrations.
|
||||
|
||||
If nothing happens, try `cargo clean` and run the app again.
|
||||
|
||||
_Note: Development builds use a separate database location from production builds._
|
||||
|
||||
20
README.md
20
README.md
@@ -1,4 +1,4 @@
|
||||
# [Yaak API Client](https://yaak.app)
|
||||
# Yaak API Client
|
||||
|
||||
Yaak is a desktop API client for organizing and executing REST, GraphQL, and gRPC
|
||||
requests. It's built using [Tauri](https://tauri.app), Rust, and ReactJS.
|
||||
@@ -7,10 +7,20 @@ requests. It's built using [Tauri](https://tauri.app), Rust, and ReactJS.
|
||||
|
||||
## Feedback and Bug Reports
|
||||
|
||||
Please [Create an Issue](https://github.com/yaakapp/app/issues/new) for bug reports and
|
||||
submit all other feedback to the [Feedback Board](https://feedback.yaak.app).
|
||||
All feedback, bug reports, questions, and feature requests should be reported to
|
||||
[feedback.yaak.app](https://feedback.yaak.app). Issues will be duplicated
|
||||
in this repository if applicable.
|
||||
|
||||
## Community Projects
|
||||
|
||||
- [`yaak2postman`](https://github.com/BiteCraft/yaak2postman) CLI for converting Yaak data
|
||||
exports to Postman-compatible collections
|
||||
|
||||
## Contribution Policy
|
||||
|
||||
Yaak open source, but currently only accepting contributions for bug fixes. See [
|
||||
`DEVELOPMENT.md`](DEVELOPMENT.md).
|
||||
Yaak is open source, but only accepting contributions for bug fixes. See the
|
||||
[`good first issue`](https://github.com/yaakapp/app/labels/good%20first%20issue) label for
|
||||
issues that are more approachable for contribution.
|
||||
|
||||
To get started, visit [`DEVELOPMENT.md`](DEVELOPMENT.md) for tips on setting up your
|
||||
environment.
|
||||
|
||||
5365
package-lock.json
generated
5365
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
39
package.json
39
package.json
@@ -4,21 +4,26 @@
|
||||
"version": "0.0.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/yaakapp/app.git"
|
||||
"url": "git+https://github.com/mountain-loop/yaak.git"
|
||||
},
|
||||
"workspaces": [
|
||||
"plugin-runtime",
|
||||
"plugin-runtime-types",
|
||||
"src-tauri/yaak_models",
|
||||
"src-tauri/yaak_plugin_runtime",
|
||||
"src-tauri/yaak_sync",
|
||||
"src-tauri/yaak_templates",
|
||||
"packages/plugin-runtime",
|
||||
"packages/plugin-runtime-types",
|
||||
"packages/common-lib",
|
||||
"src-tauri/yaak-license",
|
||||
"src-tauri/yaak-models",
|
||||
"src-tauri/yaak-plugins",
|
||||
"src-tauri/yaak-sse",
|
||||
"src-tauri/yaak-sync",
|
||||
"src-tauri/yaak-templates",
|
||||
"src-web"
|
||||
],
|
||||
"scripts": {
|
||||
"start": "npm run app-dev",
|
||||
"app-build": "tauri build",
|
||||
"app-dev": "tauri dev --no-watch --config ./src-tauri/tauri-dev.conf.json",
|
||||
"bootstrap": "run-p bootstrap:* && npm run --workspace plugin-runtime build",
|
||||
"build": "npm run --workspaces --if-present build",
|
||||
"bootstrap": "run-p bootstrap:* && npm run --workspaces --if-present bootstrap",
|
||||
"bootstrap:vendor-node": "node scripts/vendor-node.cjs",
|
||||
"bootstrap:vendor-plugins": "node scripts/vendor-plugins.cjs",
|
||||
"bootstrap:vendor-protoc": "node scripts/vendor-protoc.cjs",
|
||||
@@ -29,18 +34,18 @@
|
||||
"tauri-before-dev": "npm run --workspaces --if-present dev"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^2.0.0-rc.16",
|
||||
"@typescript-eslint/eslint-plugin": "^8.5.0",
|
||||
"@typescript-eslint/parser": "^8.5.0",
|
||||
"@tauri-apps/cli": "^2.2.2",
|
||||
"@typescript-eslint/eslint-plugin": "^8.18.1",
|
||||
"@typescript-eslint/parser": "^8.18.1",
|
||||
"eslint": "^8",
|
||||
"eslint-config-prettier": "^8",
|
||||
"eslint-plugin-import": "^2.30.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.10.0",
|
||||
"eslint-plugin-react": "^7.35.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||
"eslint-plugin-react": "^7.37.2",
|
||||
"eslint-plugin-react-hooks": "^5.1.0",
|
||||
"nodejs-file-downloader": "^4.13.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^3.3.3",
|
||||
"typescript": "^5.6.2"
|
||||
"prettier": "^3.4.2",
|
||||
"typescript": "^5.7.2"
|
||||
}
|
||||
}
|
||||
|
||||
1
packages/common-lib/index.ts
Normal file
1
packages/common-lib/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './debounce';
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@yaakapp-internal/plugin",
|
||||
"name": "@yaakapp-internal/lib",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"main": "index.ts"
|
||||
@@ -1,15 +1,18 @@
|
||||
{
|
||||
"name": "@yaakapp/api",
|
||||
"version": "0.2.7",
|
||||
"version": "0.2.17",
|
||||
"main": "lib/index.js",
|
||||
"typings": "./lib/index.d.ts",
|
||||
"files": [
|
||||
"lib/**/*"
|
||||
],
|
||||
"scripts": {
|
||||
"bootstrap": "npm run build",
|
||||
"build": "run-s build:copy-types build:tsc",
|
||||
"build:tsc": "tsc",
|
||||
"build:copy-types": "cpy --flat ../src-tauri/yaak_plugin_runtime/bindings/*.ts ./src/bindings/",
|
||||
"build:copy-types": "run-p build:copy-types:*",
|
||||
"build:copy-types:root": "cpy --flat ../../src-tauri/yaak-plugin-runtime/bindings/*.ts ./src/bindings",
|
||||
"build:copy-types:next": "cpy --flat ../../src-tauri/yaak-plugin-runtime/bindings/serde_json/*.ts ./src/bindings/serde_json",
|
||||
"prepublishOnly": "npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
338
packages/plugin-runtime-types/src/bindings/events.ts
Normal file
338
packages/plugin-runtime-types/src/bindings/events.ts
Normal file
@@ -0,0 +1,338 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type {
|
||||
Environment,
|
||||
Folder,
|
||||
GrpcRequest,
|
||||
HttpRequest,
|
||||
HttpResponse,
|
||||
Workspace,
|
||||
} from './models';
|
||||
import type { JsonValue } from './serde_json/JsonValue';
|
||||
|
||||
export type BootRequest = { dir: string; watch: boolean };
|
||||
|
||||
export type BootResponse = { name: string; version: string; capabilities: Array<string> };
|
||||
|
||||
export type CallHttpRequestActionArgs = { httpRequest: HttpRequest };
|
||||
|
||||
export type CallHttpRequestActionRequest = {
|
||||
key: string;
|
||||
pluginRefId: string;
|
||||
args: CallHttpRequestActionArgs;
|
||||
};
|
||||
|
||||
export type CallTemplateFunctionArgs = {
|
||||
purpose: RenderPurpose;
|
||||
values: { [key in string]?: string };
|
||||
};
|
||||
|
||||
export type CallTemplateFunctionRequest = { name: string; args: CallTemplateFunctionArgs };
|
||||
|
||||
export type CallTemplateFunctionResponse = { value: string | null };
|
||||
|
||||
export type Color =
|
||||
| 'custom'
|
||||
| 'default'
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| 'info'
|
||||
| 'success'
|
||||
| 'notice'
|
||||
| 'warning'
|
||||
| 'danger';
|
||||
|
||||
export type CopyTextRequest = { text: string };
|
||||
|
||||
export type ExportHttpRequestRequest = { httpRequest: HttpRequest };
|
||||
|
||||
export type ExportHttpRequestResponse = { content: string };
|
||||
|
||||
export type FilterRequest = { content: string; filter: string };
|
||||
|
||||
export type FilterResponse = { content: string };
|
||||
|
||||
export type FindHttpResponsesRequest = { requestId: string; limit?: number };
|
||||
|
||||
export type FindHttpResponsesResponse = { httpResponses: Array<HttpResponse> };
|
||||
|
||||
export type GetHttpRequestActionsRequest = Record<string, never>;
|
||||
|
||||
export type GetHttpRequestActionsResponse = {
|
||||
actions: Array<HttpRequestAction>;
|
||||
pluginRefId: string;
|
||||
};
|
||||
|
||||
export type GetHttpRequestByIdRequest = { id: string };
|
||||
|
||||
export type GetHttpRequestByIdResponse = { httpRequest: HttpRequest | null };
|
||||
|
||||
export type GetTemplateFunctionsResponse = {
|
||||
functions: Array<TemplateFunction>;
|
||||
pluginRefId: string;
|
||||
};
|
||||
|
||||
export type HttpRequestAction = { key: string; label: string; icon?: Icon };
|
||||
|
||||
export type Icon = 'copy' | 'info' | 'check_circle' | 'alert_triangle' | '_unknown';
|
||||
|
||||
export type ImportRequest = { content: string };
|
||||
|
||||
export type ImportResources = {
|
||||
workspaces: Array<Workspace>;
|
||||
environments: Array<Environment>;
|
||||
folders: Array<Folder>;
|
||||
httpRequests: Array<HttpRequest>;
|
||||
grpcRequests: Array<GrpcRequest>;
|
||||
};
|
||||
|
||||
export type ImportResponse = { resources: ImportResources };
|
||||
|
||||
export type InternalEvent = {
|
||||
id: string;
|
||||
pluginRefId: string;
|
||||
replyId: string | null;
|
||||
payload: InternalEventPayload;
|
||||
windowContext: WindowContext;
|
||||
};
|
||||
|
||||
export type InternalEventPayload =
|
||||
| ({ type: 'boot_request' } & BootRequest)
|
||||
| ({ type: 'boot_response' } & BootResponse)
|
||||
| { type: 'reload_request' }
|
||||
| { type: 'reload_response' }
|
||||
| { type: 'terminate_request' }
|
||||
| { type: 'terminate_response' }
|
||||
| ({ 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: 'template_render_request' } & TemplateRenderRequest)
|
||||
| ({ type: 'template_render_response' } & TemplateRenderResponse)
|
||||
| ({ type: 'show_toast_request' } & ShowToastRequest)
|
||||
| ({ type: 'prompt_text_request' } & PromptTextRequest)
|
||||
| ({ type: 'prompt_text_response' } & PromptTextResponse)
|
||||
| ({ 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' };
|
||||
|
||||
export type OpenFileFilter = {
|
||||
name: string;
|
||||
/**
|
||||
* File extensions to require
|
||||
*/
|
||||
extensions: Array<string>;
|
||||
};
|
||||
|
||||
export type PromptTextRequest = {
|
||||
id: string;
|
||||
title: string;
|
||||
label: string;
|
||||
description?: string;
|
||||
defaultValue?: string;
|
||||
placeholder?: string;
|
||||
/**
|
||||
* Text to add to the confirmation button
|
||||
*/
|
||||
confirmText?: string;
|
||||
/**
|
||||
* Text to add to the cancel button
|
||||
*/
|
||||
cancelText?: string;
|
||||
/**
|
||||
* Require the user to enter a non-empty value
|
||||
*/
|
||||
require?: boolean;
|
||||
};
|
||||
|
||||
export type PromptTextResponse = { value: string | null };
|
||||
|
||||
export type RenderHttpRequestRequest = { httpRequest: HttpRequest; purpose: RenderPurpose };
|
||||
|
||||
export type RenderHttpRequestResponse = { httpRequest: HttpRequest };
|
||||
|
||||
export type RenderPurpose = 'send' | 'preview';
|
||||
|
||||
export type SendHttpRequestRequest = { httpRequest: HttpRequest };
|
||||
|
||||
export type SendHttpRequestResponse = { httpResponse: HttpResponse };
|
||||
|
||||
export type ShowToastRequest = { message: string; color?: Color; icon?: Icon };
|
||||
|
||||
export type TemplateFunction = {
|
||||
name: string;
|
||||
description?: string;
|
||||
/**
|
||||
* Also support alternative names. This is useful for not breaking existing
|
||||
* tags when changing the `name` property
|
||||
*/
|
||||
aliases?: Array<string>;
|
||||
args: Array<TemplateFunctionArg>;
|
||||
};
|
||||
|
||||
export type TemplateFunctionArg =
|
||||
| ({ type: 'text' } & TemplateFunctionTextArg)
|
||||
| ({
|
||||
type: 'select';
|
||||
} & TemplateFunctionSelectArg)
|
||||
| ({ type: 'checkbox' } & TemplateFunctionCheckboxArg)
|
||||
| ({
|
||||
type: 'http_request';
|
||||
} & TemplateFunctionHttpRequestArg)
|
||||
| ({ type: 'file' } & TemplateFunctionFileArg);
|
||||
|
||||
export type TemplateFunctionBaseArg = {
|
||||
/**
|
||||
* The name of the argument. Should be `camelCase` format
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Whether the user must fill in the argument
|
||||
*/
|
||||
optional?: boolean;
|
||||
/**
|
||||
* The label of the input
|
||||
*/
|
||||
label?: string;
|
||||
/**
|
||||
* The default value
|
||||
*/
|
||||
defaultValue?: string;
|
||||
};
|
||||
|
||||
export type TemplateFunctionCheckboxArg = {
|
||||
/**
|
||||
* The name of the argument. Should be `camelCase` format
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Whether the user must fill in the argument
|
||||
*/
|
||||
optional?: boolean;
|
||||
/**
|
||||
* The label of the input
|
||||
*/
|
||||
label?: string;
|
||||
/**
|
||||
* The default value
|
||||
*/
|
||||
defaultValue?: string;
|
||||
};
|
||||
|
||||
export type TemplateFunctionFileArg = {
|
||||
/**
|
||||
* The title of the file selection window
|
||||
*/
|
||||
title: string;
|
||||
/**
|
||||
* Allow selecting multiple files
|
||||
*/
|
||||
multiple?: boolean;
|
||||
directory?: boolean;
|
||||
defaultPath?: string;
|
||||
filters?: Array<OpenFileFilter>;
|
||||
/**
|
||||
* The name of the argument. Should be `camelCase` format
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Whether the user must fill in the argument
|
||||
*/
|
||||
optional?: boolean;
|
||||
/**
|
||||
* The label of the input
|
||||
*/
|
||||
label?: string;
|
||||
/**
|
||||
* The default value
|
||||
*/
|
||||
defaultValue?: string;
|
||||
};
|
||||
|
||||
export type TemplateFunctionHttpRequestArg = {
|
||||
/**
|
||||
* The name of the argument. Should be `camelCase` format
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Whether the user must fill in the argument
|
||||
*/
|
||||
optional?: boolean;
|
||||
/**
|
||||
* The label of the input
|
||||
*/
|
||||
label?: string;
|
||||
/**
|
||||
* The default value
|
||||
*/
|
||||
defaultValue?: string;
|
||||
};
|
||||
|
||||
export type TemplateFunctionSelectArg = {
|
||||
/**
|
||||
* The options that will be available in the select input
|
||||
*/
|
||||
options: Array<TemplateFunctionSelectOption>;
|
||||
/**
|
||||
* The name of the argument. Should be `camelCase` format
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Whether the user must fill in the argument
|
||||
*/
|
||||
optional?: boolean;
|
||||
/**
|
||||
* The label of the input
|
||||
*/
|
||||
label?: string;
|
||||
/**
|
||||
* The default value
|
||||
*/
|
||||
defaultValue?: string;
|
||||
};
|
||||
|
||||
export type TemplateFunctionSelectOption = { label: string; value: string };
|
||||
|
||||
export type TemplateFunctionTextArg = {
|
||||
/**
|
||||
* Placeholder for the text input
|
||||
*/
|
||||
placeholder?: string;
|
||||
/**
|
||||
* The name of the argument. Should be `camelCase` format
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Whether the user must fill in the argument
|
||||
*/
|
||||
optional?: boolean;
|
||||
/**
|
||||
* The label of the input
|
||||
*/
|
||||
label?: string;
|
||||
/**
|
||||
* The default value
|
||||
*/
|
||||
defaultValue?: string;
|
||||
};
|
||||
|
||||
export type TemplateRenderRequest = { data: JsonValue; purpose: RenderPurpose };
|
||||
|
||||
export type TemplateRenderResponse = { data: JsonValue };
|
||||
|
||||
export type WindowContext = { type: 'none' } | { type: 'label'; label: string };
|
||||
@@ -1,23 +1,25 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type Environment = { model: "environment", id: string, workspaceId: string, createdAt: string, updatedAt: string, name: string, variables: Array<EnvironmentVariable>, };
|
||||
export type Environment = { model: "environment", id: string, workspaceId: string, environmentId: string | null, createdAt: string, updatedAt: string, name: string, variables: Array<EnvironmentVariable>, };
|
||||
|
||||
export type EnvironmentVariable = { enabled?: boolean, name: string, value: string, };
|
||||
|
||||
export type Folder = { model: "folder", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, name: string, sortPriority: number, };
|
||||
export type Folder = { model: "folder", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, name: string, description: string, sortPriority: number, };
|
||||
|
||||
export type GrpcMetadataEntry = { enabled?: boolean, name: string, value: string, };
|
||||
|
||||
export type GrpcRequest = { model: "grpc_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authenticationType: string | null, authentication: Record<string, any>, message: string, metadata: Array<GrpcMetadataEntry>, method: string | null, name: string, service: string | null, sortPriority: number, url: string, };
|
||||
export type GrpcRequest = { model: "grpc_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authenticationType: string | null, authentication: Record<string, any>, description: string, message: string, metadata: Array<GrpcMetadataEntry>, method: string | null, name: string, service: string | null, sortPriority: number, url: string, };
|
||||
|
||||
export type HttpRequest = { model: "http_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record<string, any>, authenticationType: string | null, body: Record<string, any>, bodyType: string | null, headers: Array<HttpRequestHeader>, method: string, name: string, sortPriority: number, url: string, urlParameters: Array<HttpUrlParameter>, };
|
||||
export type HttpRequest = { model: "http_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record<string, any>, authenticationType: string | null, body: Record<string, any>, bodyType: string | null, description: string, headers: Array<HttpRequestHeader>, method: string, name: string, sortPriority: number, url: string, urlParameters: Array<HttpUrlParameter>, };
|
||||
|
||||
export type HttpRequestHeader = { enabled?: boolean, name: string, value: string, };
|
||||
|
||||
export type HttpResponse = { model: "http_response", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, bodyPath: string | null, contentLength: number | null, elapsed: number, elapsedHeaders: number, error: string | null, headers: Array<HttpResponseHeader>, remoteAddr: string | null, status: number, statusReason: string | null, url: string, version: string | null, };
|
||||
export type HttpResponse = { model: "http_response", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, bodyPath: string | null, contentLength: number | null, elapsed: number, elapsedHeaders: number, error: string | null, headers: Array<HttpResponseHeader>, remoteAddr: string | null, status: number, statusReason: string | null, state: HttpResponseState, url: string, version: string | null, };
|
||||
|
||||
export type HttpResponseHeader = { name: string, value: string, };
|
||||
|
||||
export type HttpResponseState = "initialized" | "connected" | "closed";
|
||||
|
||||
export type HttpUrlParameter = { enabled?: boolean, name: string, value: string, };
|
||||
|
||||
export type Workspace = { model: "workspace", id: string, createdAt: string, updatedAt: string, name: string, description: string, variables: Array<EnvironmentVariable>, settingValidateCertificates: boolean, settingFollowRedirects: boolean, settingRequestTimeout: number, };
|
||||
export type Workspace = { model: "workspace", id: string, createdAt: string, updatedAt: string, name: string, description: string, settingValidateCertificates: boolean, settingFollowRedirects: boolean, settingRequestTimeout: number, };
|
||||
@@ -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 JsonValue = number | string | Array<JsonValue> | { [key in string]?: JsonValue };
|
||||
@@ -1,13 +1,17 @@
|
||||
import {
|
||||
import type {
|
||||
FindHttpResponsesRequest,
|
||||
FindHttpResponsesResponse,
|
||||
GetHttpRequestByIdRequest,
|
||||
GetHttpRequestByIdResponse,
|
||||
PromptTextRequest,
|
||||
PromptTextResponse,
|
||||
RenderHttpRequestRequest,
|
||||
RenderHttpRequestResponse,
|
||||
SendHttpRequestRequest,
|
||||
SendHttpRequestResponse,
|
||||
ShowToastRequest,
|
||||
TemplateRenderRequest,
|
||||
TemplateRenderResponse,
|
||||
} from '..';
|
||||
|
||||
export type Context = {
|
||||
@@ -17,6 +21,9 @@ export type Context = {
|
||||
toast: {
|
||||
show(args: ShowToastRequest): void;
|
||||
};
|
||||
prompt: {
|
||||
text(args: PromptTextRequest): Promise<PromptTextResponse['value']>;
|
||||
};
|
||||
httpRequest: {
|
||||
send(args: SendHttpRequestRequest): Promise<SendHttpRequestResponse['httpResponse']>;
|
||||
getById(args: GetHttpRequestByIdRequest): Promise<GetHttpRequestByIdResponse['httpRequest']>;
|
||||
@@ -25,4 +32,7 @@ export type Context = {
|
||||
httpResponse: {
|
||||
find(args: FindHttpResponsesRequest): Promise<FindHttpResponsesResponse['httpResponses']>;
|
||||
};
|
||||
templates: {
|
||||
render(args: TemplateRenderRequest): Promise<TemplateRenderResponse['data']>;
|
||||
};
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Context } from './Context';
|
||||
import type { Context } from './Context';
|
||||
|
||||
export type FilterPluginResponse = string[];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CallHttpRequestActionArgs, HttpRequestAction } from '..';
|
||||
import { Context } from './Context';
|
||||
import type { CallHttpRequestActionArgs, HttpRequestAction } from '..';
|
||||
import type { Context } from './Context';
|
||||
|
||||
export type HttpRequestActionPlugin = HttpRequestAction & {
|
||||
onSelect(ctx: Context, args: CallHttpRequestActionArgs): Promise<void> | void;
|
||||
@@ -1,12 +1,13 @@
|
||||
import { Environment, Folder, HttpRequest, Workspace } from '..';
|
||||
import { AtLeast } from '../helpers';
|
||||
import { Context } from './Context';
|
||||
import type { Environment, Folder, GrpcRequest, HttpRequest, Workspace } from '..';
|
||||
import type { AtLeast } from '../helpers';
|
||||
import type { Context } from './Context';
|
||||
|
||||
export type ImportPluginResponse = null | {
|
||||
workspaces: AtLeast<Workspace, 'name' | 'id' | 'model'>[];
|
||||
environments: AtLeast<Environment, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
||||
httpRequests: AtLeast<HttpRequest, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
||||
folders: AtLeast<Folder, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
||||
httpRequests: AtLeast<HttpRequest, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
||||
grpcRequests: AtLeast<GrpcRequest, 'name' | 'id' | 'model' | 'workspaceId'>[];
|
||||
};
|
||||
|
||||
export type ImporterPlugin = {
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CallTemplateFunctionArgs, TemplateFunction } from '..';
|
||||
import { Context } from './Context';
|
||||
import type { CallTemplateFunctionArgs, TemplateFunction } from '..';
|
||||
import type { Context } from './Context';
|
||||
|
||||
export type TemplateFunctionPlugin = TemplateFunction & {
|
||||
onRender(ctx: Context, args: CallTemplateFunctionArgs): Promise<string | null>;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Theme } from '../themes';
|
||||
import { Context } from './Context';
|
||||
import type { Theme } from '../themes';
|
||||
import type { Context } from './Context';
|
||||
|
||||
export type ThemePlugin = {
|
||||
name: string;
|
||||
@@ -1,8 +1,8 @@
|
||||
import { FilterPlugin } from './FilterPlugin';
|
||||
import { HttpRequestActionPlugin } from './HttpRequestActionPlugin';
|
||||
import { ImporterPlugin } from './ImporterPlugin';
|
||||
import { TemplateFunctionPlugin } from './TemplateFunctionPlugin';
|
||||
import { ThemePlugin } from './ThemePlugin';
|
||||
import type { FilterPlugin } from './FilterPlugin';
|
||||
import type { HttpRequestActionPlugin } from './HttpRequestActionPlugin';
|
||||
import type { ImporterPlugin } from './ImporterPlugin';
|
||||
import type { TemplateFunctionPlugin } from './TemplateFunctionPlugin';
|
||||
import type { ThemePlugin } from './ThemePlugin';
|
||||
|
||||
export type { Context } from './Context';
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
{
|
||||
"name": "@yaakapp-internal/plugin-runtime",
|
||||
"scripts": {
|
||||
"bootstrap": "npm run build",
|
||||
"build": "run-p build:*",
|
||||
"build:main": "esbuild src/index.ts --bundle --platform=node --outfile=../src-tauri/vendored/plugin-runtime/index.cjs",
|
||||
"build:worker": "esbuild src/index.worker.ts --bundle --platform=node --outfile=../src-tauri/vendored/plugin-runtime/index.worker.cjs",
|
||||
"build:proto": "grpc_tools_node_protoc --ts_proto_out=src/gen --ts_proto_opt=outputServices=nice-grpc,outputServices=generic-definitions,useExactTypes=false --proto_path=../proto ../proto/plugins/*.proto"
|
||||
"build:main": "esbuild src/index.ts --bundle --platform=node --outfile=../../src-tauri/vendored/plugin-runtime/index.cjs",
|
||||
"build:worker": "esbuild src/index.worker.ts --bundle --platform=node --outfile=../../src-tauri/vendored/plugin-runtime/index.worker.cjs",
|
||||
"build:proto": "grpc_tools_node_protoc --ts_proto_out=src/gen --ts_proto_opt=outputServices=nice-grpc,outputServices=generic-definitions,useExactTypes=false --proto_path=../../proto ../../proto/plugins/*.proto"
|
||||
},
|
||||
"dependencies": {
|
||||
"intercept-stdout": "^0.1.2",
|
||||
@@ -1,6 +1,6 @@
|
||||
import { InternalEvent } from '@yaakapp/api';
|
||||
import type { InternalEvent } from '@yaakapp/api';
|
||||
import EventEmitter from 'node:events';
|
||||
import { EventStreamEvent } from './gen/plugins/runtime';
|
||||
import type { EventStreamEvent } from './gen/plugins/runtime';
|
||||
|
||||
export class EventChannel {
|
||||
emitter: EventEmitter = new EventEmitter();
|
||||
@@ -1,14 +1,15 @@
|
||||
import { InternalEvent } from '@yaakapp/api';
|
||||
import type { BootRequest, InternalEvent } from '@yaakapp-internal/plugins';
|
||||
import path from 'node:path';
|
||||
import { Worker } from 'node:worker_threads';
|
||||
import { EventChannel } from './EventChannel';
|
||||
import type { EventChannel } from './EventChannel';
|
||||
import type { PluginWorkerData } from './index.worker';
|
||||
|
||||
export class PluginHandle {
|
||||
#worker: Worker;
|
||||
|
||||
constructor(
|
||||
readonly pluginDir: string,
|
||||
readonly pluginRefId: string,
|
||||
readonly bootRequest: BootRequest,
|
||||
readonly events: EventChannel,
|
||||
) {
|
||||
this.#worker = this.#createWorker();
|
||||
@@ -24,28 +25,32 @@ export class PluginHandle {
|
||||
|
||||
#createWorker(): Worker {
|
||||
const workerPath = process.env.YAAK_WORKER_PATH ?? path.join(__dirname, 'index.worker.cjs');
|
||||
const workerData: PluginWorkerData = {
|
||||
pluginRefId: this.pluginRefId,
|
||||
bootRequest: this.bootRequest,
|
||||
};
|
||||
const worker = new Worker(workerPath, {
|
||||
workerData: { pluginDir: this.pluginDir, pluginRefId: this.pluginRefId },
|
||||
workerData,
|
||||
});
|
||||
|
||||
worker.on('message', (e) => this.events.emit(e));
|
||||
worker.on('error', this.#handleError.bind(this));
|
||||
worker.on('exit', this.#handleExit.bind(this));
|
||||
|
||||
console.log('Created plugin worker for ', this.pluginDir);
|
||||
console.log('Created plugin worker for ', this.bootRequest.dir);
|
||||
|
||||
return worker;
|
||||
}
|
||||
|
||||
async #handleError(err: Error) {
|
||||
console.error('Plugin errored', this.pluginDir, err);
|
||||
console.error('Plugin errored', this.bootRequest.dir, err);
|
||||
}
|
||||
|
||||
async #handleExit(code: number) {
|
||||
if (code === 0) {
|
||||
console.log('Plugin exited successfully', this.pluginDir);
|
||||
console.log('Plugin exited successfully', this.bootRequest.dir);
|
||||
} else {
|
||||
console.log('Plugin exited with status', code, this.pluginDir);
|
||||
console.log('Plugin exited with status', code, this.bootRequest.dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-ts_proto v2.2.0
|
||||
// protoc-gen-ts_proto v2.2.3
|
||||
// protoc v3.19.1
|
||||
// source: plugins/runtime.proto
|
||||
|
||||
@@ -33,13 +33,14 @@ export const EventStreamEvent: MessageFns<EventStreamEvent> = {
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1:
|
||||
case 1: {
|
||||
if (tag !== 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.event = reader.string();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
@@ -1,12 +1,16 @@
|
||||
import { InternalEvent } from '@yaakapp/api';
|
||||
import type { InternalEvent } from '@yaakapp/api';
|
||||
import { createChannel, createClient, Status } from 'nice-grpc';
|
||||
import { EventChannel } from './EventChannel';
|
||||
import { PluginRuntimeClient, PluginRuntimeDefinition } from './gen/plugins/runtime';
|
||||
import type { PluginRuntimeClient} from './gen/plugins/runtime';
|
||||
import { PluginRuntimeDefinition } from './gen/plugins/runtime';
|
||||
import { PluginHandle } from './PluginHandle';
|
||||
|
||||
const port = process.env.PORT || '50051';
|
||||
|
||||
const channel = createChannel(`localhost:${port}`);
|
||||
const channel = createChannel(`localhost:${port}`, undefined, {
|
||||
'grpc.max_receive_message_length': Number.MAX_SAFE_INTEGER,
|
||||
'grpc.max_send_message_length': Number.MAX_SAFE_INTEGER,
|
||||
});
|
||||
const client: PluginRuntimeClient = createClient(PluginRuntimeDefinition, channel);
|
||||
|
||||
const events = new EventChannel();
|
||||
@@ -18,7 +22,7 @@ const plugins: Record<string, PluginHandle> = {};
|
||||
const pluginEvent: InternalEvent = JSON.parse(e.event);
|
||||
// Handle special event to bootstrap plugin
|
||||
if (pluginEvent.payload.type === 'boot_request') {
|
||||
const plugin = new PluginHandle(pluginEvent.payload.dir, pluginEvent.pluginRefId, events);
|
||||
const plugin = new PluginHandle(pluginEvent.pluginRefId, pluginEvent.payload, events);
|
||||
plugins[pluginEvent.pluginRefId] = plugin;
|
||||
}
|
||||
|
||||
@@ -1,26 +1,39 @@
|
||||
import {
|
||||
Context,
|
||||
import type {
|
||||
BootRequest,
|
||||
FindHttpResponsesResponse,
|
||||
GetHttpRequestByIdResponse,
|
||||
HttpRequestAction,
|
||||
ImportResponse,
|
||||
InternalEvent,
|
||||
InternalEventPayload,
|
||||
PromptTextResponse,
|
||||
RenderHttpRequestResponse,
|
||||
SendHttpRequestResponse,
|
||||
TemplateFunction,
|
||||
} from '@yaakapp/api';
|
||||
import { HttpRequestActionPlugin } from '@yaakapp/api/lib/plugins/HttpRequestActionPlugin';
|
||||
import { TemplateFunctionPlugin } from '@yaakapp/api/lib/plugins/TemplateFunctionPlugin';
|
||||
TemplateRenderResponse,
|
||||
WindowContext,
|
||||
} from '@yaakapp-internal/plugins';
|
||||
import type { Context } from '@yaakapp/api';
|
||||
import type { HttpRequestActionPlugin } from '@yaakapp/api/lib/plugins/HttpRequestActionPlugin';
|
||||
import type { TemplateFunctionPlugin } from '@yaakapp/api/lib/plugins/TemplateFunctionPlugin';
|
||||
import interceptStdout from 'intercept-stdout';
|
||||
import * as console from 'node:console';
|
||||
import { Stats, readFileSync, statSync, watch } from 'node:fs';
|
||||
import type { Stats} from 'node:fs';
|
||||
import { readFileSync, statSync, watch } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import * as util from 'node:util';
|
||||
import { parentPort, workerData } from 'node:worker_threads';
|
||||
|
||||
export interface PluginWorkerData {
|
||||
bootRequest: BootRequest;
|
||||
pluginRefId: string;
|
||||
}
|
||||
|
||||
async function initialize() {
|
||||
const { pluginDir, pluginRefId } = workerData;
|
||||
const {
|
||||
bootRequest: { dir: pluginDir, watch: enableWatch },
|
||||
pluginRefId,
|
||||
}: PluginWorkerData = workerData;
|
||||
const pathPkg = path.join(pluginDir, 'package.json');
|
||||
|
||||
const pathMod = path.posix.join(pluginDir, 'build', 'index.js');
|
||||
@@ -42,21 +55,26 @@ async function initialize() {
|
||||
if (typeof mod.pluginHookImport === 'function') capabilities.push('import');
|
||||
if (typeof mod.pluginHookResponseFilter === 'function') capabilities.push('filter');
|
||||
|
||||
console.log('Plugin initialized', pkg.name, capabilities, Object.keys(mod));
|
||||
console.log('Plugin initialized', pkg.name, { capabilities, enableWatch });
|
||||
|
||||
function buildEventToSend(
|
||||
windowContext: WindowContext,
|
||||
payload: InternalEventPayload,
|
||||
replyId: string | null = null,
|
||||
): InternalEvent {
|
||||
return { pluginRefId, id: genId(), replyId, payload };
|
||||
return { pluginRefId, id: genId(), replyId, payload, windowContext };
|
||||
}
|
||||
|
||||
function sendEmpty(replyId: string | null = null): string {
|
||||
return sendPayload({ type: 'empty_response' }, replyId);
|
||||
function sendEmpty(windowContext: WindowContext, replyId: string | null = null): string {
|
||||
return sendPayload(windowContext, { type: 'empty_response' }, replyId);
|
||||
}
|
||||
|
||||
function sendPayload(payload: InternalEventPayload, replyId: string | null): string {
|
||||
const event = buildEventToSend(payload, replyId);
|
||||
function sendPayload(
|
||||
windowContext: WindowContext,
|
||||
payload: InternalEventPayload,
|
||||
replyId: string | null,
|
||||
): string {
|
||||
const event = buildEventToSend(windowContext, payload, replyId);
|
||||
sendEvent(event);
|
||||
return event.id;
|
||||
}
|
||||
@@ -69,10 +87,11 @@ async function initialize() {
|
||||
}
|
||||
|
||||
async function sendAndWaitForReply<T extends Omit<InternalEventPayload, 'type'>>(
|
||||
windowContext: WindowContext,
|
||||
payload: InternalEventPayload,
|
||||
): Promise<T> {
|
||||
// 1. Build event to send
|
||||
const eventToSend = buildEventToSend(payload, null);
|
||||
const eventToSend = buildEventToSend(windowContext, payload, null);
|
||||
|
||||
// 2. Spawn listener in background
|
||||
const promise = new Promise<InternalEventPayload>(async (resolve) => {
|
||||
@@ -97,53 +116,93 @@ async function initialize() {
|
||||
}
|
||||
|
||||
// Reload plugin if JS or package.json changes
|
||||
const windowContextNone: WindowContext = { type: 'none' };
|
||||
const cb = async () => {
|
||||
await reloadModule();
|
||||
return sendPayload({ type: 'reload_response' }, null);
|
||||
return sendPayload(windowContextNone, { type: 'reload_response' }, null);
|
||||
};
|
||||
|
||||
watchFile(pathMod, cb);
|
||||
watchFile(pathPkg, cb);
|
||||
if (enableWatch) {
|
||||
watchFile(pathMod, cb);
|
||||
watchFile(pathPkg, cb);
|
||||
}
|
||||
|
||||
const ctx: Context = {
|
||||
const newCtx = (event: InternalEvent): Context => ({
|
||||
clipboard: {
|
||||
async copyText(text) {
|
||||
await sendAndWaitForReply({ type: 'copy_text_request', text });
|
||||
await sendAndWaitForReply(event.windowContext, { type: 'copy_text_request', text });
|
||||
},
|
||||
},
|
||||
toast: {
|
||||
async show(args) {
|
||||
await sendAndWaitForReply({ type: 'show_toast_request', ...args });
|
||||
await sendAndWaitForReply(event.windowContext, { type: 'show_toast_request', ...args });
|
||||
},
|
||||
},
|
||||
prompt: {
|
||||
async text(args) {
|
||||
const reply: PromptTextResponse = await sendAndWaitForReply(event.windowContext, {
|
||||
type: 'prompt_text_request',
|
||||
...args,
|
||||
});
|
||||
return reply.value;
|
||||
},
|
||||
},
|
||||
httpResponse: {
|
||||
async find(args) {
|
||||
const payload = { type: 'find_http_responses_request', ...args } as const;
|
||||
const { httpResponses } = await sendAndWaitForReply<FindHttpResponsesResponse>(payload);
|
||||
const { httpResponses } = await sendAndWaitForReply<FindHttpResponsesResponse>(
|
||||
event.windowContext,
|
||||
payload,
|
||||
);
|
||||
return httpResponses;
|
||||
},
|
||||
},
|
||||
httpRequest: {
|
||||
async getById(args) {
|
||||
const payload = { type: 'get_http_request_by_id_request', ...args } as const;
|
||||
const { httpRequest } = await sendAndWaitForReply<GetHttpRequestByIdResponse>(payload);
|
||||
const { httpRequest } = await sendAndWaitForReply<GetHttpRequestByIdResponse>(
|
||||
event.windowContext,
|
||||
payload,
|
||||
);
|
||||
return httpRequest;
|
||||
},
|
||||
async send(args) {
|
||||
const payload = { type: 'send_http_request_request', ...args } as const;
|
||||
const { httpResponse } = await sendAndWaitForReply<SendHttpRequestResponse>(payload);
|
||||
const { httpResponse } = await sendAndWaitForReply<SendHttpRequestResponse>(
|
||||
event.windowContext,
|
||||
payload,
|
||||
);
|
||||
return httpResponse;
|
||||
},
|
||||
async render(args) {
|
||||
const payload = { type: 'render_http_request_request', ...args } as const;
|
||||
const result = await sendAndWaitForReply<RenderHttpRequestResponse>(payload);
|
||||
return result.httpRequest;
|
||||
const { httpRequest } = await sendAndWaitForReply<RenderHttpRequestResponse>(
|
||||
event.windowContext,
|
||||
payload,
|
||||
);
|
||||
return httpRequest;
|
||||
},
|
||||
},
|
||||
};
|
||||
templates: {
|
||||
/**
|
||||
* Invoke Yaak's template engine to render a value. If the value is a nested type
|
||||
* (eg. object), it will be recursively rendered.
|
||||
* */
|
||||
async render(args) {
|
||||
const payload = { type: 'template_render_request', ...args } as const;
|
||||
const result = await sendAndWaitForReply<TemplateRenderResponse>(
|
||||
event.windowContext,
|
||||
payload,
|
||||
);
|
||||
return result.data;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Message comes into the plugin to be processed
|
||||
parentPort!.on('message', async ({ payload, id: replyId }: InternalEvent) => {
|
||||
parentPort!.on('message', async (event: InternalEvent) => {
|
||||
const { windowContext, payload, id: replyId } = event;
|
||||
const ctx = newCtx(event);
|
||||
try {
|
||||
if (payload.type === 'boot_request') {
|
||||
const payload: InternalEventPayload = {
|
||||
@@ -152,7 +211,7 @@ async function initialize() {
|
||||
version: pkg.version,
|
||||
capabilities,
|
||||
};
|
||||
sendPayload(payload, replyId);
|
||||
sendPayload(windowContext, payload, replyId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -160,7 +219,7 @@ async function initialize() {
|
||||
const payload: InternalEventPayload = {
|
||||
type: 'terminate_response',
|
||||
};
|
||||
sendPayload(payload, replyId);
|
||||
sendPayload(windowContext, payload, replyId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -171,7 +230,7 @@ async function initialize() {
|
||||
type: 'import_response',
|
||||
resources: reply?.resources,
|
||||
};
|
||||
sendPayload(replyPayload, replyId);
|
||||
sendPayload(windowContext, replyPayload, replyId);
|
||||
return;
|
||||
} else {
|
||||
// Continue, to send back an empty reply
|
||||
@@ -187,7 +246,7 @@ async function initialize() {
|
||||
type: 'export_http_request_response',
|
||||
content: reply,
|
||||
};
|
||||
sendPayload(replyPayload, replyId);
|
||||
sendPayload(windowContext, replyPayload, replyId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -200,7 +259,7 @@ async function initialize() {
|
||||
type: 'filter_response',
|
||||
content: reply,
|
||||
};
|
||||
sendPayload(replyPayload, replyId);
|
||||
sendPayload(windowContext, replyPayload, replyId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -220,7 +279,7 @@ async function initialize() {
|
||||
pluginRefId,
|
||||
actions: reply,
|
||||
};
|
||||
sendPayload(replyPayload, replyId);
|
||||
sendPayload(windowContext, replyPayload, replyId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -240,7 +299,7 @@ async function initialize() {
|
||||
pluginRefId,
|
||||
functions: reply,
|
||||
};
|
||||
sendPayload(replyPayload, replyId);
|
||||
sendPayload(windowContext, replyPayload, replyId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -253,7 +312,7 @@ async function initialize() {
|
||||
);
|
||||
if (typeof action?.onSelect === 'function') {
|
||||
await action.onSelect(ctx, payload.args);
|
||||
sendEmpty(replyId);
|
||||
sendEmpty(windowContext, replyId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -267,7 +326,14 @@ async function initialize() {
|
||||
);
|
||||
if (typeof action?.onRender === 'function') {
|
||||
const result = await action.onRender(ctx, payload.args);
|
||||
sendPayload({ type: 'call_template_function_response', value: result ?? null }, replyId);
|
||||
sendPayload(
|
||||
windowContext,
|
||||
{
|
||||
type: 'call_template_function_response',
|
||||
value: result ?? null,
|
||||
},
|
||||
replyId,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -281,7 +347,7 @@ async function initialize() {
|
||||
}
|
||||
|
||||
// No matches, so send back an empty response so the caller doesn't block forever
|
||||
sendEmpty(replyId);
|
||||
sendEmpty(windowContext, replyId);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { Environment } from "./models";
|
||||
import type { Folder } from "./models";
|
||||
import type { GrpcRequest } from "./models";
|
||||
import type { HttpRequest } from "./models";
|
||||
import type { HttpResponse } from "./models";
|
||||
import type { Workspace } from "./models";
|
||||
|
||||
export type BootRequest = { dir: string, };
|
||||
|
||||
export type BootResponse = { name: string, version: string, capabilities: Array<string>, };
|
||||
|
||||
export type CallHttpRequestActionArgs = { httpRequest: HttpRequest, };
|
||||
|
||||
export type CallHttpRequestActionRequest = { key: string, pluginRefId: string, args: CallHttpRequestActionArgs, };
|
||||
|
||||
export type CallTemplateFunctionArgs = { purpose: RenderPurpose, values: { [key in string]?: string }, };
|
||||
|
||||
export type CallTemplateFunctionRequest = { name: string, args: CallTemplateFunctionArgs, };
|
||||
|
||||
export type CallTemplateFunctionResponse = { value: string | null, };
|
||||
|
||||
export type Color = "custom" | "default" | "primary" | "secondary" | "info" | "success" | "notice" | "warning" | "danger";
|
||||
|
||||
export type CopyTextRequest = { text: string, };
|
||||
|
||||
export type ExportHttpRequestRequest = { httpRequest: HttpRequest, };
|
||||
|
||||
export type ExportHttpRequestResponse = { content: string, };
|
||||
|
||||
export type FilterRequest = { content: string, filter: string, };
|
||||
|
||||
export type FilterResponse = { content: string, };
|
||||
|
||||
export type FindHttpResponsesRequest = { requestId: string, limit: number | null, };
|
||||
|
||||
export type FindHttpResponsesResponse = { httpResponses: Array<HttpResponse>, };
|
||||
|
||||
export type GetHttpRequestActionsRequest = Record<string, never>;
|
||||
|
||||
export type GetHttpRequestActionsResponse = { actions: Array<HttpRequestAction>, pluginRefId: string, };
|
||||
|
||||
export type GetHttpRequestByIdRequest = { id: string, };
|
||||
|
||||
export type GetHttpRequestByIdResponse = { httpRequest: HttpRequest | null, };
|
||||
|
||||
export type GetTemplateFunctionsResponse = { functions: Array<TemplateFunction>, pluginRefId: string, };
|
||||
|
||||
export type HttpRequestAction = { key: string, label: string, icon: string | null, };
|
||||
|
||||
export type Icon = "copy" | "info" | "check_circle" | "alert_triangle";
|
||||
|
||||
export type ImportRequest = { content: string, };
|
||||
|
||||
export type ImportResources = { workspaces: Array<Workspace>, environments: Array<Environment>, folders: Array<Folder>, httpRequests: Array<HttpRequest>, grpcRequests: Array<GrpcRequest>, };
|
||||
|
||||
export type ImportResponse = { resources: ImportResources, };
|
||||
|
||||
export type InternalEvent = { id: string, pluginRefId: string, replyId: string | null, payload: InternalEventPayload, };
|
||||
|
||||
export type InternalEventPayload = { "type": "boot_request" } & BootRequest | { "type": "boot_response" } & BootResponse | { "type": "reload_request" } | { "type": "reload_response" } | { "type": "terminate_request" } | { "type": "terminate_response" } | { "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" };
|
||||
|
||||
export type RenderHttpRequestRequest = { httpRequest: HttpRequest, purpose: RenderPurpose, };
|
||||
|
||||
export type RenderHttpRequestResponse = { httpRequest: HttpRequest, };
|
||||
|
||||
export type RenderPurpose = "send" | "preview";
|
||||
|
||||
export type SendHttpRequestRequest = { httpRequest: HttpRequest, };
|
||||
|
||||
export type SendHttpRequestResponse = { httpResponse: HttpResponse, };
|
||||
|
||||
export type ShowToastRequest = { message: string, color?: Color | null, icon?: Icon | null, };
|
||||
|
||||
export type TemplateFunction = { name: string, args: Array<TemplateFunctionArg>, };
|
||||
|
||||
export type TemplateFunctionArg = { "type": "text" } & TemplateFunctionTextArg | { "type": "select" } & TemplateFunctionSelectArg | { "type": "checkbox" } & TemplateFunctionCheckboxArg | { "type": "http_request" } & TemplateFunctionHttpRequestArg;
|
||||
|
||||
export type TemplateFunctionBaseArg = { name: string, optional?: boolean | null, label?: string | null, defaultValue?: string | null, };
|
||||
|
||||
export type TemplateFunctionCheckboxArg = { name: string, optional?: boolean | null, label?: string | null, defaultValue?: string | null, };
|
||||
|
||||
export type TemplateFunctionHttpRequestArg = { name: string, optional?: boolean | null, label?: string | null, defaultValue?: string | null, };
|
||||
|
||||
export type TemplateFunctionSelectArg = { options: Array<TemplateFunctionSelectOption>, name: string, optional?: boolean | null, label?: string | null, defaultValue?: string | null, };
|
||||
|
||||
export type TemplateFunctionSelectOption = { name: string, value: string, };
|
||||
|
||||
export type TemplateFunctionTextArg = { placeholder?: string | null, name: string, optional?: boolean | null, label?: string | null, defaultValue?: string | null, };
|
||||
3187
plugin-runtime/package-lock.json
generated
3187
plugin-runtime/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1 +1,7 @@
|
||||
edition = "2018"
|
||||
|
||||
# Widths
|
||||
chain_width = 100
|
||||
max_width = 100
|
||||
single_line_if_else_max_width = 100
|
||||
fn_call_width = 100
|
||||
|
||||
@@ -4,7 +4,7 @@ const Downloader = require('nodejs-file-downloader');
|
||||
const { rmSync, cpSync, mkdirSync, existsSync } = require('node:fs');
|
||||
const { execSync } = require('node:child_process');
|
||||
|
||||
const NODE_VERSION = 'v22.5.1';
|
||||
const NODE_VERSION = 'v22.9.0';
|
||||
|
||||
// `${process.platform}_${process.arch}`
|
||||
const MAC_ARM = 'darwin_arm64';
|
||||
@@ -53,7 +53,12 @@ rmSync(tmpDir, { recursive: true, force: true });
|
||||
|
||||
(async function () {
|
||||
// Download GitHub release artifact
|
||||
const { filePath } = await new Downloader({ url, directory: tmpDir }).download();
|
||||
console.log('Downloading NodeJS at', url);
|
||||
const { filePath } = await new Downloader({
|
||||
url,
|
||||
directory: tmpDir,
|
||||
timeout: 1000 * 60 * 2,
|
||||
}).download();
|
||||
|
||||
// Decompress to the same directory
|
||||
await decompress(filePath, tmpDir, {});
|
||||
|
||||
@@ -3,8 +3,8 @@ const path = require('node:path');
|
||||
const { execSync } = require('node:child_process');
|
||||
const pluginsDir = process.env.YAAK_PLUGINS_DIR;
|
||||
if (!pluginsDir) {
|
||||
console.log('YAAK_PLUGINS_DIR is not set');
|
||||
process.exit(1);
|
||||
console.log('Skipping bundled plugins build because YAAK_PLUGINS_DIR is not set');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Installing Yaak plugins dependencies', pluginsDir);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const decompress = require('decompress');
|
||||
const Downloader = require('nodejs-file-downloader');
|
||||
const path = require('node:path');
|
||||
const { rmSync, mkdirSync, cpSync, existsSync } = require('node:fs');
|
||||
const { rmSync, mkdirSync, cpSync, existsSync, statSync, chmodSync } = require('node:fs');
|
||||
const { execSync } = require('node:child_process');
|
||||
|
||||
const VERSION = '27.2';
|
||||
const VERSION = '28.3';
|
||||
|
||||
// `${process.platform}_${process.arch}`
|
||||
const MAC_ARM = 'darwin_arm64';
|
||||
@@ -67,6 +67,11 @@ mkdirSync(dstDir, { recursive: true });
|
||||
cpSync(includeSrc, includeDst, { recursive: true });
|
||||
rmSync(tmpDir, { recursive: true, force: true });
|
||||
|
||||
// Make binary writable, so we can sign it during release
|
||||
const stat = statSync(binDst);
|
||||
const newMode = stat.mode | 0o200;
|
||||
chmodSync(binDst, newMode);
|
||||
|
||||
console.log('Downloaded protoc to', binDst);
|
||||
})().catch((err) => console.log('Script failed:', err));
|
||||
|
||||
|
||||
3
src-tauri/.gitignore
vendored
3
src-tauri/.gitignore
vendored
@@ -2,4 +2,5 @@
|
||||
# will have compiled files and executables
|
||||
target/
|
||||
|
||||
vendored
|
||||
vendored/*
|
||||
!vendored/plugins
|
||||
|
||||
1617
src-tauri/Cargo.lock
generated
1617
src-tauri/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,20 @@
|
||||
[workspace]
|
||||
members = ["yaak_grpc", "yaak_templates", "yaak_plugin_runtime", "yaak_models"]
|
||||
members = [
|
||||
"yaak-grpc",
|
||||
"yaak-license",
|
||||
"yaak-models",
|
||||
"yaak-plugins",
|
||||
"yaak-sse",
|
||||
"yaak-sync",
|
||||
"yaak-templates",
|
||||
]
|
||||
|
||||
[package]
|
||||
name = "yaak-app"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
authors = ["Gregory Schier"]
|
||||
publish = false
|
||||
|
||||
# Produce a library for mobile support
|
||||
[lib]
|
||||
@@ -15,8 +24,11 @@ crate-type = ["staticlib", "cdylib", "lib"]
|
||||
[profile.release]
|
||||
strip = true # Automatically strip symbols from the binary.
|
||||
|
||||
[features]
|
||||
cargo-clippy = []
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.0.0-rc.12", features = [] }
|
||||
tauri-build = { version = "2.0.4", features = [] }
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
objc = "0.2.7"
|
||||
@@ -26,42 +38,54 @@ cocoa = "0.26.0"
|
||||
openssl-sys = { version = "0.9", features = ["vendored"] } # For Ubuntu installation to work
|
||||
|
||||
[dependencies]
|
||||
yaak_grpc = { path = "yaak_grpc" }
|
||||
yaak_templates = { path = "yaak_templates" }
|
||||
yaak_plugin_runtime = { workspace = true }
|
||||
yaak_models = { workspace = true }
|
||||
anyhow = "1.0.86"
|
||||
base64 = "0.22.0"
|
||||
chrono = { version = "0.4.31", features = ["serde"] }
|
||||
datetime = "0.5.2"
|
||||
eventsource-client = { git = "https://github.com/yaakapp/rust-eventsource-client", version = "0.13.0" }
|
||||
hex_color = "3.0.0"
|
||||
http = "1"
|
||||
log = "0.4.21"
|
||||
rand = "0.8.5"
|
||||
regex = "1.10.2"
|
||||
reqwest = { version = "0.12.4", features = ["multipart", "cookies", "gzip", "brotli", "deflate", "json", "native-tls-alpn"] }
|
||||
reqwest = { workspace = true, features = ["multipart", "cookies", "gzip", "brotli", "deflate", "json", "rustls-tls-manual-roots-no-provider"] }
|
||||
reqwest_cookie_store = "0.8.0"
|
||||
serde = { version = "1.0.198", features = ["derive"] }
|
||||
serde_json = { version = "1.0.116", features = ["raw_value"] }
|
||||
serde_yaml = "0.9.34"
|
||||
tauri = { workspace = true }
|
||||
rustls = { version = "0.23.21", default-features = false }
|
||||
rustls-platform-verifier = "0.5.0"
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true, features = ["raw_value"] }
|
||||
tauri = { workspace = true, features = ["devtools", "protocol-asset"] }
|
||||
tauri-plugin-clipboard-manager = "2.2.0"
|
||||
tauri-plugin-dialog = "2.2.0"
|
||||
tauri-plugin-fs = "2.2.0"
|
||||
tauri-plugin-log = { version = "2.2.0", features = ["colored"] }
|
||||
tauri-plugin-opener = "2.2.2"
|
||||
tauri-plugin-os = "2.2.0"
|
||||
tauri-plugin-shell = { workspace = true }
|
||||
tauri-plugin-clipboard-manager = "2.1.0-beta.7"
|
||||
tauri-plugin-dialog = "2.0.0-rc.7"
|
||||
tauri-plugin-fs = "2.0.0-rc.5"
|
||||
tauri-plugin-log = { version = "2.0.0-rc.2", features = ["colored"] }
|
||||
tauri-plugin-os = "2.0.0-rc.1"
|
||||
tauri-plugin-updater = "2.0.0-rc.3"
|
||||
tauri-plugin-window-state = "2.0.0-rc.5"
|
||||
tauri-plugin-single-instance = "2.2.0"
|
||||
tauri-plugin-updater = "2.3.0"
|
||||
tauri-plugin-window-state = "2.2.0"
|
||||
tokio = { version = "1.36.0", features = ["sync"] }
|
||||
tokio-stream = "0.1.15"
|
||||
uuid = "1.7.0"
|
||||
thiserror = "1.0.61"
|
||||
ts-rs = { workspace = true }
|
||||
mime_guess = "2.0.5"
|
||||
urlencoding = "2.1.3"
|
||||
uuid = "1.7.0"
|
||||
yaak-grpc = { path = "yaak-grpc" }
|
||||
yaak-license = { path = "yaak-license" }
|
||||
yaak-models = { workspace = true }
|
||||
yaak-plugins = { workspace = true }
|
||||
yaak-sse = { workspace = true }
|
||||
yaak-sync = { path = "yaak-sync" }
|
||||
yaak-templates = { path = "yaak-templates" }
|
||||
|
||||
[workspace.dependencies]
|
||||
yaak_models = { path = "yaak_models" }
|
||||
yaak_plugin_runtime = { path = "yaak_plugin_runtime" }
|
||||
tauri-plugin-shell = "2.0.0-rc.3"
|
||||
tauri = { version = "2.0.0-rc.15", features = ["devtools", "protocol-asset"] }
|
||||
yaak-models = { path = "yaak-models" }
|
||||
yaak-sse = { path = "yaak-sse" }
|
||||
yaak-plugins = { path = "yaak-plugins" }
|
||||
serde = "1.0.215"
|
||||
serde_json = "1.0.132"
|
||||
tauri-plugin-shell = "2.2.0"
|
||||
tauri = "2.2.0"
|
||||
thiserror = "2.0.3"
|
||||
ts-rs = "10.0.0"
|
||||
reqwest = "0.12.12"
|
||||
|
||||
5
src-tauri/bindings/analytics.ts
Normal file
5
src-tauri/bindings/analytics.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type AnalyticsAction = "cancel" | "click" | "commit" | "create" | "delete" | "delete_many" | "duplicate" | "export" | "hide" | "import" | "launch" | "launch_first" | "launch_update" | "send" | "show" | "toggle" | "update" | "upsert";
|
||||
|
||||
export type AnalyticsResource = "app" | "appearance" | "button" | "checkbox" | "cookie_jar" | "dialog" | "environment" | "folder" | "grpc_connection" | "grpc_event" | "grpc_request" | "http_request" | "http_response" | "link" | "key_value" | "plugin" | "select" | "setting" | "sidebar" | "tab" | "theme" | "workspace";
|
||||
@@ -16,6 +16,7 @@
|
||||
"clipboard-manager:allow-read-text",
|
||||
"dialog:allow-open",
|
||||
"dialog:allow-save",
|
||||
"fs:allow-read-dir",
|
||||
"fs:allow-read-file",
|
||||
"fs:allow-read-text-file",
|
||||
{
|
||||
@@ -29,9 +30,13 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"shell:allow-open",
|
||||
"opener:allow-open-url",
|
||||
"opener:allow-open-path",
|
||||
"opener:allow-default-urls",
|
||||
"opener:allow-reveal-item-in-dir",
|
||||
"core:webview:allow-set-webview-zoom",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-internal-toggle-maximize",
|
||||
"core:window:allow-is-fullscreen",
|
||||
"core:window:allow-maximize",
|
||||
"core:window:allow-minimize",
|
||||
@@ -43,6 +48,8 @@
|
||||
"core:window:allow-toggle-maximize",
|
||||
"core:window:allow-unmaximize",
|
||||
"clipboard-manager:allow-read-text",
|
||||
"clipboard-manager:allow-write-text"
|
||||
"clipboard-manager:allow-write-text",
|
||||
"yaak-license:default",
|
||||
"yaak-sync:default"
|
||||
]
|
||||
}
|
||||
|
||||
2
src-tauri/gen/schemas/acl-manifests.json
generated
2
src-tauri/gen/schemas/acl-manifests.json
generated
File diff suppressed because one or more lines are too long
2
src-tauri/gen/schemas/capabilities.json
generated
2
src-tauri/gen/schemas/capabilities.json
generated
@@ -1 +1 @@
|
||||
{"main":{"identifier":"main","description":"Main permissions","local":true,"windows":["*"],"permissions":["core:event:allow-emit","core:event:allow-listen","core:event:allow-unlisten","os:allow-os-type","clipboard-manager:allow-clear","clipboard-manager:allow-write-text","clipboard-manager:allow-read-text","dialog:allow-open","dialog:allow-save","fs:allow-read-file","fs:allow-read-text-file",{"identifier":"fs:scope","allow":[{"path":"$APPDATA"},{"path":"$APPDATA/**"}]},"shell:allow-open","core:webview:allow-set-webview-zoom","core:window:allow-close","core:window:allow-is-fullscreen","core:window:allow-maximize","core:window:allow-minimize","core:window:allow-set-decorations","core:window:allow-set-title","core:window:allow-show","core:window:allow-start-dragging","core:window:allow-theme","core:window:allow-toggle-maximize","core:window:allow-unmaximize","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text"]}}
|
||||
{"main":{"identifier":"main","description":"Main permissions","local":true,"windows":["*"],"permissions":["core:event:allow-emit","core:event:allow-listen","core:event:allow-unlisten","os:allow-os-type","clipboard-manager:allow-clear","clipboard-manager:allow-write-text","clipboard-manager:allow-read-text","dialog:allow-open","dialog:allow-save","fs:allow-read-dir","fs:allow-read-file","fs:allow-read-text-file",{"identifier":"fs:scope","allow":[{"path":"$APPDATA"},{"path":"$APPDATA/**"}]},"opener:allow-open-url","opener:allow-open-path","opener:allow-default-urls","opener:allow-reveal-item-in-dir","core:webview:allow-set-webview-zoom","core:window:allow-close","core:window:allow-internal-toggle-maximize","core:window:allow-is-fullscreen","core:window:allow-maximize","core:window:allow-minimize","core:window:allow-set-decorations","core:window:allow-set-title","core:window:allow-show","core:window:allow-start-dragging","core:window:allow-theme","core:window:allow-toggle-maximize","core:window:allow-unmaximize","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text","yaak-license:default","yaak-sync:default"]}}
|
||||
615
src-tauri/gen/schemas/desktop-schema.json
generated
615
src-tauri/gen/schemas/desktop-schema.json
generated
@@ -37,7 +37,7 @@
|
||||
],
|
||||
"definitions": {
|
||||
"Capability": {
|
||||
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\nIt controls application windows fine grained access to the Tauri core, application, or plugin commands. If a window is not matching any capability then it has no access to the IPC layer at all.\n\nThis can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`. A Window can have none, one, or multiple associated capabilities.\n\n## Example\n\n```json { \"identifier\": \"main-user-files-write\", \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\", \"windows\": [ \"main\" ], \"permissions\": [ \"core:default\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] }, \"platforms\": [\"macOS\",\"windows\"] } ```",
|
||||
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\nIt controls application windows fine grained access to the Tauri core, application, or plugin commands. If a window is not matching any capability then it has no access to the IPC layer at all.\n\nThis can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`. A Window can have none, one, or multiple associated capabilities.\n\n## Example\n\n```json { \"identifier\": \"main-user-files-write\", \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\", \"windows\": [ \"main\" ], \"permissions\": [ \"core:default\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] }, ], \"platforms\": [\"macOS\",\"windows\"] } ```",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"identifier",
|
||||
@@ -84,7 +84,7 @@
|
||||
}
|
||||
},
|
||||
"permissions": {
|
||||
"description": "List of permissions attached to this capability.\n\nMust include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`. For commands directly implemented in the application itself only `${permission-name}` is required.\n\n## Example\n\n```json [ \"core:default\", \"shell:allow-open\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] } ```",
|
||||
"description": "List of permissions attached to this capability.\n\nMust include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`. For commands directly implemented in the application itself only `${permission-name}` is required.\n\n## Example\n\n```json [ \"core:default\", \"shell:allow-open\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] } ] ```",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PermissionEntry"
|
||||
@@ -140,7 +140,7 @@
|
||||
"identifier": {
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n",
|
||||
"description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n#### Included permissions within this default permission set:\n",
|
||||
"type": "string",
|
||||
"const": "fs:default"
|
||||
},
|
||||
@@ -984,6 +984,11 @@
|
||||
"type": "string",
|
||||
"const": "fs:allow-seek"
|
||||
},
|
||||
{
|
||||
"description": "Enables the size command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "fs:allow-size"
|
||||
},
|
||||
{
|
||||
"description": "Enables the stat command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -1109,6 +1114,11 @@
|
||||
"type": "string",
|
||||
"const": "fs:deny-seek"
|
||||
},
|
||||
{
|
||||
"description": "Denies the size command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "fs:deny-size"
|
||||
},
|
||||
{
|
||||
"description": "Denies the stat command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -1581,7 +1591,7 @@
|
||||
"description": "FS scope entry.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "FS scope path.",
|
||||
"description": "A path that can be accessed by the webview when using the fs APIs. FS scope path pattern.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
@@ -1591,7 +1601,7 @@
|
||||
],
|
||||
"properties": {
|
||||
"path": {
|
||||
"description": "FS scope path.",
|
||||
"description": "A path that can be accessed by the webview when using the fs APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@@ -1605,7 +1615,7 @@
|
||||
"description": "FS scope entry.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "FS scope path.",
|
||||
"description": "A path that can be accessed by the webview when using the fs APIs. FS scope path pattern.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
@@ -1615,7 +1625,167 @@
|
||||
],
|
||||
"properties": {
|
||||
"path": {
|
||||
"description": "FS scope path.",
|
||||
"description": "A path that can be accessed by the webview when using the fs APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"identifier": {
|
||||
"description": "Identifier of the permission or permission set.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Identifier"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"identifier": {
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer",
|
||||
"type": "string",
|
||||
"const": "opener:default"
|
||||
},
|
||||
{
|
||||
"description": "This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-default-urls"
|
||||
},
|
||||
{
|
||||
"description": "Enables the open_path command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-open-path"
|
||||
},
|
||||
{
|
||||
"description": "Enables the open_url command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-open-url"
|
||||
},
|
||||
{
|
||||
"description": "Enables the reveal_item_in_dir command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-reveal-item-in-dir"
|
||||
},
|
||||
{
|
||||
"description": "Denies the open_path command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:deny-open-path"
|
||||
},
|
||||
{
|
||||
"description": "Denies the open_url command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:deny-open-url"
|
||||
},
|
||||
{
|
||||
"description": "Denies the reveal_item_in_dir command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:deny-reveal-item-in-dir"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"allow": {
|
||||
"items": {
|
||||
"title": "OpenerScopeEntry",
|
||||
"description": "Opener scope entry.",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"properties": {
|
||||
"app": {
|
||||
"description": "An application to open this url with, for example: firefox.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Application"
|
||||
}
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"description": "A URL that can be opened by the webview when using the Opener APIs.\n\nWildcards can be used following the UNIX glob pattern.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
"app": {
|
||||
"description": "An application to open this path with, for example: xdg-open.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Application"
|
||||
}
|
||||
]
|
||||
},
|
||||
"path": {
|
||||
"description": "A path that can be opened by the webview when using the Opener APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"deny": {
|
||||
"items": {
|
||||
"title": "OpenerScopeEntry",
|
||||
"description": "Opener scope entry.",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"properties": {
|
||||
"app": {
|
||||
"description": "An application to open this url with, for example: firefox.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Application"
|
||||
}
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"description": "A URL that can be opened by the webview when using the Opener APIs.\n\nWildcards can be used following the UNIX glob pattern.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
"app": {
|
||||
"description": "An application to open this path with, for example: xdg-open.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Application"
|
||||
}
|
||||
]
|
||||
},
|
||||
"path": {
|
||||
"description": "A path that can be opened by the webview when using the Opener APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@@ -1704,72 +1874,122 @@
|
||||
"properties": {
|
||||
"allow": {
|
||||
"items": {
|
||||
"title": "Entry",
|
||||
"description": "A command allowed to be executed by the webview API.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"args",
|
||||
"cmd",
|
||||
"name",
|
||||
"sidecar"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ShellAllowedArgs"
|
||||
"title": "ShellScopeEntry",
|
||||
"description": "Shell scope entry.",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"cmd",
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ShellScopeEntryAllowedArgs"
|
||||
}
|
||||
]
|
||||
},
|
||||
"cmd": {
|
||||
"description": "The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"cmd": {
|
||||
"description": "The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.",
|
||||
"type": "string"
|
||||
},
|
||||
"sidecar": {
|
||||
"description": "If this command is a sidecar command.",
|
||||
"type": "boolean"
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"sidecar"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ShellScopeEntryAllowedArgs"
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.",
|
||||
"type": "string"
|
||||
},
|
||||
"sidecar": {
|
||||
"description": "If this command is a sidecar command.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"deny": {
|
||||
"items": {
|
||||
"title": "Entry",
|
||||
"description": "A command allowed to be executed by the webview API.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"args",
|
||||
"cmd",
|
||||
"name",
|
||||
"sidecar"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ShellAllowedArgs"
|
||||
"title": "ShellScopeEntry",
|
||||
"description": "Shell scope entry.",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"cmd",
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ShellScopeEntryAllowedArgs"
|
||||
}
|
||||
]
|
||||
},
|
||||
"cmd": {
|
||||
"description": "The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"cmd": {
|
||||
"description": "The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.",
|
||||
"type": "string"
|
||||
},
|
||||
"sidecar": {
|
||||
"description": "If this command is a sidecar command.",
|
||||
"type": "boolean"
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"sidecar"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ShellScopeEntryAllowedArgs"
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.",
|
||||
"type": "string"
|
||||
},
|
||||
"sidecar": {
|
||||
"description": "If this command is a sidecar command.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1922,6 +2142,11 @@
|
||||
"type": "string",
|
||||
"const": "core:app:allow-name"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_app_theme command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:app:allow-set-app-theme"
|
||||
},
|
||||
{
|
||||
"description": "Enables the tauri_version command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -1952,6 +2177,11 @@
|
||||
"type": "string",
|
||||
"const": "core:app:deny-name"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_app_theme command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:app:deny-set-app-theme"
|
||||
},
|
||||
{
|
||||
"description": "Denies the tauri_version command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2507,6 +2737,11 @@
|
||||
"type": "string",
|
||||
"const": "core:webview:default"
|
||||
},
|
||||
{
|
||||
"description": "Enables the clear_all_browsing_data command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-clear-all-browsing-data"
|
||||
},
|
||||
{
|
||||
"description": "Enables the create_webview command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2537,6 +2772,11 @@
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-reparent"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_webview_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-set-webview-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_webview_focus command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2562,16 +2802,31 @@
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-webview-close"
|
||||
},
|
||||
{
|
||||
"description": "Enables the webview_hide command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-webview-hide"
|
||||
},
|
||||
{
|
||||
"description": "Enables the webview_position command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-webview-position"
|
||||
},
|
||||
{
|
||||
"description": "Enables the webview_show command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-webview-show"
|
||||
},
|
||||
{
|
||||
"description": "Enables the webview_size command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-webview-size"
|
||||
},
|
||||
{
|
||||
"description": "Denies the clear_all_browsing_data command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-clear-all-browsing-data"
|
||||
},
|
||||
{
|
||||
"description": "Denies the create_webview command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2602,6 +2857,11 @@
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-reparent"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_webview_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-set-webview-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_webview_focus command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2627,11 +2887,21 @@
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-webview-close"
|
||||
},
|
||||
{
|
||||
"description": "Denies the webview_hide command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-webview-hide"
|
||||
},
|
||||
{
|
||||
"description": "Denies the webview_position command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-webview-position"
|
||||
},
|
||||
{
|
||||
"description": "Denies the webview_show command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-webview-show"
|
||||
},
|
||||
{
|
||||
"description": "Denies the webview_size command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2712,6 +2982,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:allow-is-decorated"
|
||||
},
|
||||
{
|
||||
"description": "Enables the is_enabled command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-is-enabled"
|
||||
},
|
||||
{
|
||||
"description": "Enables the is_focused command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2802,6 +3077,21 @@
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-always-on-top"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_badge_count command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-badge-count"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_badge_label command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-badge-label"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_closable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2842,6 +3132,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-effects"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_enabled command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-enabled"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_focus command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2882,6 +3177,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-minimizable"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_overlay_icon command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-overlay-icon"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_position command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2917,6 +3217,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-skip-taskbar"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_theme command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-theme"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_title command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3042,6 +3347,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:deny-is-decorated"
|
||||
},
|
||||
{
|
||||
"description": "Denies the is_enabled command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-is-enabled"
|
||||
},
|
||||
{
|
||||
"description": "Denies the is_focused command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3132,6 +3442,21 @@
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-always-on-top"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_badge_count command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-badge-count"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_badge_label command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-badge-label"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_closable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3172,6 +3497,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-effects"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_enabled command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-enabled"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_focus command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3212,6 +3542,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-minimizable"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_overlay_icon command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-overlay-icon"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_position command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3247,6 +3582,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-skip-taskbar"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_theme command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-theme"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_title command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3358,7 +3698,7 @@
|
||||
"const": "dialog:deny-save"
|
||||
},
|
||||
{
|
||||
"description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n",
|
||||
"description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n#### Included permissions within this default permission set:\n",
|
||||
"type": "string",
|
||||
"const": "fs:default"
|
||||
},
|
||||
@@ -4202,6 +4542,11 @@
|
||||
"type": "string",
|
||||
"const": "fs:allow-seek"
|
||||
},
|
||||
{
|
||||
"description": "Enables the size command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "fs:allow-size"
|
||||
},
|
||||
{
|
||||
"description": "Enables the stat command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -4327,6 +4672,11 @@
|
||||
"type": "string",
|
||||
"const": "fs:deny-seek"
|
||||
},
|
||||
{
|
||||
"description": "Denies the size command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "fs:deny-size"
|
||||
},
|
||||
{
|
||||
"description": "Denies the stat command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -4802,6 +5152,46 @@
|
||||
"type": "string",
|
||||
"const": "log:deny-log"
|
||||
},
|
||||
{
|
||||
"description": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer",
|
||||
"type": "string",
|
||||
"const": "opener:default"
|
||||
},
|
||||
{
|
||||
"description": "This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-default-urls"
|
||||
},
|
||||
{
|
||||
"description": "Enables the open_path command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-open-path"
|
||||
},
|
||||
{
|
||||
"description": "Enables the open_url command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-open-url"
|
||||
},
|
||||
{
|
||||
"description": "Enables the reveal_item_in_dir command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-reveal-item-in-dir"
|
||||
},
|
||||
{
|
||||
"description": "Denies the open_path command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:deny-open-path"
|
||||
},
|
||||
{
|
||||
"description": "Denies the open_url command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:deny-open-url"
|
||||
},
|
||||
{
|
||||
"description": "Denies the reveal_item_in_dir command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:deny-reveal-item-in-dir"
|
||||
},
|
||||
{
|
||||
"description": "This permission set configures which\noperating system information are available\nto gather from the frontend.\n\n#### Granted Permissions\n\nAll information except the host name are available.\n\n",
|
||||
"type": "string",
|
||||
@@ -5021,6 +5411,76 @@
|
||||
"description": "Denies the save_window_state command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "window-state:deny-save-window-state"
|
||||
},
|
||||
{
|
||||
"description": "Default permissions for the plugin",
|
||||
"type": "string",
|
||||
"const": "yaak-license:default"
|
||||
},
|
||||
{
|
||||
"description": "Enables the activate command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-license:allow-activate"
|
||||
},
|
||||
{
|
||||
"description": "Enables the check command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-license:allow-check"
|
||||
},
|
||||
{
|
||||
"description": "Denies the activate command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-license:deny-activate"
|
||||
},
|
||||
{
|
||||
"description": "Denies the check command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-license:deny-check"
|
||||
},
|
||||
{
|
||||
"description": "Default permissions for the plugin",
|
||||
"type": "string",
|
||||
"const": "yaak-sync:default"
|
||||
},
|
||||
{
|
||||
"description": "Enables the apply command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-sync:allow-apply"
|
||||
},
|
||||
{
|
||||
"description": "Enables the calculate command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-sync:allow-calculate"
|
||||
},
|
||||
{
|
||||
"description": "Enables the calculate_fs command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-sync:allow-calculate-fs"
|
||||
},
|
||||
{
|
||||
"description": "Enables the watch command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-sync:allow-watch"
|
||||
},
|
||||
{
|
||||
"description": "Denies the apply command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-sync:deny-apply"
|
||||
},
|
||||
{
|
||||
"description": "Denies the calculate command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-sync:deny-calculate"
|
||||
},
|
||||
{
|
||||
"description": "Denies the calculate_fs command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-sync:deny-calculate-fs"
|
||||
},
|
||||
{
|
||||
"description": "Denies the watch command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-sync:deny-watch"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -5118,7 +5578,24 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"ShellAllowedArg": {
|
||||
"Application": {
|
||||
"description": "Opener scope application.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Open in default application.",
|
||||
"type": "null"
|
||||
},
|
||||
{
|
||||
"description": "If true, allow open with any application.",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"description": "Allow specific application to open with.",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ShellScopeEntryAllowedArg": {
|
||||
"description": "A command argument allowed to be executed by the webview API.",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -5146,18 +5623,18 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"ShellAllowedArgs": {
|
||||
"description": "A set of command arguments allowed to be executed by the webview API.\n\nA value of `true` will allow any arguments to be passed to the command. `false` will disable all arguments. A list of [`ShellAllowedArg`] will set those arguments as the only valid arguments to be passed to the attached command configuration.",
|
||||
"ShellScopeEntryAllowedArgs": {
|
||||
"description": "A set of command arguments allowed to be executed by the webview API.\n\nA value of `true` will allow any arguments to be passed to the command. `false` will disable all arguments. A list of [`ShellScopeEntryAllowedArg`] will set those arguments as the only valid arguments to be passed to the attached command configuration.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Use a simple boolean to allow all or disable all arguments to this command configuration.",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"description": "A specific set of [`ShellAllowedArg`] that are valid to call for the command configuration.",
|
||||
"description": "A specific set of [`ShellScopeEntryAllowedArg`] that are valid to call for the command configuration.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ShellAllowedArg"
|
||||
"$ref": "#/definitions/ShellScopeEntryAllowedArg"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
8172
src-tauri/gen/schemas/linux-schema.json
generated
8172
src-tauri/gen/schemas/linux-schema.json
generated
File diff suppressed because it is too large
Load Diff
615
src-tauri/gen/schemas/macOS-schema.json
generated
615
src-tauri/gen/schemas/macOS-schema.json
generated
@@ -37,7 +37,7 @@
|
||||
],
|
||||
"definitions": {
|
||||
"Capability": {
|
||||
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\nIt controls application windows fine grained access to the Tauri core, application, or plugin commands. If a window is not matching any capability then it has no access to the IPC layer at all.\n\nThis can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`. A Window can have none, one, or multiple associated capabilities.\n\n## Example\n\n```json { \"identifier\": \"main-user-files-write\", \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\", \"windows\": [ \"main\" ], \"permissions\": [ \"core:default\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] }, \"platforms\": [\"macOS\",\"windows\"] } ```",
|
||||
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\nIt controls application windows fine grained access to the Tauri core, application, or plugin commands. If a window is not matching any capability then it has no access to the IPC layer at all.\n\nThis can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`. A Window can have none, one, or multiple associated capabilities.\n\n## Example\n\n```json { \"identifier\": \"main-user-files-write\", \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\", \"windows\": [ \"main\" ], \"permissions\": [ \"core:default\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] }, ], \"platforms\": [\"macOS\",\"windows\"] } ```",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"identifier",
|
||||
@@ -84,7 +84,7 @@
|
||||
}
|
||||
},
|
||||
"permissions": {
|
||||
"description": "List of permissions attached to this capability.\n\nMust include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`. For commands directly implemented in the application itself only `${permission-name}` is required.\n\n## Example\n\n```json [ \"core:default\", \"shell:allow-open\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] } ```",
|
||||
"description": "List of permissions attached to this capability.\n\nMust include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`. For commands directly implemented in the application itself only `${permission-name}` is required.\n\n## Example\n\n```json [ \"core:default\", \"shell:allow-open\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] } ] ```",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PermissionEntry"
|
||||
@@ -140,7 +140,7 @@
|
||||
"identifier": {
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n",
|
||||
"description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n#### Included permissions within this default permission set:\n",
|
||||
"type": "string",
|
||||
"const": "fs:default"
|
||||
},
|
||||
@@ -984,6 +984,11 @@
|
||||
"type": "string",
|
||||
"const": "fs:allow-seek"
|
||||
},
|
||||
{
|
||||
"description": "Enables the size command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "fs:allow-size"
|
||||
},
|
||||
{
|
||||
"description": "Enables the stat command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -1109,6 +1114,11 @@
|
||||
"type": "string",
|
||||
"const": "fs:deny-seek"
|
||||
},
|
||||
{
|
||||
"description": "Denies the size command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "fs:deny-size"
|
||||
},
|
||||
{
|
||||
"description": "Denies the stat command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -1581,7 +1591,7 @@
|
||||
"description": "FS scope entry.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "FS scope path.",
|
||||
"description": "A path that can be accessed by the webview when using the fs APIs. FS scope path pattern.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
@@ -1591,7 +1601,7 @@
|
||||
],
|
||||
"properties": {
|
||||
"path": {
|
||||
"description": "FS scope path.",
|
||||
"description": "A path that can be accessed by the webview when using the fs APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@@ -1605,7 +1615,7 @@
|
||||
"description": "FS scope entry.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "FS scope path.",
|
||||
"description": "A path that can be accessed by the webview when using the fs APIs. FS scope path pattern.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
@@ -1615,7 +1625,167 @@
|
||||
],
|
||||
"properties": {
|
||||
"path": {
|
||||
"description": "FS scope path.",
|
||||
"description": "A path that can be accessed by the webview when using the fs APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"identifier": {
|
||||
"description": "Identifier of the permission or permission set.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Identifier"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"identifier": {
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer",
|
||||
"type": "string",
|
||||
"const": "opener:default"
|
||||
},
|
||||
{
|
||||
"description": "This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-default-urls"
|
||||
},
|
||||
{
|
||||
"description": "Enables the open_path command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-open-path"
|
||||
},
|
||||
{
|
||||
"description": "Enables the open_url command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-open-url"
|
||||
},
|
||||
{
|
||||
"description": "Enables the reveal_item_in_dir command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-reveal-item-in-dir"
|
||||
},
|
||||
{
|
||||
"description": "Denies the open_path command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:deny-open-path"
|
||||
},
|
||||
{
|
||||
"description": "Denies the open_url command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:deny-open-url"
|
||||
},
|
||||
{
|
||||
"description": "Denies the reveal_item_in_dir command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:deny-reveal-item-in-dir"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"allow": {
|
||||
"items": {
|
||||
"title": "OpenerScopeEntry",
|
||||
"description": "Opener scope entry.",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"properties": {
|
||||
"app": {
|
||||
"description": "An application to open this url with, for example: firefox.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Application"
|
||||
}
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"description": "A URL that can be opened by the webview when using the Opener APIs.\n\nWildcards can be used following the UNIX glob pattern.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
"app": {
|
||||
"description": "An application to open this path with, for example: xdg-open.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Application"
|
||||
}
|
||||
]
|
||||
},
|
||||
"path": {
|
||||
"description": "A path that can be opened by the webview when using the Opener APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"deny": {
|
||||
"items": {
|
||||
"title": "OpenerScopeEntry",
|
||||
"description": "Opener scope entry.",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"properties": {
|
||||
"app": {
|
||||
"description": "An application to open this url with, for example: firefox.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Application"
|
||||
}
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"description": "A URL that can be opened by the webview when using the Opener APIs.\n\nWildcards can be used following the UNIX glob pattern.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
"app": {
|
||||
"description": "An application to open this path with, for example: xdg-open.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Application"
|
||||
}
|
||||
]
|
||||
},
|
||||
"path": {
|
||||
"description": "A path that can be opened by the webview when using the Opener APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@@ -1704,72 +1874,122 @@
|
||||
"properties": {
|
||||
"allow": {
|
||||
"items": {
|
||||
"title": "Entry",
|
||||
"description": "A command allowed to be executed by the webview API.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"args",
|
||||
"cmd",
|
||||
"name",
|
||||
"sidecar"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ShellAllowedArgs"
|
||||
"title": "ShellScopeEntry",
|
||||
"description": "Shell scope entry.",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"cmd",
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ShellScopeEntryAllowedArgs"
|
||||
}
|
||||
]
|
||||
},
|
||||
"cmd": {
|
||||
"description": "The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"cmd": {
|
||||
"description": "The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.",
|
||||
"type": "string"
|
||||
},
|
||||
"sidecar": {
|
||||
"description": "If this command is a sidecar command.",
|
||||
"type": "boolean"
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"sidecar"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ShellScopeEntryAllowedArgs"
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.",
|
||||
"type": "string"
|
||||
},
|
||||
"sidecar": {
|
||||
"description": "If this command is a sidecar command.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"deny": {
|
||||
"items": {
|
||||
"title": "Entry",
|
||||
"description": "A command allowed to be executed by the webview API.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"args",
|
||||
"cmd",
|
||||
"name",
|
||||
"sidecar"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ShellAllowedArgs"
|
||||
"title": "ShellScopeEntry",
|
||||
"description": "Shell scope entry.",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"cmd",
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ShellScopeEntryAllowedArgs"
|
||||
}
|
||||
]
|
||||
},
|
||||
"cmd": {
|
||||
"description": "The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"cmd": {
|
||||
"description": "The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.",
|
||||
"type": "string"
|
||||
},
|
||||
"sidecar": {
|
||||
"description": "If this command is a sidecar command.",
|
||||
"type": "boolean"
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"sidecar"
|
||||
],
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "The allowed arguments for the command execution.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ShellScopeEntryAllowedArgs"
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.",
|
||||
"type": "string"
|
||||
},
|
||||
"sidecar": {
|
||||
"description": "If this command is a sidecar command.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1922,6 +2142,11 @@
|
||||
"type": "string",
|
||||
"const": "core:app:allow-name"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_app_theme command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:app:allow-set-app-theme"
|
||||
},
|
||||
{
|
||||
"description": "Enables the tauri_version command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -1952,6 +2177,11 @@
|
||||
"type": "string",
|
||||
"const": "core:app:deny-name"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_app_theme command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:app:deny-set-app-theme"
|
||||
},
|
||||
{
|
||||
"description": "Denies the tauri_version command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2507,6 +2737,11 @@
|
||||
"type": "string",
|
||||
"const": "core:webview:default"
|
||||
},
|
||||
{
|
||||
"description": "Enables the clear_all_browsing_data command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-clear-all-browsing-data"
|
||||
},
|
||||
{
|
||||
"description": "Enables the create_webview command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2537,6 +2772,11 @@
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-reparent"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_webview_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-set-webview-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_webview_focus command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2562,16 +2802,31 @@
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-webview-close"
|
||||
},
|
||||
{
|
||||
"description": "Enables the webview_hide command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-webview-hide"
|
||||
},
|
||||
{
|
||||
"description": "Enables the webview_position command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-webview-position"
|
||||
},
|
||||
{
|
||||
"description": "Enables the webview_show command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-webview-show"
|
||||
},
|
||||
{
|
||||
"description": "Enables the webview_size command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:allow-webview-size"
|
||||
},
|
||||
{
|
||||
"description": "Denies the clear_all_browsing_data command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-clear-all-browsing-data"
|
||||
},
|
||||
{
|
||||
"description": "Denies the create_webview command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2602,6 +2857,11 @@
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-reparent"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_webview_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-set-webview-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_webview_focus command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2627,11 +2887,21 @@
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-webview-close"
|
||||
},
|
||||
{
|
||||
"description": "Denies the webview_hide command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-webview-hide"
|
||||
},
|
||||
{
|
||||
"description": "Denies the webview_position command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-webview-position"
|
||||
},
|
||||
{
|
||||
"description": "Denies the webview_show command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:webview:deny-webview-show"
|
||||
},
|
||||
{
|
||||
"description": "Denies the webview_size command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2712,6 +2982,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:allow-is-decorated"
|
||||
},
|
||||
{
|
||||
"description": "Enables the is_enabled command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-is-enabled"
|
||||
},
|
||||
{
|
||||
"description": "Enables the is_focused command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2802,6 +3077,21 @@
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-always-on-top"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_badge_count command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-badge-count"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_badge_label command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-badge-label"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_closable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2842,6 +3132,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-effects"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_enabled command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-enabled"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_focus command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2882,6 +3177,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-minimizable"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_overlay_icon command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-overlay-icon"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_position command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -2917,6 +3217,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-skip-taskbar"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_theme command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:allow-set-theme"
|
||||
},
|
||||
{
|
||||
"description": "Enables the set_title command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3042,6 +3347,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:deny-is-decorated"
|
||||
},
|
||||
{
|
||||
"description": "Denies the is_enabled command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-is-enabled"
|
||||
},
|
||||
{
|
||||
"description": "Denies the is_focused command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3132,6 +3442,21 @@
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-always-on-top"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_background_color command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-background-color"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_badge_count command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-badge-count"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_badge_label command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-badge-label"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_closable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3172,6 +3497,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-effects"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_enabled command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-enabled"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_focus command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3212,6 +3542,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-minimizable"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_overlay_icon command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-overlay-icon"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_position command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3247,6 +3582,11 @@
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-skip-taskbar"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_theme command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "core:window:deny-set-theme"
|
||||
},
|
||||
{
|
||||
"description": "Denies the set_title command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -3358,7 +3698,7 @@
|
||||
"const": "dialog:deny-save"
|
||||
},
|
||||
{
|
||||
"description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n",
|
||||
"description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n#### Included permissions within this default permission set:\n",
|
||||
"type": "string",
|
||||
"const": "fs:default"
|
||||
},
|
||||
@@ -4202,6 +4542,11 @@
|
||||
"type": "string",
|
||||
"const": "fs:allow-seek"
|
||||
},
|
||||
{
|
||||
"description": "Enables the size command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "fs:allow-size"
|
||||
},
|
||||
{
|
||||
"description": "Enables the stat command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -4327,6 +4672,11 @@
|
||||
"type": "string",
|
||||
"const": "fs:deny-seek"
|
||||
},
|
||||
{
|
||||
"description": "Denies the size command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "fs:deny-size"
|
||||
},
|
||||
{
|
||||
"description": "Denies the stat command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
@@ -4802,6 +5152,46 @@
|
||||
"type": "string",
|
||||
"const": "log:deny-log"
|
||||
},
|
||||
{
|
||||
"description": "This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer",
|
||||
"type": "string",
|
||||
"const": "opener:default"
|
||||
},
|
||||
{
|
||||
"description": "This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-default-urls"
|
||||
},
|
||||
{
|
||||
"description": "Enables the open_path command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-open-path"
|
||||
},
|
||||
{
|
||||
"description": "Enables the open_url command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-open-url"
|
||||
},
|
||||
{
|
||||
"description": "Enables the reveal_item_in_dir command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:allow-reveal-item-in-dir"
|
||||
},
|
||||
{
|
||||
"description": "Denies the open_path command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:deny-open-path"
|
||||
},
|
||||
{
|
||||
"description": "Denies the open_url command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:deny-open-url"
|
||||
},
|
||||
{
|
||||
"description": "Denies the reveal_item_in_dir command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "opener:deny-reveal-item-in-dir"
|
||||
},
|
||||
{
|
||||
"description": "This permission set configures which\noperating system information are available\nto gather from the frontend.\n\n#### Granted Permissions\n\nAll information except the host name are available.\n\n",
|
||||
"type": "string",
|
||||
@@ -5021,6 +5411,76 @@
|
||||
"description": "Denies the save_window_state command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "window-state:deny-save-window-state"
|
||||
},
|
||||
{
|
||||
"description": "Default permissions for the plugin",
|
||||
"type": "string",
|
||||
"const": "yaak-license:default"
|
||||
},
|
||||
{
|
||||
"description": "Enables the activate command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-license:allow-activate"
|
||||
},
|
||||
{
|
||||
"description": "Enables the check command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-license:allow-check"
|
||||
},
|
||||
{
|
||||
"description": "Denies the activate command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-license:deny-activate"
|
||||
},
|
||||
{
|
||||
"description": "Denies the check command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-license:deny-check"
|
||||
},
|
||||
{
|
||||
"description": "Default permissions for the plugin",
|
||||
"type": "string",
|
||||
"const": "yaak-sync:default"
|
||||
},
|
||||
{
|
||||
"description": "Enables the apply command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-sync:allow-apply"
|
||||
},
|
||||
{
|
||||
"description": "Enables the calculate command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-sync:allow-calculate"
|
||||
},
|
||||
{
|
||||
"description": "Enables the calculate_fs command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-sync:allow-calculate-fs"
|
||||
},
|
||||
{
|
||||
"description": "Enables the watch command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-sync:allow-watch"
|
||||
},
|
||||
{
|
||||
"description": "Denies the apply command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-sync:deny-apply"
|
||||
},
|
||||
{
|
||||
"description": "Denies the calculate command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-sync:deny-calculate"
|
||||
},
|
||||
{
|
||||
"description": "Denies the calculate_fs command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-sync:deny-calculate-fs"
|
||||
},
|
||||
{
|
||||
"description": "Denies the watch command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"const": "yaak-sync:deny-watch"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -5118,7 +5578,24 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"ShellAllowedArg": {
|
||||
"Application": {
|
||||
"description": "Opener scope application.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Open in default application.",
|
||||
"type": "null"
|
||||
},
|
||||
{
|
||||
"description": "If true, allow open with any application.",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"description": "Allow specific application to open with.",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ShellScopeEntryAllowedArg": {
|
||||
"description": "A command argument allowed to be executed by the webview API.",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -5146,18 +5623,18 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"ShellAllowedArgs": {
|
||||
"description": "A set of command arguments allowed to be executed by the webview API.\n\nA value of `true` will allow any arguments to be passed to the command. `false` will disable all arguments. A list of [`ShellAllowedArg`] will set those arguments as the only valid arguments to be passed to the attached command configuration.",
|
||||
"ShellScopeEntryAllowedArgs": {
|
||||
"description": "A set of command arguments allowed to be executed by the webview API.\n\nA value of `true` will allow any arguments to be passed to the command. `false` will disable all arguments. A list of [`ShellScopeEntryAllowedArg`] will set those arguments as the only valid arguments to be passed to the attached command configuration.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Use a simple boolean to allow all or disable all arguments to this command configuration.",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"description": "A specific set of [`ShellAllowedArg`] that are valid to call for the command configuration.",
|
||||
"description": "A specific set of [`ShellScopeEntryAllowedArg`] that are valid to call for the command configuration.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ShellAllowedArg"
|
||||
"$ref": "#/definitions/ShellScopeEntryAllowedArg"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
5
src-tauri/migrations/20241003134208_response-state.sql
Normal file
5
src-tauri/migrations/20241003134208_response-state.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
ALTER TABLE http_responses
|
||||
ADD COLUMN state TEXT DEFAULT 'closed' NOT NULL;
|
||||
|
||||
ALTER TABLE grpc_connections
|
||||
ADD COLUMN state TEXT DEFAULT 'closed' NOT NULL;
|
||||
1
src-tauri/migrations/20241012181547_proxy-setting.sql
Normal file
1
src-tauri/migrations/20241012181547_proxy-setting.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE settings ADD COLUMN proxy TEXT;
|
||||
8
src-tauri/migrations/20241217204951_docs.sql
Normal file
8
src-tauri/migrations/20241217204951_docs.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
ALTER TABLE http_requests
|
||||
ADD COLUMN description TEXT DEFAULT '' NOT NULL;
|
||||
|
||||
ALTER TABLE grpc_requests
|
||||
ADD COLUMN description TEXT DEFAULT '' NOT NULL;
|
||||
|
||||
ALTER TABLE folders
|
||||
ADD COLUMN description TEXT DEFAULT '' NOT NULL;
|
||||
45
src-tauri/migrations/20241219140051_base-environments.sql
Normal file
45
src-tauri/migrations/20241219140051_base-environments.sql
Normal file
@@ -0,0 +1,45 @@
|
||||
-- Add the new field
|
||||
ALTER TABLE environments
|
||||
ADD COLUMN environment_id TEXT REFERENCES environments (id) ON DELETE CASCADE;
|
||||
|
||||
-- Create temporary column so we know which rows are meant to be base environments. We'll use this to update
|
||||
-- child environments to point to them.
|
||||
ALTER TABLE environments
|
||||
ADD COLUMN migrated_base_env BOOLEAN DEFAULT FALSE NOT NULL;
|
||||
|
||||
-- Create a base environment for each workspace
|
||||
INSERT INTO environments (id, workspace_id, name, variables, migrated_base_env)
|
||||
SELECT (
|
||||
-- This is the best way to generate a random string in SQLite, apparently
|
||||
'ev_' || SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) ||
|
||||
SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) ||
|
||||
SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) ||
|
||||
SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) ||
|
||||
SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) ||
|
||||
SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) ||
|
||||
SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) ||
|
||||
SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) ||
|
||||
SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) ||
|
||||
SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1)
|
||||
),
|
||||
workspaces.id,
|
||||
'Global Variables',
|
||||
variables,
|
||||
TRUE
|
||||
FROM workspaces;
|
||||
|
||||
-- Update all non-base environments to point to newly created base environments
|
||||
UPDATE environments
|
||||
SET environment_id = ( SELECT base_env.id
|
||||
FROM environments AS base_env
|
||||
WHERE base_env.workspace_id = environments.workspace_id
|
||||
AND base_env.migrated_base_env IS TRUE )
|
||||
WHERE migrated_base_env IS FALSE;
|
||||
|
||||
-- Drop temporary column
|
||||
ALTER TABLE environments
|
||||
DROP COLUMN migrated_base_env;
|
||||
|
||||
-- Drop the old variables column
|
||||
-- IMPORTANT: Skip to give the user the option to roll back to a previous app version. We can drop it once the migration working in the real world
|
||||
-- ALTER TABLE workspaces DROP COLUMN variables;
|
||||
21
src-tauri/migrations/20250102141937_sync.sql
Normal file
21
src-tauri/migrations/20250102141937_sync.sql
Normal file
@@ -0,0 +1,21 @@
|
||||
ALTER TABLE workspaces
|
||||
ADD COLUMN setting_sync_dir TEXT;
|
||||
|
||||
CREATE TABLE sync_states
|
||||
(
|
||||
id TEXT NOT NULL
|
||||
PRIMARY KEY,
|
||||
model TEXT DEFAULT 'sync_state' NOT NULL,
|
||||
workspace_id TEXT NOT NULL
|
||||
REFERENCES workspaces
|
||||
ON DELETE CASCADE,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
flushed_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
checksum TEXT NOT NULL,
|
||||
model_id TEXT NOT NULL,
|
||||
sync_dir TEXT NOT NULL,
|
||||
rel_path TEXT NOT NULL,
|
||||
|
||||
UNIQUE (workspace_id, model_id)
|
||||
);
|
||||
2
src-tauri/migrations/20250108035425_editor-keymap.sql
Normal file
2
src-tauri/migrations/20250108035425_editor-keymap.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN editor_keymap TEXT DEFAULT 'codemirror' NOT NULL;
|
||||
11
src-tauri/migrations/20250108205117_workspace-meta.sql
Normal file
11
src-tauri/migrations/20250108205117_workspace-meta.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
CREATE TABLE workspace_metas
|
||||
(
|
||||
id TEXT NOT NULL
|
||||
PRIMARY KEY,
|
||||
model TEXT DEFAULT 'workspace_meta' NOT NULL,
|
||||
workspace_id TEXT NOT NULL
|
||||
REFERENCES workspaces ON DELETE CASCADE,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
setting_sync_dir TEXT
|
||||
);
|
||||
@@ -4,8 +4,11 @@ use log::{debug, info};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Value};
|
||||
use tauri::{Manager, Runtime, WebviewWindow};
|
||||
|
||||
use yaak_models::queries::{generate_id, get_key_value_int, get_key_value_string, get_or_create_settings, set_key_value_int, set_key_value_string};
|
||||
use ts_rs::TS;
|
||||
use yaak_models::queries::{
|
||||
generate_id, get_key_value_int, get_key_value_string, get_or_create_settings,
|
||||
set_key_value_int, set_key_value_string, UpdateSource,
|
||||
};
|
||||
|
||||
use crate::is_dev;
|
||||
|
||||
@@ -13,11 +16,14 @@ const NAMESPACE: &str = "analytics";
|
||||
const NUM_LAUNCHES_KEY: &str = "num_launches";
|
||||
|
||||
// serializable
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Serialize, Deserialize, Debug, TS)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[ts(export, export_to = "analytics.ts")]
|
||||
pub enum AnalyticsResource {
|
||||
App,
|
||||
Appearance,
|
||||
Button,
|
||||
Checkbox,
|
||||
CookieJar,
|
||||
Dialog,
|
||||
Environment,
|
||||
@@ -27,10 +33,13 @@ pub enum AnalyticsResource {
|
||||
GrpcRequest,
|
||||
HttpRequest,
|
||||
HttpResponse,
|
||||
Link,
|
||||
KeyValue,
|
||||
Plugin,
|
||||
Select,
|
||||
Setting,
|
||||
Sidebar,
|
||||
Tab,
|
||||
Theme,
|
||||
Workspace,
|
||||
}
|
||||
@@ -43,18 +52,16 @@ impl AnalyticsResource {
|
||||
|
||||
impl Display for AnalyticsResource {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
serde_json::to_string(self).unwrap().replace("\"", "")
|
||||
)
|
||||
write!(f, "{}", serde_json::to_string(self).unwrap().replace("\"", ""))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Serialize, Deserialize, Debug, TS)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[ts(export, export_to = "analytics.ts")]
|
||||
pub enum AnalyticsAction {
|
||||
Cancel,
|
||||
Click,
|
||||
Commit,
|
||||
Create,
|
||||
Delete,
|
||||
@@ -81,11 +88,7 @@ impl AnalyticsAction {
|
||||
|
||||
impl Display for AnalyticsAction {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
serde_json::to_string(self).unwrap().replace("\"", "")
|
||||
)
|
||||
write!(f, "{}", serde_json::to_string(self).unwrap().replace("\"", ""))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,13 +110,7 @@ pub async fn track_launch_event<R: Runtime>(w: &WebviewWindow<R>) -> LaunchEvent
|
||||
info.current_version = w.package_info().version.to_string();
|
||||
|
||||
if info.previous_version.is_empty() {
|
||||
track_event(
|
||||
w,
|
||||
AnalyticsResource::App,
|
||||
AnalyticsAction::LaunchFirst,
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
track_event(w, AnalyticsResource::App, AnalyticsAction::LaunchFirst, None).await;
|
||||
} else {
|
||||
info.launched_after_update = info.current_version != info.previous_version;
|
||||
if info.launched_after_update {
|
||||
@@ -143,9 +140,11 @@ pub async fn track_launch_event<R: Runtime>(w: &WebviewWindow<R>) -> LaunchEvent
|
||||
NAMESPACE,
|
||||
last_tracked_version_key,
|
||||
info.current_version.as_str(),
|
||||
&UpdateSource::Background,
|
||||
)
|
||||
.await;
|
||||
set_key_value_int(w, NAMESPACE, NUM_LAUNCHES_KEY, info.num_launches).await;
|
||||
set_key_value_int(w, NAMESPACE, NUM_LAUNCHES_KEY, info.num_launches, &UpdateSource::Background)
|
||||
.await;
|
||||
|
||||
info
|
||||
}
|
||||
@@ -156,7 +155,6 @@ pub async fn track_event<R: Runtime>(
|
||||
action: AnalyticsAction,
|
||||
attributes: Option<Value>,
|
||||
) {
|
||||
|
||||
let id = get_id(w).await;
|
||||
let event = format!("{}.{}", resource, action);
|
||||
let attributes_json = attributes.unwrap_or("{}".to_string().into()).to_string();
|
||||
@@ -180,16 +178,13 @@ pub async fn track_event<R: Runtime>(
|
||||
("tz", tz),
|
||||
("xy", get_window_size(w)),
|
||||
];
|
||||
let req = reqwest::Client::builder()
|
||||
.build()
|
||||
.unwrap()
|
||||
.get(format!("{base_url}/t/e"))
|
||||
.query(¶ms);
|
||||
let req =
|
||||
reqwest::Client::builder().build().unwrap().get(format!("{base_url}/t/e")).query(¶ms);
|
||||
|
||||
let settings = get_or_create_settings(w).await;
|
||||
if !settings.telemetry {
|
||||
info!("Track event (disabled): {}", event);
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable analytics actual sending in dev
|
||||
@@ -226,18 +221,15 @@ fn get_window_size<R: Runtime>(w: &WebviewWindow<R>) -> String {
|
||||
let width: f64 = size.width as f64 / scale_factor;
|
||||
let height: f64 = size.height as f64 / scale_factor;
|
||||
|
||||
format!(
|
||||
"{}x{}",
|
||||
(width / 100.0).round() * 100.0,
|
||||
(height / 100.0).round() * 100.0
|
||||
)
|
||||
format!("{}x{}", (width / 100.0).round() * 100.0, (height / 100.0).round() * 100.0)
|
||||
}
|
||||
|
||||
async fn get_id<R: Runtime>(w: &WebviewWindow<R>) -> String {
|
||||
let id = get_key_value_string(w, "analytics", "id", "").await;
|
||||
if id.is_empty() {
|
||||
let new_id = generate_id();
|
||||
set_key_value_string(w, "analytics", "id", new_id.as_str()).await;
|
||||
set_key_value_string(w, "analytics", "id", new_id.as_str(), &UpdateSource::Background)
|
||||
.await;
|
||||
new_id
|
||||
} else {
|
||||
id
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
use chrono::NaiveDateTime;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tauri::{Manager, WebviewWindow};
|
||||
use yaak_models::models::{Environment, Folder, GrpcRequest, HttpRequest, Workspace};
|
||||
|
||||
#[derive(Default, Debug, Deserialize, Serialize)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
pub struct WorkspaceExport {
|
||||
pub yaak_version: String,
|
||||
pub yaak_schema: i64,
|
||||
pub timestamp: NaiveDateTime,
|
||||
pub resources: WorkspaceExportResources,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Deserialize, Serialize)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
pub struct WorkspaceExportResources {
|
||||
pub workspaces: Vec<Workspace>,
|
||||
pub environments: Vec<Environment>,
|
||||
pub folders: Vec<Folder>,
|
||||
pub http_requests: Vec<HttpRequest>,
|
||||
pub grpc_requests: Vec<GrpcRequest>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Deserialize, Serialize)]
|
||||
pub struct ImportResult {
|
||||
pub resources: WorkspaceExportResources,
|
||||
}
|
||||
|
||||
pub async fn get_workspace_export_resources(
|
||||
window: &WebviewWindow,
|
||||
workspace_ids: Vec<&str>,
|
||||
) -> WorkspaceExport {
|
||||
let app_handle = window.app_handle();
|
||||
let mut data = WorkspaceExport {
|
||||
yaak_version: app_handle.package_info().version.clone().to_string(),
|
||||
yaak_schema: 2,
|
||||
timestamp: chrono::Utc::now().naive_utc(),
|
||||
resources: WorkspaceExportResources {
|
||||
workspaces: Vec::new(),
|
||||
environments: Vec::new(),
|
||||
folders: Vec::new(),
|
||||
http_requests: Vec::new(),
|
||||
grpc_requests: Vec::new(),
|
||||
},
|
||||
};
|
||||
|
||||
for workspace_id in workspace_ids {
|
||||
data.resources.workspaces.push(
|
||||
yaak_models::queries::get_workspace(window, workspace_id)
|
||||
.await
|
||||
.expect("Failed to get workspace"),
|
||||
);
|
||||
data.resources.environments.append(
|
||||
&mut yaak_models::queries::list_environments(window, workspace_id)
|
||||
.await
|
||||
.expect("Failed to get environments"),
|
||||
);
|
||||
data.resources.folders.append(
|
||||
&mut yaak_models::queries::list_folders(window, workspace_id)
|
||||
.await
|
||||
.expect("Failed to get folders"),
|
||||
);
|
||||
data.resources.http_requests.append(
|
||||
&mut yaak_models::queries::list_http_requests(window, workspace_id)
|
||||
.await
|
||||
.expect("Failed to get http requests"),
|
||||
);
|
||||
data.resources.grpc_requests.append(
|
||||
&mut yaak_models::queries::list_grpc_requests(window, workspace_id)
|
||||
.await
|
||||
.expect("Failed to get grpc requests"),
|
||||
);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -1,12 +1,3 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs;
|
||||
use std::fs::{create_dir_all, File};
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::render::render_http_request;
|
||||
use crate::response_err;
|
||||
use crate::template_callback::PluginTemplateCallback;
|
||||
@@ -14,35 +5,60 @@ use base64::prelude::BASE64_STANDARD;
|
||||
use base64::Engine;
|
||||
use http::header::{ACCEPT, USER_AGENT};
|
||||
use http::{HeaderMap, HeaderName, HeaderValue};
|
||||
use log::{error, warn};
|
||||
use log::{debug, error, warn};
|
||||
use mime_guess::Mime;
|
||||
use reqwest::redirect::Policy;
|
||||
use reqwest::Method;
|
||||
use reqwest::{multipart, Url};
|
||||
use reqwest::{multipart, Proxy, Url};
|
||||
use reqwest::{Method, Response};
|
||||
use rustls::ClientConfig;
|
||||
use rustls_platform_verifier::ConfigVerifierExt;
|
||||
use serde_json::Value;
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tauri::{Manager, Runtime, WebviewWindow};
|
||||
use tokio::sync::oneshot;
|
||||
use tokio::fs;
|
||||
use tokio::fs::{create_dir_all, File};
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::sync::watch::Receiver;
|
||||
use tokio::sync::{oneshot, Mutex};
|
||||
use yaak_models::models::{
|
||||
Cookie, CookieJar, Environment, HttpRequest, HttpResponse, HttpResponseHeader, HttpUrlParameter,
|
||||
Cookie, CookieJar, Environment, HttpRequest, HttpResponse, HttpResponseHeader,
|
||||
HttpResponseState, ProxySetting, ProxySettingAuth,
|
||||
};
|
||||
use yaak_models::queries::{get_workspace, update_response_if_id, upsert_cookie_jar};
|
||||
use yaak_models::queries::{
|
||||
get_base_environment, get_http_response, get_or_create_settings, get_workspace,
|
||||
update_response_if_id, upsert_cookie_jar, UpdateSource,
|
||||
};
|
||||
use yaak_plugins::events::{RenderPurpose, WindowContext};
|
||||
|
||||
pub async fn send_http_request<R: Runtime>(
|
||||
window: &WebviewWindow<R>,
|
||||
request: &HttpRequest,
|
||||
response: &HttpResponse,
|
||||
og_response: &HttpResponse,
|
||||
environment: Option<Environment>,
|
||||
cookie_jar: Option<CookieJar>,
|
||||
cancel_rx: &mut Receiver<bool>,
|
||||
cancelled_rx: &mut Receiver<bool>,
|
||||
) -> Result<HttpResponse, String> {
|
||||
let workspace = get_workspace(window, &request.workspace_id)
|
||||
let workspace =
|
||||
get_workspace(window, &request.workspace_id).await.expect("Failed to get Workspace");
|
||||
let base_environment = get_base_environment(window, &request.workspace_id)
|
||||
.await
|
||||
.expect("Failed to get Workspace");
|
||||
let cb = &*window.app_handle().state::<PluginTemplateCallback>();
|
||||
let cb = cb.for_send();
|
||||
.expect("Failed to get base environment");
|
||||
let settings = get_or_create_settings(window).await;
|
||||
let cb = PluginTemplateCallback::new(
|
||||
window.app_handle(),
|
||||
&WindowContext::from_window(window),
|
||||
RenderPurpose::Send,
|
||||
);
|
||||
|
||||
let response_id = og_response.id.clone();
|
||||
let response = Arc::new(Mutex::new(og_response.clone()));
|
||||
|
||||
let rendered_request =
|
||||
render_http_request(&request, &workspace, environment.as_ref(), &cb).await;
|
||||
render_http_request(&request, &base_environment, environment.as_ref(), &cb).await;
|
||||
|
||||
let mut url_string = rendered_request.url;
|
||||
|
||||
@@ -50,6 +66,7 @@ pub async fn send_http_request<R: Runtime>(
|
||||
if !url_string.starts_with("http://") && !url_string.starts_with("https://") {
|
||||
url_string = format!("http://{}", url_string);
|
||||
}
|
||||
debug!("Sending request to {url_string}");
|
||||
|
||||
let mut client_builder = reqwest::Client::builder()
|
||||
.redirect(match workspace.setting_follow_redirects {
|
||||
@@ -61,9 +78,46 @@ pub async fn send_http_request<R: Runtime>(
|
||||
.brotli(true)
|
||||
.deflate(true)
|
||||
.referer(false)
|
||||
.danger_accept_invalid_certs(!workspace.setting_validate_certificates)
|
||||
.tls_info(true);
|
||||
|
||||
if workspace.setting_validate_certificates {
|
||||
// Use platform-native verifier to validate certificates
|
||||
client_builder =
|
||||
client_builder.use_preconfigured_tls(ClientConfig::with_platform_verifier())
|
||||
} else {
|
||||
// Use rustls to skip validation because rustls_platform_verifier does not have this
|
||||
// ability
|
||||
client_builder = client_builder
|
||||
.use_rustls_tls()
|
||||
.danger_accept_invalid_hostnames(true)
|
||||
.danger_accept_invalid_certs(true);
|
||||
}
|
||||
|
||||
match settings.proxy {
|
||||
Some(ProxySetting::Disabled) => client_builder = client_builder.no_proxy(),
|
||||
Some(ProxySetting::Enabled { http, https, auth }) => {
|
||||
debug!("Using proxy http={http} https={https}");
|
||||
let mut proxy = Proxy::custom(move |url| {
|
||||
let http = if http.is_empty() { None } else { Some(http.to_owned()) };
|
||||
let https = if https.is_empty() { None } else { Some(https.to_owned()) };
|
||||
let proxy_url = match (url.scheme(), http, https) {
|
||||
("http", Some(proxy_url), _) => Some(proxy_url),
|
||||
("https", _, Some(proxy_url)) => Some(proxy_url),
|
||||
_ => None,
|
||||
};
|
||||
proxy_url
|
||||
});
|
||||
|
||||
if let Some(ProxySettingAuth { user, password }) = auth {
|
||||
debug!("Using proxy auth");
|
||||
proxy = proxy.basic_auth(user.as_str(), password.as_str());
|
||||
}
|
||||
|
||||
client_builder = client_builder.proxy(proxy);
|
||||
}
|
||||
None => {} // Nothing to do for this one, as it is the default
|
||||
}
|
||||
|
||||
// Add cookie store if specified
|
||||
let maybe_cookie_manager = match cookie_jar.clone() {
|
||||
Some(cj) => {
|
||||
@@ -103,38 +157,30 @@ pub async fn send_http_request<R: Runtime>(
|
||||
if !p.enabled || p.name.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Replace path parameters with values from URL parameters
|
||||
let old_url_string = url_string.clone();
|
||||
url_string = replace_path_placeholder(&p, url_string.as_str());
|
||||
|
||||
// Treat as regular param if wasn't used as path param
|
||||
if old_url_string == url_string {
|
||||
query_params.push((p.name, p.value));
|
||||
}
|
||||
query_params.push((p.name, p.value));
|
||||
}
|
||||
|
||||
let uri = match http::Uri::from_str(url_string.as_str()) {
|
||||
Ok(u) => u,
|
||||
Err(e) => {
|
||||
return response_err(
|
||||
response,
|
||||
return Ok(response_err(
|
||||
&*response.lock().await,
|
||||
format!("Failed to parse URL \"{}\": {}", url_string, e.to_string()),
|
||||
window,
|
||||
)
|
||||
.await;
|
||||
.await);
|
||||
}
|
||||
};
|
||||
// Yes, we're parsing both URI and URL because they could return different errors
|
||||
let url = match Url::from_str(uri.to_string().as_str()) {
|
||||
Ok(u) => u,
|
||||
Err(e) => {
|
||||
return response_err(
|
||||
response,
|
||||
return Ok(response_err(
|
||||
&*response.lock().await,
|
||||
format!("Failed to parse URL \"{}\": {}", url_string, e.to_string()),
|
||||
window,
|
||||
)
|
||||
.await;
|
||||
.await);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -193,16 +239,8 @@ pub async fn send_http_request<R: Runtime>(
|
||||
let a = rendered_request.authentication;
|
||||
|
||||
if b == "basic" {
|
||||
let username = a
|
||||
.get("username")
|
||||
.unwrap_or(empty_value)
|
||||
.as_str()
|
||||
.unwrap_or_default();
|
||||
let password = a
|
||||
.get("password")
|
||||
.unwrap_or(empty_value)
|
||||
.as_str()
|
||||
.unwrap_or_default();
|
||||
let username = a.get("username").unwrap_or(empty_value).as_str().unwrap_or_default();
|
||||
let password = a.get("password").unwrap_or(empty_value).as_str().unwrap_or_default();
|
||||
|
||||
let auth = format!("{username}:{password}");
|
||||
let encoded = BASE64_STANDARD.encode(auth);
|
||||
@@ -211,11 +249,7 @@ pub async fn send_http_request<R: Runtime>(
|
||||
HeaderValue::from_str(&format!("Basic {}", encoded)).unwrap(),
|
||||
);
|
||||
} else if b == "bearer" {
|
||||
let token = a
|
||||
.get("token")
|
||||
.unwrap_or(empty_value)
|
||||
.as_str()
|
||||
.unwrap_or_default();
|
||||
let token = a.get("token").unwrap_or(empty_value).as_str().unwrap_or_default();
|
||||
headers.insert(
|
||||
"Authorization",
|
||||
HeaderValue::from_str(&format!("Bearer {token}")).unwrap(),
|
||||
@@ -225,14 +259,11 @@ pub async fn send_http_request<R: Runtime>(
|
||||
|
||||
let request_body = rendered_request.body;
|
||||
if let Some(body_type) = &rendered_request.body_type {
|
||||
if request_body.contains_key("query") && request_body.contains_key("variables") {
|
||||
if body_type == "graphql" {
|
||||
let query = get_str_h(&request_body, "query");
|
||||
let variables = get_str_h(&request_body, "variables");
|
||||
let body = if variables.trim().is_empty() {
|
||||
format!(
|
||||
r#"{{"query":{}}}"#,
|
||||
serde_json::to_string(query).unwrap_or_default()
|
||||
)
|
||||
format!(r#"{{"query":{}}}"#, serde_json::to_string(query).unwrap_or_default())
|
||||
} else {
|
||||
format!(
|
||||
r#"{{"query":{},"variables":{variables}}}"#,
|
||||
@@ -240,9 +271,6 @@ pub async fn send_http_request<R: Runtime>(
|
||||
)
|
||||
};
|
||||
request_builder = request_builder.body(body.to_owned());
|
||||
} else if request_body.contains_key("text") {
|
||||
let body = get_str_h(&request_body, "text");
|
||||
request_builder = request_builder.body(body.to_owned());
|
||||
} else if body_type == "application/x-www-form-urlencoded"
|
||||
&& request_body.contains_key("form")
|
||||
{
|
||||
@@ -272,12 +300,12 @@ pub async fn send_http_request<R: Runtime>(
|
||||
.as_str()
|
||||
.unwrap_or_default();
|
||||
|
||||
match fs::read(file_path).map_err(|e| e.to_string()) {
|
||||
match fs::read(file_path).await.map_err(|e| e.to_string()) {
|
||||
Ok(f) => {
|
||||
request_builder = request_builder.body(f);
|
||||
}
|
||||
Err(e) => {
|
||||
return response_err(response, e, window).await;
|
||||
return Ok(response_err(&*response.lock().await, e, window).await);
|
||||
}
|
||||
}
|
||||
} else if body_type == "multipart/form-data" && request_body.contains_key("form") {
|
||||
@@ -300,10 +328,15 @@ pub async fn send_http_request<R: Runtime>(
|
||||
let mut part = if file_path.is_empty() {
|
||||
multipart::Part::text(value.clone())
|
||||
} else {
|
||||
match fs::read(file_path.clone()) {
|
||||
match fs::read(file_path.clone()).await {
|
||||
Ok(f) => multipart::Part::bytes(f),
|
||||
Err(e) => {
|
||||
return response_err(response, e.to_string(), window).await;
|
||||
return Ok(response_err(
|
||||
&*response.lock().await,
|
||||
e.to_string(),
|
||||
window,
|
||||
)
|
||||
.await);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -318,9 +351,8 @@ pub async fn send_http_request<R: Runtime>(
|
||||
Mime::from_str("application/octet-stream").unwrap();
|
||||
let mime =
|
||||
mime_guess::from_path(file_path.clone()).first_or(default_mime);
|
||||
part = part
|
||||
.mime_str(mime.essence_str())
|
||||
.map_err(|e| e.to_string())?;
|
||||
part =
|
||||
part.mime_str(mime.essence_str()).map_err(|e| e.to_string())?;
|
||||
}
|
||||
|
||||
// Set file path if not empty
|
||||
@@ -340,6 +372,9 @@ pub async fn send_http_request<R: Runtime>(
|
||||
}
|
||||
headers.remove("Content-Type"); // reqwest will add this automatically
|
||||
request_builder = request_builder.multipart(multipart_form);
|
||||
} else if request_body.contains_key("text") {
|
||||
let body = get_str_h(&request_body, "text");
|
||||
request_builder = request_builder.body(body.to_owned());
|
||||
} else {
|
||||
warn!("Unsupported body type: {}", body_type);
|
||||
}
|
||||
@@ -351,118 +386,181 @@ pub async fn send_http_request<R: Runtime>(
|
||||
let sendable_req = match request_builder.build() {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
return response_err(response, e.to_string(), window).await;
|
||||
warn!("Failed to build request builder {e:?}");
|
||||
return Ok(response_err(&*response.lock().await, e.to_string(), window).await);
|
||||
}
|
||||
};
|
||||
|
||||
let start = std::time::Instant::now();
|
||||
let (resp_tx, resp_rx) = oneshot::channel::<Result<Response, reqwest::Error>>();
|
||||
let (done_tx, done_rx) = oneshot::channel::<HttpResponse>();
|
||||
|
||||
let (resp_tx, resp_rx) = oneshot::channel();
|
||||
let start = std::time::Instant::now();
|
||||
|
||||
tokio::spawn(async move {
|
||||
let _ = resp_tx.send(client.execute(sendable_req).await);
|
||||
});
|
||||
|
||||
let raw_response = tokio::select! {
|
||||
Ok(r) = resp_rx => {r}
|
||||
_ = cancel_rx.changed() => {
|
||||
return response_err(response, "Request was cancelled".to_string(), window).await;
|
||||
Ok(r) = resp_rx => r,
|
||||
_ = cancelled_rx.changed() => {
|
||||
debug!("Request cancelled");
|
||||
return Ok(response_err(&*response.lock().await, "Request was cancelled".to_string(), window).await);
|
||||
}
|
||||
};
|
||||
|
||||
match raw_response {
|
||||
Ok(v) => {
|
||||
let mut response = response.clone();
|
||||
response.elapsed_headers = start.elapsed().as_millis() as i32;
|
||||
let response_headers = v.headers().clone();
|
||||
response.status = v.status().as_u16() as i32;
|
||||
response.status_reason = v.status().canonical_reason().map(|s| s.to_string());
|
||||
response.headers = response_headers
|
||||
.iter()
|
||||
.map(|(k, v)| HttpResponseHeader {
|
||||
name: k.as_str().to_string(),
|
||||
value: v.to_str().unwrap_or_default().to_string(),
|
||||
})
|
||||
.collect();
|
||||
response.url = v.url().to_string();
|
||||
response.remote_addr = v.remote_addr().map(|a| a.to_string());
|
||||
response.version = match v.version() {
|
||||
reqwest::Version::HTTP_09 => Some("HTTP/0.9".to_string()),
|
||||
reqwest::Version::HTTP_10 => Some("HTTP/1.0".to_string()),
|
||||
reqwest::Version::HTTP_11 => Some("HTTP/1.1".to_string()),
|
||||
reqwest::Version::HTTP_2 => Some("HTTP/2".to_string()),
|
||||
reqwest::Version::HTTP_3 => Some("HTTP/3".to_string()),
|
||||
_ => None,
|
||||
{
|
||||
let window = window.clone();
|
||||
let cancelled_rx = cancelled_rx.clone();
|
||||
let response_id = response_id.clone();
|
||||
let response = response.clone();
|
||||
tokio::spawn(async move {
|
||||
match raw_response {
|
||||
Ok(mut v) => {
|
||||
let content_length = v.content_length();
|
||||
let response_headers = v.headers().clone();
|
||||
let dir = window.app_handle().path().app_data_dir().unwrap();
|
||||
let base_dir = dir.join("responses");
|
||||
create_dir_all(base_dir.clone()).await.expect("Failed to create responses dir");
|
||||
let body_path = if response_id.is_empty() {
|
||||
base_dir.join(uuid::Uuid::new_v4().to_string())
|
||||
} else {
|
||||
base_dir.join(response_id.clone())
|
||||
};
|
||||
|
||||
{
|
||||
let mut r = response.lock().await;
|
||||
r.body_path = Some(body_path.to_str().unwrap().to_string());
|
||||
r.elapsed_headers = start.elapsed().as_millis() as i32;
|
||||
r.status = v.status().as_u16() as i32;
|
||||
r.status_reason = v.status().canonical_reason().map(|s| s.to_string());
|
||||
r.headers = response_headers
|
||||
.iter()
|
||||
.map(|(k, v)| HttpResponseHeader {
|
||||
name: k.as_str().to_string(),
|
||||
value: v.to_str().unwrap_or_default().to_string(),
|
||||
})
|
||||
.collect();
|
||||
r.url = v.url().to_string();
|
||||
r.remote_addr = v.remote_addr().map(|a| a.to_string());
|
||||
r.version = match v.version() {
|
||||
reqwest::Version::HTTP_09 => Some("HTTP/0.9".to_string()),
|
||||
reqwest::Version::HTTP_10 => Some("HTTP/1.0".to_string()),
|
||||
reqwest::Version::HTTP_11 => Some("HTTP/1.1".to_string()),
|
||||
reqwest::Version::HTTP_2 => Some("HTTP/2".to_string()),
|
||||
reqwest::Version::HTTP_3 => Some("HTTP/3".to_string()),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
r.state = HttpResponseState::Connected;
|
||||
update_response_if_id(&window, &r, &UpdateSource::Window)
|
||||
.await
|
||||
.expect("Failed to update response after connected");
|
||||
}
|
||||
|
||||
// Write body to FS
|
||||
let mut f = File::options()
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.write(true)
|
||||
.open(&body_path)
|
||||
.await
|
||||
.expect("Failed to open file");
|
||||
|
||||
let mut written_bytes: usize = 0;
|
||||
loop {
|
||||
let chunk = v.chunk().await;
|
||||
if *cancelled_rx.borrow() {
|
||||
// Request was canceled
|
||||
return;
|
||||
}
|
||||
match chunk {
|
||||
Ok(Some(bytes)) => {
|
||||
let mut r = response.lock().await;
|
||||
r.elapsed = start.elapsed().as_millis() as i32;
|
||||
f.write_all(&bytes).await.expect("Failed to write to file");
|
||||
f.flush().await.expect("Failed to flush file");
|
||||
written_bytes += bytes.len();
|
||||
r.content_length = Some(written_bytes as i32);
|
||||
update_response_if_id(&window, &r, &UpdateSource::Window)
|
||||
.await
|
||||
.expect("Failed to update response");
|
||||
}
|
||||
Ok(None) => {
|
||||
break;
|
||||
}
|
||||
Err(e) => {
|
||||
response_err(&*response.lock().await, e.to_string(), &window).await;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set final content length
|
||||
{
|
||||
let mut r = response.lock().await;
|
||||
r.content_length = match content_length {
|
||||
Some(l) => Some(l as i32),
|
||||
None => Some(written_bytes as i32),
|
||||
};
|
||||
r.state = HttpResponseState::Closed;
|
||||
update_response_if_id(&window, &r, &UpdateSource::Window)
|
||||
.await
|
||||
.expect("Failed to update response");
|
||||
};
|
||||
|
||||
// Add cookie store if specified
|
||||
if let Some((cookie_store, mut cookie_jar)) = maybe_cookie_manager {
|
||||
// let cookies = response_headers.get_all(SET_COOKIE).iter().map(|h| {
|
||||
// println!("RESPONSE COOKIE: {}", h.to_str().unwrap());
|
||||
// cookie_store::RawCookie::from_str(h.to_str().unwrap())
|
||||
// .expect("Failed to parse cookie")
|
||||
// });
|
||||
// store.store_response_cookies(cookies, &url);
|
||||
|
||||
let json_cookies: Vec<Cookie> = cookie_store
|
||||
.lock()
|
||||
.unwrap()
|
||||
.iter_any()
|
||||
.map(|c| {
|
||||
let json_cookie =
|
||||
serde_json::to_value(&c).expect("Failed to serialize cookie");
|
||||
serde_json::from_value(json_cookie)
|
||||
.expect("Failed to deserialize cookie")
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
cookie_jar.cookies = json_cookies;
|
||||
if let Err(e) =
|
||||
upsert_cookie_jar(&window, &cookie_jar, &UpdateSource::Window).await
|
||||
{
|
||||
error!("Failed to update cookie jar: {}", e);
|
||||
};
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Failed to execute request {e}");
|
||||
response_err(&*response.lock().await, format!("{e} → {e:?}"), &window).await;
|
||||
}
|
||||
};
|
||||
|
||||
let content_length = v.content_length();
|
||||
let body_bytes = v.bytes().await.expect("Failed to get body").to_vec();
|
||||
response.elapsed = start.elapsed().as_millis() as i32;
|
||||
let r = response.lock().await.clone();
|
||||
done_tx.send(r).unwrap();
|
||||
});
|
||||
};
|
||||
|
||||
// Use content length if available, otherwise use body length
|
||||
response.content_length = match content_length {
|
||||
Some(l) => Some(l as i32),
|
||||
None => Some(body_bytes.len() as i32),
|
||||
};
|
||||
|
||||
{
|
||||
// Write body to FS
|
||||
let dir = window.app_handle().path().app_data_dir().unwrap();
|
||||
let base_dir = dir.join("responses");
|
||||
create_dir_all(base_dir.clone()).expect("Failed to create responses dir");
|
||||
let body_path = match response.id.is_empty() {
|
||||
false => base_dir.join(response.id.clone()),
|
||||
true => base_dir.join(uuid::Uuid::new_v4().to_string()),
|
||||
};
|
||||
let mut f = File::options()
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.write(true)
|
||||
.open(&body_path)
|
||||
.expect("Failed to open file");
|
||||
f.write_all(body_bytes.as_slice())
|
||||
.expect("Failed to write to file");
|
||||
response.body_path = Some(
|
||||
body_path
|
||||
.to_str()
|
||||
.expect("Failed to get body path")
|
||||
.to_string(),
|
||||
);
|
||||
Ok(tokio::select! {
|
||||
Ok(r) = done_rx => r,
|
||||
_ = cancelled_rx.changed() => {
|
||||
match get_http_response(window, response_id.as_str()).await {
|
||||
Ok(mut r) => {
|
||||
r.state = HttpResponseState::Closed;
|
||||
update_response_if_id(&window, &r, &UpdateSource::Window).await.expect("Failed to update response")
|
||||
},
|
||||
_ => {
|
||||
response_err(&*response.lock().await, "Ephemeral request was cancelled".to_string(), &window).await
|
||||
}.clone(),
|
||||
}
|
||||
|
||||
response = update_response_if_id(window, &response)
|
||||
.await
|
||||
.expect("Failed to update response");
|
||||
|
||||
// Add cookie store if specified
|
||||
if let Some((cookie_store, mut cookie_jar)) = maybe_cookie_manager {
|
||||
// let cookies = response_headers.get_all(SET_COOKIE).iter().map(|h| {
|
||||
// println!("RESPONSE COOKIE: {}", h.to_str().unwrap());
|
||||
// cookie_store::RawCookie::from_str(h.to_str().unwrap())
|
||||
// .expect("Failed to parse cookie")
|
||||
// });
|
||||
// store.store_response_cookies(cookies, &url);
|
||||
|
||||
let json_cookies: Vec<Cookie> = cookie_store
|
||||
.lock()
|
||||
.unwrap()
|
||||
.iter_any()
|
||||
.map(|c| {
|
||||
let json_cookie =
|
||||
serde_json::to_value(&c).expect("Failed to serialize cookie");
|
||||
serde_json::from_value(json_cookie).expect("Failed to deserialize cookie")
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
cookie_jar.cookies = json_cookies;
|
||||
if let Err(e) = upsert_cookie_jar(window, &cookie_jar).await {
|
||||
error!("Failed to update cookie jar: {}", e);
|
||||
};
|
||||
}
|
||||
|
||||
Ok(response)
|
||||
}
|
||||
Err(e) => response_err(response, e.to_string(), window).await,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn ensure_proto(url_str: &str) -> String {
|
||||
@@ -508,123 +606,3 @@ fn get_str_h<'a>(v: &'a BTreeMap<String, Value>, key: &str) -> &'a str {
|
||||
Some(v) => v.as_str().unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn replace_path_placeholder(p: &HttpUrlParameter, url: &str) -> String {
|
||||
if !p.enabled {
|
||||
return url.to_string();
|
||||
}
|
||||
|
||||
if !p.name.starts_with(":") {
|
||||
return url.to_string();
|
||||
}
|
||||
|
||||
let re = regex::Regex::new(format!("(/){}([/?#]|$)", p.name).as_str()).unwrap();
|
||||
let result = re
|
||||
.replace_all(url, |cap: ®ex::Captures| {
|
||||
format!(
|
||||
"{}{}{}",
|
||||
cap[1].to_string(),
|
||||
urlencoding::encode(p.value.as_str()),
|
||||
cap[2].to_string()
|
||||
)
|
||||
})
|
||||
.into_owned();
|
||||
result
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::http_request::replace_path_placeholder;
|
||||
use yaak_models::models::HttpUrlParameter;
|
||||
|
||||
#[test]
|
||||
fn placeholder_middle() {
|
||||
let p = HttpUrlParameter {
|
||||
name: ":foo".into(),
|
||||
value: "xxx".into(),
|
||||
enabled: true,
|
||||
};
|
||||
assert_eq!(
|
||||
replace_path_placeholder(&p, "https://example.com/:foo/bar"),
|
||||
"https://example.com/xxx/bar",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn placeholder_end() {
|
||||
let p = HttpUrlParameter {
|
||||
name: ":foo".into(),
|
||||
value: "xxx".into(),
|
||||
enabled: true,
|
||||
};
|
||||
assert_eq!(
|
||||
replace_path_placeholder(&p, "https://example.com/:foo"),
|
||||
"https://example.com/xxx",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn placeholder_query() {
|
||||
let p = HttpUrlParameter {
|
||||
name: ":foo".into(),
|
||||
value: "xxx".into(),
|
||||
enabled: true,
|
||||
};
|
||||
assert_eq!(
|
||||
replace_path_placeholder(&p, "https://example.com/:foo?:foo"),
|
||||
"https://example.com/xxx?:foo",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn placeholder_missing() {
|
||||
let p = HttpUrlParameter {
|
||||
enabled: true,
|
||||
name: "".to_string(),
|
||||
value: "".to_string(),
|
||||
};
|
||||
assert_eq!(
|
||||
replace_path_placeholder(&p, "https://example.com/:missing"),
|
||||
"https://example.com/:missing",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn placeholder_disabled() {
|
||||
let p = HttpUrlParameter {
|
||||
enabled: false,
|
||||
name: ":foo".to_string(),
|
||||
value: "xxx".to_string(),
|
||||
};
|
||||
assert_eq!(
|
||||
replace_path_placeholder(&p, "https://example.com/:foo"),
|
||||
"https://example.com/:foo",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn placeholder_prefix() {
|
||||
let p = HttpUrlParameter {
|
||||
name: ":foo".into(),
|
||||
value: "xxx".into(),
|
||||
enabled: true,
|
||||
};
|
||||
assert_eq!(
|
||||
replace_path_placeholder(&p, "https://example.com/:foooo"),
|
||||
"https://example.com/:foooo",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn placeholder_encode() {
|
||||
let p = HttpUrlParameter {
|
||||
name: ":foo".into(),
|
||||
value: "Hello World".into(),
|
||||
enabled: true,
|
||||
};
|
||||
assert_eq!(
|
||||
replace_path_placeholder(&p, "https://example.com/:foo"),
|
||||
"https://example.com/Hello%20World",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
1483
src-tauri/src/lib.rs
1483
src-tauri/src/lib.rs
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@ use log::debug;
|
||||
use reqwest::Method;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tauri::{Emitter, Manager, Runtime, WebviewWindow};
|
||||
use yaak_models::queries::{get_key_value_raw, set_key_value_raw};
|
||||
use yaak_models::queries::{get_key_value_raw, set_key_value_raw, UpdateSource};
|
||||
|
||||
// Check for updates every hour
|
||||
const MAX_UPDATE_CHECK_SECONDS: u64 = 60 * 60;
|
||||
@@ -47,11 +47,11 @@ impl YaakNotifier {
|
||||
seen.push(id.to_string());
|
||||
debug!("Marked notification as seen {}", id);
|
||||
let seen_json = serde_json::to_string(&seen).map_err(|e| e.to_string())?;
|
||||
set_key_value_raw(w, KV_NAMESPACE, KV_KEY, seen_json.as_str()).await;
|
||||
set_key_value_raw(w, KV_NAMESPACE, KV_KEY, seen_json.as_str(), &UpdateSource::Window).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn check<R: Runtime>(&mut self, w: &WebviewWindow<R>) -> Result<(), String> {
|
||||
pub async fn check<R: Runtime>(&mut self, window: &WebviewWindow<R>) -> Result<(), String> {
|
||||
let ignore_check = self.last_check.elapsed().unwrap().as_secs() < MAX_UPDATE_CHECK_SECONDS;
|
||||
|
||||
if ignore_check {
|
||||
@@ -60,8 +60,8 @@ impl YaakNotifier {
|
||||
|
||||
self.last_check = SystemTime::now();
|
||||
|
||||
let num_launches = get_num_launches(w).await;
|
||||
let info = w.app_handle().package_info().clone();
|
||||
let num_launches = get_num_launches(window).await;
|
||||
let info = window.app_handle().package_info().clone();
|
||||
let req = reqwest::Client::default()
|
||||
.request(Method::GET, "https://notify.yaak.app/notifications")
|
||||
.query(&[
|
||||
@@ -74,20 +74,17 @@ impl YaakNotifier {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let notification = resp
|
||||
.json::<YaakNotification>()
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
let notification = resp.json::<YaakNotification>().await.map_err(|e| e.to_string())?;
|
||||
|
||||
let age = notification.timestamp.signed_duration_since(Utc::now());
|
||||
let seen = get_kv(w).await?;
|
||||
let seen = get_kv(window).await?;
|
||||
if seen.contains(¬ification.id) || (age > Duration::days(2)) {
|
||||
debug!("Already seen notification {}", notification.id);
|
||||
return Ok(());
|
||||
}
|
||||
debug!("Got notification {:?}", notification);
|
||||
|
||||
let _ = w.emit("notification", notification.clone());
|
||||
let _ = window.emit_to(window.label(), "notification", notification.clone());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,32 +1,39 @@
|
||||
use crate::template_callback::PluginTemplateCallback;
|
||||
use serde_json::{json, Map, Value};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use tauri::{AppHandle, Manager, Runtime};
|
||||
use yaak_models::models::{
|
||||
Environment, EnvironmentVariable, GrpcMetadataEntry, GrpcRequest, HttpRequest,
|
||||
HttpRequestHeader, HttpUrlParameter, Workspace,
|
||||
HttpRequestHeader, HttpUrlParameter,
|
||||
};
|
||||
use yaak_templates::{parse_and_render, TemplateCallback};
|
||||
|
||||
pub async fn render_template<R: Runtime>(
|
||||
app_handle: &AppHandle<R>,
|
||||
pub async fn render_template<T: TemplateCallback>(
|
||||
template: &str,
|
||||
w: &Workspace,
|
||||
e: Option<&Environment>,
|
||||
base_environment: &Environment,
|
||||
environment: Option<&Environment>,
|
||||
cb: &T,
|
||||
) -> String {
|
||||
let cb = &*app_handle.state::<PluginTemplateCallback>();
|
||||
let vars = &make_vars_hashmap(w, e);
|
||||
let vars = &make_vars_hashmap(base_environment, environment);
|
||||
render(template, vars, cb).await
|
||||
}
|
||||
|
||||
pub async fn render_grpc_request<R: Runtime>(
|
||||
app_handle: &AppHandle<R>,
|
||||
pub async fn render_json_value<T: TemplateCallback>(
|
||||
value: Value,
|
||||
base_environment: &Environment,
|
||||
environment: Option<&Environment>,
|
||||
cb: &T,
|
||||
) -> Value {
|
||||
let vars = &make_vars_hashmap(base_environment, environment);
|
||||
render_json_value_raw(value, vars, cb).await
|
||||
}
|
||||
|
||||
pub async fn render_grpc_request<T: TemplateCallback>(
|
||||
r: &GrpcRequest,
|
||||
w: &Workspace,
|
||||
e: Option<&Environment>,
|
||||
base_environment: &Environment,
|
||||
environment: Option<&Environment>,
|
||||
cb: &T,
|
||||
) -> GrpcRequest {
|
||||
let cb = &*app_handle.state::<PluginTemplateCallback>();
|
||||
let vars = &make_vars_hashmap(w, e);
|
||||
let vars = &make_vars_hashmap(base_environment, environment);
|
||||
|
||||
let mut metadata = Vec::new();
|
||||
for p in r.metadata.clone() {
|
||||
@@ -34,12 +41,13 @@ pub async fn render_grpc_request<R: Runtime>(
|
||||
enabled: p.enabled,
|
||||
name: render(p.name.as_str(), vars, cb).await,
|
||||
value: render(p.value.as_str(), vars, cb).await,
|
||||
id: p.id,
|
||||
})
|
||||
}
|
||||
|
||||
let mut authentication = BTreeMap::new();
|
||||
for (k, v) in r.authentication.clone() {
|
||||
authentication.insert(k, render_json_value(v, vars, cb).await);
|
||||
authentication.insert(k, render_json_value_raw(v, vars, cb).await);
|
||||
}
|
||||
|
||||
let url = render(r.url.as_str(), vars, cb).await;
|
||||
@@ -54,11 +62,11 @@ pub async fn render_grpc_request<R: Runtime>(
|
||||
|
||||
pub async fn render_http_request(
|
||||
r: &HttpRequest,
|
||||
w: &Workspace,
|
||||
e: Option<&Environment>,
|
||||
base_environment: &Environment,
|
||||
environment: Option<&Environment>,
|
||||
cb: &PluginTemplateCallback,
|
||||
) -> HttpRequest {
|
||||
let vars = &make_vars_hashmap(w, e);
|
||||
let vars = &make_vars_hashmap(base_environment, environment);
|
||||
|
||||
let mut url_parameters = Vec::new();
|
||||
for p in r.url_parameters.clone() {
|
||||
@@ -66,6 +74,7 @@ pub async fn render_http_request(
|
||||
enabled: p.enabled,
|
||||
name: render(p.name.as_str(), vars, cb).await,
|
||||
value: render(p.value.as_str(), vars, cb).await,
|
||||
id: p.id,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -75,36 +84,40 @@ pub async fn render_http_request(
|
||||
enabled: p.enabled,
|
||||
name: render(p.name.as_str(), vars, cb).await,
|
||||
value: render(p.value.as_str(), vars, cb).await,
|
||||
id: p.id,
|
||||
})
|
||||
}
|
||||
|
||||
let mut body = BTreeMap::new();
|
||||
for (k, v) in r.body.clone() {
|
||||
body.insert(k, render_json_value(v, vars, cb).await);
|
||||
body.insert(k, render_json_value_raw(v, vars, cb).await);
|
||||
}
|
||||
|
||||
let mut authentication = BTreeMap::new();
|
||||
for (k, v) in r.authentication.clone() {
|
||||
authentication.insert(k, render_json_value(v, vars, cb).await);
|
||||
authentication.insert(k, render_json_value_raw(v, vars, cb).await);
|
||||
}
|
||||
|
||||
let url = render(r.url.clone().as_str(), vars, cb).await;
|
||||
HttpRequest {
|
||||
let req = HttpRequest {
|
||||
url,
|
||||
url_parameters,
|
||||
headers,
|
||||
body,
|
||||
authentication,
|
||||
..r.to_owned()
|
||||
}
|
||||
};
|
||||
|
||||
// This doesn't fit perfectly with the concept of "rendering" but it kind of does
|
||||
apply_path_placeholders(req)
|
||||
}
|
||||
|
||||
pub fn make_vars_hashmap(
|
||||
workspace: &Workspace,
|
||||
base_environment: &Environment,
|
||||
environment: Option<&Environment>,
|
||||
) -> HashMap<String, String> {
|
||||
let mut variables = HashMap::new();
|
||||
variables = add_variable_to_map(variables, &workspace.variables);
|
||||
variables = add_variable_to_map(variables, &base_environment.variables);
|
||||
|
||||
if let Some(e) = environment {
|
||||
variables = add_variable_to_map(variables, &e.variables);
|
||||
@@ -138,7 +151,7 @@ fn add_variable_to_map(
|
||||
map
|
||||
}
|
||||
|
||||
pub async fn render_json_value<T: TemplateCallback>(
|
||||
async fn render_json_value_raw<T: TemplateCallback>(
|
||||
v: Value,
|
||||
vars: &HashMap<String, String>,
|
||||
cb: &T,
|
||||
@@ -148,7 +161,7 @@ pub async fn render_json_value<T: TemplateCallback>(
|
||||
Value::Array(a) => {
|
||||
let mut new_a = Vec::new();
|
||||
for v in a {
|
||||
new_a.push(Box::pin(render_json_value(v, vars, cb)).await)
|
||||
new_a.push(Box::pin(render_json_value_raw(v, vars, cb)).await)
|
||||
}
|
||||
json!(new_a)
|
||||
}
|
||||
@@ -156,7 +169,7 @@ pub async fn render_json_value<T: TemplateCallback>(
|
||||
let mut new_o = Map::new();
|
||||
for (k, v) in o {
|
||||
let key = Box::pin(render(k.as_str(), vars, cb)).await;
|
||||
let value = Box::pin(render_json_value(v, vars, cb)).await;
|
||||
let value = Box::pin(render_json_value_raw(v, vars, cb)).await;
|
||||
new_o.insert(key, value);
|
||||
}
|
||||
json!(new_o)
|
||||
@@ -166,7 +179,7 @@ pub async fn render_json_value<T: TemplateCallback>(
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
mod render_tests {
|
||||
use serde_json::json;
|
||||
use std::collections::HashMap;
|
||||
use yaak_templates::TemplateCallback;
|
||||
@@ -189,7 +202,7 @@ mod tests {
|
||||
let mut vars = HashMap::new();
|
||||
vars.insert("a".to_string(), "aaa".to_string());
|
||||
|
||||
let result = super::render_json_value(v, &vars, &EmptyCB {}).await;
|
||||
let result = super::render_json_value_raw(v, &vars, &EmptyCB {}).await;
|
||||
assert_eq!(result, json!("aaa"))
|
||||
}
|
||||
|
||||
@@ -199,7 +212,7 @@ mod tests {
|
||||
let mut vars = HashMap::new();
|
||||
vars.insert("a".to_string(), "aaa".to_string());
|
||||
|
||||
let result = super::render_json_value(v, &vars, &EmptyCB {}).await;
|
||||
let result = super::render_json_value_raw(v, &vars, &EmptyCB {}).await;
|
||||
assert_eq!(result, json!(["aaa", "aaa"]))
|
||||
}
|
||||
|
||||
@@ -209,7 +222,7 @@ mod tests {
|
||||
let mut vars = HashMap::new();
|
||||
vars.insert("a".to_string(), "aaa".to_string());
|
||||
|
||||
let result = super::render_json_value(v, &vars, &EmptyCB {}).await;
|
||||
let result = super::render_json_value_raw(v, &vars, &EmptyCB {}).await;
|
||||
assert_eq!(result, json!({"aaa": "aaa"}))
|
||||
}
|
||||
|
||||
@@ -226,7 +239,7 @@ mod tests {
|
||||
let mut vars = HashMap::new();
|
||||
vars.insert("a".to_string(), "aaa".to_string());
|
||||
|
||||
let result = super::render_json_value(v, &vars, &EmptyCB {}).await;
|
||||
let result = super::render_json_value_raw(v, &vars, &EmptyCB {}).await;
|
||||
assert_eq!(
|
||||
result,
|
||||
json!([
|
||||
@@ -240,3 +253,180 @@ mod tests {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn replace_path_placeholder(p: &HttpUrlParameter, url: &str) -> String {
|
||||
if !p.enabled {
|
||||
return url.to_string();
|
||||
}
|
||||
|
||||
if !p.name.starts_with(":") {
|
||||
return url.to_string();
|
||||
}
|
||||
|
||||
let re = regex::Regex::new(format!("(/){}([/?#]|$)", p.name).as_str()).unwrap();
|
||||
let result = re
|
||||
.replace_all(url, |cap: ®ex::Captures| {
|
||||
format!(
|
||||
"{}{}{}",
|
||||
cap[1].to_string(),
|
||||
urlencoding::encode(p.value.as_str()),
|
||||
cap[2].to_string()
|
||||
)
|
||||
})
|
||||
.into_owned();
|
||||
result
|
||||
}
|
||||
|
||||
fn apply_path_placeholders(rendered_request: HttpRequest) -> HttpRequest {
|
||||
let mut url = rendered_request.url.to_owned();
|
||||
let mut url_parameters = Vec::new();
|
||||
for p in rendered_request.url_parameters.clone() {
|
||||
if !p.enabled || p.name.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Replace path parameters with values from URL parameters
|
||||
let old_url_string = url.clone();
|
||||
url = replace_path_placeholder(&p, url.as_str());
|
||||
|
||||
// Remove as param if it modified the URL
|
||||
if old_url_string == url {
|
||||
url_parameters.push(p);
|
||||
}
|
||||
}
|
||||
|
||||
let mut request = rendered_request.clone();
|
||||
request.url_parameters = url_parameters;
|
||||
request.url = url;
|
||||
request
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod placeholder_tests {
|
||||
use crate::render::{apply_path_placeholders, replace_path_placeholder};
|
||||
use yaak_models::models::{HttpRequest, HttpUrlParameter};
|
||||
|
||||
#[test]
|
||||
fn placeholder_middle() {
|
||||
let p = HttpUrlParameter {
|
||||
name: ":foo".into(),
|
||||
value: "xxx".into(),
|
||||
enabled: true,
|
||||
id: "p1".into(),
|
||||
};
|
||||
assert_eq!(
|
||||
replace_path_placeholder(&p, "https://example.com/:foo/bar"),
|
||||
"https://example.com/xxx/bar",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn placeholder_end() {
|
||||
let p = HttpUrlParameter {
|
||||
name: ":foo".into(),
|
||||
value: "xxx".into(),
|
||||
enabled: true,
|
||||
id: "p1".into(),
|
||||
};
|
||||
assert_eq!(
|
||||
replace_path_placeholder(&p, "https://example.com/:foo"),
|
||||
"https://example.com/xxx",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn placeholder_query() {
|
||||
let p = HttpUrlParameter {
|
||||
name: ":foo".into(),
|
||||
value: "xxx".into(),
|
||||
enabled: true,
|
||||
id: "p1".into(),
|
||||
};
|
||||
assert_eq!(
|
||||
replace_path_placeholder(&p, "https://example.com/:foo?:foo"),
|
||||
"https://example.com/xxx?:foo",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn placeholder_missing() {
|
||||
let p = HttpUrlParameter {
|
||||
enabled: true,
|
||||
name: "".to_string(),
|
||||
value: "".to_string(),
|
||||
id: "p1".into(),
|
||||
};
|
||||
assert_eq!(
|
||||
replace_path_placeholder(&p, "https://example.com/:missing"),
|
||||
"https://example.com/:missing",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn placeholder_disabled() {
|
||||
let p = HttpUrlParameter {
|
||||
enabled: false,
|
||||
name: ":foo".to_string(),
|
||||
value: "xxx".to_string(),
|
||||
id: "p1".into(),
|
||||
};
|
||||
assert_eq!(
|
||||
replace_path_placeholder(&p, "https://example.com/:foo"),
|
||||
"https://example.com/:foo",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn placeholder_prefix() {
|
||||
let p = HttpUrlParameter {
|
||||
name: ":foo".into(),
|
||||
value: "xxx".into(),
|
||||
enabled: true,
|
||||
id: "p1".into(),
|
||||
};
|
||||
assert_eq!(
|
||||
replace_path_placeholder(&p, "https://example.com/:foooo"),
|
||||
"https://example.com/:foooo",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn placeholder_encode() {
|
||||
let p = HttpUrlParameter {
|
||||
name: ":foo".into(),
|
||||
value: "Hello World".into(),
|
||||
enabled: true,
|
||||
id: "p1".into(),
|
||||
};
|
||||
assert_eq!(
|
||||
replace_path_placeholder(&p, "https://example.com/:foo"),
|
||||
"https://example.com/Hello%20World",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn apply_placeholder() {
|
||||
let result = apply_path_placeholders(HttpRequest {
|
||||
url: "example.com/:a/bar".to_string(),
|
||||
url_parameters: vec![
|
||||
HttpUrlParameter {
|
||||
name: "b".to_string(),
|
||||
value: "bbb".to_string(),
|
||||
enabled: true,
|
||||
id: "p1".into(),
|
||||
},
|
||||
HttpUrlParameter {
|
||||
name: ":a".to_string(),
|
||||
value: "aaa".to_string(),
|
||||
enabled: true,
|
||||
id: "p2".into(),
|
||||
},
|
||||
],
|
||||
..Default::default()
|
||||
});
|
||||
assert_eq!(result.url, "example.com/aaa/bar");
|
||||
assert_eq!(result.url_parameters.len(), 1);
|
||||
assert_eq!(result.url_parameters[0].name, "b");
|
||||
assert_eq!(result.url_parameters[0].value, "bbb");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::MAIN_WINDOW_PREFIX;
|
||||
use hex_color::HexColor;
|
||||
use log::warn;
|
||||
use objc::{msg_send, sel, sel_impl};
|
||||
@@ -6,7 +7,6 @@ use tauri::{
|
||||
plugin::{Builder, TauriPlugin},
|
||||
Emitter, Listener, Manager, Runtime, Window, WindowEvent,
|
||||
};
|
||||
use crate::MAIN_WINDOW_PREFIX;
|
||||
|
||||
const WINDOW_CONTROL_PAD_X: f64 = 13.0;
|
||||
const WINDOW_CONTROL_PAD_Y: f64 = 18.0;
|
||||
@@ -202,10 +202,9 @@ pub fn setup_traffic_light_positioner<R: Runtime>(window: &Window<R>) {
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let ns_win = window
|
||||
.ns_window()
|
||||
.expect("NS Window should exist to mount traffic light delegate.")
|
||||
as id;
|
||||
let ns_win =
|
||||
window.ns_window().expect("NS Window should exist to mount traffic light delegate.")
|
||||
as id;
|
||||
|
||||
let current_delegate: id = ns_win.delegate();
|
||||
|
||||
@@ -322,10 +321,7 @@ pub fn setup_traffic_light_positioner<R: Runtime>(window: &Window<R>) {
|
||||
) {
|
||||
unsafe {
|
||||
with_window_state(&*this, |state: &mut WindowState<R>| {
|
||||
state
|
||||
.window
|
||||
.emit("did-enter-fullscreen", ())
|
||||
.expect("Failed to emit event");
|
||||
state.window.emit("did-enter-fullscreen", ()).expect("Failed to emit event");
|
||||
});
|
||||
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
@@ -339,10 +335,7 @@ pub fn setup_traffic_light_positioner<R: Runtime>(window: &Window<R>) {
|
||||
) {
|
||||
unsafe {
|
||||
with_window_state(&*this, |state: &mut WindowState<R>| {
|
||||
state
|
||||
.window
|
||||
.emit("will-enter-fullscreen", ())
|
||||
.expect("Failed to emit event");
|
||||
state.window.emit("will-enter-fullscreen", ()).expect("Failed to emit event");
|
||||
});
|
||||
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
@@ -356,10 +349,7 @@ pub fn setup_traffic_light_positioner<R: Runtime>(window: &Window<R>) {
|
||||
) {
|
||||
unsafe {
|
||||
with_window_state(&*this, |state: &mut WindowState<R>| {
|
||||
state
|
||||
.window
|
||||
.emit("did-exit-fullscreen", ())
|
||||
.expect("Failed to emit event");
|
||||
state.window.emit("did-exit-fullscreen", ()).expect("Failed to emit event");
|
||||
|
||||
let id = state.window.ns_window().expect("Failed to emit event") as id;
|
||||
position_traffic_lights(
|
||||
@@ -381,10 +371,7 @@ pub fn setup_traffic_light_positioner<R: Runtime>(window: &Window<R>) {
|
||||
) {
|
||||
unsafe {
|
||||
with_window_state(&*this, |state: &mut WindowState<R>| {
|
||||
state
|
||||
.window
|
||||
.emit("will-exit-fullscreen", ())
|
||||
.expect("Failed to emit event");
|
||||
state.window.emit("will-exit-fullscreen", ()).expect("Failed to emit event");
|
||||
});
|
||||
|
||||
let super_del: id = *this.get_ivar("super_delegate");
|
||||
@@ -432,11 +419,8 @@ pub fn setup_traffic_light_positioner<R: Runtime>(window: &Window<R>) {
|
||||
window: window.clone(),
|
||||
};
|
||||
let app_box = Box::into_raw(Box::new(app_state)) as *mut c_void;
|
||||
let random_str: String = rand::thread_rng()
|
||||
.sample_iter(&Alphanumeric)
|
||||
.take(20)
|
||||
.map(char::from)
|
||||
.collect();
|
||||
let random_str: String =
|
||||
rand::thread_rng().sample_iter(&Alphanumeric).take(20).map(char::from).collect();
|
||||
|
||||
// We need to ensure we have a unique delegate name, otherwise we will panic while trying to create a duplicate
|
||||
// delegate with the same name.
|
||||
|
||||
@@ -1,43 +1,41 @@
|
||||
use std::collections::HashMap;
|
||||
use tauri::{AppHandle, Manager};
|
||||
use yaak_plugin_runtime::events::{RenderPurpose, TemplateFunctionArg};
|
||||
use yaak_plugin_runtime::manager::PluginManager;
|
||||
use tauri::{AppHandle, Manager, Runtime};
|
||||
use yaak_plugins::events::{RenderPurpose, TemplateFunctionArg, WindowContext};
|
||||
use yaak_plugins::manager::PluginManager;
|
||||
use yaak_templates::TemplateCallback;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PluginTemplateCallback {
|
||||
app_handle: AppHandle,
|
||||
purpose: RenderPurpose,
|
||||
plugin_manager: PluginManager,
|
||||
window_context: WindowContext,
|
||||
render_purpose: RenderPurpose,
|
||||
}
|
||||
|
||||
impl PluginTemplateCallback {
|
||||
pub fn new(app_handle: AppHandle) -> PluginTemplateCallback {
|
||||
pub fn new<R: Runtime>(
|
||||
app_handle: &AppHandle<R>,
|
||||
window_context: &WindowContext,
|
||||
render_purpose: RenderPurpose,
|
||||
) -> PluginTemplateCallback {
|
||||
let plugin_manager = &*app_handle.state::<PluginManager>();
|
||||
PluginTemplateCallback {
|
||||
app_handle,
|
||||
purpose: RenderPurpose::Preview,
|
||||
plugin_manager: plugin_manager.to_owned(),
|
||||
window_context: window_context.to_owned(),
|
||||
render_purpose,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_send(&self) -> PluginTemplateCallback {
|
||||
let mut v = self.clone();
|
||||
v.purpose = RenderPurpose::Send;
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
impl TemplateCallback for PluginTemplateCallback {
|
||||
async fn run(&self, fn_name: &str, args: HashMap<String, String>) -> Result<String, String> {
|
||||
let window_context = self.window_context.to_owned();
|
||||
// The beta named the function `Response` but was changed in stable.
|
||||
// Keep this here for a while because there's no easy way to migrate
|
||||
let fn_name = if fn_name == "Response" {
|
||||
"response"
|
||||
} else {
|
||||
fn_name
|
||||
};
|
||||
let fn_name = if fn_name == "Response" { "response" } else { fn_name };
|
||||
|
||||
let plugin_manager = self.app_handle.state::<PluginManager>();
|
||||
let function = plugin_manager
|
||||
.get_template_functions()
|
||||
let function = self
|
||||
.plugin_manager
|
||||
.get_template_functions_with_context(window_context.to_owned())
|
||||
.await
|
||||
.map_err(|e| e.to_string())?
|
||||
.iter()
|
||||
@@ -53,6 +51,7 @@ impl TemplateCallback for PluginTemplateCallback {
|
||||
TemplateFunctionArg::Text(a) => a.base,
|
||||
TemplateFunctionArg::Select(a) => a.base,
|
||||
TemplateFunctionArg::Checkbox(a) => a.base,
|
||||
TemplateFunctionArg::File(a) => a.base,
|
||||
TemplateFunctionArg::HttpRequest(a) => a.base,
|
||||
};
|
||||
if let None = args_with_defaults.get(base.name.as_str()) {
|
||||
@@ -60,8 +59,14 @@ impl TemplateCallback for PluginTemplateCallback {
|
||||
}
|
||||
}
|
||||
|
||||
let resp = plugin_manager
|
||||
.call_template_function(fn_name, args_with_defaults, self.purpose.clone())
|
||||
let resp = self
|
||||
.plugin_manager
|
||||
.call_template_function(
|
||||
window_context,
|
||||
fn_name,
|
||||
args_with_defaults,
|
||||
self.render_purpose.to_owned(),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
Ok(resp.unwrap_or_default())
|
||||
|
||||
@@ -3,10 +3,10 @@ use std::time::SystemTime;
|
||||
|
||||
use log::info;
|
||||
use tauri::{AppHandle, Manager};
|
||||
use tauri_plugin_dialog::DialogExt;
|
||||
use tauri_plugin_dialog::{DialogExt, MessageDialogButtons};
|
||||
use tauri_plugin_updater::UpdaterExt;
|
||||
use tokio::task::block_in_place;
|
||||
use yaak_plugin_runtime::manager::PluginManager;
|
||||
use yaak_plugins::manager::PluginManager;
|
||||
|
||||
use crate::is_dev;
|
||||
|
||||
@@ -92,8 +92,10 @@ impl YaakUpdater {
|
||||
"{} is available. Would you like to download and install it now?",
|
||||
update.version
|
||||
))
|
||||
.ok_button_label("Download")
|
||||
.cancel_button_label("Later")
|
||||
.buttons(MessageDialogButtons::OkCancelCustom(
|
||||
"Download".to_string(),
|
||||
"Later".to_string(),
|
||||
))
|
||||
.title("Update Available")
|
||||
.show(|confirmed| {
|
||||
if !confirmed {
|
||||
@@ -105,8 +107,10 @@ impl YaakUpdater {
|
||||
if h.dialog()
|
||||
.message("Would you like to restart the app?")
|
||||
.title("Update Installed")
|
||||
.ok_button_label("Restart")
|
||||
.cancel_button_label("Later")
|
||||
.buttons(MessageDialogButtons::OkCancelCustom(
|
||||
"Restart".to_string(),
|
||||
"Later".to_string(),
|
||||
))
|
||||
.blocking_show()
|
||||
{
|
||||
h.restart();
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
"active": true,
|
||||
"category": "DeveloperTool",
|
||||
"externalBin": [
|
||||
"vendored/protoc/yaakprotoc",
|
||||
"vendored/node/yaaknode"
|
||||
"vendored/node/yaaknode",
|
||||
"vendored/protoc/yaakprotoc"
|
||||
],
|
||||
"icon": [
|
||||
"icons/release/32x32.png",
|
||||
@@ -72,17 +72,14 @@
|
||||
"rpm"
|
||||
],
|
||||
"createUpdaterArtifacts": "v1Compatible",
|
||||
"iOS": {
|
||||
"developmentTeam": "7PU3P6ELJ8"
|
||||
},
|
||||
"macOS": {
|
||||
"minimumSystemVersion": "13.0",
|
||||
"exceptionDomain": "",
|
||||
"entitlements": "macos/entitlements.plist",
|
||||
"frameworks": []
|
||||
},
|
||||
"windows": {
|
||||
"digestAlgorithm": "sha256",
|
||||
"timestampUrl": ""
|
||||
"signCommand": "trusted-signing-cli -e https://eus.codesigning.azure.net/ -a Yaak -c yaakapp %1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
109
src-tauri/vendored/plugins/exporter-curl/build/index.js
generated
Normal file
109
src-tauri/vendored/plugins/exporter-curl/build/index.js
generated
Normal file
@@ -0,0 +1,109 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// src/index.ts
|
||||
var src_exports = {};
|
||||
__export(src_exports, {
|
||||
plugin: () => plugin,
|
||||
pluginHookExport: () => pluginHookExport
|
||||
});
|
||||
module.exports = __toCommonJS(src_exports);
|
||||
var NEWLINE = "\\\n ";
|
||||
var plugin = {
|
||||
httpRequestActions: [{
|
||||
key: "export-curl",
|
||||
label: "Copy as Curl",
|
||||
icon: "copy",
|
||||
async onSelect(ctx, args) {
|
||||
const rendered_request = await ctx.httpRequest.render({ httpRequest: args.httpRequest, purpose: "preview" });
|
||||
const data = await pluginHookExport(ctx, rendered_request);
|
||||
ctx.clipboard.copyText(data);
|
||||
ctx.toast.show({ message: "Curl copied to clipboard", icon: "copy" });
|
||||
}
|
||||
}]
|
||||
};
|
||||
async function pluginHookExport(_ctx, request) {
|
||||
const xs = ["curl"];
|
||||
if (request.method) xs.push("-X", request.method);
|
||||
if (request.url) xs.push(quote(request.url));
|
||||
xs.push(NEWLINE);
|
||||
for (const p of (request.urlParameters ?? []).filter(onlyEnabled)) {
|
||||
xs.push("--url-query", quote(`${p.name}=${p.value}`));
|
||||
xs.push(NEWLINE);
|
||||
}
|
||||
for (const h of (request.headers ?? []).filter(onlyEnabled)) {
|
||||
xs.push("--header", quote(`${h.name}: ${h.value}`));
|
||||
xs.push(NEWLINE);
|
||||
}
|
||||
if (Array.isArray(request.body?.form)) {
|
||||
const flag = request.bodyType === "multipart/form-data" ? "--form" : "--data";
|
||||
for (const p of (request.body?.form ?? []).filter(onlyEnabled)) {
|
||||
if (p.file) {
|
||||
let v = `${p.name}=@${p.file}`;
|
||||
v += p.contentType ? `;type=${p.contentType}` : "";
|
||||
xs.push(flag, v);
|
||||
} else {
|
||||
xs.push(flag, quote(`${p.name}=${p.value}`));
|
||||
}
|
||||
xs.push(NEWLINE);
|
||||
}
|
||||
} else if (typeof request.body?.query === "string") {
|
||||
const body = { query: request.body.query || "", variables: maybeParseJSON(request.body.variables, void 0) };
|
||||
xs.push("--data-raw", `${quote(JSON.stringify(body))}`);
|
||||
xs.push(NEWLINE);
|
||||
} else if (typeof request.body?.text === "string") {
|
||||
xs.push("--data-raw", `${quote(request.body.text)}`);
|
||||
xs.push(NEWLINE);
|
||||
}
|
||||
if (request.authenticationType === "basic" || request.authenticationType === "digest") {
|
||||
if (request.authenticationType === "digest") xs.push("--digest");
|
||||
xs.push(
|
||||
"--user",
|
||||
quote(`${request.authentication?.username ?? ""}:${request.authentication?.password ?? ""}`)
|
||||
);
|
||||
xs.push(NEWLINE);
|
||||
}
|
||||
if (request.authenticationType === "bearer") {
|
||||
xs.push("--header", quote(`Authorization: Bearer ${request.authentication?.token ?? ""}`));
|
||||
xs.push(NEWLINE);
|
||||
}
|
||||
if (xs[xs.length - 1] === NEWLINE) {
|
||||
xs.splice(xs.length - 1, 1);
|
||||
}
|
||||
return xs.join(" ");
|
||||
}
|
||||
function quote(arg) {
|
||||
const escaped = arg.replace(/'/g, "\\'");
|
||||
return `'${escaped}'`;
|
||||
}
|
||||
function onlyEnabled(v) {
|
||||
return v.enabled !== false && !!v.name;
|
||||
}
|
||||
function maybeParseJSON(v, fallback) {
|
||||
try {
|
||||
return JSON.parse(v);
|
||||
} catch (err) {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
plugin,
|
||||
pluginHookExport
|
||||
});
|
||||
9
src-tauri/vendored/plugins/exporter-curl/package.json
generated
Normal file
9
src-tauri/vendored/plugins/exporter-curl/package.json
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "@yaakapp/exporter-curl",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.js",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
}
|
||||
}
|
||||
510
src-tauri/vendored/plugins/filter-jsonpath/build/index.js
generated
Normal file
510
src-tauri/vendored/plugins/filter-jsonpath/build/index.js
generated
Normal file
@@ -0,0 +1,510 @@
|
||||
"use strict";
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||
// If the importer is in node compatibility mode or this is not an ESM
|
||||
// file that has been converted to a CommonJS file using a Babel-
|
||||
// compatible transform (i.e. "__esModule" has not been set), then set
|
||||
// "default" to the CommonJS "module.exports" for node compatibility.
|
||||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||
mod
|
||||
));
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// src/index.ts
|
||||
var src_exports = {};
|
||||
__export(src_exports, {
|
||||
pluginHookResponseFilter: () => pluginHookResponseFilter
|
||||
});
|
||||
module.exports = __toCommonJS(src_exports);
|
||||
|
||||
// ../../node_modules/jsonpath-plus/dist/index-node-esm.js
|
||||
var import_vm = __toESM(require("vm"), 1);
|
||||
var {
|
||||
hasOwnProperty: hasOwnProp
|
||||
} = Object.prototype;
|
||||
function push(arr, item) {
|
||||
arr = arr.slice();
|
||||
arr.push(item);
|
||||
return arr;
|
||||
}
|
||||
function unshift(item, arr) {
|
||||
arr = arr.slice();
|
||||
arr.unshift(item);
|
||||
return arr;
|
||||
}
|
||||
var NewError = class extends Error {
|
||||
/**
|
||||
* @param {AnyResult} value The evaluated scalar value
|
||||
*/
|
||||
constructor(value) {
|
||||
super('JSONPath should not be called with "new" (it prevents return of (unwrapped) scalar values)');
|
||||
this.avoidNew = true;
|
||||
this.value = value;
|
||||
this.name = "NewError";
|
||||
}
|
||||
};
|
||||
function JSONPath(opts, expr, obj, callback, otherTypeCallback) {
|
||||
if (!(this instanceof JSONPath)) {
|
||||
try {
|
||||
return new JSONPath(opts, expr, obj, callback, otherTypeCallback);
|
||||
} catch (e) {
|
||||
if (!e.avoidNew) {
|
||||
throw e;
|
||||
}
|
||||
return e.value;
|
||||
}
|
||||
}
|
||||
if (typeof opts === "string") {
|
||||
otherTypeCallback = callback;
|
||||
callback = obj;
|
||||
obj = expr;
|
||||
expr = opts;
|
||||
opts = null;
|
||||
}
|
||||
const optObj = opts && typeof opts === "object";
|
||||
opts = opts || {};
|
||||
this.json = opts.json || obj;
|
||||
this.path = opts.path || expr;
|
||||
this.resultType = opts.resultType || "value";
|
||||
this.flatten = opts.flatten || false;
|
||||
this.wrap = hasOwnProp.call(opts, "wrap") ? opts.wrap : true;
|
||||
this.sandbox = opts.sandbox || {};
|
||||
this.eval = opts.eval === void 0 ? "safe" : opts.eval;
|
||||
this.ignoreEvalErrors = typeof opts.ignoreEvalErrors === "undefined" ? false : opts.ignoreEvalErrors;
|
||||
this.parent = opts.parent || null;
|
||||
this.parentProperty = opts.parentProperty || null;
|
||||
this.callback = opts.callback || callback || null;
|
||||
this.otherTypeCallback = opts.otherTypeCallback || otherTypeCallback || function() {
|
||||
throw new TypeError("You must supply an otherTypeCallback callback option with the @other() operator.");
|
||||
};
|
||||
if (opts.autostart !== false) {
|
||||
const args = {
|
||||
path: optObj ? opts.path : expr
|
||||
};
|
||||
if (!optObj) {
|
||||
args.json = obj;
|
||||
} else if ("json" in opts) {
|
||||
args.json = opts.json;
|
||||
}
|
||||
const ret = this.evaluate(args);
|
||||
if (!ret || typeof ret !== "object") {
|
||||
throw new NewError(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
JSONPath.prototype.evaluate = function(expr, json, callback, otherTypeCallback) {
|
||||
let currParent = this.parent, currParentProperty = this.parentProperty;
|
||||
let {
|
||||
flatten,
|
||||
wrap
|
||||
} = this;
|
||||
this.currResultType = this.resultType;
|
||||
this.currEval = this.eval;
|
||||
this.currSandbox = this.sandbox;
|
||||
callback = callback || this.callback;
|
||||
this.currOtherTypeCallback = otherTypeCallback || this.otherTypeCallback;
|
||||
json = json || this.json;
|
||||
expr = expr || this.path;
|
||||
if (expr && typeof expr === "object" && !Array.isArray(expr)) {
|
||||
if (!expr.path && expr.path !== "") {
|
||||
throw new TypeError('You must supply a "path" property when providing an object argument to JSONPath.evaluate().');
|
||||
}
|
||||
if (!hasOwnProp.call(expr, "json")) {
|
||||
throw new TypeError('You must supply a "json" property when providing an object argument to JSONPath.evaluate().');
|
||||
}
|
||||
({
|
||||
json
|
||||
} = expr);
|
||||
flatten = hasOwnProp.call(expr, "flatten") ? expr.flatten : flatten;
|
||||
this.currResultType = hasOwnProp.call(expr, "resultType") ? expr.resultType : this.currResultType;
|
||||
this.currSandbox = hasOwnProp.call(expr, "sandbox") ? expr.sandbox : this.currSandbox;
|
||||
wrap = hasOwnProp.call(expr, "wrap") ? expr.wrap : wrap;
|
||||
this.currEval = hasOwnProp.call(expr, "eval") ? expr.eval : this.currEval;
|
||||
callback = hasOwnProp.call(expr, "callback") ? expr.callback : callback;
|
||||
this.currOtherTypeCallback = hasOwnProp.call(expr, "otherTypeCallback") ? expr.otherTypeCallback : this.currOtherTypeCallback;
|
||||
currParent = hasOwnProp.call(expr, "parent") ? expr.parent : currParent;
|
||||
currParentProperty = hasOwnProp.call(expr, "parentProperty") ? expr.parentProperty : currParentProperty;
|
||||
expr = expr.path;
|
||||
}
|
||||
currParent = currParent || null;
|
||||
currParentProperty = currParentProperty || null;
|
||||
if (Array.isArray(expr)) {
|
||||
expr = JSONPath.toPathString(expr);
|
||||
}
|
||||
if (!expr && expr !== "" || !json) {
|
||||
return void 0;
|
||||
}
|
||||
const exprList = JSONPath.toPathArray(expr);
|
||||
if (exprList[0] === "$" && exprList.length > 1) {
|
||||
exprList.shift();
|
||||
}
|
||||
this._hasParentSelector = null;
|
||||
const result = this._trace(exprList, json, ["$"], currParent, currParentProperty, callback).filter(function(ea) {
|
||||
return ea && !ea.isParentSelector;
|
||||
});
|
||||
if (!result.length) {
|
||||
return wrap ? [] : void 0;
|
||||
}
|
||||
if (!wrap && result.length === 1 && !result[0].hasArrExpr) {
|
||||
return this._getPreferredOutput(result[0]);
|
||||
}
|
||||
return result.reduce((rslt, ea) => {
|
||||
const valOrPath = this._getPreferredOutput(ea);
|
||||
if (flatten && Array.isArray(valOrPath)) {
|
||||
rslt = rslt.concat(valOrPath);
|
||||
} else {
|
||||
rslt.push(valOrPath);
|
||||
}
|
||||
return rslt;
|
||||
}, []);
|
||||
};
|
||||
JSONPath.prototype._getPreferredOutput = function(ea) {
|
||||
const resultType = this.currResultType;
|
||||
switch (resultType) {
|
||||
case "all": {
|
||||
const path = Array.isArray(ea.path) ? ea.path : JSONPath.toPathArray(ea.path);
|
||||
ea.pointer = JSONPath.toPointer(path);
|
||||
ea.path = typeof ea.path === "string" ? ea.path : JSONPath.toPathString(ea.path);
|
||||
return ea;
|
||||
}
|
||||
case "value":
|
||||
case "parent":
|
||||
case "parentProperty":
|
||||
return ea[resultType];
|
||||
case "path":
|
||||
return JSONPath.toPathString(ea[resultType]);
|
||||
case "pointer":
|
||||
return JSONPath.toPointer(ea.path);
|
||||
default:
|
||||
throw new TypeError("Unknown result type");
|
||||
}
|
||||
};
|
||||
JSONPath.prototype._handleCallback = function(fullRetObj, callback, type) {
|
||||
if (callback) {
|
||||
const preferredOutput = this._getPreferredOutput(fullRetObj);
|
||||
fullRetObj.path = typeof fullRetObj.path === "string" ? fullRetObj.path : JSONPath.toPathString(fullRetObj.path);
|
||||
callback(preferredOutput, type, fullRetObj);
|
||||
}
|
||||
};
|
||||
JSONPath.prototype._trace = function(expr, val, path, parent, parentPropName, callback, hasArrExpr, literalPriority) {
|
||||
let retObj;
|
||||
if (!expr.length) {
|
||||
retObj = {
|
||||
path,
|
||||
value: val,
|
||||
parent,
|
||||
parentProperty: parentPropName,
|
||||
hasArrExpr
|
||||
};
|
||||
this._handleCallback(retObj, callback, "value");
|
||||
return retObj;
|
||||
}
|
||||
const loc = expr[0], x = expr.slice(1);
|
||||
const ret = [];
|
||||
function addRet(elems) {
|
||||
if (Array.isArray(elems)) {
|
||||
elems.forEach((t) => {
|
||||
ret.push(t);
|
||||
});
|
||||
} else {
|
||||
ret.push(elems);
|
||||
}
|
||||
}
|
||||
if ((typeof loc !== "string" || literalPriority) && val && hasOwnProp.call(val, loc)) {
|
||||
addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback, hasArrExpr));
|
||||
} else if (loc === "*") {
|
||||
this._walk(val, (m) => {
|
||||
addRet(this._trace(x, val[m], push(path, m), val, m, callback, true, true));
|
||||
});
|
||||
} else if (loc === "..") {
|
||||
addRet(this._trace(x, val, path, parent, parentPropName, callback, hasArrExpr));
|
||||
this._walk(val, (m) => {
|
||||
if (typeof val[m] === "object") {
|
||||
addRet(this._trace(expr.slice(), val[m], push(path, m), val, m, callback, true));
|
||||
}
|
||||
});
|
||||
} else if (loc === "^") {
|
||||
this._hasParentSelector = true;
|
||||
return {
|
||||
path: path.slice(0, -1),
|
||||
expr: x,
|
||||
isParentSelector: true
|
||||
};
|
||||
} else if (loc === "~") {
|
||||
retObj = {
|
||||
path: push(path, loc),
|
||||
value: parentPropName,
|
||||
parent,
|
||||
parentProperty: null
|
||||
};
|
||||
this._handleCallback(retObj, callback, "property");
|
||||
return retObj;
|
||||
} else if (loc === "$") {
|
||||
addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));
|
||||
} else if (/^(-?\d*):(-?\d*):?(\d*)$/u.test(loc)) {
|
||||
addRet(this._slice(loc, x, val, path, parent, parentPropName, callback));
|
||||
} else if (loc.indexOf("?(") === 0) {
|
||||
if (this.currEval === false) {
|
||||
throw new Error("Eval [?(expr)] prevented in JSONPath expression.");
|
||||
}
|
||||
const safeLoc = loc.replace(/^\?\((.*?)\)$/u, "$1");
|
||||
const nested = /@.?([^?]*)[['](\??\(.*?\))(?!.\)\])[\]']/gu.exec(safeLoc);
|
||||
if (nested) {
|
||||
this._walk(val, (m) => {
|
||||
const npath = [nested[2]];
|
||||
const nvalue = nested[1] ? val[m][nested[1]] : val[m];
|
||||
const filterResults = this._trace(npath, nvalue, path, parent, parentPropName, callback, true);
|
||||
if (filterResults.length > 0) {
|
||||
addRet(this._trace(x, val[m], push(path, m), val, m, callback, true));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this._walk(val, (m) => {
|
||||
if (this._eval(safeLoc, val[m], m, path, parent, parentPropName)) {
|
||||
addRet(this._trace(x, val[m], push(path, m), val, m, callback, true));
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (loc[0] === "(") {
|
||||
if (this.currEval === false) {
|
||||
throw new Error("Eval [(expr)] prevented in JSONPath expression.");
|
||||
}
|
||||
addRet(this._trace(unshift(this._eval(loc, val, path[path.length - 1], path.slice(0, -1), parent, parentPropName), x), val, path, parent, parentPropName, callback, hasArrExpr));
|
||||
} else if (loc[0] === "@") {
|
||||
let addType = false;
|
||||
const valueType = loc.slice(1, -2);
|
||||
switch (valueType) {
|
||||
case "scalar":
|
||||
if (!val || !["object", "function"].includes(typeof val)) {
|
||||
addType = true;
|
||||
}
|
||||
break;
|
||||
case "boolean":
|
||||
case "string":
|
||||
case "undefined":
|
||||
case "function":
|
||||
if (typeof val === valueType) {
|
||||
addType = true;
|
||||
}
|
||||
break;
|
||||
case "integer":
|
||||
if (Number.isFinite(val) && !(val % 1)) {
|
||||
addType = true;
|
||||
}
|
||||
break;
|
||||
case "number":
|
||||
if (Number.isFinite(val)) {
|
||||
addType = true;
|
||||
}
|
||||
break;
|
||||
case "nonFinite":
|
||||
if (typeof val === "number" && !Number.isFinite(val)) {
|
||||
addType = true;
|
||||
}
|
||||
break;
|
||||
case "object":
|
||||
if (val && typeof val === valueType) {
|
||||
addType = true;
|
||||
}
|
||||
break;
|
||||
case "array":
|
||||
if (Array.isArray(val)) {
|
||||
addType = true;
|
||||
}
|
||||
break;
|
||||
case "other":
|
||||
addType = this.currOtherTypeCallback(val, path, parent, parentPropName);
|
||||
break;
|
||||
case "null":
|
||||
if (val === null) {
|
||||
addType = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new TypeError("Unknown value type " + valueType);
|
||||
}
|
||||
if (addType) {
|
||||
retObj = {
|
||||
path,
|
||||
value: val,
|
||||
parent,
|
||||
parentProperty: parentPropName
|
||||
};
|
||||
this._handleCallback(retObj, callback, "value");
|
||||
return retObj;
|
||||
}
|
||||
} else if (loc[0] === "`" && val && hasOwnProp.call(val, loc.slice(1))) {
|
||||
const locProp = loc.slice(1);
|
||||
addRet(this._trace(x, val[locProp], push(path, locProp), val, locProp, callback, hasArrExpr, true));
|
||||
} else if (loc.includes(",")) {
|
||||
const parts = loc.split(",");
|
||||
for (const part of parts) {
|
||||
addRet(this._trace(unshift(part, x), val, path, parent, parentPropName, callback, true));
|
||||
}
|
||||
} else if (!literalPriority && val && hasOwnProp.call(val, loc)) {
|
||||
addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback, hasArrExpr, true));
|
||||
}
|
||||
if (this._hasParentSelector) {
|
||||
for (let t = 0; t < ret.length; t++) {
|
||||
const rett = ret[t];
|
||||
if (rett && rett.isParentSelector) {
|
||||
const tmp = this._trace(rett.expr, val, rett.path, parent, parentPropName, callback, hasArrExpr);
|
||||
if (Array.isArray(tmp)) {
|
||||
ret[t] = tmp[0];
|
||||
const tl = tmp.length;
|
||||
for (let tt = 1; tt < tl; tt++) {
|
||||
t++;
|
||||
ret.splice(t, 0, tmp[tt]);
|
||||
}
|
||||
} else {
|
||||
ret[t] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
JSONPath.prototype._walk = function(val, f) {
|
||||
if (Array.isArray(val)) {
|
||||
const n = val.length;
|
||||
for (let i = 0; i < n; i++) {
|
||||
f(i);
|
||||
}
|
||||
} else if (val && typeof val === "object") {
|
||||
Object.keys(val).forEach((m) => {
|
||||
f(m);
|
||||
});
|
||||
}
|
||||
};
|
||||
JSONPath.prototype._slice = function(loc, expr, val, path, parent, parentPropName, callback) {
|
||||
if (!Array.isArray(val)) {
|
||||
return void 0;
|
||||
}
|
||||
const len = val.length, parts = loc.split(":"), step = parts[2] && Number.parseInt(parts[2]) || 1;
|
||||
let start = parts[0] && Number.parseInt(parts[0]) || 0, end = parts[1] && Number.parseInt(parts[1]) || len;
|
||||
start = start < 0 ? Math.max(0, start + len) : Math.min(len, start);
|
||||
end = end < 0 ? Math.max(0, end + len) : Math.min(len, end);
|
||||
const ret = [];
|
||||
for (let i = start; i < end; i += step) {
|
||||
const tmp = this._trace(unshift(i, expr), val, path, parent, parentPropName, callback, true);
|
||||
tmp.forEach((t) => {
|
||||
ret.push(t);
|
||||
});
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
JSONPath.prototype._eval = function(code, _v, _vname, path, parent, parentPropName) {
|
||||
this.currSandbox._$_parentProperty = parentPropName;
|
||||
this.currSandbox._$_parent = parent;
|
||||
this.currSandbox._$_property = _vname;
|
||||
this.currSandbox._$_root = this.json;
|
||||
this.currSandbox._$_v = _v;
|
||||
const containsPath = code.includes("@path");
|
||||
if (containsPath) {
|
||||
this.currSandbox._$_path = JSONPath.toPathString(path.concat([_vname]));
|
||||
}
|
||||
const scriptCacheKey = this.currEval + "Script:" + code;
|
||||
if (!JSONPath.cache[scriptCacheKey]) {
|
||||
let script = code.replace(/@parentProperty/gu, "_$_parentProperty").replace(/@parent/gu, "_$_parent").replace(/@property/gu, "_$_property").replace(/@root/gu, "_$_root").replace(/@([.\s)[])/gu, "_$_v$1");
|
||||
if (containsPath) {
|
||||
script = script.replace(/@path/gu, "_$_path");
|
||||
}
|
||||
if (this.currEval === "safe" || this.currEval === true || this.currEval === void 0) {
|
||||
JSONPath.cache[scriptCacheKey] = new this.safeVm.Script(script);
|
||||
} else if (this.currEval === "native") {
|
||||
JSONPath.cache[scriptCacheKey] = new this.vm.Script(script);
|
||||
} else if (typeof this.currEval === "function" && this.currEval.prototype && hasOwnProp.call(this.currEval.prototype, "runInNewContext")) {
|
||||
const CurrEval = this.currEval;
|
||||
JSONPath.cache[scriptCacheKey] = new CurrEval(script);
|
||||
} else if (typeof this.currEval === "function") {
|
||||
JSONPath.cache[scriptCacheKey] = {
|
||||
runInNewContext: (context) => this.currEval(script, context)
|
||||
};
|
||||
} else {
|
||||
throw new TypeError(`Unknown "eval" property "${this.currEval}"`);
|
||||
}
|
||||
}
|
||||
try {
|
||||
return JSONPath.cache[scriptCacheKey].runInNewContext(this.currSandbox);
|
||||
} catch (e) {
|
||||
if (this.ignoreEvalErrors) {
|
||||
return false;
|
||||
}
|
||||
throw new Error("jsonPath: " + e.message + ": " + code);
|
||||
}
|
||||
};
|
||||
JSONPath.cache = {};
|
||||
JSONPath.toPathString = function(pathArr) {
|
||||
const x = pathArr, n = x.length;
|
||||
let p = "$";
|
||||
for (let i = 1; i < n; i++) {
|
||||
if (!/^(~|\^|@.*?\(\))$/u.test(x[i])) {
|
||||
p += /^[0-9*]+$/u.test(x[i]) ? "[" + x[i] + "]" : "['" + x[i] + "']";
|
||||
}
|
||||
}
|
||||
return p;
|
||||
};
|
||||
JSONPath.toPointer = function(pointer) {
|
||||
const x = pointer, n = x.length;
|
||||
let p = "";
|
||||
for (let i = 1; i < n; i++) {
|
||||
if (!/^(~|\^|@.*?\(\))$/u.test(x[i])) {
|
||||
p += "/" + x[i].toString().replace(/~/gu, "~0").replace(/\//gu, "~1");
|
||||
}
|
||||
}
|
||||
return p;
|
||||
};
|
||||
JSONPath.toPathArray = function(expr) {
|
||||
const {
|
||||
cache
|
||||
} = JSONPath;
|
||||
if (cache[expr]) {
|
||||
return cache[expr].concat();
|
||||
}
|
||||
const subx = [];
|
||||
const normalized = expr.replace(/@(?:null|boolean|number|string|integer|undefined|nonFinite|scalar|array|object|function|other)\(\)/gu, ";$&;").replace(/[['](\??\(.*?\))[\]'](?!.\])/gu, function($0, $1) {
|
||||
return "[#" + (subx.push($1) - 1) + "]";
|
||||
}).replace(/\[['"]([^'\]]*)['"]\]/gu, function($0, prop) {
|
||||
return "['" + prop.replace(/\./gu, "%@%").replace(/~/gu, "%%@@%%") + "']";
|
||||
}).replace(/~/gu, ";~;").replace(/['"]?\.['"]?(?![^[]*\])|\[['"]?/gu, ";").replace(/%@%/gu, ".").replace(/%%@@%%/gu, "~").replace(/(?:;)?(\^+)(?:;)?/gu, function($0, ups) {
|
||||
return ";" + ups.split("").join(";") + ";";
|
||||
}).replace(/;;;|;;/gu, ";..;").replace(/;$|'?\]|'$/gu, "");
|
||||
const exprList = normalized.split(";").map(function(exp) {
|
||||
const match = exp.match(/#(\d+)/u);
|
||||
return !match || !match[1] ? exp : subx[match[1]];
|
||||
});
|
||||
cache[expr] = exprList;
|
||||
return cache[expr].concat();
|
||||
};
|
||||
JSONPath.prototype.vm = import_vm.default;
|
||||
JSONPath.prototype.safeVm = import_vm.default;
|
||||
var SafeScript = import_vm.default.Script;
|
||||
|
||||
// src/index.ts
|
||||
function pluginHookResponseFilter(_ctx, args) {
|
||||
const parsed = JSON.parse(args.body);
|
||||
const filtered = JSONPath({ path: args.filter, json: parsed });
|
||||
return JSON.stringify(filtered, null, 2);
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
pluginHookResponseFilter
|
||||
});
|
||||
15
src-tauri/vendored/plugins/filter-jsonpath/package.json
generated
Normal file
15
src-tauri/vendored/plugins/filter-jsonpath/package.json
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "@yaakapp/filter-jsonpath",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsonpath-plus": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jsonpath": "^0.2.4"
|
||||
}
|
||||
}
|
||||
8366
src-tauri/vendored/plugins/filter-xpath/build/index.js
generated
Normal file
8366
src-tauri/vendored/plugins/filter-xpath/build/index.js
generated
Normal file
File diff suppressed because it is too large
Load Diff
13
src-tauri/vendored/plugins/filter-xpath/package.json
generated
Normal file
13
src-tauri/vendored/plugins/filter-xpath/package.json
generated
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "@yaakapp/filter-xpath",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.js",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@xmldom/xmldom": "^0.8.10",
|
||||
"xpath": "^0.0.34"
|
||||
}
|
||||
}
|
||||
574
src-tauri/vendored/plugins/importer-curl/build/index.js
generated
Normal file
574
src-tauri/vendored/plugins/importer-curl/build/index.js
generated
Normal file
@@ -0,0 +1,574 @@
|
||||
"use strict";
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __commonJS = (cb, mod) => function __require() {
|
||||
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
||||
};
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||
// If the importer is in node compatibility mode or this is not an ESM
|
||||
// file that has been converted to a CommonJS file using a Babel-
|
||||
// compatible transform (i.e. "__esModule" has not been set), then set
|
||||
// "default" to the CommonJS "module.exports" for node compatibility.
|
||||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||
mod
|
||||
));
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// ../../node_modules/shell-quote/quote.js
|
||||
var require_quote = __commonJS({
|
||||
"../../node_modules/shell-quote/quote.js"(exports2, module2) {
|
||||
"use strict";
|
||||
module2.exports = function quote(xs) {
|
||||
return xs.map(function(s) {
|
||||
if (s && typeof s === "object") {
|
||||
return s.op.replace(/(.)/g, "\\$1");
|
||||
}
|
||||
if (/["\s]/.test(s) && !/'/.test(s)) {
|
||||
return "'" + s.replace(/(['\\])/g, "\\$1") + "'";
|
||||
}
|
||||
if (/["'\s]/.test(s)) {
|
||||
return '"' + s.replace(/(["\\$`!])/g, "\\$1") + '"';
|
||||
}
|
||||
return String(s).replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}])/g, "$1\\$2");
|
||||
}).join(" ");
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// ../../node_modules/shell-quote/parse.js
|
||||
var require_parse = __commonJS({
|
||||
"../../node_modules/shell-quote/parse.js"(exports2, module2) {
|
||||
"use strict";
|
||||
var CONTROL = "(?:" + [
|
||||
"\\|\\|",
|
||||
"\\&\\&",
|
||||
";;",
|
||||
"\\|\\&",
|
||||
"\\<\\(",
|
||||
"\\<\\<\\<",
|
||||
">>",
|
||||
">\\&",
|
||||
"<\\&",
|
||||
"[&;()|<>]"
|
||||
].join("|") + ")";
|
||||
var controlRE = new RegExp("^" + CONTROL + "$");
|
||||
var META = "|&;()<> \\t";
|
||||
var SINGLE_QUOTE = '"((\\\\"|[^"])*?)"';
|
||||
var DOUBLE_QUOTE = "'((\\\\'|[^'])*?)'";
|
||||
var hash = /^#$/;
|
||||
var SQ = "'";
|
||||
var DQ = '"';
|
||||
var DS = "$";
|
||||
var TOKEN = "";
|
||||
var mult = 4294967296;
|
||||
for (i = 0; i < 4; i++) {
|
||||
TOKEN += (mult * Math.random()).toString(16);
|
||||
}
|
||||
var i;
|
||||
var startsWithToken = new RegExp("^" + TOKEN);
|
||||
function matchAll(s, r) {
|
||||
var origIndex = r.lastIndex;
|
||||
var matches = [];
|
||||
var matchObj;
|
||||
while (matchObj = r.exec(s)) {
|
||||
matches.push(matchObj);
|
||||
if (r.lastIndex === matchObj.index) {
|
||||
r.lastIndex += 1;
|
||||
}
|
||||
}
|
||||
r.lastIndex = origIndex;
|
||||
return matches;
|
||||
}
|
||||
function getVar(env, pre, key) {
|
||||
var r = typeof env === "function" ? env(key) : env[key];
|
||||
if (typeof r === "undefined" && key != "") {
|
||||
r = "";
|
||||
} else if (typeof r === "undefined") {
|
||||
r = "$";
|
||||
}
|
||||
if (typeof r === "object") {
|
||||
return pre + TOKEN + JSON.stringify(r) + TOKEN;
|
||||
}
|
||||
return pre + r;
|
||||
}
|
||||
function parseInternal(string, env, opts) {
|
||||
if (!opts) {
|
||||
opts = {};
|
||||
}
|
||||
var BS = opts.escape || "\\";
|
||||
var BAREWORD = "(\\" + BS + `['"` + META + `]|[^\\s'"` + META + "])+";
|
||||
var chunker = new RegExp([
|
||||
"(" + CONTROL + ")",
|
||||
// control chars
|
||||
"(" + BAREWORD + "|" + SINGLE_QUOTE + "|" + DOUBLE_QUOTE + ")+"
|
||||
].join("|"), "g");
|
||||
var matches = matchAll(string, chunker);
|
||||
if (matches.length === 0) {
|
||||
return [];
|
||||
}
|
||||
if (!env) {
|
||||
env = {};
|
||||
}
|
||||
var commented = false;
|
||||
return matches.map(function(match) {
|
||||
var s = match[0];
|
||||
if (!s || commented) {
|
||||
return void 0;
|
||||
}
|
||||
if (controlRE.test(s)) {
|
||||
return { op: s };
|
||||
}
|
||||
var quote = false;
|
||||
var esc = false;
|
||||
var out = "";
|
||||
var isGlob = false;
|
||||
var i2;
|
||||
function parseEnvVar() {
|
||||
i2 += 1;
|
||||
var varend;
|
||||
var varname;
|
||||
var char = s.charAt(i2);
|
||||
if (char === "{") {
|
||||
i2 += 1;
|
||||
if (s.charAt(i2) === "}") {
|
||||
throw new Error("Bad substitution: " + s.slice(i2 - 2, i2 + 1));
|
||||
}
|
||||
varend = s.indexOf("}", i2);
|
||||
if (varend < 0) {
|
||||
throw new Error("Bad substitution: " + s.slice(i2));
|
||||
}
|
||||
varname = s.slice(i2, varend);
|
||||
i2 = varend;
|
||||
} else if (/[*@#?$!_-]/.test(char)) {
|
||||
varname = char;
|
||||
i2 += 1;
|
||||
} else {
|
||||
var slicedFromI = s.slice(i2);
|
||||
varend = slicedFromI.match(/[^\w\d_]/);
|
||||
if (!varend) {
|
||||
varname = slicedFromI;
|
||||
i2 = s.length;
|
||||
} else {
|
||||
varname = slicedFromI.slice(0, varend.index);
|
||||
i2 += varend.index - 1;
|
||||
}
|
||||
}
|
||||
return getVar(env, "", varname);
|
||||
}
|
||||
for (i2 = 0; i2 < s.length; i2++) {
|
||||
var c = s.charAt(i2);
|
||||
isGlob = isGlob || !quote && (c === "*" || c === "?");
|
||||
if (esc) {
|
||||
out += c;
|
||||
esc = false;
|
||||
} else if (quote) {
|
||||
if (c === quote) {
|
||||
quote = false;
|
||||
} else if (quote == SQ) {
|
||||
out += c;
|
||||
} else {
|
||||
if (c === BS) {
|
||||
i2 += 1;
|
||||
c = s.charAt(i2);
|
||||
if (c === DQ || c === BS || c === DS) {
|
||||
out += c;
|
||||
} else {
|
||||
out += BS + c;
|
||||
}
|
||||
} else if (c === DS) {
|
||||
out += parseEnvVar();
|
||||
} else {
|
||||
out += c;
|
||||
}
|
||||
}
|
||||
} else if (c === DQ || c === SQ) {
|
||||
quote = c;
|
||||
} else if (controlRE.test(c)) {
|
||||
return { op: s };
|
||||
} else if (hash.test(c)) {
|
||||
commented = true;
|
||||
var commentObj = { comment: string.slice(match.index + i2 + 1) };
|
||||
if (out.length) {
|
||||
return [out, commentObj];
|
||||
}
|
||||
return [commentObj];
|
||||
} else if (c === BS) {
|
||||
esc = true;
|
||||
} else if (c === DS) {
|
||||
out += parseEnvVar();
|
||||
} else {
|
||||
out += c;
|
||||
}
|
||||
}
|
||||
if (isGlob) {
|
||||
return { op: "glob", pattern: out };
|
||||
}
|
||||
return out;
|
||||
}).reduce(function(prev, arg) {
|
||||
return typeof arg === "undefined" ? prev : prev.concat(arg);
|
||||
}, []);
|
||||
}
|
||||
module2.exports = function parse2(s, env, opts) {
|
||||
var mapped = parseInternal(s, env, opts);
|
||||
if (typeof env !== "function") {
|
||||
return mapped;
|
||||
}
|
||||
return mapped.reduce(function(acc, s2) {
|
||||
if (typeof s2 === "object") {
|
||||
return acc.concat(s2);
|
||||
}
|
||||
var xs = s2.split(RegExp("(" + TOKEN + ".*?" + TOKEN + ")", "g"));
|
||||
if (xs.length === 1) {
|
||||
return acc.concat(xs[0]);
|
||||
}
|
||||
return acc.concat(xs.filter(Boolean).map(function(x) {
|
||||
if (startsWithToken.test(x)) {
|
||||
return JSON.parse(x.split(TOKEN)[1]);
|
||||
}
|
||||
return x;
|
||||
}));
|
||||
}, []);
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// ../../node_modules/shell-quote/index.js
|
||||
var require_shell_quote = __commonJS({
|
||||
"../../node_modules/shell-quote/index.js"(exports2) {
|
||||
"use strict";
|
||||
exports2.quote = require_quote();
|
||||
exports2.parse = require_parse();
|
||||
}
|
||||
});
|
||||
|
||||
// src/index.ts
|
||||
var src_exports = {};
|
||||
__export(src_exports, {
|
||||
pluginHookImport: () => pluginHookImport
|
||||
});
|
||||
module.exports = __toCommonJS(src_exports);
|
||||
var import_shell_quote = __toESM(require_shell_quote());
|
||||
var DATA_FLAGS = ["d", "data", "data-raw", "data-urlencode", "data-binary", "data-ascii"];
|
||||
var SUPPORTED_FLAGS = [
|
||||
["cookie", "b"],
|
||||
["d", "data"],
|
||||
// Add url encoded data
|
||||
["data-ascii"],
|
||||
["data-binary"],
|
||||
["data-raw"],
|
||||
["data-urlencode"],
|
||||
["digest"],
|
||||
// Apply auth as digest
|
||||
["form", "F"],
|
||||
// Add multipart data
|
||||
["get", "G"],
|
||||
// Put the post data in the URL
|
||||
["header", "H"],
|
||||
["request", "X"],
|
||||
// Request method
|
||||
["url"],
|
||||
// Specify the URL explicitly
|
||||
["url-query"],
|
||||
["user", "u"],
|
||||
// Authentication
|
||||
DATA_FLAGS
|
||||
].flatMap((v) => v);
|
||||
var BOOLEAN_FLAGS = ["G", "get", "digest"];
|
||||
function pluginHookImport(_ctx, rawData) {
|
||||
if (!rawData.match(/^\s*curl /)) {
|
||||
return null;
|
||||
}
|
||||
const commands = [];
|
||||
const normalizedData = rawData.replace(/\ncurl/g, "; curl");
|
||||
let currentCommand = [];
|
||||
const parsed = (0, import_shell_quote.parse)(normalizedData);
|
||||
const normalizedParseEntries = parsed.flatMap((entry) => {
|
||||
if (typeof entry === "string" && entry.startsWith("-") && !entry.startsWith("--") && entry.length > 2) {
|
||||
return [entry.slice(0, 2), entry.slice(2)];
|
||||
}
|
||||
return entry;
|
||||
});
|
||||
for (const parseEntry of normalizedParseEntries) {
|
||||
if (typeof parseEntry === "string") {
|
||||
if (parseEntry.startsWith("$")) {
|
||||
currentCommand.push(parseEntry.slice(1));
|
||||
} else {
|
||||
currentCommand.push(parseEntry);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ("comment" in parseEntry) {
|
||||
continue;
|
||||
}
|
||||
const { op } = parseEntry;
|
||||
if (op === ";") {
|
||||
commands.push(currentCommand);
|
||||
currentCommand = [];
|
||||
continue;
|
||||
}
|
||||
if (op?.startsWith("$")) {
|
||||
const str = op.slice(2, op.length - 1).replace(/\\'/g, "'");
|
||||
currentCommand.push(str);
|
||||
continue;
|
||||
}
|
||||
if (op === "glob") {
|
||||
currentCommand.push(parseEntry.pattern);
|
||||
}
|
||||
}
|
||||
commands.push(currentCommand);
|
||||
const workspace = {
|
||||
model: "workspace",
|
||||
id: generateId("workspace"),
|
||||
name: "Curl Import"
|
||||
};
|
||||
const requests = commands.filter((command) => command[0] === "curl").map((v) => importCommand(v, workspace.id));
|
||||
return {
|
||||
resources: {
|
||||
httpRequests: requests,
|
||||
workspaces: [workspace]
|
||||
}
|
||||
};
|
||||
}
|
||||
function importCommand(parseEntries, workspaceId) {
|
||||
const flagsByName = {};
|
||||
const singletons = [];
|
||||
for (let i = 1; i < parseEntries.length; i++) {
|
||||
let parseEntry = parseEntries[i];
|
||||
if (typeof parseEntry === "string") {
|
||||
parseEntry = parseEntry.trim();
|
||||
}
|
||||
if (typeof parseEntry === "string" && parseEntry.match(/^-{1,2}[\w-]+/)) {
|
||||
const isSingleDash = parseEntry[0] === "-" && parseEntry[1] !== "-";
|
||||
let name = parseEntry.replace(/^-{1,2}/, "");
|
||||
if (!SUPPORTED_FLAGS.includes(name)) {
|
||||
continue;
|
||||
}
|
||||
let value;
|
||||
const nextEntry = parseEntries[i + 1];
|
||||
const hasValue = !BOOLEAN_FLAGS.includes(name);
|
||||
if (isSingleDash && name.length > 1) {
|
||||
value = name.slice(1);
|
||||
name = name.slice(0, 1);
|
||||
} else if (typeof nextEntry === "string" && hasValue && !nextEntry.startsWith("-")) {
|
||||
value = nextEntry;
|
||||
i++;
|
||||
} else {
|
||||
value = true;
|
||||
}
|
||||
flagsByName[name] = flagsByName[name] || [];
|
||||
flagsByName[name].push(value);
|
||||
} else if (parseEntry) {
|
||||
singletons.push(parseEntry);
|
||||
}
|
||||
}
|
||||
let urlParameters;
|
||||
let url;
|
||||
const urlArg = getPairValue(flagsByName, singletons[0] || "", ["url"]);
|
||||
const [baseUrl, search] = splitOnce(urlArg, "?");
|
||||
urlParameters = search?.split("&").map((p) => {
|
||||
const v = splitOnce(p, "=");
|
||||
return { name: decodeURIComponent(v[0] ?? ""), value: decodeURIComponent(v[1] ?? ""), enabled: true };
|
||||
}) ?? [];
|
||||
url = baseUrl ?? urlArg;
|
||||
for (const p of flagsByName["url-query"] ?? []) {
|
||||
if (typeof p !== "string") {
|
||||
continue;
|
||||
}
|
||||
const [name, value] = p.split("=");
|
||||
urlParameters.push({
|
||||
name: name ?? "",
|
||||
value: value ?? "",
|
||||
enabled: true
|
||||
});
|
||||
}
|
||||
const [username, password] = getPairValue(flagsByName, "", ["u", "user"]).split(/:(.*)$/);
|
||||
const isDigest = getPairValue(flagsByName, false, ["digest"]);
|
||||
const authenticationType = username ? isDigest ? "digest" : "basic" : null;
|
||||
const authentication = username ? {
|
||||
username: username.trim(),
|
||||
password: (password ?? "").trim()
|
||||
} : {};
|
||||
const headers = [
|
||||
...flagsByName["header"] || [],
|
||||
...flagsByName["H"] || []
|
||||
].map((header) => {
|
||||
const [name, value] = header.split(/:(.*)$/);
|
||||
if (!value) {
|
||||
return {
|
||||
name: (name ?? "").trim().replace(/;$/, ""),
|
||||
value: "",
|
||||
enabled: true
|
||||
};
|
||||
}
|
||||
return {
|
||||
name: (name ?? "").trim(),
|
||||
value: value.trim(),
|
||||
enabled: true
|
||||
};
|
||||
});
|
||||
const cookieHeaderValue = [
|
||||
...flagsByName["cookie"] || [],
|
||||
...flagsByName["b"] || []
|
||||
].map((str) => {
|
||||
const name = str.split("=", 1)[0];
|
||||
const value = str.replace(`${name}=`, "");
|
||||
return `${name}=${value}`;
|
||||
}).join("; ");
|
||||
const existingCookieHeader = headers.find((header) => header.name.toLowerCase() === "cookie");
|
||||
if (cookieHeaderValue && existingCookieHeader) {
|
||||
existingCookieHeader.value += `; ${cookieHeaderValue}`;
|
||||
} else if (cookieHeaderValue) {
|
||||
headers.push({
|
||||
name: "Cookie",
|
||||
value: cookieHeaderValue,
|
||||
enabled: true
|
||||
});
|
||||
}
|
||||
const dataParameters = pairsToDataParameters(flagsByName);
|
||||
const contentTypeHeader = headers.find((header) => header.name.toLowerCase() === "content-type");
|
||||
const mimeType = contentTypeHeader ? contentTypeHeader.value.split(";")[0] : null;
|
||||
const formDataParams = [
|
||||
...flagsByName["form"] || [],
|
||||
...flagsByName["F"] || []
|
||||
].map((str) => {
|
||||
const parts = str.split("=");
|
||||
const name = parts[0] ?? "";
|
||||
const value = parts[1] ?? "";
|
||||
const item = {
|
||||
name,
|
||||
enabled: true
|
||||
};
|
||||
if (value.indexOf("@") === 0) {
|
||||
item["file"] = value.slice(1);
|
||||
} else {
|
||||
item["value"] = value;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
let body = {};
|
||||
let bodyType = null;
|
||||
const bodyAsGET = getPairValue(flagsByName, false, ["G", "get"]);
|
||||
if (dataParameters.length > 0 && bodyAsGET) {
|
||||
urlParameters.push(...dataParameters);
|
||||
} else if (dataParameters.length > 0 && (mimeType == null || mimeType === "application/x-www-form-urlencoded")) {
|
||||
bodyType = mimeType ?? "application/x-www-form-urlencoded";
|
||||
body = {
|
||||
form: dataParameters.map((parameter) => ({
|
||||
...parameter,
|
||||
name: decodeURIComponent(parameter.name || ""),
|
||||
value: decodeURIComponent(parameter.value || "")
|
||||
}))
|
||||
};
|
||||
headers.push({
|
||||
name: "Content-Type",
|
||||
value: "application/x-www-form-urlencoded",
|
||||
enabled: true
|
||||
});
|
||||
} else if (dataParameters.length > 0) {
|
||||
bodyType = mimeType === "application/json" || mimeType === "text/xml" || mimeType === "text/plain" ? mimeType : "other";
|
||||
body = {
|
||||
text: dataParameters.map(({ name, value }) => name && value ? `${name}=${value}` : name || value).join("&")
|
||||
};
|
||||
} else if (formDataParams.length) {
|
||||
bodyType = mimeType ?? "multipart/form-data";
|
||||
body = {
|
||||
form: formDataParams
|
||||
};
|
||||
if (mimeType == null) {
|
||||
headers.push({
|
||||
name: "Content-Type",
|
||||
value: "multipart/form-data",
|
||||
enabled: true
|
||||
});
|
||||
}
|
||||
}
|
||||
let method = getPairValue(flagsByName, "", ["X", "request"]).toUpperCase();
|
||||
if (method === "" && body) {
|
||||
method = "text" in body || "form" in body ? "POST" : "GET";
|
||||
}
|
||||
const request = {
|
||||
id: generateId("http_request"),
|
||||
model: "http_request",
|
||||
workspaceId,
|
||||
name: "",
|
||||
urlParameters,
|
||||
url,
|
||||
method,
|
||||
headers,
|
||||
authentication,
|
||||
authenticationType,
|
||||
body,
|
||||
bodyType,
|
||||
folderId: null,
|
||||
sortPriority: 0
|
||||
};
|
||||
return request;
|
||||
}
|
||||
function pairsToDataParameters(keyedPairs) {
|
||||
let dataParameters = [];
|
||||
for (const flagName of DATA_FLAGS) {
|
||||
const pairs = keyedPairs[flagName];
|
||||
if (!pairs || pairs.length === 0) {
|
||||
continue;
|
||||
}
|
||||
for (const p of pairs) {
|
||||
if (typeof p !== "string") continue;
|
||||
const [name, value] = p.split("=");
|
||||
if (p.startsWith("@")) {
|
||||
dataParameters.push({
|
||||
name: name ?? "",
|
||||
value: "",
|
||||
filePath: p.slice(1),
|
||||
enabled: true
|
||||
});
|
||||
} else {
|
||||
dataParameters.push({
|
||||
name: name ?? "",
|
||||
value: flagName === "data-urlencode" ? encodeURIComponent(value ?? "") : value ?? "",
|
||||
enabled: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return dataParameters;
|
||||
}
|
||||
var getPairValue = (pairsByName, defaultValue, names) => {
|
||||
for (const name of names) {
|
||||
if (pairsByName[name] && pairsByName[name].length) {
|
||||
return pairsByName[name][0];
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
};
|
||||
function splitOnce(str, sep) {
|
||||
const index = str.indexOf(sep);
|
||||
if (index > -1) {
|
||||
return [str.slice(0, index), str.slice(index + 1)];
|
||||
}
|
||||
return [str];
|
||||
}
|
||||
var idCount = {};
|
||||
function generateId(model) {
|
||||
idCount[model] = (idCount[model] ?? -1) + 1;
|
||||
return `GENERATE_ID::${model.toUpperCase()}_${idCount[model]}`;
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
pluginHookImport
|
||||
});
|
||||
15
src-tauri/vendored/plugins/importer-curl/package.json
generated
Normal file
15
src-tauri/vendored/plugins/importer-curl/package.json
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "@yaakapp/importer-curl",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.js",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"shell-quote": "^1.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/shell-quote": "^1.7.5"
|
||||
}
|
||||
}
|
||||
7443
src-tauri/vendored/plugins/importer-insomnia/build/index.js
generated
Normal file
7443
src-tauri/vendored/plugins/importer-insomnia/build/index.js
generated
Normal file
File diff suppressed because it is too large
Load Diff
12
src-tauri/vendored/plugins/importer-insomnia/package.json
generated
Normal file
12
src-tauri/vendored/plugins/importer-insomnia/package.json
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "@yaakapp/importer-insomnia",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.js",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"yaml": "^2.4.2"
|
||||
}
|
||||
}
|
||||
146253
src-tauri/vendored/plugins/importer-openapi/build/index.js
generated
Normal file
146253
src-tauri/vendored/plugins/importer-openapi/build/index.js
generated
Normal file
File diff suppressed because one or more lines are too long
16
src-tauri/vendored/plugins/importer-openapi/package.json
generated
Normal file
16
src-tauri/vendored/plugins/importer-openapi/package.json
generated
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "@yaakapp/importer-openapi",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.js",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"openapi-to-postmanv2": "^4.23.1",
|
||||
"yaml": "^2.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/openapi-to-postmanv2": "^3.2.4"
|
||||
}
|
||||
}
|
||||
321
src-tauri/vendored/plugins/importer-postman/build/index.js
generated
Normal file
321
src-tauri/vendored/plugins/importer-postman/build/index.js
generated
Normal file
@@ -0,0 +1,321 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// src/index.ts
|
||||
var src_exports = {};
|
||||
__export(src_exports, {
|
||||
pluginHookImport: () => pluginHookImport
|
||||
});
|
||||
module.exports = __toCommonJS(src_exports);
|
||||
var POSTMAN_2_1_0_SCHEMA = "https://schema.getpostman.com/json/collection/v2.1.0/collection.json";
|
||||
var POSTMAN_2_0_0_SCHEMA = "https://schema.getpostman.com/json/collection/v2.0.0/collection.json";
|
||||
var VALID_SCHEMAS = [POSTMAN_2_0_0_SCHEMA, POSTMAN_2_1_0_SCHEMA];
|
||||
function pluginHookImport(_ctx, contents) {
|
||||
const root = parseJSONToRecord(contents);
|
||||
if (root == null) return;
|
||||
const info = toRecord(root.info);
|
||||
const isValidSchema = VALID_SCHEMAS.includes(info.schema);
|
||||
if (!isValidSchema || !Array.isArray(root.item)) {
|
||||
return;
|
||||
}
|
||||
const globalAuth = importAuth(root.auth);
|
||||
const exportResources = {
|
||||
workspaces: [],
|
||||
environments: [],
|
||||
httpRequests: [],
|
||||
folders: []
|
||||
};
|
||||
const workspace = {
|
||||
model: "workspace",
|
||||
id: generateId("workspace"),
|
||||
name: info.name || "Postman Import",
|
||||
description: info.description?.content ?? info.description
|
||||
};
|
||||
exportResources.workspaces.push(workspace);
|
||||
const environment = {
|
||||
model: "environment",
|
||||
id: generateId("environment"),
|
||||
name: "Global Variables",
|
||||
workspaceId: workspace.id,
|
||||
variables: root.variable?.map((v) => ({
|
||||
name: v.key,
|
||||
value: v.value
|
||||
})) ?? []
|
||||
};
|
||||
exportResources.environments.push(environment);
|
||||
const importItem = (v, folderId = null) => {
|
||||
if (typeof v.name === "string" && Array.isArray(v.item)) {
|
||||
const folder = {
|
||||
model: "folder",
|
||||
workspaceId: workspace.id,
|
||||
id: generateId("folder"),
|
||||
name: v.name,
|
||||
folderId
|
||||
};
|
||||
exportResources.folders.push(folder);
|
||||
for (const child of v.item) {
|
||||
importItem(child, folder.id);
|
||||
}
|
||||
} else if (typeof v.name === "string" && "request" in v) {
|
||||
const r = toRecord(v.request);
|
||||
const bodyPatch = importBody(r.body);
|
||||
const requestAuthPath = importAuth(r.auth);
|
||||
const authPatch = requestAuthPath.authenticationType == null ? globalAuth : requestAuthPath;
|
||||
const headers = toArray(r.header).map((h) => {
|
||||
return {
|
||||
name: h.key,
|
||||
value: h.value,
|
||||
enabled: !h.disabled
|
||||
};
|
||||
});
|
||||
for (const bodyPatchHeader of bodyPatch.headers) {
|
||||
const existingHeader = headers.find((h) => h.name.toLowerCase() === bodyPatchHeader.name.toLowerCase());
|
||||
if (existingHeader) {
|
||||
continue;
|
||||
}
|
||||
headers.push(bodyPatchHeader);
|
||||
}
|
||||
const { url, urlParameters } = convertUrl(r.url);
|
||||
const request = {
|
||||
model: "http_request",
|
||||
id: generateId("http_request"),
|
||||
workspaceId: workspace.id,
|
||||
folderId,
|
||||
name: v.name,
|
||||
description: v.description || void 0,
|
||||
method: r.method || "GET",
|
||||
url,
|
||||
urlParameters,
|
||||
body: bodyPatch.body,
|
||||
bodyType: bodyPatch.bodyType,
|
||||
authentication: authPatch.authentication,
|
||||
authenticationType: authPatch.authenticationType,
|
||||
headers
|
||||
};
|
||||
exportResources.httpRequests.push(request);
|
||||
} else {
|
||||
console.log("Unknown item", v, folderId);
|
||||
}
|
||||
};
|
||||
for (const item of root.item) {
|
||||
importItem(item);
|
||||
}
|
||||
const resources = deleteUndefinedAttrs(convertTemplateSyntax(exportResources));
|
||||
return { resources };
|
||||
}
|
||||
function convertUrl(url) {
|
||||
if (typeof url === "string") {
|
||||
return { url, urlParameters: [] };
|
||||
}
|
||||
url = toRecord(url);
|
||||
let v = "";
|
||||
if ("protocol" in url && typeof url.protocol === "string") {
|
||||
v += `${url.protocol}://`;
|
||||
}
|
||||
if ("host" in url) {
|
||||
v += `${Array.isArray(url.host) ? url.host.join(".") : url.host}`;
|
||||
}
|
||||
if ("port" in url && typeof url.port === "string") {
|
||||
v += `:${url.port}`;
|
||||
}
|
||||
if ("path" in url && Array.isArray(url.path) && url.path.length > 0) {
|
||||
v += `/${Array.isArray(url.path) ? url.path.join("/") : url.path}`;
|
||||
}
|
||||
const params = [];
|
||||
if ("query" in url && Array.isArray(url.query) && url.query.length > 0) {
|
||||
for (const query of url.query) {
|
||||
params.push({
|
||||
name: query.key ?? "",
|
||||
value: query.value ?? "",
|
||||
enabled: !query.disabled
|
||||
});
|
||||
}
|
||||
}
|
||||
if ("variable" in url && Array.isArray(url.variable) && url.variable.length > 0) {
|
||||
for (const v2 of url.variable) {
|
||||
params.push({
|
||||
name: ":" + (v2.key ?? ""),
|
||||
value: v2.value ?? "",
|
||||
enabled: !v2.disabled
|
||||
});
|
||||
}
|
||||
}
|
||||
if ("hash" in url && typeof url.hash === "string") {
|
||||
v += `#${url.hash}`;
|
||||
}
|
||||
return { url: v, urlParameters: params };
|
||||
}
|
||||
function importAuth(rawAuth) {
|
||||
const auth = toRecord(rawAuth);
|
||||
if ("basic" in auth) {
|
||||
return {
|
||||
authenticationType: "basic",
|
||||
authentication: {
|
||||
username: auth.basic.username || "",
|
||||
password: auth.basic.password || ""
|
||||
}
|
||||
};
|
||||
} else if ("bearer" in auth) {
|
||||
return {
|
||||
authenticationType: "bearer",
|
||||
authentication: {
|
||||
token: auth.bearer.token || ""
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return { authenticationType: null, authentication: {} };
|
||||
}
|
||||
}
|
||||
function importBody(rawBody) {
|
||||
const body = toRecord(rawBody);
|
||||
if (body.mode === "graphql") {
|
||||
return {
|
||||
headers: [
|
||||
{
|
||||
name: "Content-Type",
|
||||
value: "application/json",
|
||||
enabled: true
|
||||
}
|
||||
],
|
||||
bodyType: "graphql",
|
||||
body: {
|
||||
text: JSON.stringify(
|
||||
{ query: body.graphql.query, variables: parseJSONToRecord(body.graphql.variables) },
|
||||
null,
|
||||
2
|
||||
)
|
||||
}
|
||||
};
|
||||
} else if (body.mode === "urlencoded") {
|
||||
return {
|
||||
headers: [
|
||||
{
|
||||
name: "Content-Type",
|
||||
value: "application/x-www-form-urlencoded",
|
||||
enabled: true
|
||||
}
|
||||
],
|
||||
bodyType: "application/x-www-form-urlencoded",
|
||||
body: {
|
||||
form: toArray(body.urlencoded).map((f) => ({
|
||||
enabled: !f.disabled,
|
||||
name: f.key ?? "",
|
||||
value: f.value ?? ""
|
||||
}))
|
||||
}
|
||||
};
|
||||
} else if (body.mode === "formdata") {
|
||||
return {
|
||||
headers: [
|
||||
{
|
||||
name: "Content-Type",
|
||||
value: "multipart/form-data",
|
||||
enabled: true
|
||||
}
|
||||
],
|
||||
bodyType: "multipart/form-data",
|
||||
body: {
|
||||
form: toArray(body.formdata).map(
|
||||
(f) => f.src != null ? {
|
||||
enabled: !f.disabled,
|
||||
contentType: f.contentType ?? null,
|
||||
name: f.key ?? "",
|
||||
file: f.src ?? ""
|
||||
} : {
|
||||
enabled: !f.disabled,
|
||||
name: f.key ?? "",
|
||||
value: f.value ?? ""
|
||||
}
|
||||
)
|
||||
}
|
||||
};
|
||||
} else if (body.mode === "raw") {
|
||||
return {
|
||||
headers: [
|
||||
{
|
||||
name: "Content-Type",
|
||||
value: body.options?.raw?.language === "json" ? "application/json" : "",
|
||||
enabled: true
|
||||
}
|
||||
],
|
||||
bodyType: body.options?.raw?.language === "json" ? "application/json" : "other",
|
||||
body: {
|
||||
text: body.raw ?? ""
|
||||
}
|
||||
};
|
||||
} else if (body.mode === "file") {
|
||||
return {
|
||||
headers: [],
|
||||
bodyType: "binary",
|
||||
body: {
|
||||
filePath: body.file?.src
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return { headers: [], bodyType: null, body: {} };
|
||||
}
|
||||
}
|
||||
function parseJSONToRecord(jsonStr) {
|
||||
try {
|
||||
return toRecord(JSON.parse(jsonStr));
|
||||
} catch (err) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function toRecord(value) {
|
||||
if (Object.prototype.toString.call(value) === "[object Object]") return value;
|
||||
else return {};
|
||||
}
|
||||
function toArray(value) {
|
||||
if (Object.prototype.toString.call(value) === "[object Array]") return value;
|
||||
else return [];
|
||||
}
|
||||
function convertTemplateSyntax(obj) {
|
||||
if (typeof obj === "string") {
|
||||
return obj.replace(/{{\s*(_\.)?([^}]+)\s*}}/g, "${[$2]}");
|
||||
} else if (Array.isArray(obj) && obj != null) {
|
||||
return obj.map(convertTemplateSyntax);
|
||||
} else if (typeof obj === "object" && obj != null) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(obj).map(([k, v]) => [k, convertTemplateSyntax(v)])
|
||||
);
|
||||
} else {
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
function deleteUndefinedAttrs(obj) {
|
||||
if (Array.isArray(obj) && obj != null) {
|
||||
return obj.map(deleteUndefinedAttrs);
|
||||
} else if (typeof obj === "object" && obj != null) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(obj).filter(([, v]) => v !== void 0).map(([k, v]) => [k, deleteUndefinedAttrs(v)])
|
||||
);
|
||||
} else {
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
var idCount = {};
|
||||
function generateId(model) {
|
||||
idCount[model] = (idCount[model] ?? -1) + 1;
|
||||
return `GENERATE_ID::${model.toUpperCase()}_${idCount[model]}`;
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
pluginHookImport
|
||||
});
|
||||
10
src-tauri/vendored/plugins/importer-postman/package.json
generated
Normal file
10
src-tauri/vendored/plugins/importer-postman/package.json
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "@yaakapp/importer-postman",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"main": "./build/index.js",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.js",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
}
|
||||
}
|
||||
70
src-tauri/vendored/plugins/importer-yaak/build/index.js
generated
Normal file
70
src-tauri/vendored/plugins/importer-yaak/build/index.js
generated
Normal file
@@ -0,0 +1,70 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// src/index.ts
|
||||
var src_exports = {};
|
||||
__export(src_exports, {
|
||||
pluginHookImport: () => pluginHookImport
|
||||
});
|
||||
module.exports = __toCommonJS(src_exports);
|
||||
function pluginHookImport(_ctx, contents) {
|
||||
let parsed;
|
||||
try {
|
||||
parsed = JSON.parse(contents);
|
||||
} catch (err) {
|
||||
return void 0;
|
||||
}
|
||||
if (!isJSObject(parsed)) {
|
||||
return void 0;
|
||||
}
|
||||
const isYaakExport = "yaakSchema" in parsed;
|
||||
if (!isYaakExport) {
|
||||
return;
|
||||
}
|
||||
if ("requests" in parsed.resources) {
|
||||
parsed.resources.httpRequests = parsed.resources.requests;
|
||||
delete parsed.resources["requests"];
|
||||
}
|
||||
for (const workspace of parsed.resources.workspaces ?? []) {
|
||||
if ("variables" in workspace) {
|
||||
const baseEnvironment = {
|
||||
id: `GENERATE_ID::base_env_${workspace["id"]}`,
|
||||
name: "Global Variables",
|
||||
variables: workspace.variables,
|
||||
workspaceId: workspace.id
|
||||
};
|
||||
parsed.resources.environments = parsed.resources.environments ?? [];
|
||||
parsed.resources.environments.push(baseEnvironment);
|
||||
delete workspace.variables;
|
||||
for (const environment of parsed.resources.environments) {
|
||||
if (environment.workspaceId === workspace.id && environment.id !== baseEnvironment.id) {
|
||||
environment.environmentId = baseEnvironment.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return { resources: parsed.resources };
|
||||
}
|
||||
function isJSObject(obj) {
|
||||
return Object.prototype.toString.call(obj) === "[object Object]";
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
pluginHookImport
|
||||
});
|
||||
9
src-tauri/vendored/plugins/importer-yaak/package.json
generated
Normal file
9
src-tauri/vendored/plugins/importer-yaak/package.json
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "@yaakapp/importer-yaak",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.js",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
}
|
||||
}
|
||||
54
src-tauri/vendored/plugins/template-function-file/build/index.js
generated
Normal file
54
src-tauri/vendored/plugins/template-function-file/build/index.js
generated
Normal file
@@ -0,0 +1,54 @@
|
||||
"use strict";
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||
// If the importer is in node compatibility mode or this is not an ESM
|
||||
// file that has been converted to a CommonJS file using a Babel-
|
||||
// compatible transform (i.e. "__esModule" has not been set), then set
|
||||
// "default" to the CommonJS "module.exports" for node compatibility.
|
||||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||
mod
|
||||
));
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// src/index.ts
|
||||
var src_exports = {};
|
||||
__export(src_exports, {
|
||||
plugin: () => plugin
|
||||
});
|
||||
module.exports = __toCommonJS(src_exports);
|
||||
var import_node_fs = __toESM(require("node:fs"));
|
||||
var plugin = {
|
||||
templateFunctions: [{
|
||||
name: "fs.readFile",
|
||||
args: [{ title: "Select File", type: "file", name: "path", label: "File" }],
|
||||
async onRender(_ctx, args) {
|
||||
if (!args.values.path) return null;
|
||||
try {
|
||||
return import_node_fs.default.promises.readFile(args.values.path, "utf-8");
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}]
|
||||
};
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
plugin
|
||||
});
|
||||
9
src-tauri/vendored/plugins/template-function-file/package.json
generated
Normal file
9
src-tauri/vendored/plugins/template-function-file/package.json
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "@yaakapp/template-function-file",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
}
|
||||
}
|
||||
55
src-tauri/vendored/plugins/template-function-fs/build/index.js
generated
Normal file
55
src-tauri/vendored/plugins/template-function-fs/build/index.js
generated
Normal file
@@ -0,0 +1,55 @@
|
||||
"use strict";
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||
// If the importer is in node compatibility mode or this is not an ESM
|
||||
// file that has been converted to a CommonJS file using a Babel-
|
||||
// compatible transform (i.e. "__esModule" has not been set), then set
|
||||
// "default" to the CommonJS "module.exports" for node compatibility.
|
||||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||
mod
|
||||
));
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// src/index.ts
|
||||
var src_exports = {};
|
||||
__export(src_exports, {
|
||||
plugin: () => plugin
|
||||
});
|
||||
module.exports = __toCommonJS(src_exports);
|
||||
var import_node_fs = __toESM(require("node:fs"));
|
||||
var plugin = {
|
||||
templateFunctions: [{
|
||||
name: "fs.readFile",
|
||||
description: "Read the contents of a file as utf-8",
|
||||
args: [{ title: "Select File", type: "file", name: "path", label: "File" }],
|
||||
async onRender(_ctx, args) {
|
||||
if (!args.values.path) return null;
|
||||
try {
|
||||
return import_node_fs.default.promises.readFile(args.values.path, "utf-8");
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}]
|
||||
};
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
plugin
|
||||
});
|
||||
9
src-tauri/vendored/plugins/template-function-fs/package.json
generated
Normal file
9
src-tauri/vendored/plugins/template-function-fs/package.json
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "@yaakapp/template-function-fs",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
}
|
||||
}
|
||||
49
src-tauri/vendored/plugins/template-function-hash/build/index.js
generated
Normal file
49
src-tauri/vendored/plugins/template-function-hash/build/index.js
generated
Normal file
@@ -0,0 +1,49 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// src/index.ts
|
||||
var src_exports = {};
|
||||
__export(src_exports, {
|
||||
plugin: () => plugin
|
||||
});
|
||||
module.exports = __toCommonJS(src_exports);
|
||||
var import_node_crypto = require("node:crypto");
|
||||
var algorithms = ["md5", "sha1", "sha256", "sha512"];
|
||||
var plugin = {
|
||||
templateFunctions: algorithms.map((algorithm) => ({
|
||||
name: `hash.${algorithm}`,
|
||||
description: "Hash a value to its hexidecimal representation",
|
||||
args: [
|
||||
{
|
||||
name: "input",
|
||||
label: "Input",
|
||||
placeholder: "input text",
|
||||
type: "text"
|
||||
}
|
||||
],
|
||||
async onRender(_ctx, args) {
|
||||
if (!args.values.input) return "";
|
||||
return (0, import_node_crypto.createHash)(algorithm).update(args.values.input, "utf-8").digest("hex");
|
||||
}
|
||||
}))
|
||||
};
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
plugin
|
||||
});
|
||||
9
src-tauri/vendored/plugins/template-function-hash/package.json
generated
Executable file
9
src-tauri/vendored/plugins/template-function-hash/package.json
generated
Executable file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "@yaakapp/template-function-hash",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
}
|
||||
}
|
||||
51
src-tauri/vendored/plugins/template-function-prompt/build/index.js
generated
Normal file
51
src-tauri/vendored/plugins/template-function-prompt/build/index.js
generated
Normal file
@@ -0,0 +1,51 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// src/index.ts
|
||||
var src_exports = {};
|
||||
__export(src_exports, {
|
||||
plugin: () => plugin
|
||||
});
|
||||
module.exports = __toCommonJS(src_exports);
|
||||
var plugin = {
|
||||
templateFunctions: [{
|
||||
name: "prompt.text",
|
||||
description: "Prompt the user for input when sending a request",
|
||||
args: [
|
||||
{ type: "text", name: "title", label: "Title" },
|
||||
{ type: "text", name: "label", label: "Label", optional: true },
|
||||
{ type: "text", name: "defaultValue", label: "Default Value", optional: true },
|
||||
{ type: "text", name: "placeholder", label: "Placeholder", optional: true }
|
||||
],
|
||||
async onRender(ctx, args) {
|
||||
if (args.purpose !== "send") return null;
|
||||
return await ctx.prompt.text({
|
||||
id: `prompt-${args.values.label}`,
|
||||
label: args.values.title ?? "",
|
||||
title: args.values.title ?? "",
|
||||
defaultValue: args.values.defaultValue,
|
||||
placeholder: args.values.placeholder
|
||||
});
|
||||
}
|
||||
}]
|
||||
};
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
plugin
|
||||
});
|
||||
9
src-tauri/vendored/plugins/template-function-prompt/package.json
generated
Normal file
9
src-tauri/vendored/plugins/template-function-prompt/package.json
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "@yaakapp/template-function-prompt",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
}
|
||||
}
|
||||
73
src-tauri/vendored/plugins/template-function-request/build/index.js
generated
Normal file
73
src-tauri/vendored/plugins/template-function-request/build/index.js
generated
Normal file
@@ -0,0 +1,73 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// src/index.ts
|
||||
var src_exports = {};
|
||||
__export(src_exports, {
|
||||
plugin: () => plugin
|
||||
});
|
||||
module.exports = __toCommonJS(src_exports);
|
||||
var plugin = {
|
||||
templateFunctions: [
|
||||
{
|
||||
name: "request.body",
|
||||
args: [{
|
||||
name: "requestId",
|
||||
label: "Http Request",
|
||||
type: "http_request"
|
||||
}],
|
||||
async onRender(ctx, args) {
|
||||
const httpRequest = await ctx.httpRequest.getById({ id: args.values.requestId ?? "n/a" });
|
||||
if (httpRequest == null) return null;
|
||||
return String(await ctx.templates.render({
|
||||
data: httpRequest.body?.text ?? "",
|
||||
purpose: args.purpose
|
||||
}));
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "request.header",
|
||||
args: [
|
||||
{
|
||||
name: "requestId",
|
||||
label: "Http Request",
|
||||
type: "http_request"
|
||||
},
|
||||
{
|
||||
name: "header",
|
||||
label: "Header Name",
|
||||
type: "text"
|
||||
}
|
||||
],
|
||||
async onRender(ctx, args) {
|
||||
const httpRequest = await ctx.httpRequest.getById({ id: args.values.requestId ?? "n/a" });
|
||||
if (httpRequest == null) return null;
|
||||
const header = httpRequest.headers.find((h) => h.name.toLowerCase() === args.values.header?.toLowerCase());
|
||||
return String(await ctx.templates.render({
|
||||
data: header?.value ?? "",
|
||||
purpose: args.purpose
|
||||
}));
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
plugin
|
||||
});
|
||||
9
src-tauri/vendored/plugins/template-function-request/package.json
generated
Executable file
9
src-tauri/vendored/plugins/template-function-request/package.json
generated
Executable file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "@yaakapp/template-function-request",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
}
|
||||
}
|
||||
8979
src-tauri/vendored/plugins/template-function-response/build/index.js
generated
Normal file
8979
src-tauri/vendored/plugins/template-function-response/build/index.js
generated
Normal file
File diff suppressed because it is too large
Load Diff
17
src-tauri/vendored/plugins/template-function-response/package.json
generated
Normal file
17
src-tauri/vendored/plugins/template-function-response/package.json
generated
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "@yaakapp/template-function-response",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"build": "yaakcli build ./src/index.ts",
|
||||
"dev": "yaakcli dev ./src/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsonpath-plus": "^9.0.0",
|
||||
"xpath": "^0.0.34",
|
||||
"@xmldom/xmldom": "^0.8.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jsonpath": "^0.2.4"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
[package]
|
||||
name = "yaak_grpc"
|
||||
name = "yaak-grpc"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
tonic = "0.10.2"
|
||||
@@ -22,3 +23,4 @@ tauri = { workspace = true }
|
||||
tauri-plugin-shell = { workspace = true }
|
||||
md5 = "0.7.0"
|
||||
dunce = "1.0.4"
|
||||
async-recursion = "1.1.1"
|
||||
@@ -33,8 +33,7 @@ impl Encoder for DynamicCodec {
|
||||
type Error = Status;
|
||||
|
||||
fn encode(&mut self, item: Self::Item, dst: &mut EncodeBuf<'_>) -> Result<(), Self::Error> {
|
||||
item.encode(dst)
|
||||
.expect("buffer is too small to decode this message");
|
||||
item.encode(dst).expect("buffer is too small to decode this message");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -45,8 +44,7 @@ impl Decoder for DynamicCodec {
|
||||
|
||||
fn decode(&mut self, src: &mut DecodeBuf<'_>) -> Result<Option<Self::Item>, Self::Error> {
|
||||
let mut msg = DynamicMessage::new(self.0.output());
|
||||
msg.merge(src)
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
msg.merge(src).map_err(|err| Status::internal(err.to_string()))?;
|
||||
Ok(Some(msg))
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user