Compare commits
232 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1e4e0e6c9 | ||
|
|
b3aa8b893b | ||
|
|
f057139634 | ||
|
|
71a2b11ab4 | ||
|
|
587254a0e7 | ||
|
|
9f4de66f3c | ||
|
|
b0d8908724 | ||
|
|
15c22d98c6 | ||
|
|
3105ae0edc | ||
|
|
11a89f06c1 | ||
|
|
9cbe24e740 | ||
|
|
bfbed13b8f | ||
|
|
2268de6321 | ||
|
|
dd99aa7fcd | ||
|
|
be436bb706 | ||
|
|
bd48726f44 | ||
|
|
10bea83f98 | ||
|
|
8122b4fb84 | ||
|
|
3ae57fb2d8 | ||
|
|
6dc3eecca4 | ||
|
|
9d1d732154 | ||
|
|
8a117415b7 | ||
|
|
d36623ebc9 | ||
|
|
94a3ae3696 | ||
|
|
2836a28988 | ||
|
|
946d7dc89e | ||
|
|
af6300f18b | ||
|
|
905cb4b18e | ||
|
|
305ed09547 | ||
|
|
643356bad3 | ||
|
|
e458675627 | ||
|
|
91e3853692 | ||
|
|
5f0876a136 | ||
|
|
3a38127fb4 | ||
|
|
f3b6070235 | ||
|
|
5e6e78eb9e | ||
|
|
9b66a1d1a8 | ||
|
|
e954d0d7bc | ||
|
|
dab2df7e79 | ||
|
|
bc40e22008 | ||
|
|
eef262c398 | ||
|
|
8eab6e14db | ||
|
|
ded33a110a | ||
|
|
e448a7602a | ||
|
|
4c22215ca5 | ||
|
|
4f501abb72 | ||
|
|
b2dcc38982 | ||
|
|
11b719955b | ||
|
|
d563ac63db | ||
|
|
6d826064c6 | ||
|
|
d30b9d6518 | ||
|
|
8da3364d0f | ||
|
|
07c372b7f5 | ||
|
|
7e01f38253 | ||
|
|
ba637009a7 | ||
|
|
da7388e510 | ||
|
|
3ec88fc896 | ||
|
|
1c9381b2bd | ||
|
|
06349b8d5b | ||
|
|
6dc7dc6ad2 | ||
|
|
f981a15ec3 | ||
|
|
8b648c0301 | ||
|
|
83ce09075b | ||
|
|
168dfb9f6b | ||
|
|
9b8961c23d | ||
|
|
89bca42ee6 | ||
|
|
07d2a43a17 | ||
|
|
c84f2afd09 | ||
|
|
df4dbaecc8 | ||
|
|
d9bf03cefe | ||
|
|
39223e8d89 | ||
|
|
67925e18b2 | ||
|
|
89ad65513d | ||
|
|
90166ddfa3 | ||
|
|
0981b23faf | ||
|
|
664f3b4d87 | ||
|
|
dc97b91a4e | ||
|
|
d310272d19 | ||
|
|
f1be3f01e1 | ||
|
|
c57b6e1d73 | ||
|
|
a938dc45f0 | ||
|
|
bb139744a1 | ||
|
|
3aa3e09552 | ||
|
|
74abfd21b8 | ||
|
|
e703817ba2 | ||
|
|
80dd1e457b | ||
|
|
ea9f8d3ab2 | ||
|
|
fa222bdf12 | ||
|
|
45b360dabd | ||
|
|
5923399359 | ||
|
|
f4600f3e90 | ||
|
|
f883837685 | ||
|
|
b58bc409f0 | ||
|
|
e893e539bb | ||
|
|
90294fbb5d | ||
|
|
ae65f222bc | ||
|
|
1b9813fb4c | ||
|
|
b708b5ae41 | ||
|
|
df136fa915 | ||
|
|
f8329f5b8d | ||
|
|
21141090de | ||
|
|
c0d9740a7d | ||
|
|
afcf630443 | ||
|
|
1fe2c9826a | ||
|
|
7272b80a3f | ||
|
|
92114b7368 | ||
|
|
f39d3e7eed | ||
|
|
cbe0d27a5e | ||
|
|
cd39699467 | ||
|
|
b3ea67aacf | ||
|
|
db4ed9797c | ||
|
|
1ea7d7d685 | ||
|
|
2df725b57a | ||
|
|
74e6648249 | ||
|
|
1026350d9c | ||
|
|
98fb87874d | ||
|
|
41fc3afdc1 | ||
|
|
83dbf46ba4 | ||
|
|
0b2e35bdde | ||
|
|
d90a7331c9 | ||
|
|
264e64a996 | ||
|
|
8915915c47 | ||
|
|
951ed787fa | ||
|
|
64ef6b0c22 | ||
|
|
ef18377b3c | ||
|
|
5904b6fded | ||
|
|
f4401e77bb | ||
|
|
efa5455a7b | ||
|
|
619c8d9e72 | ||
|
|
bdf89ac288 | ||
|
|
debd3c8185 | ||
|
|
f81a3ae8e7 | ||
|
|
7d4e9894c3 | ||
|
|
4bf22d8a60 | ||
|
|
8be4971a23 | ||
|
|
359e916b73 | ||
|
|
68058f3e41 | ||
|
|
0c6fa3e634 | ||
|
|
0fa25c6335 | ||
|
|
5684479f1d | ||
|
|
2d1603601c | ||
|
|
f5394b2210 | ||
|
|
833db5df06 | ||
|
|
525ac7e980 | ||
|
|
44a747c80a | ||
|
|
2056e7f40a | ||
|
|
9b6c1ad364 | ||
|
|
34987bcacb | ||
|
|
b62c11222a | ||
|
|
b3cee3ace3 | ||
|
|
222c054c95 | ||
|
|
46f18a2491 | ||
|
|
f2ca8e2753 | ||
|
|
b0d243c378 | ||
|
|
6161fb86c8 | ||
|
|
b09cc91fe5 | ||
|
|
ef1638cbb3 | ||
|
|
00ef8743f2 | ||
|
|
68222659e3 | ||
|
|
69420a4bba | ||
|
|
0161bbaeb1 | ||
|
|
948dbfe3cc | ||
|
|
338ba8b189 | ||
|
|
ca4655b441 | ||
|
|
bf37499428 | ||
|
|
0b94b57e2a | ||
|
|
fc40aead98 | ||
|
|
7d7f934e6a | ||
|
|
d5fbf4d622 | ||
|
|
e4f6c919dc | ||
|
|
4d806ff2b1 | ||
|
|
bf8f12274f | ||
|
|
f4f438d9fe | ||
|
|
2434f373be | ||
|
|
2bb2061f97 | ||
|
|
2c011a5c2a | ||
|
|
f66b0ccea1 | ||
|
|
665dd8447d | ||
|
|
1b61ce31e6 | ||
|
|
ef4d960698 | ||
|
|
b6d557b632 | ||
|
|
b700bd356c | ||
|
|
620dd7d3ef | ||
|
|
6575121902 | ||
|
|
7c1755a0dc | ||
|
|
8ad301a666 | ||
|
|
ae24cd4939 | ||
|
|
7152e1845e | ||
|
|
96c1dd4081 | ||
|
|
87c7b3a663 | ||
|
|
c1be46a539 | ||
|
|
4655e0018b | ||
|
|
da5ba2e3be | ||
|
|
aaf95f565f | ||
|
|
f32b984e77 | ||
|
|
548aa4c7cd | ||
|
|
0ccceaac77 | ||
|
|
70f534f1d8 | ||
|
|
61fe95b300 | ||
|
|
915e0e8613 | ||
|
|
aace2580da | ||
|
|
3d36905664 | ||
|
|
0d671423da | ||
|
|
aebfcb9437 | ||
|
|
be7ef7beb1 | ||
|
|
d77ed0c5cc | ||
|
|
e57e7bcec5 | ||
|
|
a637842ce4 | ||
|
|
fc54ec49af | ||
|
|
5c43d8510a | ||
|
|
83f84ded8d | ||
|
|
5658da34a2 | ||
|
|
38e8ef6535 | ||
|
|
8c89b06238 | ||
|
|
d85c021305 | ||
|
|
83bb18df03 | ||
|
|
93105a3e89 | ||
|
|
ba3b899115 | ||
|
|
fcfbc1d1da | ||
|
|
72486b448c | ||
|
|
7dea1b7870 | ||
|
|
4de2c496c9 | ||
|
|
9e1393a392 | ||
|
|
0901690ed6 | ||
|
|
95303648cc | ||
|
|
1dbb08c045 | ||
|
|
00a7d9a180 | ||
|
|
6c549dc086 | ||
|
|
dc368e326a | ||
|
|
e42188a627 | ||
|
|
7a6a337eff | ||
|
|
3907344884 |
@@ -1,6 +1,5 @@
|
||||
node_modules/
|
||||
dist/
|
||||
.eslintrc.cjs
|
||||
.prettierrc.cjs
|
||||
src-web/postcss.config.cjs
|
||||
src-web/vite.config.ts
|
||||
.eslintrc.cjs
|
||||
env.d.ts
|
||||
|
||||
@@ -1,49 +1,37 @@
|
||||
module.exports = {
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:react/recommended',
|
||||
'plugin:react-hooks/recommended',
|
||||
'plugin:import/recommended',
|
||||
'plugin:jsx-a11y/recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'eslint-config-prettier',
|
||||
"eslint:recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react-hooks/recommended",
|
||||
"plugin:import/recommended",
|
||||
"plugin:jsx-a11y/recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"eslint-config-prettier"
|
||||
],
|
||||
plugins: ['react-refresh'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.json'],
|
||||
},
|
||||
ignorePatterns: [
|
||||
'scripts/**/*',
|
||||
'packages/plugin-runtime/**/*',
|
||||
'packages/plugin-runtime-types/**/*',
|
||||
'src-tauri/**/*',
|
||||
'src-web/tailwind.config.cjs',
|
||||
'src-web/vite.config.ts',
|
||||
],
|
||||
ignorePatterns: ["src-tauri/**/*"],
|
||||
settings: {
|
||||
react: {
|
||||
version: 'detect',
|
||||
version: "detect"
|
||||
},
|
||||
'import/resolver': {
|
||||
"import/resolver": {
|
||||
node: {
|
||||
paths: ['src-web'],
|
||||
extensions: ['.ts', '.tsx'],
|
||||
},
|
||||
},
|
||||
paths: ["src-web"],
|
||||
extensions: [".ts", ".tsx"]
|
||||
}
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
'react-refresh/only-export-components': 'error',
|
||||
'jsx-a11y/no-autofocus': 'off',
|
||||
'react/react-in-jsx-scope': 'off',
|
||||
'import/no-unresolved': 'off',
|
||||
'@typescript-eslint/consistent-type-imports': [
|
||||
'error',
|
||||
{
|
||||
prefer: 'type-imports',
|
||||
disallowTypeAnnotations: true,
|
||||
fixStyle: 'separate-type-imports',
|
||||
},
|
||||
],
|
||||
},
|
||||
"jsx-a11y/no-autofocus": "warn",
|
||||
"react/react-in-jsx-scope": "off",
|
||||
"import/no-unresolved": "off",
|
||||
"@typescript-eslint/consistent-type-imports": ["error", {
|
||||
prefer: "type-imports",
|
||||
disallowTypeAnnotations: true,
|
||||
fixStyle: "separate-type-imports"
|
||||
}],
|
||||
}
|
||||
};
|
||||
|
||||
2
.gitattributes
vendored
@@ -1,2 +0,0 @@
|
||||
src-tauri/vendored/**/* linguist-generated=true
|
||||
src-tauri/gen/schemas/**/* linguist-generated=true
|
||||
15
.github/FUNDING.yml
vendored
@@ -1,15 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: gschier
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
polar: # Replace with a single Polar username
|
||||
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
|
||||
thanks_dev: # Replace with a single thanks.dev username
|
||||
custom: https://yaak.app/pricing
|
||||
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,38 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,5 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Bugs, Feedback, Feature Requests, and Questions
|
||||
url: https://feedback.yaak.app
|
||||
about: "Please report to Yaak's public feedback board. Issues will be created and linked here when applicable."
|
||||
56
.github/workflows/artifacts.yml
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
name: Generate Artifacts
|
||||
on:
|
||||
push:
|
||||
tags: [ v* ]
|
||||
|
||||
jobs:
|
||||
build-artifacts:
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# platform: [ ubuntu-latest, macos-latest, windows-latest ]
|
||||
platform: [ macos-latest ]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- name: Cache Rust
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
./src-tauri/target
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('src-tauri/Cargo.lock') }}
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'npm'
|
||||
- name: install dependencies (ubuntu only)
|
||||
if: matrix.platform == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Run tests
|
||||
run: npm test
|
||||
- uses: tauri-apps/tauri-action@v0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_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_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
with:
|
||||
tagName: v__VERSION__
|
||||
releaseName: 'App v__VERSION__'
|
||||
releaseBody: 'See the assets to download this version and install.'
|
||||
releaseDraft: true
|
||||
prerelease: false
|
||||
18
.github/workflows/ci-js.yml
vendored
@@ -1,18 +0,0 @@
|
||||
on:
|
||||
pull_request:
|
||||
branches: [develop]
|
||||
|
||||
name: CI (JS)
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Lint/Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- run: npm ci
|
||||
- run: npm run lint
|
||||
- run: npm test
|
||||
36
.github/workflows/ci-rust.yml
vendored
@@ -1,36 +0,0 @@
|
||||
on:
|
||||
pull_request:
|
||||
branches: [develop]
|
||||
paths:
|
||||
- src-tauri/**
|
||||
- .github/workflows/**
|
||||
|
||||
name: CI (Rust)
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: src-tauri
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Check/Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libwebkit2gtk-4.1-dev
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- uses: actions/cache@v3
|
||||
continue-on-error: false
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
target/
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
restore-keys: ${{ runner.os }}-cargo-
|
||||
- run: cargo check --all
|
||||
- run: cargo test --all
|
||||
125
.github/workflows/release.yml
vendored
@@ -1,125 +0,0 @@
|
||||
name: Generate Artifacts
|
||||
on:
|
||||
push:
|
||||
tags: [ v* ]
|
||||
|
||||
env:
|
||||
YAAK_PLUGINS_DIR: checkout/plugins
|
||||
|
||||
jobs:
|
||||
build-artifacts:
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
name: Build
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: 'macos-latest' # for Arm-based Macs (M1 and above).
|
||||
args: '--target aarch64-apple-darwin'
|
||||
yaak_arch: 'arm64'
|
||||
- platform: 'macos-latest' # for Intel-based Macs.
|
||||
args: '--target x86_64-apple-darwin'
|
||||
yaak_arch: 'x64'
|
||||
- platform: 'ubuntu-22.04'
|
||||
args: ''
|
||||
yaak_arch: 'x64'
|
||||
- platform: 'windows-latest'
|
||||
args: ''
|
||||
yaak_arch: 'x64'
|
||||
runs-on: ${{ matrix.platform }}
|
||||
timeout-minutes: 40
|
||||
steps:
|
||||
- name: Checkout yaakapp/app
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
- name: install Rust stable
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
# Those targets are only used on macos runners so it's in an `if` to slightly speed up windows and linux builds.
|
||||
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
|
||||
|
||||
- uses: actions/cache@v3
|
||||
continue-on-error: false
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
src-tauri/target/
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
restore-keys: ${{ runner.os }}-cargo-
|
||||
|
||||
- name: install dependencies (ubuntu only)
|
||||
if: matrix.platform == 'ubuntu-22.04' # This must match the platform value defined above.
|
||||
run: |
|
||||
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 --version 0.5.0
|
||||
|
||||
- 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
|
||||
|
||||
- name: Checkout yaakapp/plugins
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: yaakapp/plugins
|
||||
path: ${{ env.YAAK_PLUGINS_DIR }}
|
||||
|
||||
- name: Set version
|
||||
run: npm run replace-version
|
||||
env:
|
||||
YAAK_VERSION: ${{ github.ref_name }}
|
||||
|
||||
- uses: tauri-apps/tauri-action@v0
|
||||
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 }}
|
||||
|
||||
# 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: '[Changelog __VERSION__](https://yaak.app/blog/__VERSION__)'
|
||||
releaseDraft: true
|
||||
prerelease: false
|
||||
args: ${{ matrix.args }}
|
||||
7
.gitignore
vendored
@@ -22,12 +22,5 @@ dist-ssr
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
.eslintcache
|
||||
|
||||
*.sqlite
|
||||
*.sqlite-*
|
||||
|
||||
.cargo
|
||||
|
||||
.tmp
|
||||
tmp
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
node_modules/
|
||||
dist/
|
||||
out/
|
||||
.prettierrc.cjs
|
||||
|
||||
8
.prettierrc.cjs
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
"trailingComma": "all",
|
||||
"tabWidth": 2,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"printWidth": 100,
|
||||
"bracketSpacing": true
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
export default {
|
||||
"trailingComma": "all",
|
||||
"tabWidth": 2,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"printWidth": 100,
|
||||
"bracketSpacing": true
|
||||
}
|
||||
12
.run/Dev Desktop.run.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Dev Desktop" type="js.build_tools.npm">
|
||||
<package-json value="$PROJECT_DIR$/package.json" />
|
||||
<command value="run" />
|
||||
<scripts>
|
||||
<script value="tauri-dev" />
|
||||
</scripts>
|
||||
<node-interpreter value="project" />
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -1,69 +0,0 @@
|
||||
# Developer Setup
|
||||
|
||||
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)
|
||||
|
||||
Check the installations with the following commands:
|
||||
|
||||
```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
|
||||
|
||||
New migrations can be created from the `src-tauri/` directory:
|
||||
|
||||
```shell
|
||||
cd src-tauri
|
||||
sqlx migrate add migration-name
|
||||
```
|
||||
|
||||
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._
|
||||
|
||||
## Lezer Grammer Generation
|
||||
|
||||
```sh
|
||||
# Example
|
||||
lezer-generator components/core/Editor/<LANG>/<LANG>.grammar > components/core/Editor/<LANG>/<LANG>.ts
|
||||
```
|
||||
21
LICENSE
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Yaak
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
42
README.md
@@ -1,34 +1,16 @@
|
||||
# Yaak API Client
|
||||
# Yaak Network Toolkit
|
||||
|
||||
Yaak is a desktop API client for interacting with REST, GraphQL, Server Sent Events (SSE), WebSocket, and gRPC
|
||||
APIs. It's built using [Tauri](https://tauri.app), Rust, and ReactJS.
|
||||
The most fun you'll ever have working with APIs.
|
||||
|
||||

|
||||
## Common Commands
|
||||
|
||||
## Contribution Policy
|
||||
```sh
|
||||
# Start dev app
|
||||
npm run tauri-dev
|
||||
|
||||
Yaak is open source, but only accepting contributions for bug fixes. To get started,
|
||||
visit [`DEVELOPMENT.md`](DEVELOPMENT.md) for tips on setting up your environment.
|
||||
|
||||
## Feature Overview
|
||||
|
||||
- 🪂 Import data from Postman, Insomnia, OpenAPI, Swagger, or Curl.<br/>
|
||||
- 📤 Send requests via REST, GraphQL, Server Sent Events (SSE), WebSockets, or gRPC.<br/>
|
||||
- 🔐 Automatically authorize requests with OAuth 2.0, JWT tokens, Basic Auth, and more.<br/>
|
||||
- 🔎 Filter response bodies using JSONPath or XPath queries.<br/>
|
||||
- ⛓️ Chain together multiple requests to dynamically reference values.<br/>
|
||||
- 📂 Organize requests into workspaces and nested folders.<br/>
|
||||
- 🧮 Use environment variables to easily switch between Prod and Dev.<br/>
|
||||
- 🛡️ Secure arbitrary text values with end-to-end encryption<br/>
|
||||
- 🏷️ Send dynamic values like UUIDs or timestamps using template tags.<br/>
|
||||
- 🎨 Choose from many of the included themes, or make your own.<br/>
|
||||
- 💽 Mirror workspace data to a directory for integration with Git or Dropbox.<br/>
|
||||
- 📜 View response history for each request.<br/>
|
||||
- 🔌 Create your own plugins for authentication, template tags, and more!<br/>
|
||||
- 🛜 Configure a proxy to access firewall-blocked APIs
|
||||
|
||||
## Useful Resources
|
||||
|
||||
- [Feedback and Bug Reports](https://feedback.yaak.app)
|
||||
- [Documentation](https://feedback.yaak.app/help)
|
||||
- [Yaak vs Postman](https://yaak.app/blog/postman-alternative)
|
||||
# Migration commands
|
||||
cd src-tauri
|
||||
cargo sqlx migrate add <name>
|
||||
cargo sqlx migrate run --database-url 'sqlite://db.sqlite?mode=rw'
|
||||
cargo sqlx prepare --database-url 'sqlite://db.sqlite'
|
||||
```
|
||||
|
||||
28
index.html
Normal file
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Yaak App</title>
|
||||
<script src="http://localhost:8097"></script>
|
||||
<style>
|
||||
body {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: black;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<div id="cm-portal" class="cm-portal"></div>
|
||||
<div id="react-portal"></div>
|
||||
<div id="radix-portal" class="cm-portal"></div>
|
||||
<script type="module" src="/src-web/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
18539
package-lock.json
generated
117
package.json
@@ -2,57 +2,80 @@
|
||||
"name": "yaak-app",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/mountain-loop/yaak.git"
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/plugin-runtime",
|
||||
"packages/plugin-runtime-types",
|
||||
"packages/common-lib",
|
||||
"src-tauri/yaak-crypto",
|
||||
"src-tauri/yaak-git",
|
||||
"src-tauri/yaak-license",
|
||||
"src-tauri/yaak-mac-window",
|
||||
"src-tauri/yaak-models",
|
||||
"src-tauri/yaak-plugins",
|
||||
"src-tauri/yaak-sse",
|
||||
"src-tauri/yaak-sync",
|
||||
"src-tauri/yaak-templates",
|
||||
"src-tauri/yaak-ws",
|
||||
"src-web"
|
||||
],
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "npm run app-dev",
|
||||
"app-build": "tauri build",
|
||||
"app-dev": "tauri dev --no-watch --config ./src-tauri/tauri-dev.conf.json",
|
||||
"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",
|
||||
"lint": "npm run --workspaces --if-present lint",
|
||||
"replace-version": "node scripts/replace-version.cjs",
|
||||
"tauri": "tauri",
|
||||
"tauri-before-build": "npm run bootstrap && npm run --workspaces --if-present build",
|
||||
"tauri-before-dev": "npm run --workspaces --if-present dev"
|
||||
"tauri-dev": "YAAK_ENV=development tauri dev",
|
||||
"tauri-build": "tauri build",
|
||||
"build": "npm run build:frontend",
|
||||
"dev": "vite dev",
|
||||
"lint": "tsc && eslint . --ext .ts,.tsx",
|
||||
"build:icon": "tauri icon src-tauri/icons/icon.png",
|
||||
"build:frontend": "vite build",
|
||||
"test": "vitest",
|
||||
"coverage": "vitest run --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"jotai": "^2.12.2"
|
||||
"@codemirror/commands": "^6.2.1",
|
||||
"@codemirror/lang-html": "^6.4.2",
|
||||
"@codemirror/lang-javascript": "^6.1.4",
|
||||
"@codemirror/lang-json": "^6.0.1",
|
||||
"@codemirror/lang-xml": "^6.0.2",
|
||||
"@codemirror/language": "^6.6.0",
|
||||
"@codemirror/search": "^6.2.3",
|
||||
"@lezer/generator": "^1.2.2",
|
||||
"@lezer/highlight": "^1.1.3",
|
||||
"@lezer/lr": "^1.3.3",
|
||||
"@radix-ui/react-icons": "^1.2.0",
|
||||
"@react-hook/resize-observer": "^1.2.6",
|
||||
"@tailwindcss/container-queries": "^0.1.0",
|
||||
"@tanstack/query-sync-storage-persister": "^4.27.1",
|
||||
"@tanstack/react-query": "^4.28.0",
|
||||
"@tanstack/react-query-devtools": "^4.28.0",
|
||||
"@tanstack/react-query-persist-client": "^4.28.0",
|
||||
"@tauri-apps/api": "^1.2.0",
|
||||
"@vitejs/plugin-react": "^3.1.0",
|
||||
"classnames": "^2.3.2",
|
||||
"cm6-graphql": "^0.0.4-canary-b30a2325.0",
|
||||
"codemirror": "^6.0.1",
|
||||
"focus-trap-react": "^10.1.1",
|
||||
"format-graphql": "^1.4.0",
|
||||
"framer-motion": "^9.0.4",
|
||||
"parse-color": "^1.0.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dnd": "^16.0.1",
|
||||
"react-dnd-html5-backend": "^16.0.1",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-helmet-async": "^1.3.0",
|
||||
"react-router-dom": "^6.8.1",
|
||||
"react-use": "^17.4.0",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^2.4.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.27.0",
|
||||
"@typescript-eslint/parser": "^8.27.0",
|
||||
"eslint": "^8",
|
||||
"eslint-config-prettier": "^8",
|
||||
"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.4.2",
|
||||
"typescript": "^5.8.2"
|
||||
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
||||
"@tauri-apps/cli": "^1.2.2",
|
||||
"@types/node": "^18.7.10",
|
||||
"@types/parse-color": "^1.0.1",
|
||||
"@types/parse-json": "^4.0.0",
|
||||
"@types/react": "^18.0.31",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"@types/uuid": "^9.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.57.0",
|
||||
"@typescript-eslint/parser": "^5.57.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"eslint": "^8.34.0",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||
"eslint-plugin-react": "^7.32.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"postcss": "^8.4.21",
|
||||
"postcss-nesting": "^11.2.1",
|
||||
"prettier": "^2.8.4",
|
||||
"tailwindcss": "^3.2.7",
|
||||
"typescript": "^5.0.2",
|
||||
"vite": "^4.0.0",
|
||||
"vite-plugin-svgr": "^2.4.0",
|
||||
"vite-plugin-top-level-await": "^1.2.4",
|
||||
"vitest": "^0.29.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
export function formatSize(bytes: number): string {
|
||||
let num;
|
||||
let unit;
|
||||
|
||||
if (bytes > 1000 * 1000 * 1000) {
|
||||
num = bytes / 1000 / 1000 / 1000;
|
||||
unit = 'GB';
|
||||
} else if (bytes > 1000 * 1000) {
|
||||
num = bytes / 1000 / 1000;
|
||||
unit = 'MB';
|
||||
} else if (bytes > 1000) {
|
||||
num = bytes / 1000;
|
||||
unit = 'KB';
|
||||
} else {
|
||||
num = bytes;
|
||||
unit = 'B';
|
||||
}
|
||||
|
||||
return `${Math.round(num * 10) / 10} ${unit}`;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export * from './debounce';
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"name": "@yaakapp-internal/lib",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"main": "index.ts"
|
||||
}
|
||||
2
packages/plugin-runtime-types/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
lib
|
||||
node_modules
|
||||
47
packages/plugin-runtime-types/package-lock.json
generated
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"name": "@yaakapp/api",
|
||||
"version": "0.1.17",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@yaakapp/api",
|
||||
"version": "0.1.17",
|
||||
"dependencies": {
|
||||
"@types/node": "^22.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz",
|
||||
"integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.19.2"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.6.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz",
|
||||
"integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.19.8",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
||||
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"name": "@yaakapp/api",
|
||||
"version": "0.5.3",
|
||||
"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": "run-p build:copy-types:*",
|
||||
"build:copy-types:root": "cpy --flat ../../src-tauri/yaak-plugins/bindings/*.ts ./src/bindings",
|
||||
"build:copy-types:next": "cpy --flat ../../src-tauri/yaak-plugins/bindings/serde_json/*.ts ./src/bindings/serde_json",
|
||||
"publish": "npm publish",
|
||||
"prepublishOnly": "npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": "^22.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cpy-cli": "^5.0.0"
|
||||
}
|
||||
}
|
||||
@@ -1,411 +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 "./gen_models.js";
|
||||
import type { Folder } from "./gen_models.js";
|
||||
import type { GrpcRequest } from "./gen_models.js";
|
||||
import type { HttpRequest } from "./gen_models.js";
|
||||
import type { HttpResponse } from "./gen_models.js";
|
||||
import type { JsonValue } from "./serde_json/JsonValue.js";
|
||||
import type { WebsocketRequest } from "./gen_models.js";
|
||||
import type { Workspace } from "./gen_models.js";
|
||||
|
||||
export type BootRequest = { dir: string, watch: boolean, };
|
||||
|
||||
export type BootResponse = { name: string, version: string, };
|
||||
|
||||
export type CallHttpAuthenticationActionArgs = { contextId: string, values: { [key in string]?: JsonPrimitive }, };
|
||||
|
||||
export type CallHttpAuthenticationActionRequest = { index: number, pluginRefId: string, args: CallHttpAuthenticationActionArgs, };
|
||||
|
||||
export type CallHttpAuthenticationRequest = { contextId: string, values: { [key in string]?: JsonPrimitive }, method: string, url: string, headers: Array<HttpHeader>, };
|
||||
|
||||
export type CallHttpAuthenticationResponse = {
|
||||
/**
|
||||
* HTTP headers to add to the request. Existing headers will be replaced, while
|
||||
* new headers will be added.
|
||||
*/
|
||||
setHeaders: Array<HttpHeader>, };
|
||||
|
||||
export type CallHttpRequestActionArgs = { httpRequest: HttpRequest, };
|
||||
|
||||
export type CallHttpRequestActionRequest = { index: number, 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 CloseWindowRequest = { label: string, };
|
||||
|
||||
export type Color = "primary" | "secondary" | "info" | "success" | "notice" | "warning" | "danger";
|
||||
|
||||
export type CompletionOptionType = "constant" | "variable";
|
||||
|
||||
export type Content = { "type": "text", content: string, } | { "type": "markdown", content: string, };
|
||||
|
||||
export type CopyTextRequest = { text: string, };
|
||||
|
||||
export type DeleteKeyValueRequest = { key: string, };
|
||||
|
||||
export type DeleteKeyValueResponse = { deleted: boolean, };
|
||||
|
||||
export type EditorLanguage = "text" | "javascript" | "json" | "html" | "xml" | "graphql" | "markdown";
|
||||
|
||||
export type EmptyPayload = {};
|
||||
|
||||
export type ErrorResponse = { error: string, };
|
||||
|
||||
export type ExportHttpRequestRequest = { httpRequest: HttpRequest, };
|
||||
|
||||
export type ExportHttpRequestResponse = { content: string, };
|
||||
|
||||
export type FileFilter = { name: string,
|
||||
/**
|
||||
* File extensions to require
|
||||
*/
|
||||
extensions: Array<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 FormInput = { "type": "text" } & FormInputText | { "type": "editor" } & FormInputEditor | { "type": "select" } & FormInputSelect | { "type": "checkbox" } & FormInputCheckbox | { "type": "file" } & FormInputFile | { "type": "http_request" } & FormInputHttpRequest | { "type": "accordion" } & FormInputAccordion | { "type": "banner" } & FormInputBanner | { "type": "markdown" } & FormInputMarkdown;
|
||||
|
||||
export type FormInputAccordion = { label: string, inputs?: Array<FormInput>, hidden?: boolean, };
|
||||
|
||||
export type FormInputBanner = { inputs?: Array<FormInput>, hidden?: boolean, color?: Color, };
|
||||
|
||||
export type FormInputBase = {
|
||||
/**
|
||||
* The name of the input. The value will be stored at this object attribute in the resulting data
|
||||
*/
|
||||
name: string,
|
||||
/**
|
||||
* Whether this input is visible for the given configuration. Use this to
|
||||
* make branching forms.
|
||||
*/
|
||||
hidden?: boolean,
|
||||
/**
|
||||
* Whether the user must fill in the argument
|
||||
*/
|
||||
optional?: boolean,
|
||||
/**
|
||||
* The label of the input
|
||||
*/
|
||||
label?: string,
|
||||
/**
|
||||
* Visually hide the label of the input
|
||||
*/
|
||||
hideLabel?: boolean,
|
||||
/**
|
||||
* The default value
|
||||
*/
|
||||
defaultValue?: string, disabled?: boolean, };
|
||||
|
||||
export type FormInputCheckbox = {
|
||||
/**
|
||||
* The name of the input. The value will be stored at this object attribute in the resulting data
|
||||
*/
|
||||
name: string,
|
||||
/**
|
||||
* Whether this input is visible for the given configuration. Use this to
|
||||
* make branching forms.
|
||||
*/
|
||||
hidden?: boolean,
|
||||
/**
|
||||
* Whether the user must fill in the argument
|
||||
*/
|
||||
optional?: boolean,
|
||||
/**
|
||||
* The label of the input
|
||||
*/
|
||||
label?: string,
|
||||
/**
|
||||
* Visually hide the label of the input
|
||||
*/
|
||||
hideLabel?: boolean,
|
||||
/**
|
||||
* The default value
|
||||
*/
|
||||
defaultValue?: string, disabled?: boolean, };
|
||||
|
||||
export type FormInputEditor = {
|
||||
/**
|
||||
* Placeholder for the text input
|
||||
*/
|
||||
placeholder?: string | null,
|
||||
/**
|
||||
* Don't show the editor gutter (line numbers, folds, etc.)
|
||||
*/
|
||||
hideGutter?: boolean,
|
||||
/**
|
||||
* Language for syntax highlighting
|
||||
*/
|
||||
language?: EditorLanguage, readOnly?: boolean, completionOptions?: Array<GenericCompletionOption>,
|
||||
/**
|
||||
* The name of the input. The value will be stored at this object attribute in the resulting data
|
||||
*/
|
||||
name: string,
|
||||
/**
|
||||
* Whether this input is visible for the given configuration. Use this to
|
||||
* make branching forms.
|
||||
*/
|
||||
hidden?: boolean,
|
||||
/**
|
||||
* Whether the user must fill in the argument
|
||||
*/
|
||||
optional?: boolean,
|
||||
/**
|
||||
* The label of the input
|
||||
*/
|
||||
label?: string,
|
||||
/**
|
||||
* Visually hide the label of the input
|
||||
*/
|
||||
hideLabel?: boolean,
|
||||
/**
|
||||
* The default value
|
||||
*/
|
||||
defaultValue?: string, disabled?: boolean, };
|
||||
|
||||
export type FormInputFile = {
|
||||
/**
|
||||
* The title of the file selection window
|
||||
*/
|
||||
title: string,
|
||||
/**
|
||||
* Allow selecting multiple files
|
||||
*/
|
||||
multiple?: boolean, directory?: boolean, defaultPath?: string, filters?: Array<FileFilter>,
|
||||
/**
|
||||
* The name of the input. The value will be stored at this object attribute in the resulting data
|
||||
*/
|
||||
name: string,
|
||||
/**
|
||||
* Whether this input is visible for the given configuration. Use this to
|
||||
* make branching forms.
|
||||
*/
|
||||
hidden?: boolean,
|
||||
/**
|
||||
* Whether the user must fill in the argument
|
||||
*/
|
||||
optional?: boolean,
|
||||
/**
|
||||
* The label of the input
|
||||
*/
|
||||
label?: string,
|
||||
/**
|
||||
* Visually hide the label of the input
|
||||
*/
|
||||
hideLabel?: boolean,
|
||||
/**
|
||||
* The default value
|
||||
*/
|
||||
defaultValue?: string, disabled?: boolean, };
|
||||
|
||||
export type FormInputHttpRequest = {
|
||||
/**
|
||||
* The name of the input. The value will be stored at this object attribute in the resulting data
|
||||
*/
|
||||
name: string,
|
||||
/**
|
||||
* Whether this input is visible for the given configuration. Use this to
|
||||
* make branching forms.
|
||||
*/
|
||||
hidden?: boolean,
|
||||
/**
|
||||
* Whether the user must fill in the argument
|
||||
*/
|
||||
optional?: boolean,
|
||||
/**
|
||||
* The label of the input
|
||||
*/
|
||||
label?: string,
|
||||
/**
|
||||
* Visually hide the label of the input
|
||||
*/
|
||||
hideLabel?: boolean,
|
||||
/**
|
||||
* The default value
|
||||
*/
|
||||
defaultValue?: string, disabled?: boolean, };
|
||||
|
||||
export type FormInputMarkdown = { content: string, hidden?: boolean, };
|
||||
|
||||
export type FormInputSelect = {
|
||||
/**
|
||||
* The options that will be available in the select input
|
||||
*/
|
||||
options: Array<FormInputSelectOption>,
|
||||
/**
|
||||
* The name of the input. The value will be stored at this object attribute in the resulting data
|
||||
*/
|
||||
name: string,
|
||||
/**
|
||||
* Whether this input is visible for the given configuration. Use this to
|
||||
* make branching forms.
|
||||
*/
|
||||
hidden?: boolean,
|
||||
/**
|
||||
* Whether the user must fill in the argument
|
||||
*/
|
||||
optional?: boolean,
|
||||
/**
|
||||
* The label of the input
|
||||
*/
|
||||
label?: string,
|
||||
/**
|
||||
* Visually hide the label of the input
|
||||
*/
|
||||
hideLabel?: boolean,
|
||||
/**
|
||||
* The default value
|
||||
*/
|
||||
defaultValue?: string, disabled?: boolean, };
|
||||
|
||||
export type FormInputSelectOption = { label: string, value: string, };
|
||||
|
||||
export type FormInputText = {
|
||||
/**
|
||||
* Placeholder for the text input
|
||||
*/
|
||||
placeholder?: string | null,
|
||||
/**
|
||||
* Placeholder for the text input
|
||||
*/
|
||||
password?: boolean,
|
||||
/**
|
||||
* Whether to allow newlines in the input, like a <textarea/>
|
||||
*/
|
||||
multiLine?: boolean, completionOptions?: Array<GenericCompletionOption>,
|
||||
/**
|
||||
* The name of the input. The value will be stored at this object attribute in the resulting data
|
||||
*/
|
||||
name: string,
|
||||
/**
|
||||
* Whether this input is visible for the given configuration. Use this to
|
||||
* make branching forms.
|
||||
*/
|
||||
hidden?: boolean,
|
||||
/**
|
||||
* Whether the user must fill in the argument
|
||||
*/
|
||||
optional?: boolean,
|
||||
/**
|
||||
* The label of the input
|
||||
*/
|
||||
label?: string,
|
||||
/**
|
||||
* Visually hide the label of the input
|
||||
*/
|
||||
hideLabel?: boolean,
|
||||
/**
|
||||
* The default value
|
||||
*/
|
||||
defaultValue?: string, disabled?: boolean, };
|
||||
|
||||
export type GenericCompletionOption = { label: string, detail?: string, info?: string, type?: CompletionOptionType, boost?: number, };
|
||||
|
||||
export type GetHttpAuthenticationConfigRequest = { contextId: string, values: { [key in string]?: JsonPrimitive }, };
|
||||
|
||||
export type GetHttpAuthenticationConfigResponse = { args: Array<FormInput>, pluginRefId: string, actions?: Array<HttpAuthenticationAction>, };
|
||||
|
||||
export type GetHttpAuthenticationSummaryResponse = { name: string, label: string, shortLabel: string, };
|
||||
|
||||
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 GetKeyValueRequest = { key: string, };
|
||||
|
||||
export type GetKeyValueResponse = { value?: string, };
|
||||
|
||||
export type GetTemplateFunctionsResponse = { functions: Array<TemplateFunction>, pluginRefId: string, };
|
||||
|
||||
export type HttpAuthenticationAction = { label: string, icon?: Icon, };
|
||||
|
||||
export type HttpHeader = { name: string, value: string, };
|
||||
|
||||
export type HttpRequestAction = { label: string, icon?: Icon, };
|
||||
|
||||
export type Icon = "alert_triangle" | "check" | "check_circle" | "chevron_down" | "copy" | "info" | "pin" | "search" | "trash" | "_unknown";
|
||||
|
||||
export type ImportRequest = { content: string, };
|
||||
|
||||
export type ImportResources = { workspaces: Array<Workspace>, environments: Array<Environment>, folders: Array<Folder>, httpRequests: Array<HttpRequest>, grpcRequests: Array<GrpcRequest>, websocketRequests: Array<WebsocketRequest>, };
|
||||
|
||||
export type ImportResponse = { resources: ImportResources, };
|
||||
|
||||
export type InternalEvent = { id: string, pluginRefId: string, pluginName: string, replyId: string | null, windowContext: PluginWindowContext, payload: InternalEventPayload, };
|
||||
|
||||
export type InternalEventPayload = { "type": "boot_request" } & BootRequest | { "type": "boot_response" } & BootResponse | { "type": "reload_request" } & EmptyPayload | { "type": "reload_response" } & EmptyPayload | { "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" } & EmptyPayload | { "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": "get_http_authentication_summary_request" } & EmptyPayload | { "type": "get_http_authentication_summary_response" } & GetHttpAuthenticationSummaryResponse | { "type": "get_http_authentication_config_request" } & GetHttpAuthenticationConfigRequest | { "type": "get_http_authentication_config_response" } & GetHttpAuthenticationConfigResponse | { "type": "call_http_authentication_request" } & CallHttpAuthenticationRequest | { "type": "call_http_authentication_response" } & CallHttpAuthenticationResponse | { "type": "call_http_authentication_action_request" } & CallHttpAuthenticationActionRequest | { "type": "call_http_authentication_action_response" } & EmptyPayload | { "type": "copy_text_request" } & CopyTextRequest | { "type": "copy_text_response" } & EmptyPayload | { "type": "render_http_request_request" } & RenderHttpRequestRequest | { "type": "render_http_request_response" } & RenderHttpRequestResponse | { "type": "get_key_value_request" } & GetKeyValueRequest | { "type": "get_key_value_response" } & GetKeyValueResponse | { "type": "set_key_value_request" } & SetKeyValueRequest | { "type": "set_key_value_response" } & SetKeyValueResponse | { "type": "delete_key_value_request" } & DeleteKeyValueRequest | { "type": "delete_key_value_response" } & DeleteKeyValueResponse | { "type": "open_window_request" } & OpenWindowRequest | { "type": "window_navigate_event" } & WindowNavigateEvent | { "type": "window_close_event" } | { "type": "close_window_request" } & CloseWindowRequest | { "type": "template_render_request" } & TemplateRenderRequest | { "type": "template_render_response" } & TemplateRenderResponse | { "type": "show_toast_request" } & ShowToastRequest | { "type": "show_toast_response" } & EmptyPayload | { "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" } & EmptyPayload | { "type": "error_response" } & ErrorResponse;
|
||||
|
||||
export type JsonPrimitive = string | number | boolean | null;
|
||||
|
||||
export type OpenWindowRequest = { url: string,
|
||||
/**
|
||||
* Label for the window. If not provided, a random one will be generated.
|
||||
*/
|
||||
label: string, title?: string, size?: WindowSize, dataDirKey?: string, };
|
||||
|
||||
export type PluginWindowContext = { "type": "none" } | { "type": "label", label: string, workspace_id: string | null, };
|
||||
|
||||
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
|
||||
*/
|
||||
required?: 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: Partial<HttpRequest>, };
|
||||
|
||||
export type SendHttpRequestResponse = { httpResponse: HttpResponse, };
|
||||
|
||||
export type SetKeyValueRequest = { key: string, value: string, };
|
||||
|
||||
export type SetKeyValueResponse = {};
|
||||
|
||||
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>, };
|
||||
|
||||
/**
|
||||
* Similar to FormInput, but contains
|
||||
*/
|
||||
export type TemplateFunctionArg = FormInput;
|
||||
|
||||
export type TemplateRenderRequest = { data: JsonValue, purpose: RenderPurpose, };
|
||||
|
||||
export type TemplateRenderResponse = { data: JsonValue, };
|
||||
|
||||
export type WindowNavigateEvent = { url: string, };
|
||||
|
||||
export type WindowSize = { width: number, height: number, };
|
||||
@@ -1,27 +0,0 @@
|
||||
// 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, public: boolean, base: boolean, variables: Array<EnvironmentVariable>, };
|
||||
|
||||
export type EnvironmentVariable = { enabled?: boolean, name: string, value: string, id?: string, };
|
||||
|
||||
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, id?: 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, 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, id?: 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, 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, id?: string, };
|
||||
|
||||
export type WebsocketRequest = { model: "websocket_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record<string, any>, authenticationType: string | null, description: string, headers: Array<HttpRequestHeader>, message: string, name: string, sortPriority: number, url: string, urlParameters: Array<HttpUrlParameter>, };
|
||||
|
||||
export type Workspace = { model: "workspace", id: string, createdAt: string, updatedAt: string, name: string, description: string, encryptionKeyChallenge: string | null, settingValidateCertificates: boolean, settingFollowRedirects: boolean, settingRequestTimeout: number, };
|
||||
@@ -1,3 +0,0 @@
|
||||
// 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 | boolean | Array<JsonValue> | { [key in string]?: JsonValue } | null;
|
||||
@@ -1,2 +0,0 @@
|
||||
export type AtLeast<T, K extends keyof T> = Partial<T> & Pick<T, K>;
|
||||
export type MaybePromise<T> = Promise<T> | T;
|
||||
@@ -1,9 +0,0 @@
|
||||
export type * from './plugins';
|
||||
export type * from './themes';
|
||||
|
||||
export * from './bindings/gen_models';
|
||||
export * from './bindings/gen_events';
|
||||
|
||||
// Some extras for utility
|
||||
|
||||
export type { PartialImportResources } from './plugins/ImporterPlugin';
|
||||
@@ -1,29 +0,0 @@
|
||||
import {
|
||||
CallHttpAuthenticationActionArgs,
|
||||
CallHttpAuthenticationRequest,
|
||||
CallHttpAuthenticationResponse,
|
||||
FormInput,
|
||||
GetHttpAuthenticationConfigRequest,
|
||||
GetHttpAuthenticationSummaryResponse,
|
||||
HttpAuthenticationAction,
|
||||
} from '../bindings/gen_events';
|
||||
import { MaybePromise } from '../helpers';
|
||||
import { Context } from './Context';
|
||||
|
||||
type DynamicFormInput = FormInput & {
|
||||
dynamic(
|
||||
ctx: Context,
|
||||
args: GetHttpAuthenticationConfigRequest,
|
||||
): MaybePromise<Partial<FormInput> | undefined | null>;
|
||||
};
|
||||
|
||||
export type AuthenticationPlugin = GetHttpAuthenticationSummaryResponse & {
|
||||
args: (FormInput | DynamicFormInput)[];
|
||||
onApply(
|
||||
ctx: Context,
|
||||
args: CallHttpAuthenticationRequest,
|
||||
): MaybePromise<CallHttpAuthenticationResponse>;
|
||||
actions?: (HttpAuthenticationAction & {
|
||||
onSelect(ctx: Context, args: CallHttpAuthenticationActionArgs): Promise<void> | void;
|
||||
})[];
|
||||
};
|
||||
@@ -1,52 +0,0 @@
|
||||
import type {
|
||||
FindHttpResponsesRequest,
|
||||
FindHttpResponsesResponse,
|
||||
GetHttpRequestByIdRequest,
|
||||
GetHttpRequestByIdResponse,
|
||||
OpenWindowRequest,
|
||||
PromptTextRequest,
|
||||
PromptTextResponse,
|
||||
RenderHttpRequestRequest,
|
||||
RenderHttpRequestResponse,
|
||||
SendHttpRequestRequest,
|
||||
SendHttpRequestResponse,
|
||||
ShowToastRequest,
|
||||
TemplateRenderRequest,
|
||||
TemplateRenderResponse,
|
||||
} from '../bindings/gen_events.ts';
|
||||
|
||||
export interface Context {
|
||||
clipboard: {
|
||||
copyText(text: string): Promise<void>;
|
||||
};
|
||||
toast: {
|
||||
show(args: ShowToastRequest): Promise<void>;
|
||||
};
|
||||
prompt: {
|
||||
text(args: PromptTextRequest): Promise<PromptTextResponse['value']>;
|
||||
};
|
||||
store: {
|
||||
set<T>(key: string, value: T): Promise<void>;
|
||||
get<T>(key: string): Promise<T | undefined>;
|
||||
delete(key: string): Promise<boolean>;
|
||||
};
|
||||
window: {
|
||||
openUrl(
|
||||
args: OpenWindowRequest & {
|
||||
onNavigate?: (args: { url: string }) => void;
|
||||
onClose?: () => void;
|
||||
},
|
||||
): Promise<{ close: () => void }>;
|
||||
};
|
||||
httpRequest: {
|
||||
send(args: SendHttpRequestRequest): Promise<SendHttpRequestResponse['httpResponse']>;
|
||||
getById(args: GetHttpRequestByIdRequest): Promise<GetHttpRequestByIdResponse['httpRequest']>;
|
||||
render(args: RenderHttpRequestRequest): Promise<RenderHttpRequestResponse['httpRequest']>;
|
||||
};
|
||||
httpResponse: {
|
||||
find(args: FindHttpResponsesRequest): Promise<FindHttpResponsesResponse['httpResponses']>;
|
||||
};
|
||||
templates: {
|
||||
render(args: TemplateRenderRequest): Promise<TemplateRenderResponse['data']>;
|
||||
};
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import type { Context } from './Context';
|
||||
|
||||
type FilterPluginResponse = { filtered: string };
|
||||
|
||||
export type FilterPlugin = {
|
||||
name: string;
|
||||
description?: string;
|
||||
onFilter(
|
||||
ctx: Context,
|
||||
args: { payload: string; filter: string; mimeType: string },
|
||||
): Promise<FilterPluginResponse> | FilterPluginResponse;
|
||||
};
|
||||
@@ -1,6 +0,0 @@
|
||||
import type { CallHttpRequestActionArgs, HttpRequestAction } from '../bindings/gen_events';
|
||||
import type { Context } from './Context';
|
||||
|
||||
export type HttpRequestActionPlugin = HttpRequestAction & {
|
||||
onSelect(ctx: Context, args: CallHttpRequestActionArgs): Promise<void> | void;
|
||||
};
|
||||
@@ -1,25 +0,0 @@
|
||||
import { ImportResources } from '../bindings/gen_events';
|
||||
import { AtLeast } from '../helpers';
|
||||
import type { Context } from './Context';
|
||||
|
||||
type RootFields = 'name' | 'id' | 'model';
|
||||
type CommonFields = RootFields | 'workspaceId';
|
||||
|
||||
export type PartialImportResources = {
|
||||
workspaces: Array<AtLeast<ImportResources['workspaces'][0], RootFields>>;
|
||||
environments: Array<AtLeast<ImportResources['environments'][0], CommonFields>>;
|
||||
folders: Array<AtLeast<ImportResources['folders'][0], CommonFields>>;
|
||||
httpRequests: Array<AtLeast<ImportResources['httpRequests'][0], CommonFields>>;
|
||||
grpcRequests: Array<AtLeast<ImportResources['grpcRequests'][0], CommonFields>>;
|
||||
websocketRequests: Array<AtLeast<ImportResources['websocketRequests'][0], CommonFields>>;
|
||||
};
|
||||
|
||||
export type ImportPluginResponse = null | {
|
||||
resources: PartialImportResources;
|
||||
};
|
||||
|
||||
export type ImporterPlugin = {
|
||||
name: string;
|
||||
description?: string;
|
||||
onImport(ctx: Context, args: { text: string }): Promise<ImportPluginResponse>;
|
||||
};
|
||||
@@ -1,12 +0,0 @@
|
||||
import {
|
||||
CallTemplateFunctionArgs,
|
||||
TemplateFunction,
|
||||
} from "../bindings/gen_events";
|
||||
import { Context } from "./Context";
|
||||
|
||||
export type TemplateFunctionPlugin = TemplateFunction & {
|
||||
onRender(
|
||||
ctx: Context,
|
||||
args: CallTemplateFunctionArgs,
|
||||
): Promise<string | null>;
|
||||
};
|
||||
@@ -1,8 +0,0 @@
|
||||
import { Index } from "../themes";
|
||||
import { Context } from "./Context";
|
||||
|
||||
export type ThemePlugin = {
|
||||
name: string;
|
||||
description?: string;
|
||||
getTheme(ctx: Context, fileContents: string): Promise<Index>;
|
||||
};
|
||||
@@ -1,20 +0,0 @@
|
||||
import { AuthenticationPlugin } from './AuthenticationPlugin';
|
||||
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';
|
||||
|
||||
/**
|
||||
* The global structure of a Yaak plugin
|
||||
*/
|
||||
export type PluginDefinition = {
|
||||
importer?: ImporterPlugin;
|
||||
theme?: ThemePlugin;
|
||||
filter?: FilterPlugin;
|
||||
authentication?: AuthenticationPlugin;
|
||||
httpRequestActions?: HttpRequestActionPlugin[];
|
||||
templateFunctions?: TemplateFunctionPlugin[];
|
||||
};
|
||||
@@ -1,44 +0,0 @@
|
||||
export type Colors = {
|
||||
surface: string;
|
||||
surfaceHighlight?: string;
|
||||
surfaceActive?: string;
|
||||
|
||||
text: string;
|
||||
textSubtle?: string;
|
||||
textSubtlest?: string;
|
||||
|
||||
border?: string;
|
||||
borderSubtle?: string;
|
||||
borderFocus?: string;
|
||||
|
||||
shadow?: string;
|
||||
backdrop?: string;
|
||||
selection?: string;
|
||||
|
||||
primary?: string;
|
||||
secondary?: string;
|
||||
info?: string;
|
||||
success?: string;
|
||||
notice?: string;
|
||||
warning?: string;
|
||||
danger?: string;
|
||||
};
|
||||
|
||||
export type Index = Colors & {
|
||||
id: string;
|
||||
name: string;
|
||||
components?: Partial<{
|
||||
dialog: Partial<Colors>;
|
||||
menu: Partial<Colors>;
|
||||
toast: Partial<Colors>;
|
||||
sidebar: Partial<Colors>;
|
||||
responsePane: Partial<Colors>;
|
||||
appHeader: Partial<Colors>;
|
||||
button: Partial<Colors>;
|
||||
banner: Partial<Colors>;
|
||||
placeholder: Partial<Colors>;
|
||||
urlBar: Partial<Colors>;
|
||||
editor: Partial<Colors>;
|
||||
input: Partial<Colors>;
|
||||
}>;
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "node16",
|
||||
"target": "es6",
|
||||
"lib": ["es2021"],
|
||||
"declaration": true,
|
||||
"declarationDir": "./lib",
|
||||
"outDir": "./lib",
|
||||
"strict": true,
|
||||
"types": ["node"]
|
||||
},
|
||||
"files": [
|
||||
"src/index.ts"
|
||||
]
|
||||
}
|
||||
10
packages/plugin-runtime/package-lock.json
generated
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"name": "@yaakapp-internal/plugin-runtime",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@yaakapp-internal/plugin-runtime"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
},
|
||||
"dependencies": {
|
||||
"ws": "^8.18.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/ws": "^8.5.13"
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import type { InternalEvent } from '@yaakapp/api';
|
||||
|
||||
export class EventChannel {
|
||||
#listeners = new Set<(event: InternalEvent) => void>();
|
||||
|
||||
emit(e: InternalEvent) {
|
||||
for (const l of this.#listeners) {
|
||||
l(e);
|
||||
}
|
||||
}
|
||||
|
||||
listen(cb: (e: InternalEvent) => void) {
|
||||
this.#listeners.add(cb);
|
||||
}
|
||||
|
||||
unlisten(cb: (e: InternalEvent) => void) {
|
||||
this.#listeners.delete(cb);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import type { BootRequest, InternalEvent } from '@yaakapp/api';
|
||||
import type { EventChannel } from './EventChannel';
|
||||
import { PluginInstance, PluginWorkerData } from './PluginInstance';
|
||||
|
||||
export class PluginHandle {
|
||||
#instance: PluginInstance;
|
||||
|
||||
constructor(
|
||||
readonly pluginRefId: string,
|
||||
readonly bootRequest: BootRequest,
|
||||
readonly pluginToAppEvents: EventChannel,
|
||||
) {
|
||||
const workerData: PluginWorkerData = {
|
||||
pluginRefId: this.pluginRefId,
|
||||
bootRequest: this.bootRequest,
|
||||
};
|
||||
this.#instance = new PluginInstance(workerData, pluginToAppEvents);
|
||||
}
|
||||
|
||||
sendToWorker(event: InternalEvent) {
|
||||
this.#instance.postMessage(event);
|
||||
}
|
||||
|
||||
terminate() {
|
||||
this.#instance.terminate();
|
||||
}
|
||||
}
|
||||
@@ -1,582 +0,0 @@
|
||||
import { PluginWindowContext, TemplateFunctionArg } from '@yaakapp-internal/plugins';
|
||||
import type {
|
||||
BootRequest,
|
||||
Context,
|
||||
DeleteKeyValueResponse,
|
||||
FindHttpResponsesResponse,
|
||||
FormInput,
|
||||
GetHttpRequestByIdResponse,
|
||||
GetKeyValueResponse,
|
||||
HttpAuthenticationAction,
|
||||
HttpRequestAction,
|
||||
InternalEvent,
|
||||
InternalEventPayload,
|
||||
JsonPrimitive,
|
||||
PluginDefinition,
|
||||
PromptTextResponse,
|
||||
RenderHttpRequestResponse,
|
||||
SendHttpRequestResponse,
|
||||
TemplateFunction,
|
||||
TemplateRenderResponse,
|
||||
} from '@yaakapp/api';
|
||||
import console from 'node:console';
|
||||
import { readFileSync, type Stats, statSync, watch } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
// import util from 'node:util';
|
||||
import { EventChannel } from './EventChannel';
|
||||
// import { interceptStdout } from './interceptStdout';
|
||||
import { migrateTemplateFunctionSelectOptions } from './migrations';
|
||||
|
||||
export interface PluginWorkerData {
|
||||
bootRequest: BootRequest;
|
||||
pluginRefId: string;
|
||||
}
|
||||
|
||||
export class PluginInstance {
|
||||
#workerData: PluginWorkerData;
|
||||
#mod: PluginDefinition;
|
||||
#pkg: { name?: string; version?: string };
|
||||
#pluginToAppEvents: EventChannel;
|
||||
#appToPluginEvents: EventChannel;
|
||||
|
||||
constructor(workerData: PluginWorkerData, pluginEvents: EventChannel) {
|
||||
this.#workerData = workerData;
|
||||
this.#pluginToAppEvents = pluginEvents;
|
||||
this.#appToPluginEvents = new EventChannel();
|
||||
|
||||
// Forward incoming events to onMessage()
|
||||
this.#appToPluginEvents.listen(async (event) => {
|
||||
await this.#onMessage(event);
|
||||
});
|
||||
|
||||
// Reload plugin if the JS or package.json changes
|
||||
const windowContextNone: PluginWindowContext = { type: 'none' };
|
||||
const fileChangeCallback = async () => {
|
||||
this.#importModule();
|
||||
return this.#sendPayload(windowContextNone, { type: 'reload_response' }, null);
|
||||
};
|
||||
|
||||
if (this.#workerData.bootRequest.watch) {
|
||||
watchFile(this.#pathMod(), fileChangeCallback);
|
||||
watchFile(this.#pathPkg(), fileChangeCallback);
|
||||
}
|
||||
|
||||
this.#mod = {};
|
||||
this.#pkg = JSON.parse(readFileSync(this.#pathPkg(), 'utf8'));
|
||||
|
||||
// TODO: Re-implement this now that we're not using workers
|
||||
// prefixStdout(`[plugin][${this.#pkg.name}] %s`);
|
||||
|
||||
this.#importModule();
|
||||
}
|
||||
|
||||
postMessage(event: InternalEvent) {
|
||||
this.#appToPluginEvents.emit(event);
|
||||
}
|
||||
|
||||
terminate() {
|
||||
this.#unimportModule();
|
||||
}
|
||||
|
||||
async #onMessage(event: InternalEvent) {
|
||||
const ctx = this.#newCtx(event);
|
||||
|
||||
const { windowContext, payload, id: replyId } = event;
|
||||
try {
|
||||
if (payload.type === 'boot_request') {
|
||||
// console.log('Plugin initialized', pkg.name, { capabilities, enableWatch });
|
||||
const payload: InternalEventPayload = {
|
||||
type: 'boot_response',
|
||||
name: this.#pkg.name ?? 'unknown',
|
||||
version: this.#pkg.version ?? '0.0.1',
|
||||
};
|
||||
this.#sendPayload(windowContext, payload, replyId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload.type === 'terminate_request') {
|
||||
const payload: InternalEventPayload = {
|
||||
type: 'terminate_response',
|
||||
};
|
||||
this.#sendPayload(windowContext, payload, replyId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
payload.type === 'import_request' &&
|
||||
typeof this.#mod?.importer?.onImport === 'function'
|
||||
) {
|
||||
const reply = await this.#mod.importer.onImport(ctx, {
|
||||
text: payload.content,
|
||||
});
|
||||
if (reply != null) {
|
||||
const replyPayload: InternalEventPayload = {
|
||||
type: 'import_response',
|
||||
// deno-lint-ignore no-explicit-any
|
||||
resources: reply.resources as any,
|
||||
};
|
||||
this.#sendPayload(windowContext, replyPayload, replyId);
|
||||
return;
|
||||
} else {
|
||||
// Continue, to send back an empty reply
|
||||
}
|
||||
}
|
||||
|
||||
if (payload.type === 'filter_request' && typeof this.#mod?.filter?.onFilter === 'function') {
|
||||
const reply = await this.#mod.filter.onFilter(ctx, {
|
||||
filter: payload.filter,
|
||||
payload: payload.content,
|
||||
mimeType: payload.type,
|
||||
});
|
||||
const replyPayload: InternalEventPayload = {
|
||||
type: 'filter_response',
|
||||
content: reply.filtered,
|
||||
};
|
||||
this.#sendPayload(windowContext, replyPayload, replyId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
payload.type === 'get_http_request_actions_request' &&
|
||||
Array.isArray(this.#mod?.httpRequestActions)
|
||||
) {
|
||||
const reply: HttpRequestAction[] = this.#mod.httpRequestActions.map((a) => ({
|
||||
...a,
|
||||
// Add everything except onSelect
|
||||
onSelect: undefined,
|
||||
}));
|
||||
const replyPayload: InternalEventPayload = {
|
||||
type: 'get_http_request_actions_response',
|
||||
pluginRefId: this.#workerData.pluginRefId,
|
||||
actions: reply,
|
||||
};
|
||||
this.#sendPayload(windowContext, replyPayload, replyId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
payload.type === 'get_template_functions_request' &&
|
||||
Array.isArray(this.#mod?.templateFunctions)
|
||||
) {
|
||||
const reply: TemplateFunction[] = this.#mod.templateFunctions.map((templateFunction) => {
|
||||
return {
|
||||
...migrateTemplateFunctionSelectOptions(templateFunction),
|
||||
// Add everything except render
|
||||
onRender: undefined,
|
||||
};
|
||||
});
|
||||
const replyPayload: InternalEventPayload = {
|
||||
type: 'get_template_functions_response',
|
||||
pluginRefId: this.#workerData.pluginRefId,
|
||||
functions: reply,
|
||||
};
|
||||
this.#sendPayload(windowContext, replyPayload, replyId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload.type === 'get_http_authentication_summary_request' && this.#mod?.authentication) {
|
||||
const { name, shortLabel, label } = this.#mod.authentication;
|
||||
const replyPayload: InternalEventPayload = {
|
||||
type: 'get_http_authentication_summary_response',
|
||||
name,
|
||||
label,
|
||||
shortLabel,
|
||||
};
|
||||
|
||||
this.#sendPayload(windowContext, replyPayload, replyId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload.type === 'get_http_authentication_config_request' && this.#mod?.authentication) {
|
||||
const { args, actions } = this.#mod.authentication;
|
||||
const resolvedArgs: FormInput[] = [];
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
let v = args[i];
|
||||
if ('dynamic' in v) {
|
||||
const dynamicAttrs = await v.dynamic(ctx, payload);
|
||||
const { dynamic, ...other } = v;
|
||||
resolvedArgs.push({ ...other, ...dynamicAttrs } as FormInput);
|
||||
} else {
|
||||
resolvedArgs.push(v);
|
||||
}
|
||||
}
|
||||
const resolvedActions: HttpAuthenticationAction[] = [];
|
||||
for (const { onSelect, ...action } of actions ?? []) {
|
||||
resolvedActions.push(action);
|
||||
}
|
||||
|
||||
const replyPayload: InternalEventPayload = {
|
||||
type: 'get_http_authentication_config_response',
|
||||
args: resolvedArgs,
|
||||
actions: resolvedActions,
|
||||
pluginRefId: this.#workerData.pluginRefId,
|
||||
};
|
||||
|
||||
this.#sendPayload(windowContext, replyPayload, replyId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload.type === 'call_http_authentication_request' && this.#mod?.authentication) {
|
||||
const auth = this.#mod.authentication;
|
||||
if (typeof auth?.onApply === 'function') {
|
||||
applyFormInputDefaults(auth.args, payload.values);
|
||||
const result = await auth.onApply(ctx, payload);
|
||||
this.#sendPayload(
|
||||
windowContext,
|
||||
{
|
||||
type: 'call_http_authentication_response',
|
||||
setHeaders: result.setHeaders,
|
||||
},
|
||||
replyId,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
payload.type === 'call_http_authentication_action_request' &&
|
||||
this.#mod.authentication != null
|
||||
) {
|
||||
const action = this.#mod.authentication.actions?.[payload.index];
|
||||
if (typeof action?.onSelect === 'function') {
|
||||
await action.onSelect(ctx, payload.args);
|
||||
this.#sendEmpty(windowContext, replyId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
payload.type === 'call_http_request_action_request' &&
|
||||
Array.isArray(this.#mod.httpRequestActions)
|
||||
) {
|
||||
const action = this.#mod.httpRequestActions[payload.index];
|
||||
if (typeof action?.onSelect === 'function') {
|
||||
await action.onSelect(ctx, payload.args);
|
||||
this.#sendEmpty(windowContext, replyId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
payload.type === 'call_template_function_request' &&
|
||||
Array.isArray(this.#mod?.templateFunctions)
|
||||
) {
|
||||
const fn = this.#mod.templateFunctions.find((a) => a.name === payload.name);
|
||||
if (typeof fn?.onRender === 'function') {
|
||||
applyFormInputDefaults(fn.args, payload.args.values);
|
||||
const result = await fn.onRender(ctx, payload.args);
|
||||
this.#sendPayload(
|
||||
windowContext,
|
||||
{
|
||||
type: 'call_template_function_response',
|
||||
value: result ?? null,
|
||||
},
|
||||
replyId,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (payload.type === 'reload_request') {
|
||||
this.#importModule();
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('Plugin call threw exception', payload.type, err);
|
||||
this.#sendPayload(
|
||||
windowContext,
|
||||
{
|
||||
type: 'error_response',
|
||||
error: `${err}`,
|
||||
},
|
||||
replyId,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// No matches, so send back an empty response so the caller doesn't block forever
|
||||
this.#sendEmpty(windowContext, replyId);
|
||||
}
|
||||
|
||||
#pathMod() {
|
||||
return path.posix.join(this.#workerData.bootRequest.dir, 'build', 'index.js');
|
||||
}
|
||||
|
||||
#pathPkg() {
|
||||
return path.join(this.#workerData.bootRequest.dir, 'package.json');
|
||||
}
|
||||
|
||||
#unimportModule() {
|
||||
const id = require.resolve(this.#pathMod());
|
||||
delete require.cache[id];
|
||||
}
|
||||
|
||||
#importModule() {
|
||||
const id = require.resolve(this.#pathMod());
|
||||
delete require.cache[id];
|
||||
this.#mod = require(id).plugin;
|
||||
}
|
||||
|
||||
#buildEventToSend(
|
||||
windowContext: PluginWindowContext,
|
||||
payload: InternalEventPayload,
|
||||
replyId: string | null = null,
|
||||
): InternalEvent {
|
||||
return {
|
||||
pluginRefId: this.#workerData.pluginRefId,
|
||||
pluginName: path.basename(this.#workerData.bootRequest.dir),
|
||||
id: genId(),
|
||||
replyId,
|
||||
payload,
|
||||
windowContext,
|
||||
};
|
||||
}
|
||||
|
||||
#sendPayload(
|
||||
windowContext: PluginWindowContext,
|
||||
payload: InternalEventPayload,
|
||||
replyId: string | null,
|
||||
): string {
|
||||
const event = this.#buildEventToSend(windowContext, payload, replyId);
|
||||
this.#sendEvent(event);
|
||||
return event.id;
|
||||
}
|
||||
|
||||
#sendEvent(event: InternalEvent) {
|
||||
// if (event.payload.type !== 'empty_response') {
|
||||
// console.log('Sending event to app', this.#pkg.name, event.id, event.payload.type);
|
||||
// }
|
||||
this.#pluginToAppEvents.emit(event);
|
||||
}
|
||||
|
||||
#sendEmpty(windowContext: PluginWindowContext, replyId: string | null = null): string {
|
||||
return this.#sendPayload(windowContext, { type: 'empty_response' }, replyId);
|
||||
}
|
||||
|
||||
#sendAndWaitForReply<T extends Omit<InternalEventPayload, 'type'>>(
|
||||
windowContext: PluginWindowContext,
|
||||
payload: InternalEventPayload,
|
||||
): Promise<T> {
|
||||
// 1. Build event to send
|
||||
const eventToSend = this.#buildEventToSend(windowContext, payload, null);
|
||||
|
||||
// 2. Spawn listener in background
|
||||
const promise = new Promise<T>((resolve) => {
|
||||
const cb = (event: InternalEvent) => {
|
||||
if (event.replyId === eventToSend.id) {
|
||||
this.#appToPluginEvents.unlisten(cb); // Unlisten, now that we're done
|
||||
const { type: _, ...payload } = event.payload;
|
||||
resolve(payload as T);
|
||||
}
|
||||
};
|
||||
this.#appToPluginEvents.listen(cb);
|
||||
});
|
||||
|
||||
// 3. Send the event after we start listening (to prevent race)
|
||||
this.#sendEvent(eventToSend);
|
||||
|
||||
// 4. Return the listener promise
|
||||
return promise as unknown as Promise<T>;
|
||||
}
|
||||
|
||||
#sendAndListenForEvents(
|
||||
windowContext: PluginWindowContext,
|
||||
payload: InternalEventPayload,
|
||||
onEvent: (event: InternalEventPayload) => void,
|
||||
): void {
|
||||
// 1. Build event to send
|
||||
const eventToSend = this.#buildEventToSend(windowContext, payload, null);
|
||||
|
||||
// 2. Listen for replies in the background
|
||||
this.#appToPluginEvents.listen((event: InternalEvent) => {
|
||||
if (event.replyId === eventToSend.id) {
|
||||
onEvent(event.payload);
|
||||
}
|
||||
});
|
||||
|
||||
// 3. Send the event after we start listening (to prevent race)
|
||||
this.#sendEvent(eventToSend);
|
||||
}
|
||||
|
||||
#newCtx(event: InternalEvent): Context {
|
||||
return {
|
||||
clipboard: {
|
||||
copyText: async (text) => {
|
||||
await this.#sendAndWaitForReply(event.windowContext, {
|
||||
type: 'copy_text_request',
|
||||
text,
|
||||
});
|
||||
},
|
||||
},
|
||||
toast: {
|
||||
show: async (args) => {
|
||||
await this.#sendAndWaitForReply(event.windowContext, {
|
||||
type: 'show_toast_request',
|
||||
...args,
|
||||
});
|
||||
},
|
||||
},
|
||||
window: {
|
||||
openUrl: async ({ onNavigate, onClose, ...args }) => {
|
||||
args.label = args.label || `${Math.random()}`;
|
||||
const payload: InternalEventPayload = { type: 'open_window_request', ...args };
|
||||
const onEvent = (event: InternalEventPayload) => {
|
||||
if (event.type === 'window_navigate_event') {
|
||||
onNavigate?.(event);
|
||||
} else if (event.type === 'window_close_event') {
|
||||
onClose?.();
|
||||
}
|
||||
};
|
||||
this.#sendAndListenForEvents(event.windowContext, payload, onEvent);
|
||||
return {
|
||||
close: () => {
|
||||
const closePayload: InternalEventPayload = {
|
||||
type: 'close_window_request',
|
||||
label: args.label,
|
||||
};
|
||||
this.#sendPayload(event.windowContext, closePayload, null);
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
prompt: {
|
||||
text: async (args) => {
|
||||
const reply: PromptTextResponse = await this.#sendAndWaitForReply(event.windowContext, {
|
||||
type: 'prompt_text_request',
|
||||
...args,
|
||||
});
|
||||
return reply.value;
|
||||
},
|
||||
},
|
||||
httpResponse: {
|
||||
find: async (args) => {
|
||||
const payload = {
|
||||
type: 'find_http_responses_request',
|
||||
...args,
|
||||
} as const;
|
||||
const { httpResponses } = await this.#sendAndWaitForReply<FindHttpResponsesResponse>(
|
||||
event.windowContext,
|
||||
payload,
|
||||
);
|
||||
return httpResponses;
|
||||
},
|
||||
},
|
||||
httpRequest: {
|
||||
getById: async (args) => {
|
||||
const payload = {
|
||||
type: 'get_http_request_by_id_request',
|
||||
...args,
|
||||
} as const;
|
||||
const { httpRequest } = await this.#sendAndWaitForReply<GetHttpRequestByIdResponse>(
|
||||
event.windowContext,
|
||||
payload,
|
||||
);
|
||||
return httpRequest;
|
||||
},
|
||||
send: async (args) => {
|
||||
const payload = {
|
||||
type: 'send_http_request_request',
|
||||
...args,
|
||||
} as const;
|
||||
const { httpResponse } = await this.#sendAndWaitForReply<SendHttpRequestResponse>(
|
||||
event.windowContext,
|
||||
payload,
|
||||
);
|
||||
return httpResponse;
|
||||
},
|
||||
render: async (args) => {
|
||||
const payload = {
|
||||
type: 'render_http_request_request',
|
||||
...args,
|
||||
} as const;
|
||||
const { httpRequest } = await this.#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.
|
||||
*/
|
||||
render: async (args) => {
|
||||
const payload = { type: 'template_render_request', ...args } as const;
|
||||
const result = await this.#sendAndWaitForReply<TemplateRenderResponse>(
|
||||
event.windowContext,
|
||||
payload,
|
||||
);
|
||||
return result.data;
|
||||
},
|
||||
},
|
||||
store: {
|
||||
get: async <T>(key: string) => {
|
||||
const payload = { type: 'get_key_value_request', key } as const;
|
||||
const result = await this.#sendAndWaitForReply<GetKeyValueResponse>(
|
||||
event.windowContext,
|
||||
payload,
|
||||
);
|
||||
return result.value ? (JSON.parse(result.value) as T) : undefined;
|
||||
},
|
||||
set: async <T>(key: string, value: T) => {
|
||||
const valueStr = JSON.stringify(value);
|
||||
const payload: InternalEventPayload = {
|
||||
type: 'set_key_value_request',
|
||||
key,
|
||||
value: valueStr,
|
||||
};
|
||||
await this.#sendAndWaitForReply<GetKeyValueResponse>(event.windowContext, payload);
|
||||
},
|
||||
delete: async (key: string) => {
|
||||
const payload = { type: 'delete_key_value_request', key } as const;
|
||||
const result = await this.#sendAndWaitForReply<DeleteKeyValueResponse>(
|
||||
event.windowContext,
|
||||
payload,
|
||||
);
|
||||
return result.deleted;
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function genId(len = 5): string {
|
||||
const alphabet = '01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
let id = '';
|
||||
for (let i = 0; i < len; i++) {
|
||||
id += alphabet[Math.floor(Math.random() * alphabet.length)];
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
/** Recursively apply form input defaults to a set of values */
|
||||
function applyFormInputDefaults(
|
||||
inputs: TemplateFunctionArg[],
|
||||
values: { [p: string]: JsonPrimitive | undefined },
|
||||
) {
|
||||
for (const input of inputs) {
|
||||
if ('inputs' in input) {
|
||||
applyFormInputDefaults(input.inputs ?? [], values);
|
||||
} else if ('defaultValue' in input && values[input.name] === undefined) {
|
||||
values[input.name] = input.defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const watchedFiles: Record<string, Stats> = {};
|
||||
|
||||
/**
|
||||
* Watch a file and trigger callback on change.
|
||||
*
|
||||
* We also track the stat for each file because fs.watch() will
|
||||
* trigger a "change" event when the access date changes
|
||||
*/
|
||||
function watchFile(filepath: string, cb: (filepath: string) => void) {
|
||||
watch(filepath, () => {
|
||||
const stat = statSync(filepath);
|
||||
if (stat.mtimeMs !== watchedFiles[filepath]?.mtimeMs) {
|
||||
cb(filepath);
|
||||
}
|
||||
watchedFiles[filepath] = stat;
|
||||
});
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
import type { InternalEvent } from '@yaakapp/api';
|
||||
import { EventChannel } from './EventChannel';
|
||||
import { PluginHandle } from './PluginHandle';
|
||||
import WebSocket from 'ws';
|
||||
|
||||
const port = process.env.PORT;
|
||||
if (!port) {
|
||||
throw new Error('Plugin runtime missing PORT')
|
||||
}
|
||||
|
||||
const pluginToAppEvents = new EventChannel();
|
||||
const plugins: Record<string, PluginHandle> = {};
|
||||
|
||||
const ws = new WebSocket(`ws://localhost:${port}`);
|
||||
|
||||
ws.on('message', async (e: Buffer) => {
|
||||
try {
|
||||
await handleIncoming(e.toString());
|
||||
} catch (err) {
|
||||
console.log('Failed to handle incoming plugin event', err);
|
||||
}
|
||||
});
|
||||
ws.on('open', () => console.log('Plugin runtime connected to websocket'));
|
||||
ws.on('error', (err: any) => console.error('Plugin runtime websocket error', err));
|
||||
ws.on('close', (code: number) => console.log('Plugin runtime websocket closed', code));
|
||||
|
||||
// Listen for incoming events from plugins
|
||||
pluginToAppEvents.listen((e) => {
|
||||
const eventStr = JSON.stringify(e);
|
||||
ws.send(eventStr);
|
||||
});
|
||||
|
||||
async function handleIncoming(msg: string) {
|
||||
const pluginEvent: InternalEvent = JSON.parse(msg);
|
||||
// Handle special event to bootstrap plugin
|
||||
if (pluginEvent.payload.type === 'boot_request') {
|
||||
const plugin = new PluginHandle(pluginEvent.pluginRefId, pluginEvent.payload, pluginToAppEvents);
|
||||
plugins[pluginEvent.pluginRefId] = plugin;
|
||||
}
|
||||
|
||||
// Once booted, forward all events to the plugin worker
|
||||
const plugin = plugins[pluginEvent.pluginRefId];
|
||||
if (!plugin) {
|
||||
console.warn('Failed to get plugin for event by', pluginEvent.pluginRefId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pluginEvent.payload.type === 'terminate_request') {
|
||||
plugin.terminate();
|
||||
console.log('Terminated plugin worker', pluginEvent.pluginRefId);
|
||||
delete plugins[pluginEvent.pluginRefId];
|
||||
}
|
||||
|
||||
plugin.sendToWorker(pluginEvent);
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
import process from "node:process";
|
||||
|
||||
export function interceptStdout(
|
||||
intercept: (text: string) => string,
|
||||
) {
|
||||
const old_stdout_write = process.stdout.write;
|
||||
const old_stderr_write = process.stderr.write;
|
||||
|
||||
process.stdout.write = (function (write) {
|
||||
return function (text: string) {
|
||||
arguments[0] = interceptor(text, intercept);
|
||||
// deno-lint-ignore no-explicit-any
|
||||
write.apply(process.stdout, arguments as any);
|
||||
return true;
|
||||
};
|
||||
})(process.stdout.write);
|
||||
|
||||
process.stderr.write = (function (write) {
|
||||
return function (text: string) {
|
||||
arguments[0] = interceptor(text, intercept);
|
||||
// deno-lint-ignore no-explicit-any
|
||||
write.apply(process.stderr, arguments as any);
|
||||
return true;
|
||||
};
|
||||
})(process.stderr.write);
|
||||
|
||||
// puts back to original
|
||||
return function unhook() {
|
||||
process.stdout.write = old_stdout_write;
|
||||
process.stderr.write = old_stderr_write;
|
||||
};
|
||||
}
|
||||
|
||||
function interceptor(text: string, fn: (text: string) => string) {
|
||||
return fn(text).replace(/\n$/, "") +
|
||||
(fn(text) && /\n$/.test(text) ? "\n" : "");
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { TemplateFunction } from '@yaakapp/api';
|
||||
|
||||
export function migrateTemplateFunctionSelectOptions(f: TemplateFunction): TemplateFunction {
|
||||
const migratedArgs = f.args.map((a) => {
|
||||
if (a.type === 'select') {
|
||||
a.options = a.options.map((o) => ({
|
||||
...o,
|
||||
label: o.label || (o as any).name,
|
||||
}));
|
||||
}
|
||||
return a;
|
||||
});
|
||||
|
||||
return {
|
||||
...f,
|
||||
args: migratedArgs,
|
||||
};
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "node16",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"target": "es2021",
|
||||
"lib": ["es2021"],
|
||||
"noImplicitAny": false,
|
||||
"moduleResolution": "node16",
|
||||
"resolveJsonModule": true,
|
||||
"sourceMap": true,
|
||||
"outDir": "build",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"*": [
|
||||
"node_modules/*",
|
||||
"src/types/*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package yaak.plugins.runtime;
|
||||
|
||||
service PluginRuntime {
|
||||
rpc EventStream (stream EventStreamEvent) returns (stream EventStreamEvent);
|
||||
}
|
||||
|
||||
message EventStreamEvent {
|
||||
string event = 1;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
edition = "2024"
|
||||
|
||||
# Widths
|
||||
chain_width = 100
|
||||
max_width = 100
|
||||
single_line_if_else_max_width = 100
|
||||
fn_call_width = 100
|
||||
1
scripts/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
tmp-*
|
||||
@@ -1,15 +0,0 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const version = process.env.YAAK_VERSION?.replace('v', '');
|
||||
if (!version) {
|
||||
throw new Error('YAAK_VERSION environment variable not set')
|
||||
}
|
||||
|
||||
const tauriConfigPath = path.join(__dirname, '../src-tauri/tauri.conf.json');
|
||||
const tauriConfig = JSON.parse(fs.readFileSync(tauriConfigPath, 'utf8'));
|
||||
|
||||
tauriConfig.version = version;
|
||||
|
||||
console.log('Writing version ' + version + ' to ' + tauriConfigPath)
|
||||
fs.writeFileSync(tauriConfigPath, JSON.stringify(tauriConfig, null, 2));
|
||||
@@ -1,87 +0,0 @@
|
||||
const path = require('node:path');
|
||||
const decompress = require('decompress');
|
||||
const Downloader = require('nodejs-file-downloader');
|
||||
const { rmSync, cpSync, mkdirSync, existsSync } = require('node:fs');
|
||||
const { execSync } = require('node:child_process');
|
||||
|
||||
const NODE_VERSION = 'v22.9.0';
|
||||
|
||||
// `${process.platform}_${process.arch}`
|
||||
const MAC_ARM = 'darwin_arm64';
|
||||
const MAC_X64 = 'darwin_x64';
|
||||
const LNX_ARM = 'linux_arm64';
|
||||
const LNX_X64 = 'linux_x64';
|
||||
const WIN_X64 = 'win32_x64';
|
||||
|
||||
const URL_MAP = {
|
||||
[MAC_ARM]: `https://nodejs.org/download/release/${NODE_VERSION}/node-${NODE_VERSION}-darwin-arm64.tar.gz`,
|
||||
[MAC_X64]: `https://nodejs.org/download/release/${NODE_VERSION}/node-${NODE_VERSION}-darwin-x64.tar.gz`,
|
||||
[LNX_ARM]: `https://nodejs.org/download/release/${NODE_VERSION}/node-${NODE_VERSION}-linux-arm64.tar.gz`,
|
||||
[LNX_X64]: `https://nodejs.org/download/release/${NODE_VERSION}/node-${NODE_VERSION}-linux-x64.tar.gz`,
|
||||
[WIN_X64]: `https://nodejs.org/download/release/${NODE_VERSION}/node-${NODE_VERSION}-win-x64.zip`,
|
||||
};
|
||||
|
||||
const SRC_BIN_MAP = {
|
||||
[MAC_ARM]: `node-${NODE_VERSION}-darwin-arm64/bin/node`,
|
||||
[MAC_X64]: `node-${NODE_VERSION}-darwin-x64/bin/node`,
|
||||
[LNX_ARM]: `node-${NODE_VERSION}-linux-arm64/bin/node`,
|
||||
[LNX_X64]: `node-${NODE_VERSION}-linux-x64/bin/node`,
|
||||
[WIN_X64]: `node-${NODE_VERSION}-win-x64/node.exe`,
|
||||
};
|
||||
|
||||
const DST_BIN_MAP = {
|
||||
[MAC_ARM]: 'yaaknode-aarch64-apple-darwin',
|
||||
[MAC_X64]: 'yaaknode-x86_64-apple-darwin',
|
||||
[LNX_ARM]: 'yaaknode-aarch64-unknown-linux-gnu',
|
||||
[LNX_X64]: 'yaaknode-x86_64-unknown-linux-gnu',
|
||||
[WIN_X64]: 'yaaknode-x86_64-pc-windows-msvc.exe',
|
||||
};
|
||||
|
||||
const key = `${process.platform}_${process.env.YAAK_TARGET_ARCH ?? process.arch}`;
|
||||
|
||||
const destDir = path.join(__dirname, `..`, 'src-tauri', 'vendored', 'node');
|
||||
const binDest = path.join(destDir, DST_BIN_MAP[key]);
|
||||
console.log(`Vendoring NodeJS ${NODE_VERSION} for ${key}`);
|
||||
|
||||
if (existsSync(binDest) && tryExecSync(`${binDest} --version`).trim() === NODE_VERSION) {
|
||||
console.log('NodeJS already vendored');
|
||||
return;
|
||||
}
|
||||
|
||||
rmSync(destDir, { recursive: true, force: true });
|
||||
mkdirSync(destDir, { recursive: true });
|
||||
|
||||
const url = URL_MAP[key];
|
||||
const tmpDir = path.join(__dirname, 'tmp-node');
|
||||
rmSync(tmpDir, { recursive: true, force: true });
|
||||
|
||||
(async function () {
|
||||
// Download GitHub release artifact
|
||||
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, {});
|
||||
|
||||
// Copy binary
|
||||
const binSrc = path.join(tmpDir, SRC_BIN_MAP[key]);
|
||||
cpSync(binSrc, binDest);
|
||||
rmSync(tmpDir, { recursive: true, force: true });
|
||||
|
||||
console.log('Downloaded NodeJS to', binDest);
|
||||
})().catch((err) => {
|
||||
console.log('Script failed:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
function tryExecSync(cmd) {
|
||||
try {
|
||||
return execSync(cmd).toString('utf-8');
|
||||
} catch (_) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
const { readdirSync, cpSync } = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const { execSync } = require('node:child_process');
|
||||
const pluginsDir = process.env.YAAK_PLUGINS_DIR;
|
||||
if (!pluginsDir) {
|
||||
console.log('Skipping bundled plugins build because YAAK_PLUGINS_DIR is not set');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Installing Yaak plugins dependencies', pluginsDir);
|
||||
execSync('npm ci', { cwd: pluginsDir });
|
||||
console.log('Building Yaak plugins', pluginsDir);
|
||||
execSync('npm run build', { cwd: pluginsDir });
|
||||
|
||||
console.log('Copying Yaak plugins to', pluginsDir);
|
||||
|
||||
const pluginsRoot = path.join(pluginsDir, 'plugins');
|
||||
for (const name of readdirSync(pluginsRoot)) {
|
||||
const dir = path.join(pluginsRoot, name);
|
||||
if (name.startsWith('.')) continue;
|
||||
const destDir = path.join(__dirname, '../src-tauri/vendored/plugins/', name);
|
||||
console.log(`Copying ${name} to ${destDir}`);
|
||||
cpSync(path.join(dir, 'package.json'), path.join(destDir, 'package.json'));
|
||||
cpSync(path.join(dir, 'build/index.js'), path.join(destDir, 'build/index.js'));
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
const decompress = require('decompress');
|
||||
const Downloader = require('nodejs-file-downloader');
|
||||
const path = require('node:path');
|
||||
const { rmSync, mkdirSync, cpSync, existsSync, statSync, chmodSync } = require('node:fs');
|
||||
const { execSync } = require('node:child_process');
|
||||
|
||||
const VERSION = '28.3';
|
||||
|
||||
// `${process.platform}_${process.arch}`
|
||||
const MAC_ARM = 'darwin_arm64';
|
||||
const MAC_X64 = 'darwin_x64';
|
||||
const LNX_ARM = 'linux_arm64';
|
||||
const LNX_X64 = 'linux_x64';
|
||||
const WIN_X64 = 'win32_x64';
|
||||
|
||||
const URL_MAP = {
|
||||
[MAC_ARM]: `https://github.com/protocolbuffers/protobuf/releases/download/v${VERSION}/protoc-${VERSION}-osx-aarch_64.zip`,
|
||||
[MAC_X64]: `https://github.com/protocolbuffers/protobuf/releases/download/v${VERSION}/protoc-${VERSION}-osx-x86_64.zip`,
|
||||
[LNX_ARM]: `https://github.com/protocolbuffers/protobuf/releases/download/v${VERSION}/protoc-${VERSION}-linux-aarch_64.zip`,
|
||||
[LNX_X64]: `https://github.com/protocolbuffers/protobuf/releases/download/v${VERSION}/protoc-${VERSION}-linux-x86_64.zip`,
|
||||
[WIN_X64]: `https://github.com/protocolbuffers/protobuf/releases/download/v${VERSION}/protoc-${VERSION}-win64.zip`,
|
||||
};
|
||||
|
||||
const SRC_BIN_MAP = {
|
||||
[MAC_ARM]: 'bin/protoc',
|
||||
[MAC_X64]: 'bin/protoc',
|
||||
[LNX_ARM]: 'bin/protoc',
|
||||
[LNX_X64]: 'bin/protoc',
|
||||
[WIN_X64]: 'bin/protoc.exe',
|
||||
};
|
||||
|
||||
const DST_BIN_MAP = {
|
||||
[MAC_ARM]: 'yaakprotoc-aarch64-apple-darwin',
|
||||
[MAC_X64]: 'yaakprotoc-x86_64-apple-darwin',
|
||||
[LNX_ARM]: 'yaakprotoc-aarch64-unknown-linux-gnu',
|
||||
[LNX_X64]: 'yaakprotoc-x86_64-unknown-linux-gnu',
|
||||
[WIN_X64]: 'yaakprotoc-x86_64-pc-windows-msvc.exe',
|
||||
};
|
||||
|
||||
const dstDir = path.join(__dirname, `..`, 'src-tauri', 'vendored', 'protoc');
|
||||
const key = `${process.platform}_${process.env.YAAK_TARGET_ARCH ?? process.arch}`;
|
||||
console.log(`Vendoring protoc ${VERSION} for ${key}`);
|
||||
|
||||
const url = URL_MAP[key];
|
||||
const tmpDir = path.join(__dirname, 'tmp-protoc');
|
||||
const binSrc = path.join(tmpDir, SRC_BIN_MAP[key]);
|
||||
const binDst = path.join(dstDir, DST_BIN_MAP[key]);
|
||||
|
||||
if (existsSync(binDst) && tryExecSync(`${binDst} --version`).trim().includes(VERSION)) {
|
||||
console.log('Protoc already vendored');
|
||||
return;
|
||||
}
|
||||
|
||||
rmSync(tmpDir, { recursive: true, force: true });
|
||||
rmSync(dstDir, { recursive: true, force: true });
|
||||
mkdirSync(dstDir, { recursive: true });
|
||||
|
||||
(async function () {
|
||||
// Download GitHub release artifact
|
||||
const { filePath } = await new Downloader({ url, directory: tmpDir }).download();
|
||||
|
||||
// Decompress to the same directory
|
||||
await decompress(filePath, tmpDir, {});
|
||||
|
||||
// Copy binary
|
||||
cpSync(binSrc, binDst);
|
||||
|
||||
// Copy other files
|
||||
const includeSrc = path.join(tmpDir, 'include');
|
||||
const includeDst = path.join(dstDir, 'include');
|
||||
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));
|
||||
|
||||
function tryExecSync(cmd) {
|
||||
try {
|
||||
return execSync(cmd).toString('utf-8');
|
||||
} catch (_) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
9
src-tauri/.gitignore
vendored
@@ -1,11 +1,4 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
target/
|
||||
/target/
|
||||
|
||||
vendored/*
|
||||
!vendored/plugins
|
||||
|
||||
gen/*
|
||||
|
||||
**/permissions/autogenerated
|
||||
**/permissions/schemas
|
||||
|
||||
7476
src-tauri/Cargo.lock
generated
@@ -1,102 +1,42 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"yaak-crypto",
|
||||
"yaak-git",
|
||||
"yaak-grpc",
|
||||
"yaak-http",
|
||||
"yaak-license",
|
||||
"yaak-mac-window",
|
||||
"yaak-models",
|
||||
"yaak-plugins",
|
||||
"yaak-sse",
|
||||
"yaak-sync",
|
||||
"yaak-templates",
|
||||
"yaak-ws",
|
||||
]
|
||||
|
||||
[package]
|
||||
name = "yaak-app"
|
||||
version = "0.0.0"
|
||||
edition = "2024"
|
||||
description = "A network protocol testing utility app"
|
||||
authors = ["Gregory Schier"]
|
||||
publish = false
|
||||
|
||||
# Produce a library for mobile support
|
||||
[lib]
|
||||
name = "tauri_app_lib"
|
||||
crate-type = ["staticlib", "cdylib", "lib"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/gschier/yaak-app"
|
||||
edition = "2021"
|
||||
|
||||
[profile.release]
|
||||
strip = true # Automatically strip symbols from the binary.
|
||||
|
||||
[features]
|
||||
cargo-clippy = []
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.1.1", features = [] }
|
||||
tauri-build = { version = "1.2", features = [] }
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
openssl-sys = { version = "0.9.105", features = ["vendored"] } # For Ubuntu installation to work
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
objc = "0.2.7"
|
||||
cocoa = "0.24.1"
|
||||
|
||||
[dependencies]
|
||||
chrono = { version = "0.4.31", features = ["serde"] }
|
||||
encoding_rs = "0.8.35"
|
||||
eventsource-client = { git = "https://github.com/yaakapp/rust-eventsource-client", version = "0.14.0" }
|
||||
http = { version = "1.2.0", default-features = false }
|
||||
log = "0.4.27"
|
||||
md5 = "0.7.0"
|
||||
mime_guess = "2.0.5"
|
||||
rand = "0.9.0"
|
||||
reqwest = { workspace = true, features = ["multipart", "cookies", "gzip", "brotli", "deflate", "json", "rustls-tls-manual-roots-no-provider"] }
|
||||
reqwest_cookie_store = "0.8.0"
|
||||
rustls = { version = "0.23.25", default-features = false, features = ["custom-provider", "ring"] }
|
||||
rustls-platform-verifier = "0.5.1"
|
||||
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.2"
|
||||
tauri-plugin-dialog = "2.2.0"
|
||||
tauri-plugin-fs = "2.2.0"
|
||||
tauri-plugin-log = { version = "2.3.1", features = ["colored"] }
|
||||
tauri-plugin-opener = "2.2.6"
|
||||
tauri-plugin-os = "2.2.1"
|
||||
tauri-plugin-shell = { workspace = true }
|
||||
tauri-plugin-single-instance = "2.2.2"
|
||||
tauri-plugin-updater = "2.6.1"
|
||||
tauri-plugin-window-state = "2.2.1"
|
||||
thiserror = { workspace = true }
|
||||
tokio = { workspace = true, features = ["sync"] }
|
||||
tokio-stream = "0.1.17"
|
||||
uuid = "1.12.1"
|
||||
yaak-common = { workspace = true }
|
||||
yaak-crypto = { workspace = true }
|
||||
yaak-git = { path = "yaak-git" }
|
||||
yaak-grpc = { path = "yaak-grpc" }
|
||||
yaak-http = { workspace = true }
|
||||
yaak-license = { path = "yaak-license" }
|
||||
yaak-mac-window = { path = "yaak-mac-window" }
|
||||
yaak-models = { workspace = true }
|
||||
yaak-plugins = { workspace = true }
|
||||
yaak-sse = { workspace = true }
|
||||
yaak-sync = { workspace = true }
|
||||
yaak-templates = { workspace = true }
|
||||
yaak-ws = { path = "yaak-ws" }
|
||||
serde_json = { version = "1.0", features = ["raw_value"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tauri = { version = "1.2", features = ["config-toml", "devtools", "shell-open", "system-tray", "updater", "window-start-dragging"] }
|
||||
http = "0.2.8"
|
||||
reqwest = { version = "0.11.14", features = ["json"] }
|
||||
tokio = { version = "1.25.0", features = ["sync"] }
|
||||
futures = "0.3.26"
|
||||
deno_core = "0.178.0"
|
||||
deno_ast = { version = "0.25.0", features = ["transpiling"] }
|
||||
sqlx = { version = "0.6.2", features = ["sqlite", "runtime-tokio-rustls", "json", "chrono", "time", "offline"] }
|
||||
uuid = "1.3.0"
|
||||
rand = "0.8.5"
|
||||
chrono = { version = "0.4.23", features = ["serde"] }
|
||||
base64 = "0.21.0"
|
||||
|
||||
[workspace.dependencies]
|
||||
reqwest = "0.12.15"
|
||||
serde = "1.0.219"
|
||||
serde_json = "1.0.140"
|
||||
tauri = "2.4.1"
|
||||
tauri-plugin = "2.1.1"
|
||||
tauri-plugin-shell = "2.2.1"
|
||||
tokio = "1.44.2"
|
||||
thiserror = "2.0.12"
|
||||
ts-rs = "10.1.0"
|
||||
yaak-common = { path = "yaak-common" }
|
||||
yaak-http = { path = "yaak-http" }
|
||||
yaak-models = { path = "yaak-models" }
|
||||
yaak-plugins = { path = "yaak-plugins" }
|
||||
yaak-sse = { path = "yaak-sse" }
|
||||
yaak-sync = { path = "yaak-sync" }
|
||||
yaak-templates = { path = "yaak-templates" }
|
||||
yaak-crypto = { path = "yaak-crypto" }
|
||||
[features]
|
||||
# by default Tauri runs in production mode
|
||||
# when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL
|
||||
default = ["custom-protocol"]
|
||||
# this feature is used used for production builds where `devPath` points to the filesystem
|
||||
# DO NOT remove this
|
||||
custom-protocol = ["tauri/custom-protocol"]
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/capabilities.json",
|
||||
"identifier": "main",
|
||||
"description": "Main permissions",
|
||||
"local": true,
|
||||
"windows": [
|
||||
"*"
|
||||
],
|
||||
"permissions": [
|
||||
"core:app:allow-identifier",
|
||||
"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/**"
|
||||
}
|
||||
]
|
||||
},
|
||||
"clipboard-manager:allow-read-text",
|
||||
"clipboard-manager:allow-write-text",
|
||||
"core:webview:allow-set-webview-zoom",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-internal-toggle-maximize",
|
||||
"core:window:allow-is-fullscreen",
|
||||
"core:window:allow-is-maximized",
|
||||
"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-unmaximize",
|
||||
"opener:allow-default-urls",
|
||||
"opener:allow-open-path",
|
||||
"opener:allow-open-url",
|
||||
"opener:allow-reveal-item-in-dir",
|
||||
"shell:allow-open",
|
||||
"yaak-crypto:default",
|
||||
"yaak-git:default",
|
||||
"yaak-license:default",
|
||||
"yaak-mac-window:default",
|
||||
"yaak-models:default",
|
||||
"yaak-sync:default",
|
||||
"yaak-ws:default"
|
||||
]
|
||||
}
|
||||
BIN
src-tauri/icons/128x128.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
src-tauri/icons/128x128@2x.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
src-tauri/icons/32x32.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
src-tauri/icons/Square107x107Logo.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src-tauri/icons/Square142x142Logo.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
src-tauri/icons/Square150x150Logo.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
src-tauri/icons/Square284x284Logo.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
src-tauri/icons/Square30x30Logo.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
src-tauri/icons/Square310x310Logo.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
src-tauri/icons/Square44x44Logo.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
src-tauri/icons/Square71x71Logo.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
src-tauri/icons/Square89x89Logo.png
Normal file
|
After Width: | Height: | Size: 9.3 KiB |
BIN
src-tauri/icons/StoreLogo.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |